0

ash: Add CreateArcCustomTabController() to NewWindowClient interface

Add CreateArcCustomTabController() to NewWindowClient interface.
Add OpenArcCustomTab() to OpenUrlDelegate interface.
Add OnOpenCustomTab() to IntentHelperHost interface.

BUG=925769
TEST=manually

Change-Id: I7a9bdcb53c176cf1fb0edbf73e393d3cab9c3038
Reviewed-on: https://chromium-review.googlesource.com/c/1469817
Commit-Queue: Ryo Hashimoto <hashimoto@chromium.org>
Reviewed-by: Daniel Cheng <dcheng@chromium.org>
Reviewed-by: Jun Mukai <mukai@chromium.org>
Reviewed-by: Mitsuru Oshima <oshima@chromium.org>
Reviewed-by: Yusuke Sato <yusukes@chromium.org>
Cr-Commit-Position: refs/heads/master@{#635382}
This commit is contained in:
Ryo Hashimoto
2019-02-26 03:04:28 +00:00
committed by Commit Bot
parent 55c9b10475
commit bac835aaa0
18 changed files with 496 additions and 10 deletions

@ -194,6 +194,10 @@ component("ash") {
"cast_config_controller.h",
"contained_shell/contained_shell_controller.cc",
"contained_shell/contained_shell_controller.h",
"custom_tab/arc_custom_tab_controller.cc",
"custom_tab/arc_custom_tab_controller.h",
"custom_tab/arc_custom_tab_view.cc",
"custom_tab/arc_custom_tab_view.h",
"dbus/ash_dbus_services.cc",
"dbus/ash_dbus_services.h",
"dbus/display_service_provider.cc",

@ -0,0 +1,31 @@
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ash/custom_tab/arc_custom_tab_controller.h"
#include <utility>
#include "ash/custom_tab/arc_custom_tab_view.h"
namespace ash {
ArcCustomTabController::ArcCustomTabController() : binding_(this) {}
ArcCustomTabController::~ArcCustomTabController() = default;
void ArcCustomTabController::BindRequest(
mojom::ArcCustomTabControllerRequest request) {
binding_.Close();
binding_.Bind(std::move(request));
}
void ArcCustomTabController::CreateView(int32_t task_id,
int32_t surface_id,
int32_t top_margin,
CreateViewCallback callback) {
std::move(callback).Run(
ArcCustomTabView::Create(task_id, surface_id, top_margin));
}
} // namespace ash

@ -0,0 +1,36 @@
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef ASH_CUSTOM_TAB_ARC_CUSTOM_TAB_CONTROLLER_H_
#define ASH_CUSTOM_TAB_ARC_CUSTOM_TAB_CONTROLLER_H_
#include "ash/public/interfaces/arc_custom_tab.mojom.h"
#include "base/macros.h"
#include "mojo/public/cpp/bindings/binding.h"
namespace ash {
// Provides the ArcCustomTabController interface to the outside world.
class ArcCustomTabController : public mojom::ArcCustomTabController {
public:
ArcCustomTabController();
~ArcCustomTabController() override;
void BindRequest(mojom::ArcCustomTabControllerRequest request);
// ArcCustomTabController:
void CreateView(int32_t task_id,
int32_t surface_id,
int32_t top_margin,
CreateViewCallback callback) override;
private:
mojo::Binding<mojom::ArcCustomTabController> binding_;
DISALLOW_COPY_AND_ASSIGN(ArcCustomTabController);
};
} // namespace ash
#endif // ASH_CUSTOM_TAB_ARC_CUSTOM_TAB_CONTROLLER_H_

@ -0,0 +1,146 @@
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ash/custom_tab/arc_custom_tab_view.h"
#include <memory>
#include <string>
#include <utility>
#include "ash/shell.h"
#include "ash/ws/window_service_owner.h"
#include "components/exo/shell_surface_util.h"
#include "components/exo/surface.h"
#include "ui/aura/window.h"
#include "ui/views/layout/fill_layout.h"
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_delegate.h"
namespace ash {
namespace {
// Tries to find the specified ARC window recursively.
aura::Window* FindArcWindow(const aura::Window::Windows& windows,
const std::string& arc_app_id) {
for (aura::Window* window : windows) {
const std::string* id = exo::GetShellApplicationId(window);
if (id && *id == arc_app_id)
return window;
aura::Window* result = FindArcWindow(window->children(), arc_app_id);
if (result)
return result;
}
return nullptr;
}
// Tries to find the specified ARC surface window recursively.
aura::Window* FindSurfaceWindow(aura::Window* window, int surface_id) {
auto* surface = exo::Surface::AsSurface(window);
if (surface && surface->GetClientSurfaceId() == surface_id)
return window;
for (aura::Window* child : window->children()) {
aura::Window* result = FindSurfaceWindow(child, surface_id);
if (result)
return result;
}
return nullptr;
}
} // namespace
// static
mojom::ArcCustomTabViewPtr ArcCustomTabView::Create(int32_t task_id,
int32_t surface_id,
int32_t top_margin) {
const std::string arc_app_id =
base::StringPrintf("org.chromium.arc.%d", task_id);
aura::Window* arc_app_window =
FindArcWindow(ash::Shell::Get()->GetAllRootWindows(), arc_app_id);
if (!arc_app_window) {
LOG(ERROR) << "No ARC window with the specified task ID " << task_id;
return nullptr;
}
views::Widget* widget =
views::Widget::GetWidgetForNativeWindow(arc_app_window);
if (!widget) {
LOG(ERROR) << "No widget for the ARC app window.";
return nullptr;
}
auto* parent = widget->widget_delegate()->GetContentsView();
auto* view = new ArcCustomTabView(surface_id, top_margin);
parent->AddChildView(view);
parent->SetLayoutManager(std::make_unique<views::FillLayout>());
parent->Layout();
mojom::ArcCustomTabViewPtr ptr;
view->Bind(&ptr);
return ptr;
}
void ArcCustomTabView::EmbedUsingToken(const base::UnguessableToken& token) {
remote_view_host_->EmbedUsingToken(token, 0, base::BindOnce([](bool success) {
LOG_IF(ERROR, !success)
<< "Failed to embed.";
}));
}
void ArcCustomTabView::Layout() {
if (!GetWidget()) {
LOG(ERROR) << "No widget";
return;
}
DCHECK(GetWidget()->GetNativeWindow());
aura::Window* surface_window =
FindSurfaceWindow(GetWidget()->GetNativeWindow(), surface_id_);
if (!surface_window) {
LOG(ERROR) << "Surface not found " << surface_id_;
return;
}
gfx::Point topleft(0, top_margin_),
bottomright(surface_window->bounds().width(),
surface_window->bounds().height());
ConvertPointFromWindow(surface_window, &topleft);
ConvertPointFromWindow(surface_window, &bottomright);
gfx::Rect bounds(topleft, gfx::Size(bottomright.x() - topleft.x(),
bottomright.y() - topleft.y()));
remote_view_host_->SetBoundsRect(bounds);
// Stack the remote view window at top.
aura::Window* window = remote_view_host_->GetNativeViewContainer();
window->parent()->StackChildAtTop(window);
}
ArcCustomTabView::ArcCustomTabView(int32_t surface_id, int32_t top_margin)
: binding_(this),
remote_view_host_(new ws::ServerRemoteViewHost(
ash::Shell::Get()->window_service_owner()->window_service())),
surface_id_(surface_id),
top_margin_(top_margin),
weak_ptr_factory_(this) {
AddChildView(remote_view_host_.get());
}
ArcCustomTabView::~ArcCustomTabView() = default;
void ArcCustomTabView::Bind(mojom::ArcCustomTabViewPtr* ptr) {
binding_.Bind(mojo::MakeRequest(ptr));
binding_.set_connection_error_handler(
base::BindOnce(&ArcCustomTabView::Close, weak_ptr_factory_.GetWeakPtr()));
}
void ArcCustomTabView::Close() {
delete this;
}
void ArcCustomTabView::ConvertPointFromWindow(aura::Window* window,
gfx::Point* point) {
aura::Window::ConvertPointToTarget(window, GetWidget()->GetNativeWindow(),
point);
views::View::ConvertPointFromWidget(parent(), point);
}
} // namespace ash

@ -0,0 +1,56 @@
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef ASH_CUSTOM_TAB_ARC_CUSTOM_TAB_VIEW_H_
#define ASH_CUSTOM_TAB_ARC_CUSTOM_TAB_VIEW_H_
#include <memory>
#include "ash/public/interfaces/arc_custom_tab.mojom.h"
#include "base/macros.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "services/ws/remote_view_host/server_remote_view_host.h"
#include "ui/views/view.h"
namespace ash {
// Implementation of ArcCustomTabView interface.
class ArcCustomTabView : public views::View, public mojom::ArcCustomTabView {
public:
// Creates a new ArcCustomTabView instance. The instance will be deleted when
// the pointer is closed. Returns null when the arguments are invalid.
static mojom::ArcCustomTabViewPtr Create(int32_t task_id,
int32_t surface_id,
int32_t top_margin);
// mojom::ArcCustomTabView:
void EmbedUsingToken(const base::UnguessableToken& token) override;
// views::View:
void Layout() override;
private:
ArcCustomTabView(int32_t surface_id, int32_t top_margin);
~ArcCustomTabView() override;
// Binds this instance to the pointer.
void Bind(mojom::ArcCustomTabViewPtr* ptr);
// Deletes this object when the mojo connection is closed.
void Close();
// Converts the point from the given window to this view.
void ConvertPointFromWindow(aura::Window* window, gfx::Point* point);
mojo::Binding<mojom::ArcCustomTabView> binding_;
std::unique_ptr<ws::ServerRemoteViewHost> remote_view_host_;
int32_t surface_id_, top_margin_;
base::WeakPtrFactory<ArcCustomTabView> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(ArcCustomTabView);
};
} // namespace ash
#endif // ASH_CUSTOM_TAB_ARC_CUSTOM_TAB_VIEW_H_

@ -17,6 +17,7 @@
#include "ash/assistant/assistant_setup_controller.h"
#include "ash/cast_config_controller.h"
#include "ash/contained_shell/contained_shell_controller.h"
#include "ash/custom_tab/arc_custom_tab_controller.h"
#include "ash/display/ash_display_controller.h"
#include "ash/display/cros_display_config.h"
#include "ash/display/display_output_protection.h"
@ -82,6 +83,11 @@ void BindAppListControllerRequestOnMainThread(
Shell::Get()->app_list_controller()->BindRequest(std::move(request));
}
void BindArcCustomTabControllerRequestOnMainThread(
mojom::ArcCustomTabControllerRequest request) {
Shell::Get()->arc_custom_tab_controller()->BindRequest(std::move(request));
}
void BindAshDisplayControllerRequestOnMainThread(
mojom::AshDisplayControllerRequest request) {
Shell::Get()->ash_display_controller()->BindRequest(std::move(request));
@ -274,6 +280,9 @@ void RegisterInterfaces(
registry->AddInterface(
base::BindRepeating(&BindAppListControllerRequestOnMainThread),
main_thread_task_runner);
registry->AddInterface(
base::BindRepeating(&BindArcCustomTabControllerRequestOnMainThread),
main_thread_task_runner);
if (chromeos::switches::IsAssistantEnabled()) {
registry->AddInterface(
base::BindRepeating(

@ -8,6 +8,7 @@
#include "ash/public/interfaces/accessibility_controller.mojom.h"
#include "ash/public/interfaces/accessibility_focus_ring_controller.mojom.h"
#include "ash/public/interfaces/app_list.mojom.h"
#include "ash/public/interfaces/arc_custom_tab.mojom.h"
#include "ash/public/interfaces/ash_display_controller.mojom.h"
#include "ash/public/interfaces/ash_message_center_controller.mojom.h"
#include "ash/public/interfaces/assistant_controller.mojom.h"
@ -79,7 +80,8 @@ const service_manager::Manifest& GetManifest() {
service_manager::Manifest::InterfaceList<
mojom::AcceleratorController, mojom::AccessibilityController,
mojom::AccessibilityFocusRingController,
mojom::AppListController, mojom::AshMessageCenterController,
mojom::AppListController, mojom::ArcCustomTabController,
mojom::AshMessageCenterController,
mojom::AssistantAlarmTimerController,
mojom::AssistantController,
mojom::AssistantNotificationController,

@ -18,6 +18,7 @@ mojom("interfaces_internal") {
"accessibility_controller_enums.mojom",
"accessibility_focus_ring_controller.mojom",
"app_list.mojom",
"arc_custom_tab.mojom",
"ash_display_controller.mojom",
"ash_message_center_controller.mojom",
"ash_window_manager.mojom",

@ -0,0 +1,22 @@
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
module ash.mojom;
import "mojo/public/mojom/base/unguessable_token.mojom";
// An interface that an ash user uses to interact with each ARC custom tab.
interface ArcCustomTabView {
// Embeds the remote view specified by the token.
EmbedUsingToken(mojo_base.mojom.UnguessableToken token);
};
// An exported object in ash which lets an ash consumer set a client interface.
interface ArcCustomTabController {
// Creates an ArcCustomTabView instance for the ARC window specified by the
// task ID and the surface ID.
// May return null when the arguments are invalid.
CreateView(int32 task_id, int32 surface_id, int32 top_margin)
=> (ArcCustomTabView? controller);
};

@ -25,6 +25,7 @@
#include "ash/cast_config_controller.h"
#include "ash/components/tap_visualizer/public/mojom/tap_visualizer.mojom.h"
#include "ash/contained_shell/contained_shell_controller.h"
#include "ash/custom_tab/arc_custom_tab_controller.h"
#include "ash/dbus/ash_dbus_services.h"
#include "ash/detachable_base/detachable_base_handler.h"
#include "ash/detachable_base/detachable_base_notification_controller.h"
@ -632,6 +633,7 @@ Shell::Shell(std::unique_ptr<ShellDelegate> shell_delegate,
: nullptr),
aura_env_(owned_aura_env_.get() ? owned_aura_env_.get()
: aura::Env::GetInstance()),
arc_custom_tab_controller_(std::make_unique<ArcCustomTabController>()),
ash_display_controller_(std::make_unique<AshDisplayController>()),
brightness_control_delegate_(
std::make_unique<system::BrightnessControllerChromeos>()),

@ -94,6 +94,7 @@ class AcceleratorController;
class AccessibilityController;
class AccessibilityDelegate;
class AccessibilityFocusRingController;
class ArcCustomTabController;
class AshDBusServices;
class AshDisplayController;
class AppListControllerImpl;
@ -343,6 +344,9 @@ class ASH_EXPORT Shell : public SessionObserver,
AppListControllerImpl* app_list_controller() {
return app_list_controller_.get();
}
ArcCustomTabController* arc_custom_tab_controller() {
return arc_custom_tab_controller_.get();
}
AshDisplayController* ash_display_controller() {
return ash_display_controller_.get();
}
@ -704,6 +708,7 @@ class ASH_EXPORT Shell : public SessionObserver,
std::unique_ptr<AccessibilityFocusRingController>
accessibility_focus_ring_controller_;
std::unique_ptr<AppListControllerImpl> app_list_controller_;
std::unique_ptr<ArcCustomTabController> arc_custom_tab_controller_;
std::unique_ptr<AshDBusServices> ash_dbus_services_;
std::unique_ptr<AshDisplayController> ash_display_controller_;
std::unique_ptr<AssistantController> assistant_controller_;

@ -4,6 +4,8 @@
#include "chrome/browser/ui/ash/chrome_new_window_client.h"
#include <utility>
#include "ash/public/cpp/ash_features.h"
#include "ash/public/interfaces/constants.mojom.h"
#include "base/macros.h"
@ -17,6 +19,7 @@
#include "chrome/browser/prefs/incognito_mode_prefs.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/sessions/tab_restore_service_factory.h"
#include "chrome/browser/tab_contents/tab_util.h"
#include "chrome/browser/ui/ash/ksv/keyboard_shortcut_viewer_util.h"
#include "chrome/browser/ui/ash/multi_user/multi_user_util.h"
#include "chrome/browser/ui/browser.h"
@ -44,8 +47,10 @@
#include "extensions/common/constants.h"
#include "extensions/common/extension.h"
#include "services/service_manager/public/cpp/connector.h"
#include "ui/aura/window.h"
#include "ui/base/page_transition_types.h"
#include "ui/base/window_open_disposition.h"
#include "ui/views/mus/remote_view/remote_view_provider.h"
#include "url/url_constants.h"
namespace {
@ -65,6 +70,88 @@ bool IsIncognitoAllowed() {
IncognitoModePrefs::DISABLED;
}
// Converts the given ARC URL to an external file URL to read it via ARC content
// file system when necessary. Otherwise, returns the given URL unchanged.
GURL ConvertArcUrlToExternalFileUrlIfNeeded(const GURL& url) {
if (url.SchemeIs(url::kFileScheme) || url.SchemeIs(url::kContentScheme)) {
// Chrome cannot open this URL. Read the contents via ARC content file
// system with an external file URL.
return arc::ArcUrlToExternalFileUrl(url);
}
return url;
}
// Implementation of CustomTabSession interface.
class CustomTabSessionImpl : public arc::mojom::CustomTabSession {
public:
static arc::mojom::CustomTabSessionPtr Create(
Profile* profile,
const GURL& url,
ash::mojom::ArcCustomTabViewPtr view) {
// This object will be deleted when the mojo connection is closed.
auto* tab = new CustomTabSessionImpl(profile, url, std::move(view));
arc::mojom::CustomTabSessionPtr ptr;
tab->Bind(&ptr);
return ptr;
}
private:
CustomTabSessionImpl(Profile* profile,
const GURL& url,
ash::mojom::ArcCustomTabViewPtr view)
: binding_(this),
view_(std::move(view)),
web_contents_(CreateWebContents(profile, url)),
weak_ptr_factory_(this) {
aura::Window* window = web_contents_->GetNativeView();
remote_view_provider_ = std::make_unique<views::RemoteViewProvider>(window);
remote_view_provider_->GetEmbedToken(base::BindOnce(
&CustomTabSessionImpl::OnEmbedToken, weak_ptr_factory_.GetWeakPtr()));
window->Show();
}
~CustomTabSessionImpl() override = default;
void Bind(arc::mojom::CustomTabSessionPtr* ptr) {
binding_.Bind(mojo::MakeRequest(ptr));
binding_.set_connection_error_handler(base::BindOnce(
&CustomTabSessionImpl::Close, weak_ptr_factory_.GetWeakPtr()));
}
// Deletes this object when the mojo connection is closed.
void Close() { delete this; }
std::unique_ptr<content::WebContents> CreateWebContents(Profile* profile,
const GURL& url) {
scoped_refptr<content::SiteInstance> site_instance =
tab_util::GetSiteInstanceForNewTab(profile, url);
content::WebContents::CreateParams create_params(profile, site_instance);
std::unique_ptr<content::WebContents> web_contents =
content::WebContents::Create(create_params);
content::NavigationController::LoadURLParams load_url_params(url);
load_url_params.source_site_instance = site_instance;
web_contents->GetController().LoadURLWithParams(load_url_params);
// Add a flag to remember this tab originated in the ARC context.
web_contents->SetUserData(&arc::ArcWebContentsData::kArcTransitionFlag,
std::make_unique<arc::ArcWebContentsData>());
return web_contents;
}
void OnEmbedToken(const base::UnguessableToken& token) {
view_->EmbedUsingToken(token);
}
mojo::Binding<arc::mojom::CustomTabSession> binding_;
ash::mojom::ArcCustomTabViewPtr view_;
std::unique_ptr<content::WebContents> web_contents_;
std::unique_ptr<views::RemoteViewProvider> remote_view_provider_;
base::WeakPtrFactory<CustomTabSessionImpl> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(CustomTabSessionImpl);
};
} // namespace
ChromeNewWindowClient::ChromeNewWindowClient() : binding_(this) {
@ -73,6 +160,8 @@ ChromeNewWindowClient::ChromeNewWindowClient() : binding_(this) {
service_manager::Connector* connector =
content::ServiceManagerConnection::GetForProcess()->GetConnector();
connector->BindInterface(ash::mojom::kServiceName, &new_window_controller_);
connector->BindInterface(ash::mojom::kServiceName,
&arc_custom_tab_controller_);
// Register this object as the client interface implementation.
ash::mojom::NewWindowClientAssociatedPtrInfo ptr_info;
@ -255,13 +344,7 @@ void ChromeNewWindowClient::OpenUrlFromArc(const GURL& url) {
if (!url.is_valid())
return;
GURL url_to_open = url;
if (url.SchemeIs(url::kFileScheme) || url.SchemeIs(url::kContentScheme)) {
// Chrome cannot open this URL. Read the contents via ARC content file
// system with an external file URL.
url_to_open = arc::ArcUrlToExternalFileUrl(url_to_open);
}
GURL url_to_open = ConvertArcUrlToExternalFileUrlIfNeeded(url);
content::WebContents* tab =
OpenUrlImpl(url_to_open, false /* from_user_interaction */);
if (!tab)
@ -310,6 +393,30 @@ void ChromeNewWindowClient::OpenWebAppFromArc(const GURL& url) {
std::make_unique<arc::ArcWebContentsData>());
}
void ChromeNewWindowClient::OpenArcCustomTab(
const GURL& url,
int32_t task_id,
int32_t surface_id,
int32_t top_margin,
arc::mojom::IntentHelperHost::OnOpenCustomTabCallback callback) {
GURL url_to_open = ConvertArcUrlToExternalFileUrlIfNeeded(url);
Profile* profile = ProfileManager::GetActiveUserProfile();
arc_custom_tab_controller_->CreateView(
task_id, surface_id, top_margin,
base::BindOnce(
[](Profile* profile, const GURL& url,
arc::mojom::IntentHelperHost::OnOpenCustomTabCallback callback,
ash::mojom::ArcCustomTabViewPtr view) {
if (!view) {
std::move(callback).Run(nullptr);
return;
}
std::move(callback).Run(
CustomTabSessionImpl::Create(profile, url, std::move(view)));
},
profile, url_to_open, std::move(callback)));
}
content::WebContents* ChromeNewWindowClient::OpenUrlImpl(
const GURL& url,
bool from_user_interaction) {

@ -7,6 +7,7 @@
#include <memory>
#include "ash/public/interfaces/arc_custom_tab.mojom.h"
#include "ash/public/interfaces/new_window.mojom.h"
#include "base/macros.h"
#include "components/arc/intent_helper/open_url_delegate.h"
@ -42,6 +43,12 @@ class ChromeNewWindowClient : public ash::mojom::NewWindowClient,
// arc::OpenUrlDelegate:
void OpenUrlFromArc(const GURL& url) override;
void OpenWebAppFromArc(const GURL& url) override;
void OpenArcCustomTab(
const GURL& url,
int32_t task_id,
int32_t surface_id,
int32_t top_margin,
arc::mojom::IntentHelperHost::OnOpenCustomTabCallback callback) override;
private:
class TabRestoreHelper;
@ -58,6 +65,8 @@ class ChromeNewWindowClient : public ash::mojom::NewWindowClient,
ash::mojom::NewWindowControllerPtr new_window_controller_;
ash::mojom::ArcCustomTabControllerPtr arc_custom_tab_controller_;
// Binds this object to the client interface.
mojo::AssociatedBinding<ash::mojom::NewWindowClient> binding_;

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// Next MinVersion: 25
// Next MinVersion: 26
module arc.mojom;
@ -163,9 +163,14 @@ struct TextSelectionAction {
[MinVersion=23] ArcBitmap? bitmap_icon;
};
// Interface to interact with a custom tab.
// Close the interface pointer to close the custom tab.
interface CustomTabSession {
};
// Handles intents from ARC in Chrome.
// Deprecated method ID: 4
// Next method ID: 10
// Next method ID: 11
interface IntentHelperHost {
// Called when icons associated with the package are no longer up to date.
[MinVersion=3] OnIconInvalidated@1(string package_name);
@ -182,6 +187,17 @@ interface IntentHelperHost {
// navigate to as well. No special URLs that allow access to privileged functions are allowed.
OnOpenUrl@0(string url);
// Opens the url with a custom tab.
// |task_id| and |surface_id| specify the Android task and the surface on
// which the custom tab should be shown.
// |top_margin| is the height of the space at the top of the window which
// needs to be vacant to display the top bar rendered by Android code.
[MinVersion=25] OnOpenCustomTab@10(string url,
int32 task_id,
int32 surface_id,
int32 top_margin)
=> (CustomTabSession? session);
// Opens the wallpaper picker dialog.
[MinVersion=6] OpenWallpaperPicker@3();

@ -171,6 +171,23 @@ void ArcIntentHelperBridge::OnOpenUrl(const std::string& url) {
g_open_url_delegate->OpenUrlFromArc(gurl);
}
void ArcIntentHelperBridge::OnOpenCustomTab(const std::string& url,
int32_t task_id,
int32_t surface_id,
int32_t top_margin,
OnOpenCustomTabCallback callback) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
// Converts |url| to a fixed-up one and checks validity.
const GURL gurl(url_formatter::FixupURL(url, /*desired_tld=*/std::string()));
if (!gurl.is_valid() ||
allowed_arc_schemes_.find(gurl.scheme()) == allowed_arc_schemes_.end()) {
std::move(callback).Run(nullptr);
return;
}
g_open_url_delegate->OpenArcCustomTab(gurl, task_id, surface_id, top_margin,
std::move(callback));
}
void ArcIntentHelperBridge::OnOpenChromePage(mojom::ChromePage page) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
auto it = allowed_chrome_pages_map_.find(page);

@ -65,6 +65,11 @@ class ArcIntentHelperBridge
std::vector<IntentFilter> intent_filters) override;
void OnOpenDownloads() override;
void OnOpenUrl(const std::string& url) override;
void OnOpenCustomTab(const std::string& url,
int32_t task_id,
int32_t surface_id,
int32_t top_margin,
OnOpenCustomTabCallback callback) override;
void OnOpenChromePage(mojom::ChromePage page) override;
void OpenWallpaperPicker() override;
void SetWallpaperDeprecated(const std::vector<uint8_t>& jpeg_data) override;

@ -40,6 +40,14 @@ class ArcIntentHelperTest : public testing::Test {
// OpenUrlDelegate:
void OpenUrlFromArc(const GURL& url) override { last_opened_url_ = url; }
void OpenWebAppFromArc(const GURL& url) override { last_opened_url_ = url; }
void OpenArcCustomTab(
const GURL& url,
int32_t task_id,
int32_t surface_id,
int32_t top_margin,
mojom::IntentHelperHost::OnOpenCustomTabCallback callback) override {
std::move(callback).Run(nullptr);
}
GURL TakeLastOpenedUrl() {
GURL result = std::move(last_opened_url_);

@ -5,6 +5,8 @@
#ifndef COMPONENTS_ARC_INTENT_HELPER_OPEN_URL_DELEGATE_H_
#define COMPONENTS_ARC_INTENT_HELPER_OPEN_URL_DELEGATE_H_
#include "components/arc/common/intent_helper.mojom.h"
class GURL;
namespace arc {
@ -19,6 +21,14 @@ class OpenUrlDelegate {
// Opens the given URL as a web app in the Chrome browser, falling back to
// opening as a tab if no installed web app is found.
virtual void OpenWebAppFromArc(const GURL& url) = 0;
// Opens the given URL in a custom tab.
virtual void OpenArcCustomTab(
const GURL& url,
int32_t task_id,
int32_t surface_id,
int32_t top_margin,
mojom::IntentHelperHost::OnOpenCustomTabCallback callback) = 0;
};
} // namespace arc