| // Copyright 2017 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 "base/bind.h" |
| #include "base/strings/stringprintf.h" |
| #include "base/test/metrics/histogram_tester.h" |
| #include "base/test/scoped_feature_list.h" |
| #include "build/build_config.h" |
| #include "chrome/app/chrome_command_ids.h" |
| #include "chrome/browser/extensions/bookmark_app_navigation_browsertest.h" |
| #include "chrome/browser/extensions/bookmark_app_navigation_throttle_utils.h" |
| #include "chrome/browser/extensions/launch_util.h" |
| #include "chrome/browser/prefs/session_startup_pref.h" |
| #include "chrome/browser/prerender/prerender_manager.h" |
| #include "chrome/browser/renderer_context_menu/render_view_context_menu_test_util.h" |
| #include "chrome/browser/ui/browser_commands.h" |
| #include "chrome/browser/ui/browser_finder.h" |
| #include "chrome/browser/ui/browser_list.h" |
| #include "chrome/browser/ui/extensions/app_launch_params.h" |
| #include "chrome/browser/ui/extensions/application_launch.h" |
| #include "chrome/browser/ui/tabs/tab_strip_model.h" |
| #include "chrome/browser/web_applications/components/web_app_helpers.h" |
| #include "chrome/browser/web_applications/extensions/bookmark_app_util.h" |
| #include "chrome/common/chrome_features.h" |
| #include "chrome/common/extensions/manifest_handlers/app_launch_info.h" |
| #include "chrome/test/base/ui_test_utils.h" |
| #include "content/public/browser/navigation_handle.h" |
| #include "content/public/browser/notification_details.h" |
| #include "content/public/browser/notification_service.h" |
| #include "content/public/browser/render_frame_host.h" |
| #include "content/public/common/context_menu_params.h" |
| #include "content/public/test/browser_test_utils.h" |
| #include "content/public/test/test_frame_navigation_observer.h" |
| #include "content/public/test/test_navigation_observer.h" |
| #include "content/public/test/test_utils.h" |
| #include "extensions/browser/extension_registry.h" |
| #include "extensions/browser/notification_types.h" |
| #include "extensions/common/constants.h" |
| #include "net/base/escape.h" |
| #include "net/http/http_request_headers.h" |
| #include "net/url_request/url_fetcher.h" |
| #include "services/network/public/cpp/resource_request_body.h" |
| #include "testing/gmock/include/gmock/gmock.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| namespace extensions { |
| namespace test { |
| |
| enum class StartIn { |
| BROWSER, |
| APP, |
| }; |
| |
| enum class WindowAccessResult { |
| CAN_ACCESS, |
| CANNOT_ACCESS, |
| // Used for when there was an unexpected issue when accessing the other window |
| // e.g. there is no other window, or the other window's URL does not match the |
| // expected URL. |
| OTHER, |
| }; |
| |
| namespace { |
| |
| const char kTextPlainEncType[] = "text/plain"; |
| |
| const char kQueryParam[] = "test="; |
| const char kQueryParamName[] = "test"; |
| |
| // On macOS the Meta key is used as a modifier instead of Control. |
| #if defined(OS_MACOSX) |
| constexpr int kCtrlOrMeta = blink::WebInputEvent::kMetaKey; |
| #else |
| constexpr int kCtrlOrMeta = blink::WebInputEvent::kControlKey; |
| #endif |
| |
| // Subclass of TestNavigationObserver that saves extra information about the |
| // navigation and watches all navigations to |target_url|. |
| class BookmarkAppNavigationObserver : public content::TestNavigationObserver { |
| public: |
| // Creates an observer that watches navigations to |target_url| on all |
| // existing and newly added WebContents. |
| explicit BookmarkAppNavigationObserver(const GURL& target_url) |
| : content::TestNavigationObserver(target_url), |
| last_navigation_is_post_(false) { |
| WatchExistingWebContents(); |
| StartWatchingNewWebContents(); |
| } |
| |
| bool last_navigation_is_post() const { return last_navigation_is_post_; } |
| |
| const net::HttpRequestHeaders& last_request_headers() const { |
| return last_request_headers_; |
| } |
| |
| const scoped_refptr<network::ResourceRequestBody>& |
| last_resource_request_body() const { |
| return last_resource_request_body_; |
| } |
| |
| private: |
| void OnDidFinishNavigation( |
| content::NavigationHandle* navigation_handle) override { |
| last_navigation_is_post_ = navigation_handle->IsPost(); |
| last_request_headers_ = navigation_handle->GetRequestHeaders(); |
| last_resource_request_body_ = navigation_handle->GetResourceRequestBody(); |
| content::TestNavigationObserver::OnDidFinishNavigation(navigation_handle); |
| } |
| |
| // True if the last navigation was a post. |
| bool last_navigation_is_post_; |
| |
| // The request headers of the last navigation. |
| net::HttpRequestHeaders last_request_headers_; |
| |
| // The request body of the last navigation if it was a post request. |
| scoped_refptr<network::ResourceRequestBody> last_resource_request_body_; |
| }; |
| |
| void ExpectNavigationResultHistogramEquals( |
| const base::HistogramTester& histogram_tester, |
| const std::vector<std::pair<BookmarkAppNavigationThrottleResult, |
| base::HistogramBase::Count>>& expected_counts) { |
| std::vector<base::Bucket> expected_bucket_counts; |
| for (const auto& pair : expected_counts) { |
| expected_bucket_counts.push_back(base::Bucket( |
| static_cast<base::HistogramBase::Sample>(pair.first), pair.second)); |
| } |
| |
| EXPECT_THAT( |
| histogram_tester.GetAllSamples("Extensions.BookmarkApp.NavigationResult"), |
| testing::UnorderedElementsAreArray(expected_bucket_counts)); |
| } |
| |
| // When an app is launched, whether it's in response to a navigation or click |
| // in a launch surface e.g. App Shelf, the first navigation in the app is |
| // an AUTO_BOOKMARK navigation. |
| std::pair<BookmarkAppNavigationThrottleResult, base::HistogramBase::Count> |
| GetAppLaunchedEntry() { |
| return {BookmarkAppNavigationThrottleResult::kProceedTransitionAutoBookmark, |
| 1}; |
| } |
| |
| std::string CreateClientRedirect(const GURL& target_url) { |
| const char* const kClientRedirectBase = "/client-redirect?"; |
| return kClientRedirectBase + |
| net::EscapeQueryParamValue(target_url.spec(), false); |
| } |
| |
| // Inserts an iframe in the main frame of |web_contents|. |
| void InsertIFrame(content::WebContents* web_contents) { |
| ASSERT_TRUE( |
| content::ExecuteScript(web_contents, |
| "let iframe = document.createElement('iframe');" |
| "document.body.appendChild(iframe);")); |
| } |
| |
| void ExecuteContextMenuLinkCommandAndWait(content::WebContents* web_contents, |
| const GURL& target_url, |
| int command_id) { |
| auto observer = |
| BookmarkAppNavigationBrowserTest::GetTestNavigationObserver(target_url); |
| content::ContextMenuParams params; |
| params.page_url = web_contents->GetLastCommittedURL(); |
| params.link_url = target_url; |
| TestRenderViewContextMenu menu(web_contents->GetMainFrame(), params); |
| menu.Init(); |
| menu.ExecuteCommand(command_id, 0 /* event_flags */); |
| observer->WaitForNavigationFinished(); |
| } |
| |
| void OpenPopupAndWait(content::WebContents* web_contents, |
| const GURL& target_url) { |
| auto observer = |
| BookmarkAppNavigationBrowserTest::GetTestNavigationObserver(target_url); |
| const std::string script = base::StringPrintf( |
| "(() => {" |
| " window.openedWindow = window.open('%s', '_blank', 'toolbar=no');" |
| "})();", |
| target_url.spec().c_str()); |
| ASSERT_TRUE(content::ExecuteScript(web_contents, script)); |
| observer->WaitForNavigationFinished(); |
| } |
| |
| // Calls window.open() with |target_url| on the main frame of |web_contents|. |
| // Returns once the new window has navigated to |target_url|. |
| void WindowOpenAndWait(content::WebContents* web_contents, |
| const GURL& target_url) { |
| auto observer = |
| BookmarkAppNavigationBrowserTest::GetTestNavigationObserver(target_url); |
| const std::string script = base::StringPrintf( |
| "(() => {" |
| " window.openedWindow = window.open('%s');" |
| "})();", |
| target_url.spec().c_str()); |
| ASSERT_TRUE(content::ExecuteScript(web_contents, script)); |
| observer->WaitForNavigationFinished(); |
| } |
| |
| // Calls window.open() with |target_url| on the main frame of |web_contents|. |
| // Returns true if the resulting child window is allowed to access members of |
| // its opener. |
| WindowAccessResult CanChildWindowAccessOpener( |
| content::WebContents* web_contents, |
| const GURL& target_url) { |
| WindowOpenAndWait(web_contents, target_url); |
| |
| content::WebContents* new_contents = |
| chrome::FindLastActive()->tab_strip_model()->GetActiveWebContents(); |
| |
| const std::string script = base::StringPrintf( |
| "(() => {" |
| " const [CAN_ACCESS, CANNOT_ACCESS, OTHER] = [0, 1, 2];" |
| " let result = OTHER;" |
| " try {" |
| " if (window.opener.location.href === '%s')" |
| " result = CAN_ACCESS;" |
| " } catch (e) {" |
| " if (e.name === 'SecurityError')" |
| " result = CANNOT_ACCESS;" |
| " }" |
| " window.domAutomationController.send(result);" |
| "})();", |
| web_contents->GetLastCommittedURL().spec().c_str()); |
| |
| int access_result; |
| CHECK(content::ExecuteScriptAndExtractInt(new_contents, script, |
| &access_result)); |
| |
| switch (access_result) { |
| case 0: |
| return WindowAccessResult::CAN_ACCESS; |
| case 1: |
| return WindowAccessResult::CANNOT_ACCESS; |
| case 2: |
| return WindowAccessResult::OTHER; |
| default: |
| NOTREACHED(); |
| return WindowAccessResult::OTHER; |
| } |
| } |
| |
| // Adds a query parameter to |base_url|. |
| GURL AddTestQueryParam(const GURL& base_url) { |
| GURL::Replacements replacements; |
| std::string query(kQueryParam); |
| replacements.SetQuery(query.c_str(), url::Component(0, query.length())); |
| return base_url.ReplaceComponents(replacements); |
| } |
| |
| // Creates a <form> element with a |target_url| action and |method| method. Adds |
| // the form to the DOM with a button and clicks the button. Returns once |
| // |target_url| has been loaded. |
| // |
| // If |method| is net::URLFetcher::RequestType::GET, |target_url| should contain |
| // an empty query string, since that URL will be loaded when submitting the form |
| // e.g. "https://www.example.com/?". |
| void SubmitFormAndWait(content::WebContents* web_contents, |
| const GURL& target_url, |
| net::URLFetcher::RequestType method) { |
| bool is_post = true; |
| if (method == net::URLFetcher::RequestType::GET) { |
| is_post = false; |
| ASSERT_TRUE(target_url.has_query()); |
| ASSERT_EQ(kQueryParam, target_url.query()); |
| } |
| |
| BookmarkAppNavigationObserver observer(target_url); |
| std::string script = base::StringPrintf( |
| "(() => {" |
| "const form = document.createElement('form');" |
| "form.action = '%s';" |
| "form.method = '%s';" |
| "form.enctype = '%s';" |
| "const input = document.createElement('input');" |
| "input.name = '%s';" |
| "form.appendChild(input);" |
| "const button = document.createElement('input');" |
| "button.type = 'submit';" |
| "form.appendChild(button);" |
| "document.body.appendChild(form);" |
| "button.dispatchEvent(new MouseEvent('click', {'view': window}));" |
| "})();", |
| target_url.spec().c_str(), |
| method == net::URLFetcher::RequestType::POST ? "post" : "get", |
| kTextPlainEncType, kQueryParamName); |
| ASSERT_TRUE(content::ExecuteScript(web_contents, script)); |
| observer.WaitForNavigationFinished(); |
| |
| EXPECT_EQ(is_post, observer.last_navigation_is_post()); |
| if (is_post) { |
| const net::HttpRequestHeaders& headers = observer.last_request_headers(); |
| std::string post_content_type; |
| headers.GetHeader(net::HttpRequestHeaders::kContentType, |
| &post_content_type); |
| EXPECT_EQ(kTextPlainEncType, post_content_type); |
| |
| const std::vector<network::DataElement>* elements = |
| observer.last_resource_request_body()->elements(); |
| EXPECT_EQ(1u, elements->size()); |
| const auto& element = elements->front(); |
| |
| // The text/plain enconding algorithm appends "\r\n". |
| EXPECT_EQ(std::string(kQueryParam) + "\r\n", |
| std::string(element.bytes(), element.length())); |
| } |
| } |
| |
| // Uses |params| to navigate to a URL. Blocks until the URL is loaded. |
| void NavigateToURLAndWait(NavigateParams* params) { |
| auto observer = |
| BookmarkAppNavigationBrowserTest::GetTestNavigationObserver(params->url); |
| ui_test_utils::NavigateToURL(params); |
| observer->WaitForNavigationFinished(); |
| } |
| |
| // Wrapper so that we can use base::BindOnce with NavigateToURL. |
| void NavigateToURLWrapper(NavigateParams* params) { |
| ui_test_utils::NavigateToURL(params); |
| } |
| |
| } // namespace |
| |
| // Tests for the behavior when the kDesktopPWAsLinkCapturing flag is on. |
| class BookmarkAppNavigationThrottleExperimentalBrowserTest |
| : public BookmarkAppNavigationBrowserTest { |
| public: |
| void SetUp() override { |
| scoped_feature_list_.InitWithFeatures( |
| {features::kDesktopPWAWindowing, features::kDesktopPWAsLinkCapturing}, |
| {}); |
| BookmarkAppNavigationBrowserTest::SetUp(); |
| } |
| |
| private: |
| base::test::ScopedFeatureList scoped_feature_list_; |
| }; |
| |
| // Tests that the result is the same regardless of the 'rel' attribute of links. |
| class BookmarkAppNavigationThrottleExperimentalLinkBrowserTest |
| : public BookmarkAppNavigationThrottleExperimentalBrowserTest, |
| public ::testing::WithParamInterface<std::string> {}; |
| |
| // Tests that navigating to the Web App's app_url doesn't open a new window |
| // if features::kDesktopPWAsLinkCapturing is disabled before installing the app. |
| IN_PROC_BROWSER_TEST_P(BookmarkAppNavigationThrottleExperimentalLinkBrowserTest, |
| FeatureDisable_BeforeInstall) { |
| base::test::ScopedFeatureList feature_list; |
| feature_list.InitWithFeatures({}, {features::kDesktopPWAsLinkCapturing}); |
| InstallTestBookmarkApp(); |
| NavigateToLaunchingPage(); |
| |
| const GURL app_url = https_server().GetURL(GetAppUrlHost(), GetAppUrlPath()); |
| TestTabActionDoesNotOpenAppWindow( |
| app_url, |
| base::BindOnce(&ClickLinkAndWait, |
| browser()->tab_strip_model()->GetActiveWebContents(), |
| app_url, LinkTarget::SELF, GetParam())); |
| |
| ExpectNavigationResultHistogramEquals(global_histogram(), {}); |
| } |
| |
| // Tests that navigating to the Web App's app_url doesn't open a new window |
| // if features::kDesktopPWAWindowing is disabled after installing the app. |
| IN_PROC_BROWSER_TEST_P(BookmarkAppNavigationThrottleExperimentalLinkBrowserTest, |
| FeatureDisable_AfterInstall) { |
| InstallTestBookmarkApp(); |
| base::test::ScopedFeatureList feature_list; |
| feature_list.InitWithFeatures({}, {features::kDesktopPWAsLinkCapturing}); |
| NavigateToLaunchingPage(); |
| |
| const GURL app_url = https_server().GetURL(GetAppUrlHost(), GetAppUrlPath()); |
| TestTabActionDoesNotOpenAppWindow( |
| app_url, |
| base::BindOnce(&ClickLinkAndWait, |
| browser()->tab_strip_model()->GetActiveWebContents(), |
| app_url, LinkTarget::SELF, GetParam())); |
| |
| ExpectNavigationResultHistogramEquals(global_histogram(), {}); |
| } |
| |
| // Tests that most transition types for navigations to in-scope or |
| // out-of-scope URLs do not result in new app windows. |
| class BookmarkAppNavigationThrottleExperimentalTransitionBrowserTest |
| : public BookmarkAppNavigationThrottleExperimentalBrowserTest, |
| public ::testing::WithParamInterface< |
| std::tuple<std::string, ui::PageTransition>> {}; |
| |
| INSTANTIATE_TEST_SUITE_P( |
| /* no prefix */, |
| BookmarkAppNavigationThrottleExperimentalTransitionBrowserTest, |
| testing::Combine( |
| testing::Values( |
| BookmarkAppNavigationBrowserTest::GetInScopeUrlPath(), |
| BookmarkAppNavigationBrowserTest::GetOutOfScopeUrlPath()), |
| testing::Range(ui::PAGE_TRANSITION_FIRST, |
| ui::PAGE_TRANSITION_LAST_CORE))); |
| |
| #if defined(OS_WIN) || defined(OS_LINUX) || defined(OS_MACOSX) |
| #define MAYBE_MainFrameNavigations DISABLED_MainFrameNavigations |
| #else |
| #define MAYBE_MainFrameNavigations MainFrameNavigations |
| #endif |
| IN_PROC_BROWSER_TEST_P( |
| BookmarkAppNavigationThrottleExperimentalTransitionBrowserTest, |
| MAYBE_MainFrameNavigations) { |
| InstallTestBookmarkApp(); |
| |
| GURL target_url = |
| https_server().GetURL(GetAppUrlHost(), std::get<0>(GetParam())); |
| ui::PageTransition transition = std::get<1>(GetParam()); |
| NavigateParams params(browser(), target_url, transition); |
| |
| if (!ui::PageTransitionIsMainFrame(transition)) { |
| // Subframe navigations require a different setup. See |
| // BookmarkAppNavigationThrottleExperimentalBrowserTest.SubframeNavigation. |
| return; |
| } |
| |
| if (ui::PageTransitionCoreTypeIs(ui::PAGE_TRANSITION_LINK, transition) && |
| target_url == |
| https_server().GetURL(GetAppUrlHost(), GetInScopeUrlPath())) { |
| TestTabActionOpensAppWindow(target_url, |
| base::BindOnce(&NavigateToURLAndWait, ¶ms)); |
| } else { |
| TestTabActionDoesNotOpenAppWindow( |
| target_url, base::BindOnce(&NavigateToURLAndWait, ¶ms)); |
| } |
| } |
| |
| // Tests that navigations in subframes don't open new app windows. |
| // |
| // The transition type for subframe navigations is not set until |
| // after NavigationThrottles run. Because of this, our |
| // BookmarkAppNavigationThrottle will not see the transition type as |
| // PAGE_TRANSITION_AUTO_SUBFRAME/PAGE_TRANSITION_MANUAL_SUBFRAME, even though, |
| // by the end of the navigation, the transition type is |
| // PAGE_TRANSITION_AUTO_SUBFRAME/PAGE_TRANSITON_MANUAL_SUBFRAME. |
| IN_PROC_BROWSER_TEST_F(BookmarkAppNavigationThrottleExperimentalBrowserTest, |
| AutoSubframeNavigation) { |
| InstallTestBookmarkApp(); |
| NavigateToLaunchingPage(); |
| |
| content::WebContents* initial_tab = |
| browser()->tab_strip_model()->GetActiveWebContents(); |
| InsertIFrame(initial_tab); |
| |
| content::RenderFrameHost* iframe = GetIFrame(initial_tab); |
| const GURL app_url = https_server().GetURL(GetAppUrlHost(), GetAppUrlPath()); |
| |
| NavigateParams params(browser(), app_url, ui::PAGE_TRANSITION_LINK); |
| params.frame_tree_node_id = iframe->GetFrameTreeNodeId(); |
| content::TestFrameNavigationObserver observer(iframe); |
| TestIFrameActionDoesNotOpenAppWindow( |
| app_url, base::BindOnce(&NavigateToURLWrapper, ¶ms)); |
| |
| ASSERT_TRUE(ui::PageTransitionCoreTypeIs(observer.transition_type(), |
| ui::PAGE_TRANSITION_AUTO_SUBFRAME)); |
| |
| // Subframe navigations are completely ignored, so there should be no change |
| // in the histogram. |
| ExpectNavigationResultHistogramEquals(global_histogram(), {}); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(BookmarkAppNavigationThrottleExperimentalBrowserTest, |
| ManualSubframeNavigation) { |
| InstallTestBookmarkApp(); |
| NavigateToLaunchingPage(); |
| |
| content::WebContents* initial_tab = |
| browser()->tab_strip_model()->GetActiveWebContents(); |
| InsertIFrame(initial_tab); |
| |
| { |
| // Navigate the iframe once, so that the next navigation is a |
| // MANUAL_SUBFRAME navigation. |
| content::RenderFrameHost* iframe = GetIFrame(initial_tab); |
| NavigateParams params(browser(), GetLaunchingPageURL(), |
| ui::PAGE_TRANSITION_LINK); |
| params.frame_tree_node_id = iframe->GetFrameTreeNodeId(); |
| ASSERT_TRUE(TestIFrameActionDoesNotOpenAppWindow( |
| GetLaunchingPageURL(), base::BindOnce(&NavigateToURLWrapper, ¶ms))); |
| } |
| |
| content::RenderFrameHost* iframe = GetIFrame(initial_tab); |
| const GURL app_url = https_server().GetURL(GetAppUrlHost(), GetAppUrlPath()); |
| |
| NavigateParams params(browser(), app_url, ui::PAGE_TRANSITION_LINK); |
| params.frame_tree_node_id = iframe->GetFrameTreeNodeId(); |
| content::TestFrameNavigationObserver observer(iframe); |
| TestIFrameActionDoesNotOpenAppWindow( |
| app_url, base::BindOnce(&NavigateToURLWrapper, ¶ms)); |
| |
| ASSERT_TRUE(ui::PageTransitionCoreTypeIs( |
| observer.transition_type(), ui::PAGE_TRANSITION_MANUAL_SUBFRAME)); |
| |
| // Subframe navigations are completely ignored, so there should be no change |
| // in the histogram. |
| ExpectNavigationResultHistogramEquals(global_histogram(), {}); |
| } |
| |
| // Tests that pasting an in-scope URL into the address bar and navigating to it, |
| // does not open an app window. |
| // https://crbug.com/782004 |
| IN_PROC_BROWSER_TEST_F(BookmarkAppNavigationThrottleExperimentalBrowserTest, |
| LinkNavigationFromAddressBar) { |
| InstallTestBookmarkApp(); |
| |
| const GURL app_url = https_server().GetURL(GetAppUrlHost(), GetAppUrlPath()); |
| // Fake a navigation with a TRANSITION_LINK core type and a |
| // TRANSITION_FROM_ADDRESS_BAR qualifier. This matches the transition that |
| // results from pasting a URL into the address and navigating to it. |
| NavigateParams params( |
| browser(), app_url, |
| ui::PageTransitionFromInt(ui::PAGE_TRANSITION_LINK | |
| ui::PAGE_TRANSITION_FROM_ADDRESS_BAR)); |
| ASSERT_TRUE(TestTabActionDoesNotOpenAppWindow( |
| app_url, base::BindOnce(&NavigateToURLWrapper, ¶ms))); |
| |
| ExpectNavigationResultHistogramEquals( |
| global_histogram(), |
| {{BookmarkAppNavigationThrottleResult::kProceedTransitionFromAddressBar, |
| 1}}); |
| } |
| |
| // Tests that going back to an in-scope URL does not open a new app window. |
| IN_PROC_BROWSER_TEST_F(BookmarkAppNavigationThrottleExperimentalBrowserTest, |
| BackNavigation) { |
| InstallTestBookmarkApp(); |
| NavigateToTestAppURL(); |
| |
| // Navigate to an in-scope URL to generate a link navigation that didn't |
| // get intercepted. The navigation won't get intercepted because the target |
| // URL is in-scope of the app for the current URL. |
| const GURL in_scope_url = |
| https_server().GetURL(GetAppUrlHost(), GetInScopeUrlPath()); |
| ASSERT_TRUE(TestTabActionDoesNotOpenAppWindow( |
| in_scope_url, |
| base::BindOnce(&ClickLinkAndWait, |
| browser()->tab_strip_model()->GetActiveWebContents(), |
| in_scope_url, LinkTarget::SELF, "" /* rel */))); |
| |
| // Navigate to an out-of-scope URL. |
| { |
| const GURL out_of_scope_url = |
| https_server().GetURL(GetAppUrlHost(), GetOutOfScopeUrlPath()); |
| NavigateParams params(browser(), out_of_scope_url, |
| ui::PAGE_TRANSITION_TYPED); |
| ASSERT_TRUE(TestTabActionDoesNotOpenAppWindow( |
| out_of_scope_url, base::BindOnce(&NavigateToURLWrapper, ¶ms))); |
| } |
| |
| base::HistogramTester scoped_histogram; |
| TestTabActionDoesNotOpenAppWindow( |
| in_scope_url, |
| base::BindOnce( |
| [](content::WebContents* web_contents, const GURL& in_scope_url) { |
| auto observer = GetTestNavigationObserver(in_scope_url); |
| web_contents->GetController().GoBack(); |
| observer->WaitForNavigationFinished(); |
| }, |
| browser()->tab_strip_model()->GetActiveWebContents(), in_scope_url)); |
| |
| ExpectNavigationResultHistogramEquals( |
| scoped_histogram, |
| {{BookmarkAppNavigationThrottleResult::kProceedTransitionForwardBack, |
| 1}}); |
| } |
| |
| // Tests that clicking a link to an app that launches in a tab does not open a |
| // a new app window. |
| IN_PROC_BROWSER_TEST_P(BookmarkAppNavigationThrottleExperimentalLinkBrowserTest, |
| TabApp) { |
| InstallTestBookmarkApp(); |
| |
| // Set a pref indicating that the user wants to launch in a regular tab. |
| extensions::SetLaunchType(browser()->profile(), test_bookmark_app()->id(), |
| extensions::LAUNCH_TYPE_REGULAR); |
| |
| NavigateToLaunchingPage(); |
| |
| const GURL app_url = https_server().GetURL(GetAppUrlHost(), GetAppUrlPath()); |
| TestTabActionDoesNotOpenAppWindow( |
| app_url, |
| base::BindOnce(&ClickLinkAndWait, |
| browser()->tab_strip_model()->GetActiveWebContents(), |
| app_url, LinkTarget::SELF, GetParam())); |
| |
| // Non-windowed apps are not considered when looking for a target app, so it's |
| // as if there was no app installed for the URL. |
| ExpectNavigationResultHistogramEquals(global_histogram(), {}); |
| } |
| |
| // Tests that clicking a link to an app that isn't locally installed does not |
| // open a new app window. |
| IN_PROC_BROWSER_TEST_P(BookmarkAppNavigationThrottleExperimentalLinkBrowserTest, |
| NotLocallyInstalledApp) { |
| InstallTestBookmarkApp(); |
| |
| // Part of the installation process (setting that this is a locally installed |
| // app) runs asynchronously. Wait for that to complete before setting locally |
| // installed to false. |
| base::RunLoop().RunUntilIdle(); |
| SetBookmarkAppIsLocallyInstalled(browser()->profile(), test_bookmark_app(), |
| false /* is_locally_installed */); |
| |
| NavigateToLaunchingPage(); |
| |
| const GURL app_url = https_server().GetURL(GetAppUrlHost(), GetAppUrlPath()); |
| TestTabActionDoesNotOpenAppWindow( |
| app_url, |
| base::BindOnce(&ClickLinkAndWait, |
| browser()->tab_strip_model()->GetActiveWebContents(), |
| app_url, LinkTarget::SELF, GetParam())); |
| |
| // Non-locally installed apps are not considered when looking for a target |
| // app, so it's as if there was no app installed for the URL. |
| ExpectNavigationResultHistogramEquals(global_histogram(), {}); |
| } |
| |
| // Tests that clicking a link with target="_self" to the app's app_url opens the |
| // Bookmark App. |
| IN_PROC_BROWSER_TEST_P(BookmarkAppNavigationThrottleExperimentalLinkBrowserTest, |
| AppUrlSelf) { |
| InstallTestBookmarkApp(); |
| NavigateToLaunchingPage(); |
| |
| const GURL app_url = https_server().GetURL(GetAppUrlHost(), GetAppUrlPath()); |
| TestTabActionOpensAppWindow( |
| app_url, |
| base::BindOnce(&ClickLinkAndWait, |
| browser()->tab_strip_model()->GetActiveWebContents(), |
| app_url, LinkTarget::SELF, GetParam())); |
| |
| ExpectNavigationResultHistogramEquals( |
| global_histogram(), |
| {{BookmarkAppNavigationThrottleResult::kCancelOpenedApp, 1}, |
| GetAppLaunchedEntry()}); |
| } |
| |
| // Tests that clicking a link with target="_blank" to the app's app_url opens |
| // the Bookmark App. |
| IN_PROC_BROWSER_TEST_P(BookmarkAppNavigationThrottleExperimentalLinkBrowserTest, |
| AppUrlBlank) { |
| InstallTestBookmarkApp(); |
| NavigateToLaunchingPage(); |
| |
| const GURL app_url = https_server().GetURL(GetAppUrlHost(), GetAppUrlPath()); |
| TestTabActionOpensAppWindow( |
| app_url, |
| base::BindOnce(&ClickLinkAndWait, |
| browser()->tab_strip_model()->GetActiveWebContents(), |
| app_url, LinkTarget::BLANK, GetParam())); |
| |
| ExpectNavigationResultHistogramEquals( |
| global_histogram(), |
| {{BookmarkAppNavigationThrottleResult::kDeferMovingContentsToNewAppWindow, |
| 1}}); |
| } |
| |
| // Tests that Ctrl + Clicking a link to the app's app_url opens a new background |
| // tab and not the app. |
| IN_PROC_BROWSER_TEST_P(BookmarkAppNavigationThrottleExperimentalLinkBrowserTest, |
| AppUrlCtrlClick) { |
| InstallTestBookmarkApp(); |
| NavigateToLaunchingPage(); |
| |
| const GURL app_url = https_server().GetURL(GetAppUrlPath()); |
| TestTabActionOpensBackgroundTab( |
| app_url, |
| base::BindOnce(&ClickLinkWithModifiersAndWait, |
| browser()->tab_strip_model()->GetActiveWebContents(), |
| app_url, LinkTarget::SELF, GetParam(), kCtrlOrMeta)); |
| |
| ExpectNavigationResultHistogramEquals( |
| global_histogram(), {{BookmarkAppNavigationThrottleResult:: |
| kProceedDispositionNewBackgroundTab, |
| 1}}); |
| } |
| |
| // Tests that clicking a link with target="_self" and for which the server |
| // redirects to the app's app_url opens the Bookmark App. |
| IN_PROC_BROWSER_TEST_P(BookmarkAppNavigationThrottleExperimentalLinkBrowserTest, |
| ServerRedirectToAppUrlSelf) { |
| InstallTestBookmarkApp(); |
| NavigateToLaunchingPage(); |
| |
| const GURL app_url = https_server().GetURL(GetAppUrlHost(), GetAppUrlPath()); |
| const GURL redirecting_url = https_server().GetURL( |
| GetLaunchingPageHost(), CreateServerRedirect(app_url)); |
| TestTabActionOpensAppWindow( |
| app_url, |
| base::BindOnce(&ClickLinkAndWaitForURL, |
| browser()->tab_strip_model()->GetActiveWebContents(), |
| redirecting_url, app_url, LinkTarget::SELF, GetParam())); |
| |
| ExpectNavigationResultHistogramEquals( |
| global_histogram(), |
| {{BookmarkAppNavigationThrottleResult::kCancelOpenedApp, 1}, |
| GetAppLaunchedEntry()}); |
| } |
| |
| // Tests that clicking a link with target="_blank" and for which the server |
| // redirects to the app's app_url opens the Bookmark App. |
| IN_PROC_BROWSER_TEST_P(BookmarkAppNavigationThrottleExperimentalLinkBrowserTest, |
| ServerRedirectToAppUrlBlank) { |
| InstallTestBookmarkApp(); |
| NavigateToLaunchingPage(); |
| |
| const GURL app_url = https_server().GetURL(GetAppUrlHost(), GetAppUrlPath()); |
| const GURL redirecting_url = https_server().GetURL( |
| GetLaunchingPageHost(), CreateServerRedirect(app_url)); |
| TestTabActionOpensAppWindow( |
| app_url, |
| base::BindOnce(&ClickLinkAndWaitForURL, |
| browser()->tab_strip_model()->GetActiveWebContents(), |
| redirecting_url, app_url, LinkTarget::BLANK, GetParam())); |
| |
| ExpectNavigationResultHistogramEquals( |
| global_histogram(), |
| {{BookmarkAppNavigationThrottleResult::kDeferMovingContentsToNewAppWindow, |
| 1}}); |
| } |
| |
| // Tests that clicking a link with target="_self" and for which the client |
| // redirects to the app's app_url opens the Bookmark App. The initial tab will |
| // be left on the redirecting URL. |
| IN_PROC_BROWSER_TEST_P(BookmarkAppNavigationThrottleExperimentalLinkBrowserTest, |
| ClientRedirectToAppUrlSelf) { |
| InstallTestBookmarkApp(); |
| NavigateToLaunchingPage(); |
| |
| content::WebContents* initial_tab = |
| browser()->tab_strip_model()->GetActiveWebContents(); |
| GURL initial_url = initial_tab->GetLastCommittedURL(); |
| int num_tabs = browser()->tab_strip_model()->count(); |
| size_t num_browsers = chrome::GetBrowserCount(profile()); |
| |
| const GURL app_url = https_server().GetURL(GetAppUrlHost(), GetAppUrlPath()); |
| const GURL redirecting_url = https_server().GetURL( |
| GetLaunchingPageHost(), CreateClientRedirect(app_url)); |
| ClickLinkAndWaitForURL(browser()->tab_strip_model()->GetActiveWebContents(), |
| redirecting_url, app_url, LinkTarget::SELF, |
| GetParam()); |
| |
| EXPECT_EQ(num_tabs, browser()->tab_strip_model()->count()); |
| EXPECT_EQ(++num_browsers, chrome::GetBrowserCount(profile())); |
| EXPECT_NE(browser(), chrome::FindLastActive()); |
| |
| EXPECT_EQ(redirecting_url, initial_tab->GetLastCommittedURL()); |
| EXPECT_EQ(app_url, chrome::FindLastActive() |
| ->tab_strip_model() |
| ->GetActiveWebContents() |
| ->GetLastCommittedURL()); |
| |
| ExpectNavigationResultHistogramEquals( |
| global_histogram(), |
| {{BookmarkAppNavigationThrottleResult::kCancelOpenedApp, 1}, |
| GetAppLaunchedEntry()}); |
| } |
| |
| // Tests that clicking a link with target="_blank" and for which the client |
| // redirects to the app's app_url opens the Bookmark App. The new tab will be |
| // left on the redirecting URL. |
| IN_PROC_BROWSER_TEST_P(BookmarkAppNavigationThrottleExperimentalLinkBrowserTest, |
| ClientRedirectToAppUrlBlank) { |
| InstallTestBookmarkApp(); |
| NavigateToLaunchingPage(); |
| |
| content::WebContents* initial_tab = |
| browser()->tab_strip_model()->GetActiveWebContents(); |
| GURL initial_url = initial_tab->GetLastCommittedURL(); |
| int num_tabs = browser()->tab_strip_model()->count(); |
| size_t num_browsers = chrome::GetBrowserCount(profile()); |
| |
| const GURL app_url = https_server().GetURL(GetAppUrlHost(), GetAppUrlPath()); |
| const GURL redirecting_url = https_server().GetURL( |
| GetLaunchingPageHost(), CreateClientRedirect(app_url)); |
| ClickLinkAndWaitForURL(browser()->tab_strip_model()->GetActiveWebContents(), |
| redirecting_url, app_url, LinkTarget::BLANK, |
| GetParam()); |
| |
| EXPECT_EQ(++num_tabs, browser()->tab_strip_model()->count()); |
| EXPECT_EQ(++num_browsers, chrome::GetBrowserCount(profile())); |
| EXPECT_NE(browser(), chrome::FindLastActive()); |
| |
| content::WebContents* new_tab = |
| browser()->tab_strip_model()->GetActiveWebContents(); |
| EXPECT_NE(new_tab, initial_tab); |
| |
| EXPECT_EQ(redirecting_url, new_tab->GetLastCommittedURL()); |
| EXPECT_EQ(app_url, chrome::FindLastActive() |
| ->tab_strip_model() |
| ->GetActiveWebContents() |
| ->GetLastCommittedURL()); |
| |
| ExpectNavigationResultHistogramEquals( |
| global_histogram(), |
| {{BookmarkAppNavigationThrottleResult::kCancelOpenedApp, 1}, |
| GetAppLaunchedEntry()}); |
| } |
| |
| // Tests that clicking a link with target="_self" to a URL in the Web App's |
| // scope opens a new browser window. |
| IN_PROC_BROWSER_TEST_P(BookmarkAppNavigationThrottleExperimentalLinkBrowserTest, |
| InScopeUrlSelf) { |
| InstallTestBookmarkApp(); |
| NavigateToLaunchingPage(); |
| |
| const GURL in_scope_url = |
| https_server().GetURL(GetAppUrlHost(), GetInScopeUrlPath()); |
| TestTabActionOpensAppWindow( |
| in_scope_url, |
| base::BindOnce(&ClickLinkAndWait, |
| browser()->tab_strip_model()->GetActiveWebContents(), |
| in_scope_url, LinkTarget::SELF, GetParam())); |
| |
| ExpectNavigationResultHistogramEquals( |
| global_histogram(), |
| {{BookmarkAppNavigationThrottleResult::kCancelOpenedApp, 1}, |
| GetAppLaunchedEntry()}); |
| } |
| |
| // Tests that clicking a link with target="_self" to a URL out of the Web App's |
| // scope but with the same origin doesn't open a new browser window. |
| IN_PROC_BROWSER_TEST_P(BookmarkAppNavigationThrottleExperimentalLinkBrowserTest, |
| OutOfScopeUrlSelf) { |
| InstallTestBookmarkApp(); |
| NavigateToLaunchingPage(); |
| |
| const GURL out_of_scope_url = |
| https_server().GetURL(GetAppUrlHost(), GetOutOfScopeUrlPath()); |
| TestTabActionDoesNotOpenAppWindow( |
| out_of_scope_url, |
| base::BindOnce(&ClickLinkAndWait, |
| browser()->tab_strip_model()->GetActiveWebContents(), |
| out_of_scope_url, LinkTarget::SELF, GetParam())); |
| |
| ExpectNavigationResultHistogramEquals(global_histogram(), {}); |
| } |
| |
| // Tests that prerender links don't open the app. |
| IN_PROC_BROWSER_TEST_F(BookmarkAppNavigationThrottleExperimentalBrowserTest, |
| PrerenderLinks) { |
| prerender::PrerenderManager::SetMode( |
| prerender::PrerenderManager::DEPRECATED_PRERENDER_MODE_ENABLED); |
| |
| InstallTestBookmarkApp(); |
| NavigateToLaunchingPage(); |
| |
| TestTabActionDoesNotNavigateOrOpenAppWindow(base::BindOnce( |
| [](content::WebContents* web_contents, const GURL& target_url) { |
| std::string script = base::StringPrintf( |
| "(() => {" |
| "const prerender_link = document.createElement('link');" |
| "prerender_link.rel = 'prerender';" |
| "prerender_link.href = '%s';" |
| "prerender_link.addEventListener('webkitprerenderstop'," |
| "() => window.domAutomationController.send(true));" |
| "document.body.appendChild(prerender_link);" |
| "})();", |
| target_url.spec().c_str()); |
| bool result; |
| ASSERT_TRUE(content::ExecuteScriptAndExtractBool(web_contents, script, |
| &result)); |
| ASSERT_TRUE(result); |
| }, |
| browser()->tab_strip_model()->GetActiveWebContents(), |
| https_server().GetURL(GetAppUrlHost(), GetInScopeUrlPath()))); |
| |
| ExpectNavigationResultHistogramEquals( |
| global_histogram(), |
| {{BookmarkAppNavigationThrottleResult::kCancelPrerenderContents, 1}}); |
| } |
| |
| // Tests fetch calls don't open a new App window. |
| IN_PROC_BROWSER_TEST_F(BookmarkAppNavigationThrottleExperimentalBrowserTest, |
| Fetch) { |
| InstallTestBookmarkApp(); |
| NavigateToLaunchingPage(); |
| |
| TestTabActionDoesNotNavigateOrOpenAppWindow(base::BindOnce( |
| [](content::WebContents* web_contents, const GURL& target_url) { |
| std::string script = base::StringPrintf( |
| "(() => {" |
| "fetch('%s').then(response => {" |
| " window.domAutomationController.send(response.ok);" |
| "});" |
| "})();", |
| target_url.spec().c_str()); |
| bool result; |
| ASSERT_TRUE(content::ExecuteScriptAndExtractBool(web_contents, script, |
| &result)); |
| ASSERT_TRUE(result); |
| }, |
| browser()->tab_strip_model()->GetActiveWebContents(), |
| https_server().GetURL(GetAppUrlHost(), GetInScopeUrlPath()))); |
| |
| // Fetch requests don't go through our NavigationHandle. |
| ExpectNavigationResultHistogramEquals(global_histogram(), {}); |
| } |
| |
| // Tests that clicking "Open link in new tab" to an in-scope URL opens a new |
| // tab in the background. |
| IN_PROC_BROWSER_TEST_F(BookmarkAppNavigationThrottleExperimentalBrowserTest, |
| ContextMenuNewTab) { |
| InstallTestBookmarkApp(); |
| NavigateToLaunchingPage(); |
| |
| const GURL app_url = https_server().GetURL(GetAppUrlHost(), GetAppUrlPath()); |
| TestTabActionOpensBackgroundTab( |
| app_url, |
| base::BindOnce(&ExecuteContextMenuLinkCommandAndWait, |
| browser()->tab_strip_model()->GetActiveWebContents(), |
| app_url, IDC_CONTENT_CONTEXT_OPENLINKNEWTAB)); |
| |
| ExpectNavigationResultHistogramEquals( |
| global_histogram(), |
| {{BookmarkAppNavigationThrottleResult::kProceedStartedFromContextMenu, |
| 1}}); |
| } |
| |
| // Tests that clicking "Open link in new window" to an in-scope URL opens a new |
| // window in the foreground. |
| IN_PROC_BROWSER_TEST_F(BookmarkAppNavigationThrottleExperimentalBrowserTest, |
| ContextMenuNewWindow) { |
| InstallTestBookmarkApp(); |
| NavigateToLaunchingPage(); |
| |
| const GURL app_url = https_server().GetURL(GetAppUrlHost(), GetAppUrlPath()); |
| TestTabActionOpensForegroundWindow( |
| app_url, |
| base::BindOnce(&ExecuteContextMenuLinkCommandAndWait, |
| browser()->tab_strip_model()->GetActiveWebContents(), |
| app_url, IDC_CONTENT_CONTEXT_OPENLINKNEWWINDOW)); |
| |
| ExpectNavigationResultHistogramEquals( |
| global_histogram(), |
| {{BookmarkAppNavigationThrottleResult::kProceedStartedFromContextMenu, |
| 1}}); |
| } |
| |
| // Tests that clicking "Open link in new tab" in an app to an in-scope URL opens |
| // a new foreground tab in a regular browser window. |
| IN_PROC_BROWSER_TEST_F(BookmarkAppNavigationThrottleExperimentalBrowserTest, |
| InAppContextMenuNewTab) { |
| InstallTestBookmarkApp(); |
| Browser* app_browser = OpenTestBookmarkApp(); |
| |
| base::HistogramTester scoped_histogram; |
| const GURL app_url = https_server().GetURL(GetAppUrlHost(), GetAppUrlPath()); |
| TestAppActionOpensForegroundTab( |
| app_browser, app_url, |
| base::BindOnce(&ExecuteContextMenuLinkCommandAndWait, |
| app_browser->tab_strip_model()->GetActiveWebContents(), |
| app_url, IDC_CONTENT_CONTEXT_OPENLINKNEWTAB)); |
| |
| ExpectNavigationResultHistogramEquals( |
| scoped_histogram, |
| {{BookmarkAppNavigationThrottleResult::kProceedStartedFromContextMenu, |
| 1}}); |
| } |
| |
| // Tests that clicking "Open link in incognito window" to an in-scope URL opens |
| // an incognito window and not an app window. |
| IN_PROC_BROWSER_TEST_F(BookmarkAppNavigationThrottleExperimentalBrowserTest, |
| OpenInIncognito) { |
| InstallTestBookmarkApp(); |
| NavigateToLaunchingPage(); |
| |
| size_t num_browsers = chrome::GetBrowserCount(profile()); |
| int num_tabs = browser()->tab_strip_model()->count(); |
| content::WebContents* initial_tab = |
| browser()->tab_strip_model()->GetActiveWebContents(); |
| GURL initial_url = initial_tab->GetLastCommittedURL(); |
| |
| const GURL in_scope_url = |
| https_server().GetURL(GetAppUrlHost(), GetInScopeUrlPath()); |
| auto observer = GetTestNavigationObserver(in_scope_url); |
| content::ContextMenuParams params; |
| params.page_url = initial_url; |
| params.link_url = in_scope_url; |
| TestRenderViewContextMenu menu(initial_tab->GetMainFrame(), params); |
| menu.Init(); |
| menu.ExecuteCommand(IDC_CONTENT_CONTEXT_OPENLINKOFFTHERECORD, |
| 0 /* event_flags */); |
| observer->WaitForNavigationFinished(); |
| |
| Browser* incognito_browser = chrome::FindLastActive(); |
| EXPECT_EQ(incognito_browser->profile(), profile()->GetOffTheRecordProfile()); |
| EXPECT_NE(browser(), incognito_browser); |
| EXPECT_EQ(in_scope_url, incognito_browser->tab_strip_model() |
| ->GetActiveWebContents() |
| ->GetLastCommittedURL()); |
| |
| EXPECT_EQ(num_browsers, chrome::GetBrowserCount(profile())); |
| EXPECT_EQ(num_tabs, browser()->tab_strip_model()->count()); |
| EXPECT_EQ(initial_tab, browser()->tab_strip_model()->GetActiveWebContents()); |
| EXPECT_EQ(initial_url, initial_tab->GetLastCommittedURL()); |
| |
| // Incognito navigations are completely ignored. |
| ExpectNavigationResultHistogramEquals(global_histogram(), {}); |
| } |
| |
| // Tests that clicking a link to an in-scope URL when in incognito does not open |
| // an App window. |
| IN_PROC_BROWSER_TEST_P(BookmarkAppNavigationThrottleExperimentalLinkBrowserTest, |
| InScopeUrlIncognito) { |
| InstallTestBookmarkApp(); |
| Browser* incognito_browser = CreateIncognitoBrowser(); |
| NavigateToLaunchingPage(incognito_browser); |
| |
| const GURL in_scope_url = |
| https_server().GetURL(GetAppUrlHost(), GetInScopeUrlPath()); |
| TestActionDoesNotOpenAppWindow( |
| incognito_browser, in_scope_url, |
| base::BindOnce( |
| &ClickLinkAndWait, |
| incognito_browser->tab_strip_model()->GetActiveWebContents(), |
| in_scope_url, LinkTarget::SELF, GetParam())); |
| |
| // Incognito navigations are completely ignored. |
| ExpectNavigationResultHistogramEquals(global_histogram(), {}); |
| } |
| |
| // Tests that clicking a target=_self link from a URL out of the Web App's scope |
| // but with the same origin to an in-scope URL results in a new App window. |
| IN_PROC_BROWSER_TEST_P(BookmarkAppNavigationThrottleExperimentalLinkBrowserTest, |
| FromOutOfScopeUrlToInScopeUrlSelf) { |
| InstallTestBookmarkApp(); |
| |
| // Navigate to out-of-scope URL. Shouldn't open a new window. |
| const GURL out_of_scope_url = |
| https_server().GetURL(GetAppUrlHost(), GetOutOfScopeUrlPath()); |
| NavigateParams params(browser(), out_of_scope_url, ui::PAGE_TRANSITION_TYPED); |
| ASSERT_TRUE(TestTabActionDoesNotOpenAppWindow( |
| out_of_scope_url, base::BindOnce(&NavigateToURLWrapper, ¶ms))); |
| |
| const GURL in_scope_url = |
| https_server().GetURL(GetAppUrlHost(), GetAppUrlPath()); |
| TestTabActionOpensAppWindow( |
| in_scope_url, |
| base::BindOnce(&ClickLinkAndWait, |
| browser()->tab_strip_model()->GetActiveWebContents(), |
| in_scope_url, LinkTarget::SELF, GetParam())); |
| |
| ExpectNavigationResultHistogramEquals( |
| global_histogram(), |
| {{BookmarkAppNavigationThrottleResult::kCancelOpenedApp, 1}, |
| GetAppLaunchedEntry()}); |
| } |
| |
| // Tests that clicking a target=_blank link from a URL out of the Web App's |
| // scope but with the same origin to an in-scope URL results in a new App |
| // window. |
| // TODO(crbug.com/837277): Deflake and reenable. |
| IN_PROC_BROWSER_TEST_P(BookmarkAppNavigationThrottleExperimentalLinkBrowserTest, |
| DISABLED_FromOutOfScopeUrlToInScopeUrlBlank) { |
| InstallTestBookmarkApp(); |
| |
| // Navigate to out-of-scope URL. Shouldn't open a new window. |
| const GURL out_of_scope_url = |
| https_server().GetURL(GetAppUrlHost(), GetOutOfScopeUrlPath()); |
| NavigateParams params(browser(), out_of_scope_url, ui::PAGE_TRANSITION_TYPED); |
| ASSERT_TRUE(TestTabActionDoesNotOpenAppWindow( |
| out_of_scope_url, base::BindOnce(&NavigateToURLWrapper, ¶ms))); |
| |
| const GURL in_scope_url = |
| https_server().GetURL(GetAppUrlHost(), GetAppUrlPath()); |
| TestTabActionOpensAppWindow( |
| in_scope_url, |
| base::BindOnce(&ClickLinkAndWait, |
| browser()->tab_strip_model()->GetActiveWebContents(), |
| in_scope_url, LinkTarget::BLANK, GetParam())); |
| |
| ExpectNavigationResultHistogramEquals( |
| global_histogram(), |
| {{BookmarkAppNavigationThrottleResult::kDeferMovingContentsToNewAppWindow, |
| 1}}); |
| } |
| |
| // Tests that clicking links inside a website for an installed app doesn't open |
| // a new browser window. |
| IN_PROC_BROWSER_TEST_P(BookmarkAppNavigationThrottleExperimentalLinkBrowserTest, |
| InWebsiteNavigation) { |
| InstallTestBookmarkApp(); |
| NavigateToTestAppURL(); |
| |
| base::HistogramTester scoped_histogram; |
| const GURL in_scope_url = |
| https_server().GetURL(GetAppUrlHost(), GetInScopeUrlPath()); |
| TestTabActionDoesNotOpenAppWindow( |
| in_scope_url, |
| base::BindOnce(&ClickLinkAndWait, |
| browser()->tab_strip_model()->GetActiveWebContents(), |
| in_scope_url, LinkTarget::SELF, GetParam())); |
| |
| ExpectNavigationResultHistogramEquals( |
| scoped_histogram, |
| {{BookmarkAppNavigationThrottleResult::kProceedInBrowserSameScope, 1}}); |
| } |
| |
| class BookmarkAppNavigationThrottleExperimentalWindowOpenBrowserTest |
| : public BookmarkAppNavigationThrottleExperimentalBrowserTest, |
| public ::testing::WithParamInterface<std::string> {}; |
| |
| // Tests that same-origin or cross-origin apps created with window.open() from |
| // a regular browser window have an opener. |
| IN_PROC_BROWSER_TEST_P( |
| BookmarkAppNavigationThrottleExperimentalWindowOpenBrowserTest, |
| WindowOpenInBrowser) { |
| InstallTestBookmarkApp(); |
| InstallOtherTestBookmarkApp(); |
| |
| NavigateToTestAppURL(); |
| |
| // Call window.open() with |target_url|. |
| const GURL target_url = https_server().GetURL(GetParam(), GetAppUrlPath()); |
| TestTabActionOpensAppWindowWithOpener( |
| target_url, |
| base::BindOnce(&WindowOpenAndWait, |
| browser()->tab_strip_model()->GetActiveWebContents(), |
| target_url)); |
| } |
| |
| // Tests that same-origin or cross-origin apps created with window.open() from |
| // another app window have an opener. |
| #if defined(OS_MACOSX) |
| #define MAYBE_WindowOpenInApp DISABLED_WindowOpenInApp |
| #else |
| #define MAYBE_WindowOpenInApp WindowOpenInApp |
| #endif |
| IN_PROC_BROWSER_TEST_P( |
| BookmarkAppNavigationThrottleExperimentalWindowOpenBrowserTest, |
| MAYBE_WindowOpenInApp) { |
| InstallTestBookmarkApp(); |
| InstallOtherTestBookmarkApp(); |
| |
| // Open app window. |
| Browser* app_browser = OpenTestBookmarkApp(); |
| content::WebContents* app_web_contents = |
| app_browser->tab_strip_model()->GetActiveWebContents(); |
| |
| // Call window.open() with |target_url|. |
| const GURL target_url = https_server().GetURL(GetParam(), GetAppUrlPath()); |
| TestAppActionOpensAppWindowWithOpener( |
| app_browser, target_url, |
| base::BindOnce(&WindowOpenAndWait, app_web_contents, target_url)); |
| } |
| |
| INSTANTIATE_TEST_SUITE_P( |
| /* no prefix */, |
| BookmarkAppNavigationThrottleExperimentalWindowOpenBrowserTest, |
| testing::Values(BookmarkAppNavigationBrowserTest::GetAppUrlHost(), |
| BookmarkAppNavigationBrowserTest::GetOtherAppUrlHost())); |
| |
| // Tests that a child window can access its opener, when the opener is a regular |
| // browser tab. |
| IN_PROC_BROWSER_TEST_F(BookmarkAppNavigationThrottleExperimentalBrowserTest, |
| AccessOpenerBrowserWindowFromChildWindow) { |
| InstallTestBookmarkApp(); |
| InstallOtherTestBookmarkApp(); |
| |
| NavigateToTestAppURL(); |
| |
| content::WebContents* current_tab = |
| browser()->tab_strip_model()->GetActiveWebContents(); |
| |
| const GURL app_url = https_server().GetURL(GetAppUrlHost(), GetAppUrlPath()); |
| EXPECT_EQ(WindowAccessResult::CAN_ACCESS, |
| CanChildWindowAccessOpener(current_tab, app_url)); |
| |
| const GURL other_app_url = |
| https_server().GetURL(GetOtherAppUrlHost(), GetAppUrlPath()); |
| EXPECT_EQ(WindowAccessResult::CANNOT_ACCESS, |
| CanChildWindowAccessOpener(current_tab, other_app_url)); |
| } |
| |
| // Tests that a child window can access its opener, when the opener is another |
| // app. |
| IN_PROC_BROWSER_TEST_F(BookmarkAppNavigationThrottleExperimentalBrowserTest, |
| AccessOpenerAppWindowFromChildWindow) { |
| InstallTestBookmarkApp(); |
| InstallOtherTestBookmarkApp(); |
| |
| // Open app window. |
| Browser* app_browser = OpenTestBookmarkApp(); |
| content::WebContents* app_web_contents = |
| app_browser->tab_strip_model()->GetActiveWebContents(); |
| |
| const GURL app_url = https_server().GetURL(GetAppUrlHost(), GetAppUrlPath()); |
| EXPECT_EQ(WindowAccessResult::CAN_ACCESS, |
| CanChildWindowAccessOpener(app_web_contents, app_url)); |
| |
| const GURL other_app_url = |
| https_server().GetURL(GetOtherAppUrlHost(), GetAppUrlPath()); |
| EXPECT_EQ(WindowAccessResult::CANNOT_ACCESS, |
| CanChildWindowAccessOpener(app_web_contents, other_app_url)); |
| } |
| |
| // Tests that in-browser navigations with all the following characteristics |
| // don't open a new app window or move the tab: |
| // 1. Are to in-scope URLs |
| // 2. Result in a AUTO_BOOKMARK transtion |
| // 3. Redirect to another in-scope URL. |
| // |
| // Clicking on sites in the New Tab Page is one of the ways to trigger this |
| // type of navigation. |
| IN_PROC_BROWSER_TEST_F(BookmarkAppNavigationThrottleExperimentalBrowserTest, |
| AutoBookmarkInScopeRedirect) { |
| const Extension* app = |
| InstallImmediateRedirectingApp(GetAppUrlHost(), GetInScopeUrlPath()); |
| |
| const GURL app_url = AppLaunchInfo::GetFullLaunchURL(app); |
| NavigateParams params(browser(), app_url, ui::PAGE_TRANSITION_AUTO_BOOKMARK); |
| TestTabActionDoesNotOpenAppWindow( |
| https_server().GetURL(GetAppUrlHost(), GetInScopeUrlPath()), |
| base::BindOnce(&NavigateToURLWrapper, ¶ms)); |
| |
| // The first AUTO_BOOKMARK navigation is the one we triggered and the second |
| // one is the redirect. |
| ExpectNavigationResultHistogramEquals( |
| global_histogram(), |
| {{BookmarkAppNavigationThrottleResult::kProceedTransitionAutoBookmark, |
| 2}}); |
| } |
| |
| // Tests that in-browser navigations with all the following characteristics |
| // don't open a new app window or move the tab: |
| // 1. Are to in-scope URLs |
| // 2. Result in a AUTO_BOOKMARK transtion |
| // 3. Redirect to an out-of-scope URL. |
| // |
| // Clicking on sites in the New Tab Page is one of the ways to trigger this |
| // type of navigation. |
| IN_PROC_BROWSER_TEST_F(BookmarkAppNavigationThrottleExperimentalBrowserTest, |
| AutoBookmarkOutOfScopeRedirect) { |
| const Extension* app = InstallImmediateRedirectingApp(GetLaunchingPageHost(), |
| GetLaunchingPagePath()); |
| |
| const GURL app_url = AppLaunchInfo::GetFullLaunchURL(app); |
| NavigateParams params(browser(), app_url, ui::PAGE_TRANSITION_AUTO_BOOKMARK); |
| TestTabActionDoesNotOpenAppWindow( |
| GetLaunchingPageURL(), base::BindOnce(&NavigateToURLWrapper, ¶ms)); |
| |
| ExpectNavigationResultHistogramEquals( |
| global_histogram(), |
| {{BookmarkAppNavigationThrottleResult::kProceedTransitionAutoBookmark, |
| 1}}); |
| } |
| |
| INSTANTIATE_TEST_SUITE_P( |
| /* no prefix */, |
| BookmarkAppNavigationThrottleExperimentalLinkBrowserTest, |
| testing::Values("", "noopener", "noreferrer", "nofollow")); |
| |
| // Base class for testing the behavior is the same regardless of the |
| // kDesktopPWAsLinkCapturing feature flag. |
| class BookmarkAppNavigationThrottleBaseCommonBrowserTest |
| : public BookmarkAppNavigationBrowserTest { |
| protected: |
| void EnableFeaturesForTest(bool should_enable_link_capturing) { |
| // These tests expect that navigation to an out of scope URL will open in a |
| // new window, however, this behaviour is in the process of being changed |
| // (with the flag desktop-pwas-stay-in-window), so until the change is made |
| // permanent and these tests are removed, explicitly disable the flag. |
| if (should_enable_link_capturing) { |
| scoped_feature_list_.InitWithFeatures( |
| {features::kDesktopPWAWindowing, features::kDesktopPWAsLinkCapturing}, |
| {features::kDesktopPWAsStayInWindow}); |
| } else { |
| scoped_feature_list_.InitWithFeatures( |
| {features::kDesktopPWAWindowing}, |
| {features::kDesktopPWAsLinkCapturing, |
| features::kDesktopPWAsStayInWindow}); |
| } |
| } |
| |
| private: |
| base::test::ScopedFeatureList scoped_feature_list_; |
| }; |
| |
| // Class for testing the behavior is the same regardless of the |
| // kDesktopPWAsLinkCapturing feature flag. |
| class BookmarkAppNavigationThrottleCommonBrowserTest |
| : public BookmarkAppNavigationThrottleBaseCommonBrowserTest, |
| public ::testing::WithParamInterface<bool> { |
| public: |
| void SetUp() override { |
| EnableFeaturesForTest(GetParam()); |
| BookmarkAppNavigationThrottleBaseCommonBrowserTest::SetUp(); |
| } |
| }; |
| |
| // Tests that an app that immediately redirects to an out-of-scope URL opens a |
| // new foreground tab. |
| IN_PROC_BROWSER_TEST_P(BookmarkAppNavigationThrottleCommonBrowserTest, |
| ImmediateOutOfScopeRedirect) { |
| size_t num_browsers = chrome::GetBrowserCount(profile()); |
| int num_tabs_browser = browser()->tab_strip_model()->count(); |
| |
| content::WebContents* initial_tab = |
| browser()->tab_strip_model()->GetActiveWebContents(); |
| |
| GURL initial_url = initial_tab->GetLastCommittedURL(); |
| |
| const Extension* redirecting_app = InstallImmediateRedirectingApp( |
| GetLaunchingPageHost(), GetLaunchingPagePath()); |
| |
| auto observer = GetTestNavigationObserver(GetLaunchingPageURL()); |
| LaunchAppBrowser(redirecting_app); |
| observer->WaitForNavigationFinished(); |
| |
| EXPECT_EQ(num_browsers, chrome::GetBrowserCount(profile())); |
| |
| EXPECT_EQ(browser(), chrome::FindLastActive()); |
| EXPECT_EQ(++num_tabs_browser, browser()->tab_strip_model()->count()); |
| |
| EXPECT_EQ(initial_url, initial_tab->GetLastCommittedURL()); |
| |
| content::WebContents* new_tab = |
| browser()->tab_strip_model()->GetActiveWebContents(); |
| EXPECT_NE(initial_tab, new_tab); |
| EXPECT_EQ(GetLaunchingPageURL(), new_tab->GetLastCommittedURL()); |
| |
| // When kDesktopPWAsLinkCapturing is enabled, app launches get histogrammed, |
| // but when it's disabled, they don't. |
| if (GetParam()) { |
| ExpectNavigationResultHistogramEquals( |
| global_histogram(), {GetAppLaunchedEntry(), |
| {BookmarkAppNavigationThrottleResult:: |
| kOpenInChromeProceedOutOfScopeLaunch, |
| 1}}); |
| } else { |
| ExpectNavigationResultHistogramEquals( |
| global_histogram(), {{BookmarkAppNavigationThrottleResult:: |
| kOpenInChromeProceedOutOfScopeLaunch, |
| 1}}); |
| } |
| } |
| |
| // Tests that popups to out-of-scope URLs are opened in regular popup windows |
| // and not in app windows. |
| // TODO(crbug.com/849163) Times out flakily on MacOS. |
| #if defined(OS_MACOSX) |
| #define MAYBE_OutOfScopePopup DISABLED_OutOfScopePopup |
| #else |
| #define MAYBE_OutOfScopePopup OutOfScopePopup |
| #endif |
| IN_PROC_BROWSER_TEST_P(BookmarkAppNavigationThrottleCommonBrowserTest, |
| MAYBE_OutOfScopePopup) { |
| InstallTestBookmarkApp(); |
| Browser* app_browser = OpenTestBookmarkApp(); |
| |
| base::HistogramTester scoped_histogram; |
| |
| size_t num_browsers = chrome::GetBrowserCount(profile()); |
| int num_tabs_browser = browser()->tab_strip_model()->count(); |
| int num_tabs_app_browser = app_browser->tab_strip_model()->count(); |
| |
| content::WebContents* app_web_contents = |
| app_browser->tab_strip_model()->GetActiveWebContents(); |
| |
| content::WebContents* initial_tab = |
| browser()->tab_strip_model()->GetActiveWebContents(); |
| |
| GURL initial_app_url = app_web_contents->GetLastCommittedURL(); |
| GURL initial_tab_url = initial_tab->GetLastCommittedURL(); |
| |
| // Open a popup to an out-of-scope URL. |
| const GURL out_of_scope_url = |
| https_server().GetURL(GetAppUrlHost(), GetOutOfScopeUrlPath()); |
| OpenPopupAndWait(app_web_contents, out_of_scope_url); |
| |
| EXPECT_EQ(++num_browsers, chrome::GetBrowserCount(profile())); |
| |
| Browser* new_popup_browser = chrome::FindLastActive(); |
| EXPECT_NE(new_popup_browser, browser()); |
| EXPECT_NE(new_popup_browser, app_browser); |
| EXPECT_TRUE(new_popup_browser->is_type_popup()); |
| EXPECT_FALSE(new_popup_browser->is_app()); |
| |
| EXPECT_EQ(num_tabs_browser, browser()->tab_strip_model()->count()); |
| EXPECT_EQ(num_tabs_app_browser, app_browser->tab_strip_model()->count()); |
| |
| EXPECT_EQ(initial_app_url, app_web_contents->GetLastCommittedURL()); |
| |
| content::WebContents* new_popup_web_contents = |
| new_popup_browser->tab_strip_model()->GetActiveWebContents(); |
| EXPECT_EQ(out_of_scope_url, new_popup_web_contents->GetLastCommittedURL()); |
| |
| ExpectNavigationResultHistogramEquals( |
| scoped_histogram, |
| {{BookmarkAppNavigationThrottleResult:: |
| kReparentIntoPopupProceedOutOfScopeInitialNavigation, |
| 1}}); |
| } |
| |
| // Tests that popups to in-scope URLs are opened in App windows. |
| // TODO(crbug.com/849163) Times out flakily on MacOS. |
| #if defined(OS_MACOSX) |
| #define MAYBE_InScopePopup DISABLED_InScopePopup |
| #else |
| #define MAYBE_InScopePopup InScopePopup |
| #endif |
| IN_PROC_BROWSER_TEST_P(BookmarkAppNavigationThrottleCommonBrowserTest, |
| MAYBE_InScopePopup) { |
| InstallTestBookmarkApp(); |
| Browser* app_browser = OpenTestBookmarkApp(); |
| |
| base::HistogramTester scoped_histogram; |
| |
| // Open a popup to an out-of-scope URL. |
| const GURL in_scope_url = |
| https_server().GetURL(GetAppUrlHost(), GetInScopeUrlPath()); |
| TestAppActionOpensAppWindowWithOpener( |
| app_browser, in_scope_url, |
| base::Bind(&OpenPopupAndWait, |
| app_browser->tab_strip_model()->GetActiveWebContents(), |
| in_scope_url)); |
| |
| ExpectNavigationResultHistogramEquals( |
| scoped_histogram, |
| {{BookmarkAppNavigationThrottleResult::kProceedInAppSameScope, 1}}); |
| } |
| |
| // Apps are only restored during startup on Chrome OS. |
| #if defined(OS_CHROMEOS) |
| IN_PROC_BROWSER_TEST_P(BookmarkAppNavigationThrottleCommonBrowserTest, |
| PRE_RestoreApp) { |
| InstallTestBookmarkApp(); |
| OpenTestBookmarkApp(); |
| SessionStartupPref::SetStartupPref( |
| profile(), SessionStartupPref(SessionStartupPref::LAST)); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(BookmarkAppNavigationThrottleCommonBrowserTest, |
| RestoreApp) { |
| // There should be two windows. The app window and a regular browser window |
| // the test opens. |
| EXPECT_EQ(2u, chrome::GetBrowserCount(profile())); |
| Browser* app_browser = nullptr; |
| for (auto* browser : *BrowserList::GetInstance()) { |
| if (browser->is_app()) { |
| EXPECT_FALSE(app_browser) << "Found multiple app browsers."; |
| app_browser = browser; |
| } |
| } |
| ASSERT_TRUE(app_browser); |
| |
| const Extension* app = |
| ExtensionRegistry::Get(profile())->enabled_extensions().GetByID( |
| web_app::GetAppIdFromApplicationName(app_browser->app_name())); |
| EXPECT_EQ(GetAppName(), app->name()); |
| } |
| #endif // OS_CHROMEOS |
| |
| INSTANTIATE_TEST_SUITE_P( |
| /* no prefix */, |
| BookmarkAppNavigationThrottleCommonBrowserTest, |
| testing::Bool()); |
| |
| // Set of tests to make sure form submissions have the correct behavior |
| // regardless of the kDesktopPWAsLinkCapturing feature flag. |
| class BookmarkAppNavigationThrottleCommonFormSubmissionBrowserTest |
| : public BookmarkAppNavigationThrottleBaseCommonBrowserTest, |
| public ::testing::WithParamInterface< |
| std::tuple<bool, |
| StartIn, |
| std::string, |
| net::URLFetcher::RequestType, |
| std::string>> { |
| public: |
| void SetUp() override { |
| EnableFeaturesForTest(std::get<0>(GetParam())); |
| BookmarkAppNavigationThrottleBaseCommonBrowserTest::SetUp(); |
| } |
| }; |
| |
| IN_PROC_BROWSER_TEST_P( |
| BookmarkAppNavigationThrottleCommonFormSubmissionBrowserTest, |
| FormSubmission) { |
| bool should_enable_link_capturing; |
| StartIn start_in; |
| std::string start_url_path; |
| net::URLFetcher::RequestType request_type; |
| std::string target_url_path; |
| std::tie(should_enable_link_capturing, start_in, start_url_path, request_type, |
| target_url_path) = GetParam(); |
| |
| InstallTestBookmarkApp(); |
| |
| // Pick where the test should start. |
| Browser* current_browser; |
| if (start_in == StartIn::APP) |
| current_browser = OpenTestBookmarkApp(); |
| else |
| current_browser = browser(); |
| |
| // If in a regular browser window, navigate to the start URL. |
| if (start_in == StartIn::BROWSER) { |
| GURL start_url; |
| if (start_url_path == GetLaunchingPagePath()) |
| start_url = GetLaunchingPageURL(); |
| else |
| start_url = https_server().GetURL(GetAppUrlHost(), GetAppUrlPath()); |
| |
| NavigateParams params(current_browser, start_url, |
| ui::PAGE_TRANSITION_TYPED); |
| ASSERT_TRUE(TestTabActionDoesNotOpenAppWindow( |
| start_url, base::BindOnce(&NavigateToURLWrapper, ¶ms))); |
| } else if (start_url_path == GetLaunchingPagePath()) { |
| // Return early here since the app window can't start with an out-of-scope |
| // URL. |
| return; |
| } |
| |
| // If the submit method is GET then add an query params. |
| GURL target_url = https_server().GetURL(GetAppUrlHost(), target_url_path); |
| if (request_type == net::URLFetcher::RequestType::GET) { |
| target_url = AddTestQueryParam(target_url); |
| } |
| |
| base::HistogramTester scoped_histogram; |
| |
| // All form submissions that start in the browser should be kept in the |
| // browser. |
| if (start_in == StartIn::BROWSER) { |
| TestActionDoesNotOpenAppWindow( |
| current_browser, target_url, |
| base::BindOnce( |
| &SubmitFormAndWait, |
| current_browser->tab_strip_model()->GetActiveWebContents(), |
| target_url, request_type)); |
| |
| // Navigations to out-of-scope URLs are considered regular navigations and |
| // therefore not recorded. Nothing gets histogrammed when |
| // kDesktopPWAsLinkCapturing is disabled, because the navigation is not |
| // happening in an app window. |
| if (target_url_path == GetInScopeUrlPath() && |
| should_enable_link_capturing) { |
| ExpectNavigationResultHistogramEquals( |
| scoped_histogram, {{BookmarkAppNavigationThrottleResult:: |
| kProceedInBrowserFormSubmission, |
| 1}}); |
| } |
| return; |
| } |
| |
| // When in an app, in-scope navigations should always be kept in the app |
| // window. |
| if (target_url_path == GetInScopeUrlPath()) { |
| TestActionDoesNotOpenAppWindow( |
| current_browser, target_url, |
| base::BindOnce( |
| &SubmitFormAndWait, |
| current_browser->tab_strip_model()->GetActiveWebContents(), |
| target_url, request_type)); |
| |
| ExpectNavigationResultHistogramEquals( |
| scoped_histogram, |
| {{BookmarkAppNavigationThrottleResult::kProceedInAppSameScope, 1}}); |
| return; |
| } |
| |
| // When in an app, out-of-scope navigations should always open a new |
| // foreground tab. |
| DCHECK_EQ(target_url_path, GetOutOfScopeUrlPath()); |
| TestAppActionOpensForegroundTab( |
| current_browser, target_url, |
| base::BindOnce(&SubmitFormAndWait, |
| current_browser->tab_strip_model()->GetActiveWebContents(), |
| target_url, request_type)); |
| |
| ExpectNavigationResultHistogramEquals( |
| scoped_histogram, |
| {{BookmarkAppNavigationThrottleResult::kDeferOpenNewTabInAppOutOfScope, |
| 1}}); |
| } |
| |
| INSTANTIATE_TEST_SUITE_P( |
| /* no prefix */, |
| BookmarkAppNavigationThrottleCommonFormSubmissionBrowserTest, |
| testing::Combine( |
| testing::Bool(), |
| testing::Values(StartIn::BROWSER, StartIn::APP), |
| testing::Values( |
| BookmarkAppNavigationBrowserTest::GetLaunchingPagePath(), |
| BookmarkAppNavigationBrowserTest::GetAppUrlPath()), |
| testing::Values(net::URLFetcher::RequestType::GET, |
| net::URLFetcher::RequestType::POST), |
| testing::Values( |
| BookmarkAppNavigationBrowserTest::GetOutOfScopeUrlPath(), |
| BookmarkAppNavigationBrowserTest::GetInScopeUrlPath()))); |
| |
| // Tests that the result is the same regardless of the 'rel' attribute of links |
| // and of the kDesktopPWAsLinkCapturing feature flag. |
| class BookmarkAppNavigationThrottleCommonLinkBrowserTest |
| : public BookmarkAppNavigationThrottleBaseCommonBrowserTest, |
| public ::testing::WithParamInterface<std::tuple<bool, std::string>> { |
| public: |
| void SetUp() override { |
| EnableFeaturesForTest(std::get<0>(GetParam())); |
| BookmarkAppNavigationThrottleBaseCommonBrowserTest::SetUp(); |
| } |
| }; |
| |
| // Tests that clicking links inside the app to in-scope URLs doesn't open new |
| // browser windows. |
| IN_PROC_BROWSER_TEST_P(BookmarkAppNavigationThrottleCommonLinkBrowserTest, |
| InAppInScopeNavigation) { |
| InstallTestBookmarkApp(); |
| Browser* app_browser = OpenTestBookmarkApp(); |
| content::WebContents* app_web_contents = |
| app_browser->tab_strip_model()->GetActiveWebContents(); |
| |
| int num_tabs_browser = browser()->tab_strip_model()->count(); |
| int num_tabs_app_browser = app_browser->tab_strip_model()->count(); |
| size_t num_browsers = chrome::GetBrowserCount(profile()); |
| |
| base::HistogramTester scoped_histogram; |
| const GURL in_scope_url = |
| https_server().GetURL(GetAppUrlHost(), GetInScopeUrlPath()); |
| ClickLinkAndWait(app_web_contents, in_scope_url, LinkTarget::SELF, |
| std::get<1>(GetParam())); |
| |
| EXPECT_EQ(num_tabs_browser, browser()->tab_strip_model()->count()); |
| EXPECT_EQ(num_tabs_app_browser, app_browser->tab_strip_model()->count()); |
| EXPECT_EQ(num_browsers, chrome::GetBrowserCount(profile())); |
| EXPECT_EQ(app_browser, chrome::FindLastActive()); |
| |
| EXPECT_EQ(in_scope_url, app_web_contents->GetLastCommittedURL()); |
| |
| ExpectNavigationResultHistogramEquals( |
| scoped_histogram, |
| {{BookmarkAppNavigationThrottleResult::kProceedInAppSameScope, 1}}); |
| } |
| |
| // Tests that clicking links inside the app to out-of-scope URLs opens a new |
| // tab in an existing browser window, instead of navigating the existing |
| // app window. |
| IN_PROC_BROWSER_TEST_P(BookmarkAppNavigationThrottleCommonLinkBrowserTest, |
| InAppOutOfScopeNavigation) { |
| InstallTestBookmarkApp(); |
| Browser* app_browser = OpenTestBookmarkApp(); |
| |
| const base::HistogramTester scoped_histogram; |
| const GURL out_of_scope_url = |
| https_server().GetURL(GetAppUrlHost(), GetOutOfScopeUrlPath()); |
| TestAppActionOpensForegroundTab( |
| app_browser, out_of_scope_url, |
| base::BindOnce(&ClickLinkAndWait, |
| app_browser->tab_strip_model()->GetActiveWebContents(), |
| out_of_scope_url, LinkTarget::SELF, |
| std::get<1>(GetParam()))); |
| |
| ExpectNavigationResultHistogramEquals( |
| scoped_histogram, |
| {{BookmarkAppNavigationThrottleResult::kDeferOpenNewTabInAppOutOfScope, |
| 1}}); |
| } |
| |
| INSTANTIATE_TEST_SUITE_P( |
| /* no prefix */, |
| BookmarkAppNavigationThrottleCommonLinkBrowserTest, |
| testing::Combine( |
| testing::Bool(), |
| testing::Values("", "noopener", "noreferrer", "nofollow"))); |
| |
| } // namespace test |
| } // namespace extensions |