Commit 90a3c79b authored by Jesse Schettler's avatar Jesse Schettler Committed by Commit Bot

ash: Move CustomTabSessionImpl out of ChromeNewWindowClient

Move CustomTabSessionImpl to its own file. Also, factor out code that
can be used by other classes that create and manage an ARC Custom Tab.

BUG=b:64863368
TEST=Deploy Chrome to DUT and verify ARC Custom Tabs work correctly
R=djacobo@chromium.org, hashimoto@chromium.org, oshima@chromium.org

Change-Id: Ib11a233aa04ac52cfe73abaa9ecbb145791aa263
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1728446Reviewed-by: default avatarDavid Jacobo <djacobo@chromium.org>
Reviewed-by: default avatarMitsuru Oshima (Slow - traveling) <oshima@chromium.org>
Reviewed-by: default avatarRyo Hashimoto <hashimoto@chromium.org>
Commit-Queue: Jesse Schettler <jschettler@chromium.org>
Auto-Submit: Jesse Schettler <jschettler@chromium.org>
Cr-Commit-Position: refs/heads/master@{#683483}
parent 6cfa9bca
......@@ -550,6 +550,8 @@ source_set("chromeos") {
"arc/intent_helper/arc_intent_picker_app_fetcher.h",
"arc/intent_helper/arc_settings_service.cc",
"arc/intent_helper/arc_settings_service.h",
"arc/intent_helper/custom_tab_session_impl.cc",
"arc/intent_helper/custom_tab_session_impl.h",
"arc/intent_helper/open_with_menu.cc",
"arc/intent_helper/open_with_menu.h",
"arc/intent_helper/start_smart_selection_action_menu.cc",
......
// 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 "chrome/browser/chromeos/arc/intent_helper/custom_tab_session_impl.h"
#include <utility>
#include "ash/public/cpp/arc_custom_tab.h"
#include "base/bind.h"
#include "base/metrics/histogram_macros.h"
#include "content/public/browser/web_contents.h"
#include "mojo/public/cpp/bindings/interface_request.h"
#include "ui/aura/window.h"
// static
arc::mojom::CustomTabSessionPtr CustomTabSessionImpl::Create(
std::unique_ptr<content::WebContents> web_contents,
std::unique_ptr<ash::ArcCustomTab> custom_tab) {
if (!custom_tab)
return nullptr;
// This object will be deleted when the mojo connection is closed.
auto* tab =
new CustomTabSessionImpl(std::move(web_contents), std::move(custom_tab));
arc::mojom::CustomTabSessionPtr ptr;
tab->Bind(&ptr);
return ptr;
}
CustomTabSessionImpl::CustomTabSessionImpl(
std::unique_ptr<content::WebContents> web_contents,
std::unique_ptr<ash::ArcCustomTab> custom_tab)
: ArcCustomTabModalDialogHost(std::move(custom_tab),
std::move(web_contents)),
binding_(this),
weak_ptr_factory_(this) {
aura::Window* window = web_contents_->GetNativeView();
custom_tab_->Attach(window);
window->Show();
}
CustomTabSessionImpl::~CustomTabSessionImpl() {
// Keep in sync with ArcCustomTabsSessionEndReason in
// tools/metrics/histograms/enums.xml.
enum class SessionEndReason {
CLOSED = 0,
FORWARDED_TO_NORMAL_TAB = 1,
kMaxValue = FORWARDED_TO_NORMAL_TAB,
} session_end_reason = forwarded_to_normal_tab_
? SessionEndReason::FORWARDED_TO_NORMAL_TAB
: SessionEndReason::CLOSED;
UMA_HISTOGRAM_ENUMERATION("Arc.CustomTabs.SessionEndReason",
session_end_reason);
auto elapsed = lifetime_timer_.Elapsed();
UMA_HISTOGRAM_LONG_TIMES("Arc.CustomTabs.SessionLifetime2.All", elapsed);
switch (session_end_reason) {
case SessionEndReason::CLOSED:
UMA_HISTOGRAM_LONG_TIMES("Arc.CustomTabs.SessionLifetime2.Closed",
elapsed);
break;
case SessionEndReason::FORWARDED_TO_NORMAL_TAB:
UMA_HISTOGRAM_LONG_TIMES(
"Arc.CustomTabs.SessionLifetime2.ForwardedToNormalTab", elapsed);
break;
}
}
void CustomTabSessionImpl::OnOpenInChromeClicked() {
forwarded_to_normal_tab_ = true;
}
void CustomTabSessionImpl::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 CustomTabSessionImpl::Close() {
delete this;
}
// 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 CHROME_BROWSER_CHROMEOS_ARC_INTENT_HELPER_CUSTOM_TAB_SESSION_IMPL_H_
#define CHROME_BROWSER_CHROMEOS_ARC_INTENT_HELPER_CUSTOM_TAB_SESSION_IMPL_H_
#include <memory>
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/timer/elapsed_timer.h"
#include "chrome/browser/ui/ash/arc_custom_tab_modal_dialog_host.h"
#include "components/arc/common/intent_helper.mojom.h"
#include "mojo/public/cpp/bindings/binding.h"
namespace ash {
class ArcCustomTab;
} // namespace ash
namespace content {
class WebContents;
} // namespace content
// Implementation of CustomTabSession interface.
class CustomTabSessionImpl : public arc::mojom::CustomTabSession,
public ArcCustomTabModalDialogHost {
public:
static arc::mojom::CustomTabSessionPtr Create(
std::unique_ptr<content::WebContents> web_contents,
std::unique_ptr<ash::ArcCustomTab> custom_tab);
// arc::mojom::CustomTabSession:
void OnOpenInChromeClicked() override;
private:
CustomTabSessionImpl(std::unique_ptr<content::WebContents> web_contents,
std::unique_ptr<ash::ArcCustomTab> custom_tab);
~CustomTabSessionImpl() override;
void Bind(arc::mojom::CustomTabSessionPtr* ptr);
void Close();
// Used to bind the CustomTabSession interface implementation to a message
// pipe.
mojo::Binding<arc::mojom::CustomTabSession> binding_;
// Tracks the lifetime of the ARC Custom Tab session.
base::ElapsedTimer lifetime_timer_;
// Set to true when the user requests to view the web contents in a normal
// Chrome tab instead of an ARC Custom Tab.
bool forwarded_to_normal_tab_ = false;
// Note: This should remain the last member so it'll be destroyed and
// invalidate its weak pointers before any other members are destroyed.
base::WeakPtrFactory<CustomTabSessionImpl> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(CustomTabSessionImpl);
};
#endif // CHROME_BROWSER_CHROMEOS_ARC_INTENT_HELPER_CUSTOM_TAB_SESSION_IMPL_H_
......@@ -1427,6 +1427,8 @@ jumbo_split_static_library("ui") {
"ash/ambient/photo_controller_impl.h",
"ash/arc_chrome_actions_client.cc",
"ash/arc_chrome_actions_client.h",
"ash/arc_custom_tab_modal_dialog_host.cc",
"ash/arc_custom_tab_modal_dialog_host.h",
"ash/ash_shell_init.cc",
"ash/ash_shell_init.h",
"ash/ash_util.cc",
......
// 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 "chrome/browser/ui/ash/arc_custom_tab_modal_dialog_host.h"
#include <utility>
#include "ash/public/cpp/arc_custom_tab.h"
#include "components/web_modal/modal_dialog_host.h"
#include "components/web_modal/web_contents_modal_dialog_manager.h"
#include "content/public/browser/web_contents.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/size.h"
ArcCustomTabModalDialogHost::ArcCustomTabModalDialogHost(
std::unique_ptr<ash::ArcCustomTab> custom_tab,
std::unique_ptr<content::WebContents> web_contents)
: custom_tab_(std::move(custom_tab)),
web_contents_(std::move(web_contents)) {
// Attach any required WebContents helpers. Browser tabs automatically get
// them attached in TabHelpers::AttachTabHelpers.
web_modal::WebContentsModalDialogManager::CreateForWebContents(
web_contents_.get());
web_modal::WebContentsModalDialogManager::FromWebContents(web_contents_.get())
->SetDelegate(this);
}
ArcCustomTabModalDialogHost::~ArcCustomTabModalDialogHost() = default;
web_modal::WebContentsModalDialogHost*
ArcCustomTabModalDialogHost::GetWebContentsModalDialogHost() {
return this;
}
gfx::NativeView ArcCustomTabModalDialogHost::GetHostView() const {
return custom_tab_->GetHostView();
}
gfx::Point ArcCustomTabModalDialogHost::GetDialogPosition(
const gfx::Size& size) {
return web_contents_->GetViewBounds().origin();
}
gfx::Size ArcCustomTabModalDialogHost::GetMaximumDialogSize() {
return web_contents_->GetViewBounds().size();
}
void ArcCustomTabModalDialogHost::AddObserver(
web_modal::ModalDialogHostObserver* observer) {}
void ArcCustomTabModalDialogHost::RemoveObserver(
web_modal::ModalDialogHostObserver* observer) {}
// 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 CHROME_BROWSER_UI_ASH_ARC_CUSTOM_TAB_MODAL_DIALOG_HOST_H_
#define CHROME_BROWSER_UI_ASH_ARC_CUSTOM_TAB_MODAL_DIALOG_HOST_H_
#include <memory>
#include "base/macros.h"
#include "components/web_modal/web_contents_modal_dialog_host.h"
#include "components/web_modal/web_contents_modal_dialog_manager_delegate.h"
#include "ui/gfx/native_widget_types.h"
namespace ash {
class ArcCustomTab;
} // namespace ash
namespace contents {
class WebContents;
} // namespace contents
namespace gfx {
class Point;
class Size;
} // namespace gfx
namespace web_modal {
class ModalDialogHostObserver;
} // namespace web_modal
// Implements a WebContentsModalDialogHost for an ARC Custom Tab. This allows a
// web contents modal dialog to be drawn in the ARC Custom Tab.
class ArcCustomTabModalDialogHost
: public web_modal::WebContentsModalDialogHost,
public web_modal::WebContentsModalDialogManagerDelegate {
public:
ArcCustomTabModalDialogHost(
std::unique_ptr<ash::ArcCustomTab> custom_tab,
std::unique_ptr<content::WebContents> web_contents);
~ArcCustomTabModalDialogHost() override = 0;
// web_modal::WebContentsModalDialogManagerDelegate:
web_modal::WebContentsModalDialogHost* GetWebContentsModalDialogHost()
override;
// web_modal::WebContentsModalDialogHost:
gfx::NativeView GetHostView() const override;
gfx::Point GetDialogPosition(const gfx::Size& size) override;
gfx::Size GetMaximumDialogSize() override;
void AddObserver(web_modal::ModalDialogHostObserver* observer) override;
void RemoveObserver(web_modal::ModalDialogHostObserver* observer) override;
protected:
std::unique_ptr<ash::ArcCustomTab> custom_tab_;
std::unique_ptr<content::WebContents> web_contents_;
DISALLOW_COPY_AND_ASSIGN(ArcCustomTabModalDialogHost);
};
#endif // CHROME_BROWSER_UI_ASH_ARC_CUSTOM_TAB_MODAL_DIALOG_HOST_H_
......@@ -18,6 +18,7 @@
#include "chrome/browser/apps/launch_service/launch_service.h"
#include "chrome/browser/chromeos/arc/arc_web_contents_data.h"
#include "chrome/browser/chromeos/arc/fileapi/arc_content_file_system_url_util.h"
#include "chrome/browser/chromeos/arc/intent_helper/custom_tab_session_impl.h"
#include "chrome/browser/chromeos/file_manager/app_id.h"
#include "chrome/browser/chromeos/profiles/profile_helper.h"
#include "chrome/browser/extensions/api/terminal/terminal_extension_helper.h"
......@@ -51,9 +52,6 @@
#include "components/user_manager/user.h"
#include "components/user_manager/user_manager.h"
#include "components/version_info/version_info.h"
#include "components/web_modal/web_contents_modal_dialog_host.h"
#include "components/web_modal/web_contents_modal_dialog_manager.h"
#include "components/web_modal/web_contents_modal_dialog_manager_delegate.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/service_manager_connection.h"
#include "content/public/common/user_agent.h"
......@@ -66,9 +64,6 @@
#include "ui/aura/window.h"
#include "ui/base/page_transition_types.h"
#include "ui/base/window_open_disposition.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/native_widget_types.h"
#include "url/url_constants.h"
using arc::mojom::ChromePage;
......@@ -159,152 +154,49 @@ std::string GetPathAndQuery(const GURL& url) {
return result;
}
// Implementation of CustomTabSession interface.
class CustomTabSessionImpl
: public arc::mojom::CustomTabSession,
public web_modal::WebContentsModalDialogHost,
public web_modal::WebContentsModalDialogManagerDelegate {
public:
static arc::mojom::CustomTabSessionPtr Create(
Profile* profile,
const GURL& url,
std::unique_ptr<ash::ArcCustomTab> custom_tab) {
if (!custom_tab)
return nullptr;
// This object will be deleted when the mojo connection is closed.
auto* tab = new CustomTabSessionImpl(profile, url, std::move(custom_tab));
arc::mojom::CustomTabSessionPtr ptr;
tab->Bind(&ptr);
return ptr;
}
// web_modal::WebContentsModalDialogManagerDelegate:
web_modal::WebContentsModalDialogHost* GetWebContentsModalDialogHost()
override {
return this;
}
// web_modal::WebContentsModalDialogHost:
gfx::NativeView GetHostView() const override {
return custom_tab_->GetHostView();
}
gfx::Point GetDialogPosition(const gfx::Size& size) override {
return web_contents_->GetViewBounds().origin();
}
gfx::Size GetMaximumDialogSize() override {
return web_contents_->GetViewBounds().size();
}
void AddObserver(web_modal::ModalDialogHostObserver* observer) override {
}
void RemoveObserver(web_modal::ModalDialogHostObserver* observer) override {
}
// Creates a web contents for an ARC Custom Tab using the given profile and url.
std::unique_ptr<content::WebContents> CreateArcCustomTabWebContents(
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);
// Use the same version number as browser_commands.cc
// TODO(hashimoto): Get the actual Android version from the container.
constexpr char kOsOverrideForTabletSite[] = "Linux; Android 9; Chrome tablet";
// Override the user agent to request mobile version web sites.
const std::string product =
version_info::GetProductNameAndVersionForUserAgent();
const std::string user_agent = content::BuildUserAgentFromOSAndProduct(
kOsOverrideForTabletSite, product);
web_contents->SetUserAgentOverride(user_agent,
false /*override_in_new_tabs=*/);
content::NavigationController::LoadURLParams load_url_params(url);
load_url_params.source_site_instance = site_instance;
load_url_params.override_user_agent =
content::NavigationController::UA_OVERRIDE_TRUE;
web_contents->GetController().LoadURLWithParams(load_url_params);
// arc::mojom::CustomTabSession:
void OnOpenInChromeClicked() override { forwarded_to_normal_tab_ = true; }
private:
CustomTabSessionImpl(Profile* profile,
const GURL& url,
std::unique_ptr<ash::ArcCustomTab> custom_tab)
: binding_(this),
custom_tab_(std::move(custom_tab)),
web_contents_(CreateWebContents(profile, url)),
weak_ptr_factory_(this) {
aura::Window* window = web_contents_->GetNativeView();
custom_tab_->Attach(window);
window->Show();
}
~CustomTabSessionImpl() override {
// Keep in sync with ArcCustomTabsSessionEndReason in
// //tools/metrics/histograms/enums.xml.
enum class SessionEndReason {
CLOSED = 0,
FORWARDED_TO_NORMAL_TAB = 1,
kMaxValue = FORWARDED_TO_NORMAL_TAB,
} session_end_reason = forwarded_to_normal_tab_
? SessionEndReason::FORWARDED_TO_NORMAL_TAB
: SessionEndReason::CLOSED;
UMA_HISTOGRAM_ENUMERATION("Arc.CustomTabs.SessionEndReason",
session_end_reason);
auto elapsed = lifetime_timer_.Elapsed();
UMA_HISTOGRAM_LONG_TIMES("Arc.CustomTabs.SessionLifetime2.All", elapsed);
switch (session_end_reason) {
case SessionEndReason::CLOSED:
UMA_HISTOGRAM_LONG_TIMES("Arc.CustomTabs.SessionLifetime2.Closed",
elapsed);
break;
case SessionEndReason::FORWARDED_TO_NORMAL_TAB:
UMA_HISTOGRAM_LONG_TIMES(
"Arc.CustomTabs.SessionLifetime2.ForwardedToNormalTab", elapsed);
break;
}
}
// Add a flag to remember this tab originated in the ARC context.
web_contents->SetUserData(&arc::ArcWebContentsData::kArcTransitionFlag,
std::make_unique<arc::ArcWebContentsData>());
void Bind(arc::mojom::CustomTabSessionPtr* ptr) {
binding_.Bind(mojo::MakeRequest(ptr));
binding_.set_connection_error_handler(base::BindOnce(
&CustomTabSessionImpl::Close, weak_ptr_factory_.GetWeakPtr()));
}
return web_contents;
}
// 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);
// Use the same version number as browser_commands.cc
// TODO(hashimoto): Get the actual Android version from the container.
constexpr char kOsOverrideForTabletSite[] =
"Linux; Android 9; Chrome tablet";
// Override the user agent to request mobile version web sites.
const std::string product =
version_info::GetProductNameAndVersionForUserAgent();
const std::string user_agent = content::BuildUserAgentFromOSAndProduct(
kOsOverrideForTabletSite, product);
web_contents->SetUserAgentOverride(user_agent,
false /*override_in_new_tabs=*/);
content::NavigationController::LoadURLParams load_url_params(url);
load_url_params.source_site_instance = site_instance;
load_url_params.override_user_agent =
content::NavigationController::UA_OVERRIDE_TRUE;
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>());
// Attach any required WebContents helpers. Browser tabs automatically get
// them attached in TabHelpers::AttachTabHelpers.
web_modal::WebContentsModalDialogManager::CreateForWebContents(
web_contents.get());
web_modal::WebContentsModalDialogManager::FromWebContents(
web_contents.get())
->SetDelegate(this);
return web_contents;
// Returns an ARC window with the given task ID.
aura::Window* GetArcWindow(int32_t task_id) {
for (auto* window : ChromeLauncherController::instance()->GetArcWindows()) {
if (arc::GetWindowTaskId(window) == task_id)
return window;
}
mojo::Binding<arc::mojom::CustomTabSession> binding_;
std::unique_ptr<ash::ArcCustomTab> custom_tab_;
std::unique_ptr<content::WebContents> web_contents_;
base::ElapsedTimer lifetime_timer_;
bool forwarded_to_normal_tab_ = false;
base::WeakPtrFactory<CustomTabSessionImpl> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(CustomTabSessionImpl);
};
return nullptr;
}
} // namespace
......@@ -565,24 +457,18 @@ void ChromeNewWindowClient::OpenArcCustomTab(
GURL url_to_open = ConvertArcUrlToExternalFileUrlIfNeeded(url);
Profile* profile = ProfileManager::GetActiveUserProfile();
aura::Window* arc_window = nullptr;
for (auto* window : ChromeLauncherController::instance()->GetArcWindows()) {
if (arc::GetWindowTaskId(window) == task_id) {
arc_window = window;
break;
}
}
aura::Window* arc_window = GetArcWindow(task_id);
if (!arc_window) {
LOG(ERROR) << "No ARC window with the specified task ID " << task_id;
std::move(callback).Run(
CustomTabSessionImpl::Create(profile, url, nullptr));
std::move(callback).Run(nullptr);
return;
}
auto custom_tab =
ash::ArcCustomTab::Create(arc_window, surface_id, top_margin);
std::move(callback).Run(
CustomTabSessionImpl::Create(profile, url, std::move(custom_tab)));
auto web_contents = CreateArcCustomTabWebContents(profile, url);
std::move(callback).Run(CustomTabSessionImpl::Create(std::move(web_contents),
std::move(custom_tab)));
}
content::WebContents* ChromeNewWindowClient::OpenUrlImpl(
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment