Commit 7be964fa authored by Dominick Ng's avatar Dominick Ng Committed by Commit Bot

Implement IntentHelperHost::OnOpenWebApp.

This CL implements a method on the ARC IntentHelperHost to allow ARC to
request that a URL be opened as a web app in Chrome. If that URL does
not have a corresponding installed web app, the method falls back to
simply opening the URL in a tab.

An additional extension app launch source is added for the new launch
pathway.

BUG=893927

Change-Id: Ifbcc48f7cab65373dc6353d422580d6e9cc43796
Reviewed-on: https://chromium-review.googlesource.com/c/1282546Reviewed-by: default avatarJames Cook <jamescook@chromium.org>
Reviewed-by: default avatarDevlin <rdevlin.cronin@chromium.org>
Reviewed-by: default avatarGreg Kerr <kerrnel@chromium.org>
Reviewed-by: default avatarDavid Jacobo <djacobo@chromium.org>
Commit-Queue: Dominick Ng <dominickn@chromium.org>
Cr-Commit-Position: refs/heads/master@{#601305}
parent e8bb8226
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "chrome/browser/chromeos/arc/arc_web_contents_data.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/fileapi/arc_content_file_system_url_util.h"
#include "chrome/browser/chromeos/file_manager/app_id.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" #include "chrome/browser/extensions/api/terminal/terminal_extension_helper.h"
#include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_util.h" #include "chrome/browser/extensions/extension_util.h"
...@@ -35,14 +36,18 @@ ...@@ -35,14 +36,18 @@
#include "components/sessions/core/tab_restore_service.h" #include "components/sessions/core/tab_restore_service.h"
#include "components/sessions/core/tab_restore_service_observer.h" #include "components/sessions/core/tab_restore_service_observer.h"
#include "components/url_formatter/url_fixer.h" #include "components/url_formatter/url_fixer.h"
#include "components/user_manager/user.h"
#include "components/user_manager/user_manager.h"
#include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents.h"
#include "content/public/common/service_manager_connection.h" #include "content/public/common/service_manager_connection.h"
#include "content/public/common/was_activated_option.h" #include "content/public/common/was_activated_option.h"
#include "extensions/browser/extension_system.h" #include "extensions/browser/extension_system.h"
#include "extensions/common/constants.h" #include "extensions/common/constants.h"
#include "extensions/common/extension.h"
#include "services/service_manager/public/cpp/connector.h" #include "services/service_manager/public/cpp/connector.h"
#include "ui/base/page_transition_types.h" #include "ui/base/page_transition_types.h"
#include "ui/base/window_open_disposition.h" #include "ui/base/window_open_disposition.h"
#include "url/url_constants.h"
namespace { namespace {
...@@ -281,6 +286,38 @@ void ChromeNewWindowClient::OpenUrlFromArc(const GURL& url) { ...@@ -281,6 +286,38 @@ void ChromeNewWindowClient::OpenUrlFromArc(const GURL& url) {
std::make_unique<arc::ArcWebContentsData>()); std::make_unique<arc::ArcWebContentsData>());
} }
void ChromeNewWindowClient::OpenWebAppFromArc(const GURL& url) {
DCHECK(url.is_valid() && url.SchemeIs(url::kHttpsScheme));
const auto* user = user_manager::UserManager::Get()->GetPrimaryUser();
if (!user)
return;
Profile* profile = chromeos::ProfileHelper::Get()->GetProfileByUser(user);
if (!profile)
return;
const extensions::Extension* extension =
extensions::util::GetInstalledPwaForUrl(
profile, url, extensions::LAUNCH_CONTAINER_WINDOW);
if (!extension) {
OpenUrlFromArc(url);
return;
}
AppLaunchParams params = CreateAppLaunchParamsUserContainer(
profile, extension, WindowOpenDisposition::NEW_WINDOW,
extensions::SOURCE_ARC);
params.override_url = url;
content::WebContents* tab = OpenApplication(params);
if (!tab)
return;
// Add a flag to remember this tab originated in the ARC context.
tab->SetUserData(&arc::ArcWebContentsData::kArcTransitionFlag,
std::make_unique<arc::ArcWebContentsData>());
}
content::WebContents* ChromeNewWindowClient::OpenUrlImpl( content::WebContents* ChromeNewWindowClient::OpenUrlImpl(
const GURL& url, const GURL& url,
bool from_user_interaction) { bool from_user_interaction) {
......
...@@ -42,6 +42,7 @@ class ChromeNewWindowClient : public ash::mojom::NewWindowClient, ...@@ -42,6 +42,7 @@ class ChromeNewWindowClient : public ash::mojom::NewWindowClient,
// arc::OpenUrlDelegate: // arc::OpenUrlDelegate:
void OpenUrlFromArc(const GURL& url) override; void OpenUrlFromArc(const GURL& url) override;
void OpenWebAppFromArc(const GURL& url) override;
private: private:
class TabRestoreHelper; class TabRestoreHelper;
......
...@@ -4,18 +4,24 @@ ...@@ -4,18 +4,24 @@
#include "chrome/browser/ui/ash/chrome_new_window_client.h" #include "chrome/browser/ui/ash/chrome_new_window_client.h"
#include "chrome/browser/chromeos/arc/arc_web_contents_data.h"
#include "chrome/browser/chromeos/profiles/profile_helper.h" #include "chrome/browser/chromeos/profiles/profile_helper.h"
#include "chrome/browser/extensions/bookmark_app_navigation_browsertest.h"
#include "chrome/browser/prefs/incognito_mode_prefs.h" #include "chrome/browser/prefs/incognito_mode_prefs.h"
#include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_finder.h" #include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/browser_window.h" #include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/in_process_browser_test.h"
#include "components/account_id/account_id.h" #include "components/account_id/account_id.h"
#include "components/session_manager/core/session_manager.h" #include "components/session_manager/core/session_manager.h"
#include "components/user_manager/known_user.h" #include "components/user_manager/known_user.h"
#include "components/user_manager/user_manager.h" #include "components/user_manager/user_manager.h"
#include "content/public/test/test_navigation_observer.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
#include "ui/aura/window.h" #include "ui/aura/window.h"
#include "url/gurl.h"
namespace { namespace {
...@@ -47,6 +53,9 @@ Browser* GetLastActiveBrowser() { ...@@ -47,6 +53,9 @@ Browser* GetLastActiveBrowser() {
using ChromeNewWindowClientBrowserTest = InProcessBrowserTest; using ChromeNewWindowClientBrowserTest = InProcessBrowserTest;
using ChromeNewWindowClientWebAppBrowserTest =
extensions::test::BookmarkAppNavigationBrowserTest;
// Tests that when we open a new window by pressing 'Ctrl-N', we should use the // Tests that when we open a new window by pressing 'Ctrl-N', we should use the
// current active window's profile to determine on which profile's desktop we // current active window's profile to determine on which profile's desktop we
// should open a new window. // should open a new window.
...@@ -114,3 +123,23 @@ IN_PROC_BROWSER_TEST_F(ChromeNewWindowClientBrowserTest, IncognitoDisabled) { ...@@ -114,3 +123,23 @@ IN_PROC_BROWSER_TEST_F(ChromeNewWindowClientBrowserTest, IncognitoDisabled) {
EXPECT_EQ(Profile::INCOGNITO_PROFILE, EXPECT_EQ(Profile::INCOGNITO_PROFILE,
GetLastActiveBrowser()->profile()->GetProfileType()); GetLastActiveBrowser()->profile()->GetProfileType());
} }
IN_PROC_BROWSER_TEST_F(ChromeNewWindowClientWebAppBrowserTest, OpenWebApp) {
InstallTestBookmarkApp(GetAppUrlHost());
const GURL app_url = https_server().GetURL(GetAppUrlHost(), GetAppUrlPath());
const char* key =
arc::ArcWebContentsData::ArcWebContentsData::kArcTransitionFlag;
// Calling OpenWebAppFromArc for an installed web app URL should open in an
// app window.
auto observer = GetTestNavigationObserver(app_url);
ChromeNewWindowClient::Get()->OpenWebAppFromArc(app_url);
observer->WaitForNavigationFinished();
EXPECT_EQ(2u, chrome::GetTotalBrowserCount());
EXPECT_TRUE(GetLastActiveBrowser()->is_app());
content::WebContents* contents =
GetLastActiveBrowser()->tab_strip_model()->GetActiveWebContents();
EXPECT_EQ(app_url, contents->GetLastCommittedURL());
EXPECT_NE(nullptr, contents->GetUserData(key));
}
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// //
// Next MinVersion: 23 // Next MinVersion: 24
module arc.mojom; module arc.mojom;
...@@ -136,7 +136,7 @@ struct TextSelectionAction { ...@@ -136,7 +136,7 @@ struct TextSelectionAction {
// Handles intents from ARC in Chrome. // Handles intents from ARC in Chrome.
// Deprecated method ID: 4 // Deprecated method ID: 4
// Next method ID: 8 // Next method ID: 9
interface IntentHelperHost { interface IntentHelperHost {
// Called when icons associated with the package are no longer up to date. // Called when icons associated with the package are no longer up to date.
[MinVersion=3] OnIconInvalidated@1(string package_name); [MinVersion=3] OnIconInvalidated@1(string package_name);
...@@ -165,6 +165,10 @@ interface IntentHelperHost { ...@@ -165,6 +165,10 @@ interface IntentHelperHost {
// Opens the specified Chrome page in the Chrome browser. // Opens the specified Chrome page in the Chrome browser.
[MinVersion=17] OnOpenChromePage@7([MinVersion=18] ChromePage page); [MinVersion=17] OnOpenChromePage@7([MinVersion=18] ChromePage page);
// Opens the specified URL as a web app if it is installed. Otherwise falls
// back to the behaviour of OnOpenUrl. |url| must have a HTTPS scheme.
[MinVersion=23] OnOpenWebApp@8(string url);
}; };
// Sends intents to ARC on behalf of Chrome. // Sends intents to ARC on behalf of Chrome.
......
...@@ -161,7 +161,7 @@ void ArcIntentHelperBridge::OnOpenDownloads() { ...@@ -161,7 +161,7 @@ void ArcIntentHelperBridge::OnOpenDownloads() {
void ArcIntentHelperBridge::OnOpenUrl(const std::string& url) { void ArcIntentHelperBridge::OnOpenUrl(const std::string& url) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
// Converts |url| to a fixed-up one and checks validity. // Converts |url| to a fixed-up one and checks validity.
const GURL gurl(url_formatter::FixupURL(url, std::string())); const GURL gurl(url_formatter::FixupURL(url, /*desired_tld=*/std::string()));
if (!gurl.is_valid()) if (!gurl.is_valid())
return; return;
...@@ -208,6 +208,18 @@ void ArcIntentHelperBridge::OpenVolumeControl() { ...@@ -208,6 +208,18 @@ void ArcIntentHelperBridge::OpenVolumeControl() {
audio->ShowVolumeControls(); audio->ShowVolumeControls();
} }
void ArcIntentHelperBridge::OnOpenWebApp(const std::string& url) {
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())
return;
// Web app launches should only be invoked on HTTPS URLs.
if (gurl.SchemeIs(url::kHttpsScheme))
g_open_url_delegate->OpenWebAppFromArc(gurl);
}
ArcIntentHelperBridge::GetResult ArcIntentHelperBridge::GetActivityIcons( ArcIntentHelperBridge::GetResult ArcIntentHelperBridge::GetActivityIcons(
const std::vector<ActivityName>& activities, const std::vector<ActivityName>& activities,
OnIconsReadyCallback callback) { OnIconsReadyCallback callback) {
......
...@@ -69,6 +69,7 @@ class ArcIntentHelperBridge ...@@ -69,6 +69,7 @@ class ArcIntentHelperBridge
void OpenWallpaperPicker() override; void OpenWallpaperPicker() override;
void SetWallpaperDeprecated(const std::vector<uint8_t>& jpeg_data) override; void SetWallpaperDeprecated(const std::vector<uint8_t>& jpeg_data) override;
void OpenVolumeControl() override; void OpenVolumeControl() override;
void OnOpenWebApp(const std::string& url) override;
// Retrieves icons for the |activities| and calls |callback|. // Retrieves icons for the |activities| and calls |callback|.
// See ActivityIconLoader::GetActivityIcons() for more details. // See ActivityIconLoader::GetActivityIcons() for more details.
......
...@@ -38,6 +38,7 @@ class ArcIntentHelperTest : public testing::Test { ...@@ -38,6 +38,7 @@ class ArcIntentHelperTest : public testing::Test {
// OpenUrlDelegate: // OpenUrlDelegate:
void OpenUrlFromArc(const GURL& url) override { last_opened_url_ = url; } void OpenUrlFromArc(const GURL& url) override { last_opened_url_ = url; }
void OpenWebAppFromArc(const GURL& url) override { last_opened_url_ = url; }
GURL TakeLastOpenedUrl() { GURL TakeLastOpenedUrl() {
GURL result = std::move(last_opened_url_); GURL result = std::move(last_opened_url_);
...@@ -288,6 +289,16 @@ TEST_F(ArcIntentHelperTest, TestOnOpenUrl) { ...@@ -288,6 +289,16 @@ TEST_F(ArcIntentHelperTest, TestOnOpenUrl) {
test_open_url_delegate_->TakeLastOpenedUrl()); test_open_url_delegate_->TakeLastOpenedUrl());
} }
// Tests that OnOpenWebApp opens only HTTPS URLs.
TEST_F(ArcIntentHelperTest, TestOnOpenWebApp) {
instance_->OnOpenWebApp("http://google.com");
EXPECT_EQ(GURL(), test_open_url_delegate_->TakeLastOpenedUrl());
instance_->OnOpenWebApp("https://google.com");
EXPECT_EQ(GURL("https://google.com"),
test_open_url_delegate_->TakeLastOpenedUrl());
}
// Tests that OnOpenUrl does not open URLs with the 'chrome://' and equivalent // Tests that OnOpenUrl does not open URLs with the 'chrome://' and equivalent
// schemes like 'about:'. // schemes like 'about:'.
TEST_F(ArcIntentHelperTest, TestOnOpenUrl_ChromeScheme) { TEST_F(ArcIntentHelperTest, TestOnOpenUrl_ChromeScheme) {
......
...@@ -15,6 +15,9 @@ class OpenUrlDelegate { ...@@ -15,6 +15,9 @@ class OpenUrlDelegate {
// Opens the given URL in the Chrome browser. // Opens the given URL in the Chrome browser.
virtual void OpenUrlFromArc(const GURL& url) = 0; virtual void OpenUrlFromArc(const GURL& url) = 0;
// Opens the given URL as a web app in the Chrome browser.
virtual void OpenWebAppFromArc(const GURL& url) = 0;
}; };
} // namespace arc } // namespace arc
......
...@@ -108,6 +108,7 @@ app_runtime::LaunchSource GetLaunchSourceEnum( ...@@ -108,6 +108,7 @@ app_runtime::LaunchSource GetLaunchSourceEnum(
ASSERT_ENUM_EQUAL(SOURCE_TEST); ASSERT_ENUM_EQUAL(SOURCE_TEST);
ASSERT_ENUM_EQUAL(SOURCE_INSTALLED_NOTIFICATION); ASSERT_ENUM_EQUAL(SOURCE_INSTALLED_NOTIFICATION);
ASSERT_ENUM_EQUAL(SOURCE_CONTEXT_MENU); ASSERT_ENUM_EQUAL(SOURCE_CONTEXT_MENU);
ASSERT_ENUM_EQUAL(SOURCE_ARC);
static_assert(extensions::NUM_APP_LAUNCH_SOURCES == static_assert(extensions::NUM_APP_LAUNCH_SOURCES ==
app_runtime::LaunchSource::LAUNCH_SOURCE_LAST + 1, app_runtime::LaunchSource::LAUNCH_SOURCE_LAST + 1,
""); "");
......
...@@ -42,7 +42,8 @@ namespace app.runtime { ...@@ -42,7 +42,8 @@ namespace app.runtime {
chrome_internal, chrome_internal,
test, test,
installed_notification, installed_notification,
context_menu context_menu,
arc
}; };
// An app can be launched with a specific action in mind, for example, to // An app can be launched with a specific action in mind, for example, to
......
...@@ -144,6 +144,7 @@ enum AppLaunchSource { ...@@ -144,6 +144,7 @@ enum AppLaunchSource {
SOURCE_TEST, SOURCE_TEST,
SOURCE_INSTALLED_NOTIFICATION, SOURCE_INSTALLED_NOTIFICATION,
SOURCE_CONTEXT_MENU, SOURCE_CONTEXT_MENU,
SOURCE_ARC,
NUM_APP_LAUNCH_SOURCES NUM_APP_LAUNCH_SOURCES
}; };
......
...@@ -1398,6 +1398,8 @@ uploading your change for review. These are checked by presubmit scripts. ...@@ -1398,6 +1398,8 @@ uploading your change for review. These are checked by presubmit scripts.
<int value="18" label="LAUNCH_SOURCE_CHROME_INTERNAL"/> <int value="18" label="LAUNCH_SOURCE_CHROME_INTERNAL"/>
<int value="19" label="LAUNCH_SOURCE_TEST"/> <int value="19" label="LAUNCH_SOURCE_TEST"/>
<int value="20" label="LAUNCH_SOURCE_INSTALLED_NOTIFICATION"/> <int value="20" label="LAUNCH_SOURCE_INSTALLED_NOTIFICATION"/>
<int value="21" label="LAUNCH_SOURCE_CONTEXT_MENU"/>
<int value="22" label="LAUNCH_SOURCE_ARC"/>
</enum> </enum>
<enum name="AppleScriptCommandEvents"> <enum name="AppleScriptCommandEvents">
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