| // Copyright 2018 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include <string> |
| |
| #include "base/functional/bind.h" |
| #include "base/run_loop.h" |
| #include "base/test/scoped_feature_list.h" |
| #include "base/test/test_future.h" |
| #include "build/build_config.h" |
| #include "chrome/browser/apps/link_capturing/link_capturing_feature_test_support.h" |
| #include "chrome/browser/apps/link_capturing/link_capturing_features.h" |
| #include "chrome/browser/ui/browser.h" |
| #include "chrome/browser/ui/browser_commands.h" |
| #include "chrome/browser/ui/intent_picker_tab_helper.h" |
| #include "chrome/browser/ui/tabs/tab_strip_model.h" |
| #include "chrome/browser/ui/views/frame/browser_view.h" |
| #include "chrome/browser/ui/views/frame/toolbar_button_provider.h" |
| #include "chrome/browser/ui/views/intent_picker_bubble_view.h" |
| #include "chrome/browser/ui/views/location_bar/intent_chip_button.h" |
| #include "chrome/browser/ui/views/page_action/page_action_icon_view.h" |
| #include "chrome/browser/ui/views/web_apps/web_app_link_capturing_test_utils.h" |
| #include "chrome/browser/ui/web_applications/app_browser_controller.h" |
| #include "chrome/browser/ui/web_applications/test/web_app_navigation_browsertest.h" |
| #include "chrome/browser/web_applications/test/web_app_install_test_utils.h" |
| #include "chrome/test/base/ui_test_utils.h" |
| #include "content/public/test/browser_test.h" |
| #include "content/public/test/browser_test_utils.h" |
| #include "content/public/test/fenced_frame_test_util.h" |
| #include "content/public/test/prerender_test_util.h" |
| #include "net/dns/mock_host_resolver.h" |
| #include "net/test/embedded_test_server/embedded_test_server.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "third_party/blink/public/common/features.h" |
| #include "ui/views/test/button_test_api.h" |
| #include "ui/views/widget/any_widget_observer.h" |
| #include "url/gurl.h" |
| |
| #if BUILDFLAG(IS_CHROMEOS) |
| #include "chrome/browser/apps/app_service/app_service_proxy.h" |
| #include "chrome/browser/apps/app_service/app_service_proxy_factory.h" |
| #include "chrome/browser/apps/intent_helper/preferred_apps_test_util.h" |
| #include "components/services/app_service/public/cpp/preferred_apps_list_handle.h" |
| #include "ui/views/controls/button/checkbox.h" |
| #include "ui/views/view_utils.h" |
| #endif |
| |
| class IntentPickerBrowserTest : public web_app::WebAppNavigationBrowserTest { |
| public: |
| IntentPickerBrowserTest() = default; |
| |
| template <typename Action> |
| testing::AssertionResult DoAndWaitForIntentPickerIconUpdate(Action action) { |
| base::test::TestFuture<void> intent_picker_done; |
| auto* tab_helper = IntentPickerTabHelper::FromWebContents(GetWebContents()); |
| tab_helper->SetIconUpdateCallbackForTesting( |
| intent_picker_done.GetCallback()); |
| action(); |
| if (HasFailure()) { |
| return testing::AssertionFailure(); |
| } |
| if (intent_picker_done.Wait()) { |
| return testing::AssertionSuccess(); |
| } |
| return testing::AssertionFailure() << "Intent picker never resolved"; |
| } |
| |
| content::WebContents* OpenNewTab(const GURL& url, |
| const std::string& rel = "") { |
| chrome::NewTab(browser()); |
| content::WebContents* web_contents = |
| browser()->tab_strip_model()->GetActiveWebContents(); |
| |
| EXPECT_TRUE(DoAndWaitForIntentPickerIconUpdate( |
| [this] { NavigateToLaunchingPage(browser()); })); |
| EXPECT_TRUE(DoAndWaitForIntentPickerIconUpdate([this, url] { |
| ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url)); |
| })); |
| |
| return web_contents; |
| } |
| |
| // Inserts an iframe in the main frame of |web_contents|. |
| bool InsertIFrame(content::WebContents* web_contents) { |
| return content::ExecJs(web_contents, |
| "let iframe = document.createElement('iframe');" |
| "iframe.id = 'iframe';" |
| "document.body.appendChild(iframe);"); |
| } |
| |
| views::Button* GetIntentPickerIcon() { |
| if (apps::features::ShouldShowLinkCapturingUX()) { |
| return BrowserView::GetBrowserViewForBrowser(browser()) |
| ->toolbar_button_provider() |
| ->GetIntentChipButton(); |
| } |
| return BrowserView::GetBrowserViewForBrowser(browser()) |
| ->toolbar_button_provider() |
| ->GetPageActionIconView(PageActionIconType::kIntentPicker); |
| } |
| |
| content::WebContents* GetWebContents() { |
| return browser()->tab_strip_model()->GetActiveWebContents(); |
| } |
| |
| IntentPickerBubbleView* intent_picker_bubble() { |
| return IntentPickerBubbleView::intent_picker_bubble(); |
| } |
| }; |
| |
| // Tests to do with the behavior of the intent picker icon in the omnibox. Does |
| // not test the behavior of the intent picker bubble itself. |
| // Note that behavior specific to the chip version of the icon is tested |
| // separately in intent_chip_button_browsertest.cc. |
| class IntentPickerIconBrowserTest |
| : public IntentPickerBrowserTest, |
| public ::testing::WithParamInterface<std::tuple<std::string, bool>> { |
| public: |
| // TODO(crbug.com/1001189): Stop disabling Paint Holding. |
| IntentPickerIconBrowserTest() { |
| feature_list_.InitWithFeaturesAndParameters( |
| apps::test::GetFeaturesToEnableLinkCapturingUX( |
| /*override_captures_by_default=*/IsLinkCapturingEnabled()), |
| {blink::features::kPaintHolding}); |
| } |
| |
| bool IsLinkCapturingEnabled() { return std::get<bool>(GetParam()); } |
| |
| std::string rel() { return std::get<std::string>(GetParam()); } |
| |
| bool IsDefaultOnEnabled() { |
| #if BUILDFLAG(IS_CHROMEOS) |
| return false; |
| #else |
| return IsLinkCapturingEnabled(); |
| #endif // BUILDFLAG(IS_CHROMEOS) |
| } |
| |
| private: |
| base::test::ScopedFeatureList feature_list_; |
| }; |
| |
| // Tests that clicking a link from a tabbed browser to outside the scope of an |
| // installed app does not show the intent picker. |
| IN_PROC_BROWSER_TEST_P(IntentPickerIconBrowserTest, |
| NavigationToOutOfScopeLinkDoesNotShowIntentPicker) { |
| InstallTestWebApp(); |
| |
| const GURL out_of_scope_url = |
| https_server().GetURL(GetAppUrlHost(), GetOutOfScopeUrlPath()); |
| NavigateToLaunchingPage(browser()); |
| ASSERT_TRUE(ExpectLinkClickNotCapturedIntoAppBrowser( |
| browser(), out_of_scope_url, rel())); |
| |
| views::Button* intent_picker_view = GetIntentPickerIcon(); |
| EXPECT_FALSE(intent_picker_view->GetVisible()); |
| |
| EXPECT_EQ(nullptr, intent_picker_bubble()); |
| } |
| |
| // Tests that clicking a link from a tabbed browser to within the scope of an |
| // installed app shows the intent picker icon in Omnibox. |
| // TODO(crbug.com/1515480): Flaky on Mac. |
| #if BUILDFLAG(IS_MAC) |
| #define MAYBE_NavigationToInScopeLinkShowsIntentPicker \ |
| DISABLED_NavigationToInScopeLinkShowsIntentPicker |
| #else |
| #define MAYBE_NavigationToInScopeLinkShowsIntentPicker \ |
| NavigationToInScopeLinkShowsIntentPicker |
| #endif |
| IN_PROC_BROWSER_TEST_P(IntentPickerIconBrowserTest, |
| MAYBE_NavigationToInScopeLinkShowsIntentPicker) { |
| if (IsDefaultOnEnabled()) { |
| GTEST_SKIP() << "Default On will launch app by default"; |
| } |
| InstallTestWebApp(); |
| |
| const GURL in_scope_url = |
| https_server().GetURL(GetAppUrlHost(), GetInScopeUrlPath()); |
| auto* tab_helper = IntentPickerTabHelper::FromWebContents(GetWebContents()); |
| NavigateToLaunchingPage(browser()); |
| |
| base::RunLoop run_loop; |
| tab_helper->SetIconUpdateCallbackForTesting(run_loop.QuitClosure()); |
| ASSERT_TRUE( |
| ExpectLinkClickNotCapturedIntoAppBrowser(browser(), in_scope_url, rel())); |
| run_loop.Run(); |
| |
| views::Button* intent_picker_icon = GetIntentPickerIcon(); |
| EXPECT_TRUE(intent_picker_icon->GetVisible()); |
| } |
| |
| // TODO(crbug.com/1515480): This test is flaky on Mac. |
| #if BUILDFLAG(IS_MAC) |
| #define MAYBE_IconVisibilityAfterTabSwitching \ |
| DISABLED_IconVisibilityAfterTabSwitching |
| #else |
| #define MAYBE_IconVisibilityAfterTabSwitching IconVisibilityAfterTabSwitching |
| #endif |
| // Tests that the intent icon updates its visibility when switching between |
| // tabs. |
| IN_PROC_BROWSER_TEST_P(IntentPickerIconBrowserTest, |
| MAYBE_IconVisibilityAfterTabSwitching) { |
| InstallTestWebApp(); |
| |
| const GURL in_scope_url = |
| https_server().GetURL(GetAppUrlHost(), GetInScopeUrlPath()); |
| const GURL out_of_scope_url = |
| https_server().GetURL(GetAppUrlHost(), GetOutOfScopeUrlPath()); |
| |
| views::Button* intent_picker_icon = GetIntentPickerIcon(); |
| |
| // OpenNewTab opens a new tab and focus on the new tab. |
| OpenNewTab(in_scope_url, /*rel=*/rel()); |
| EXPECT_TRUE(intent_picker_icon->GetVisible()); |
| OpenNewTab(out_of_scope_url, /*rel=*/rel()); |
| EXPECT_FALSE(intent_picker_icon->GetVisible()); |
| |
| chrome::SelectPreviousTab(browser()); |
| EXPECT_TRUE(intent_picker_icon->GetVisible()); |
| chrome::SelectNextTab(browser()); |
| EXPECT_FALSE(intent_picker_icon->GetVisible()); |
| } |
| |
| // Tests that the navigation in iframe doesn't affect intent picker icon |
| IN_PROC_BROWSER_TEST_P(IntentPickerIconBrowserTest, |
| IframeNavigationDoesNotAffectIntentPicker) { |
| InstallTestWebApp(); |
| |
| const GURL in_scope_url = |
| https_server().GetURL(GetAppUrlHost(), GetInScopeUrlPath()); |
| const GURL out_of_scope_url = |
| https_server().GetURL(GetAppUrlHost(), GetOutOfScopeUrlPath()); |
| |
| views::Button* intent_picker_icon = GetIntentPickerIcon(); |
| |
| content::WebContents* initial_tab = OpenNewTab(out_of_scope_url); |
| ASSERT_TRUE(InsertIFrame(initial_tab)); |
| |
| EXPECT_TRUE( |
| content::NavigateIframeToURL(initial_tab, "iframe", in_scope_url)); |
| EXPECT_FALSE(intent_picker_icon->GetVisible()); |
| |
| content::WebContents* new_tab = OpenNewTab(in_scope_url); |
| ASSERT_TRUE(InsertIFrame(new_tab)); |
| |
| EXPECT_TRUE( |
| content::NavigateIframeToURL(initial_tab, "iframe", out_of_scope_url)); |
| EXPECT_TRUE(intent_picker_icon->GetVisible()); |
| } |
| |
| // Tests that the intent picker icon is not visible if the navigation redirects |
| // to a URL that doesn't have an installed PWA. |
| // TODO(crbug.com/1515480): This test is flaky. Re-enable this test. |
| #if BUILDFLAG(IS_MAC) |
| #define MAYBE_DoesNotShowIntentPickerWhenRedirectedOutOfScope \ |
| DISABLED_DoesNotShowIntentPickerWhenRedirectedOutOfScope |
| #else |
| #define MAYBE_DoesNotShowIntentPickerWhenRedirectedOutOfScope \ |
| DoesNotShowIntentPickerWhenRedirectedOutOfScope |
| #endif |
| IN_PROC_BROWSER_TEST_P(IntentPickerIconBrowserTest, |
| MAYBE_DoesNotShowIntentPickerWhenRedirectedOutOfScope) { |
| InstallTestWebApp(GetOtherAppUrlHost(), /*app_scope=*/"/"); |
| |
| const GURL out_of_scope_url = |
| https_server().GetURL(GetAppUrlHost(), GetOutOfScopeUrlPath()); |
| const GURL in_scope_url = https_server().GetURL(GetOtherAppUrlHost(), "/"); |
| const GURL redirect_url = https_server().GetURL( |
| GetOtherAppUrlHost(), CreateServerRedirect(out_of_scope_url)); |
| |
| views::Button* intent_picker_icon = GetIntentPickerIcon(); |
| |
| OpenNewTab(in_scope_url); |
| EXPECT_TRUE(intent_picker_icon->GetVisible()); |
| ASSERT_TRUE(DoAndWaitForIntentPickerIconUpdate( |
| [this, redirect_url, out_of_scope_url] { |
| ClickLinkAndWaitForURL(GetWebContents(), redirect_url, out_of_scope_url, |
| LinkTarget::SELF, rel()); |
| })); |
| EXPECT_FALSE(intent_picker_icon->GetVisible()); |
| } |
| |
| // Test that navigating to service pages (chrome://) will hide the intent picker |
| // icon. |
| // TODO(crbug.com/1515480): Re-enable this test |
| #if BUILDFLAG(IS_MAC) |
| #define MAYBE_DoNotShowIconAndBubbleOnServicePages \ |
| DISABLED_DoNotShowIconAndBubbleOnServicePages |
| #else |
| #define MAYBE_DoNotShowIconAndBubbleOnServicePages \ |
| DoNotShowIconAndBubbleOnServicePages |
| #endif |
| IN_PROC_BROWSER_TEST_P(IntentPickerIconBrowserTest, |
| MAYBE_DoNotShowIconAndBubbleOnServicePages) { |
| InstallTestWebApp(); |
| |
| const GURL in_scope_url = |
| https_server().GetURL(GetAppUrlHost(), GetInScopeUrlPath()); |
| GURL chrome_pages_url("chrome://version"); |
| std::string app_name = "test_name"; |
| |
| views::Button* intent_picker_view = GetIntentPickerIcon(); |
| |
| OpenNewTab(in_scope_url); |
| ASSERT_TRUE(intent_picker_view); |
| EXPECT_TRUE(intent_picker_view->GetVisible()); |
| |
| // Now switch to chrome://version. |
| ASSERT_TRUE(DoAndWaitForIntentPickerIconUpdate([this, &chrome_pages_url]() { |
| NavigateParams params(browser(), chrome_pages_url, |
| ui::PageTransition::PAGE_TRANSITION_TYPED); |
| // Navigates and waits for loading to finish. |
| ui_test_utils::NavigateToURL(¶ms); |
| })); |
| |
| // Make sure that the intent picker icon is no longer visible. |
| EXPECT_FALSE(intent_picker_view->GetVisible()); |
| } |
| |
| // Test that error pages do not show the intent picker icon. |
| // TODO(https://crbug.com/1515480): Fix the test. |
| #if BUILDFLAG(IS_MAC) |
| #define MAYBE_DoNotShowIconOnErrorPages DISABLED_DoNotShowIconOnErrorPages |
| #else |
| #define MAYBE_DoNotShowIconOnErrorPages DoNotShowIconOnErrorPages |
| #endif // BUILDFLAG(IS_MAC) |
| IN_PROC_BROWSER_TEST_P(IntentPickerIconBrowserTest, |
| MAYBE_DoNotShowIconOnErrorPages) { |
| InstallTestWebApp(); |
| InstallTestWebApp("www.google.com", "/"); |
| |
| const GURL in_scope_url = |
| https_server().GetURL(GetAppUrlHost(), GetInScopeUrlPath()); |
| |
| views::Button* intent_picker_view = GetIntentPickerIcon(); |
| ASSERT_TRUE(intent_picker_view); |
| |
| // Go to the test app and wait for the intent picker icon to load. |
| OpenNewTab(in_scope_url); |
| EXPECT_TRUE(intent_picker_view->GetVisible()); |
| |
| // Now switch to www.google.com, which gives a network error in the test |
| // environment. |
| ASSERT_TRUE(DoAndWaitForIntentPickerIconUpdate([this]() { |
| NavigateParams params(browser(), GURL("https://www.google.com"), |
| ui::PageTransition::PAGE_TRANSITION_TYPED); |
| // Navigates and waits for loading to finish. |
| ui_test_utils::NavigateToURL(¶ms); |
| })); |
| |
| // Make sure that the intent picker icon is not shown on the error page, even |
| // though there's a PWA available for www.google.com. |
| EXPECT_FALSE(intent_picker_view->GetVisible()); |
| } |
| |
| // Test that loading a page with pushState() call that changes URL updates the |
| // intent picker view. |
| // TODO(crbug.com/1515480): Re-enable this test |
| #if BUILDFLAG(IS_MAC) |
| #define MAYBE_PushStateURLChangeTest DISABLED_PushStateURLChangeTest |
| #else |
| #define MAYBE_PushStateURLChangeTest PushStateURLChangeTest |
| #endif |
| IN_PROC_BROWSER_TEST_P(IntentPickerIconBrowserTest, |
| MAYBE_PushStateURLChangeTest) { |
| // Note: The test page is served from embedded_test_server() as https_server() |
| // always returns empty responses. |
| ASSERT_TRUE(embedded_test_server()->Start()); |
| ASSERT_TRUE(https_server().Start()); |
| |
| const GURL test_url = |
| embedded_test_server()->GetURL("/intent_picker/push_state_test.html"); |
| web_app::test::InstallDummyWebApp(profile(), "Test app", test_url); |
| |
| views::Button* intent_picker_view = GetIntentPickerIcon(); |
| |
| OpenNewTab(test_url); |
| EXPECT_TRUE(intent_picker_view->GetVisible()); |
| |
| content::WebContents* web_contents = |
| browser()->tab_strip_model()->GetActiveWebContents(); |
| ASSERT_TRUE(DoAndWaitForIntentPickerIconUpdate([web_contents] { |
| ASSERT_TRUE(content::ExecJs( |
| web_contents, |
| "document.getElementById('push_to_new_url_button').click();")); |
| })); |
| |
| EXPECT_FALSE(intent_picker_view->GetVisible()); |
| } |
| |
| INSTANTIATE_TEST_SUITE_P( |
| All, |
| IntentPickerIconBrowserTest, |
| testing::Combine(testing::Values("", "noopener", "noreferrer", "nofollow"), |
| #if BUILDFLAG(IS_CHROMEOS) |
| testing::Values(false)), |
| #else |
| testing::Values(true, false)), |
| #endif // BUILDFLAG(IS_CHROMEOS) |
| [](const testing::TestParamInfo<std::tuple<std::string, bool>>& info) { |
| std::string test_name; |
| test_name = std::get<std::string>(info.param); |
| test_name.append(std::get<bool>(info.param) ? "DefaultOn" : "DefaultOff"); |
| return test_name; |
| }); |
| |
| class IntentPickerIconBrowserBubbleTest |
| : public IntentPickerBrowserTest, |
| public testing::WithParamInterface<bool> { |
| public: |
| // TODO(crbug.com/1001189): Stop disabling Paint Holding. |
| IntentPickerIconBrowserBubbleTest() { |
| feature_list_.InitWithFeaturesAndParameters( |
| apps::test::GetFeaturesToEnableLinkCapturingUX( |
| /*override_captures_by_default=*/GetParam()), |
| {blink::features::kPaintHolding}); |
| } |
| bool LinkCapturingEnabledByDefault() const { return GetParam(); } |
| |
| size_t GetItemContainerSize(IntentPickerBubbleView* bubble) { |
| return bubble->GetViewByID(IntentPickerBubbleView::ViewId::kItemContainer) |
| ->children() |
| .size(); |
| } |
| |
| private: |
| base::test::ScopedFeatureList feature_list_; |
| }; |
| |
| #if BUILDFLAG(IS_CHROMEOS) |
| IN_PROC_BROWSER_TEST_P(IntentPickerIconBrowserBubbleTest, |
| IntentChipOpensBubble) { |
| InstallTestWebApp(); |
| const GURL in_scope_url = |
| https_server().GetURL(GetAppUrlHost(), GetInScopeUrlPath()); |
| |
| views::Button* intent_picker_icon = GetIntentPickerIcon(); |
| |
| OpenNewTab(in_scope_url); |
| EXPECT_TRUE(intent_picker_icon->GetVisible()); |
| |
| ASSERT_TRUE(web_app::ClickIntentPickerAndWaitForBubble(browser())); |
| |
| EXPECT_EQ(1U, GetItemContainerSize(intent_picker_bubble())); |
| auto& app_info = intent_picker_bubble()->app_info_for_testing(); |
| ASSERT_EQ(1U, app_info.size()); |
| EXPECT_EQ(test_web_app_id(), app_info[0].launch_name); |
| EXPECT_EQ(GetAppName(), app_info[0].display_name); |
| } |
| |
| // Test that the "Remember this choice" checkbox works. |
| IN_PROC_BROWSER_TEST_P(IntentPickerIconBrowserBubbleTest, RememberOpenWebApp) { |
| base::HistogramTester histogram_tester; |
| |
| InstallTestWebApp(); |
| const GURL in_scope_url = |
| https_server().GetURL(GetAppUrlHost(), GetInScopeUrlPath()); |
| |
| OpenNewTab(in_scope_url); |
| ASSERT_TRUE(web_app::ClickIntentPickerAndWaitForBubble(browser())); |
| |
| // Check "Remember my choice" and accept the bubble. |
| views::Checkbox* remember_selection_checkbox = |
| views::AsViewClass<views::Checkbox>(intent_picker_bubble()->GetViewByID( |
| IntentPickerBubbleView::ViewId::kRememberCheckbox)); |
| ASSERT_TRUE(remember_selection_checkbox); |
| ASSERT_TRUE(remember_selection_checkbox->GetEnabled()); |
| remember_selection_checkbox->SetChecked(true); |
| |
| apps::PreferredAppsListHandle& preferred_apps = |
| apps::AppServiceProxyFactory::GetForProfile(profile()) |
| ->PreferredAppsList(); |
| apps_util::PreferredAppUpdateWaiter preference_update_waiter( |
| preferred_apps, test_web_app_id()); |
| |
| ui_test_utils::BrowserChangeObserver added_observer( |
| nullptr, ui_test_utils::BrowserChangeObserver::ChangeType::kAdded); |
| intent_picker_bubble()->AcceptDialog(); |
| |
| // Accepting the bubble should open the app. |
| Browser* app_browser = added_observer.Wait(); |
| ASSERT_TRUE(web_app::AppBrowserController::IsForWebApp(app_browser, |
| test_web_app_id())); |
| |
| // The link capturing preference should be updated. |
| preference_update_waiter.Wait(); |
| ASSERT_TRUE( |
| preferred_apps.IsPreferredAppForSupportedLinks(test_web_app_id())); |
| |
| // Check that we recorded that settings were changed. |
| histogram_tester.ExpectBucketCount( |
| "ChromeOS.Intents.LinkCapturingEvent2.WebApp", |
| apps::IntentHandlingMetrics::LinkCapturingEvent::kSettingsChanged, 1); |
| histogram_tester.ExpectBucketCount( |
| "ChromeOS.Intents.LinkCapturingEvent2.ArcApp", |
| apps::IntentHandlingMetrics::LinkCapturingEvent::kSettingsChanged, 0); |
| histogram_tester.ExpectBucketCount( |
| "ChromeOS.Intents.LinkCapturingEvent2", |
| apps::IntentHandlingMetrics::LinkCapturingEvent::kSettingsChanged, 1); |
| } |
| |
| #else |
| IN_PROC_BROWSER_TEST_P(IntentPickerIconBrowserBubbleTest, |
| DISABLED_IntentChipLaunchesAppDirectly) { |
| InstallTestWebApp(); |
| const GURL in_scope_url = |
| https_server().GetURL(GetAppUrlHost(), GetInScopeUrlPath()); |
| |
| views::Button* intent_picker_icon = GetIntentPickerIcon(); |
| |
| OpenNewTab(in_scope_url); |
| EXPECT_TRUE(intent_picker_icon->GetVisible()); |
| |
| views::test::ButtonTestApi test_api(intent_picker_icon); |
| test_api.NotifyClick(ui::MouseEvent( |
| ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(), base::TimeTicks(), |
| ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON)); |
| Browser* app_browser = ui_test_utils::WaitForBrowserToOpen(); |
| EXPECT_FALSE(intent_picker_bubble()); |
| EXPECT_TRUE(app_browser); |
| ASSERT_TRUE(web_app::AppBrowserController::IsForWebApp(app_browser, |
| test_web_app_id())); |
| } |
| #endif // BUILDFLAG(IS_CHROMEOS) |
| |
| INSTANTIATE_TEST_SUITE_P(, |
| IntentPickerIconBrowserBubbleTest, |
| #if BUILDFLAG(IS_CHROMEOS) |
| testing::Values(false), |
| #else |
| testing::Values(true, false), |
| #endif |
| [](const testing::TestParamInfo<bool>& info) { |
| return info.param ? "DefaultOn" : "DefaultOff"; |
| }); |
| |
| // This test only works when link capturing is set to default off for desktop |
| // platforms, as prerendering navigations are aborted during link captured app |
| // launches. See LinkCapturingNavigationThrottle::MaybeCreate for more |
| // information. |
| // TODO(b/297256243): Investigate prerendering integration with link capturing. |
| class IntentPickerIconPrerenderingBrowserTest |
| : public IntentPickerIconBrowserTest { |
| public: |
| IntentPickerIconPrerenderingBrowserTest() |
| : prerender_helper_(base::BindRepeating( |
| &IntentPickerIconPrerenderingBrowserTest::GetWebContents, |
| base::Unretained(this))) {} |
| ~IntentPickerIconPrerenderingBrowserTest() override = default; |
| IntentPickerIconPrerenderingBrowserTest( |
| const IntentPickerIconPrerenderingBrowserTest&) = delete; |
| |
| IntentPickerIconPrerenderingBrowserTest& operator=( |
| const IntentPickerIconPrerenderingBrowserTest&) = delete; |
| |
| void SetUp() override { |
| prerender_helper_.RegisterServerRequestMonitor(embedded_test_server()); |
| IntentPickerIconBrowserTest::SetUp(); |
| } |
| |
| void SetUpOnMainThread() override { |
| host_resolver()->AddRule("*", "127.0.0.1"); |
| ASSERT_TRUE(embedded_test_server()->Start()); |
| IntentPickerIconBrowserTest::SetUpOnMainThread(); |
| } |
| |
| content::test::PrerenderTestHelper& prerender_test_helper() { |
| return prerender_helper_; |
| } |
| |
| private: |
| content::test::PrerenderTestHelper prerender_helper_; |
| }; |
| |
| IN_PROC_BROWSER_TEST_P(IntentPickerIconPrerenderingBrowserTest, |
| PrerenderingShouldNotShowIntentPicker) { |
| InstallTestWebApp(); |
| |
| const GURL initial_url = |
| https_server().GetURL(GetAppUrlHost(), "/empty.html"); |
| OpenNewTab(initial_url); |
| |
| views::Button* intent_picker_icon = GetIntentPickerIcon(); |
| EXPECT_FALSE(intent_picker_icon->GetVisible()); |
| |
| // Load a prerender page and prerendering should not try to show the |
| // intent picker. |
| const GURL prerender_url = https_server().GetURL( |
| GetAppUrlHost(), std::string(GetAppScopePath()) + "index1.html"); |
| int host_id = prerender_test_helper().AddPrerender(prerender_url); |
| content::test::PrerenderHostObserver host_observer(*GetWebContents(), |
| host_id); |
| EXPECT_FALSE(host_observer.was_activated()); |
| EXPECT_FALSE(intent_picker_icon->GetVisible()); |
| |
| // Activate the prerender page. |
| ASSERT_TRUE(DoAndWaitForIntentPickerIconUpdate([this, prerender_url] { |
| prerender_test_helper().NavigatePrimaryPage(prerender_url); |
| })); |
| EXPECT_TRUE(host_observer.was_activated()); |
| |
| // After activation, IntentPickerTabHelper should show the |
| // intent picker. |
| EXPECT_TRUE(intent_picker_icon->GetVisible()); |
| } |
| |
| INSTANTIATE_TEST_SUITE_P( |
| All, |
| IntentPickerIconPrerenderingBrowserTest, |
| testing::Combine(testing::Values("", "noopener", "noreferrer", "nofollow"), |
| testing::Values(false)), |
| [](const testing::TestParamInfo<std::tuple<std::string, bool>>& info) { |
| std::string test_name; |
| test_name = std::get<std::string>(info.param); |
| test_name.append("DefaultOff"); |
| return test_name; |
| }); |
| |
| class IntentPickerIconFencedFrameBrowserTest |
| : public IntentPickerIconBrowserTest { |
| public: |
| IntentPickerIconFencedFrameBrowserTest() = default; |
| ~IntentPickerIconFencedFrameBrowserTest() override = default; |
| IntentPickerIconFencedFrameBrowserTest( |
| const IntentPickerIconFencedFrameBrowserTest&) = delete; |
| |
| IntentPickerIconFencedFrameBrowserTest& operator=( |
| const IntentPickerIconFencedFrameBrowserTest&) = delete; |
| |
| content::test::FencedFrameTestHelper& fenced_frame_test_helper() { |
| return fenced_frame_helper_; |
| } |
| |
| private: |
| content::test::FencedFrameTestHelper fenced_frame_helper_; |
| }; |
| |
| IN_PROC_BROWSER_TEST_P(IntentPickerIconFencedFrameBrowserTest, |
| ShouldShowIntentPickerInFencedFrame) { |
| InstallTestWebApp(); |
| |
| views::Button* intent_picker_icon = GetIntentPickerIcon(); |
| |
| const GURL initial_url = |
| https_server().GetURL(GetAppUrlHost(), "/empty.html"); |
| OpenNewTab(initial_url); |
| EXPECT_FALSE(intent_picker_icon->GetVisible()); |
| |
| const GURL fenced_frame_url = https_server().GetURL( |
| GetAppUrlHost(), std::string(GetAppScopePath()) + "index1.html"); |
| // Create a fenced frame. |
| ASSERT_TRUE(fenced_frame_test_helper().CreateFencedFrame( |
| GetWebContents()->GetPrimaryMainFrame(), fenced_frame_url)); |
| |
| EXPECT_FALSE(intent_picker_icon->GetVisible()); |
| } |
| |
| INSTANTIATE_TEST_SUITE_P( |
| All, |
| IntentPickerIconFencedFrameBrowserTest, |
| testing::Combine(testing::Values("", "noopener", "noreferrer", "nofollow"), |
| #if BUILDFLAG(IS_CHROMEOS) |
| testing::Values(false)), |
| #else |
| testing::Values(true, false)), |
| #endif |
| [](const testing::TestParamInfo<std::tuple<std::string, bool>>& info) { |
| std::string test_name; |
| test_name = std::get<std::string>(info.param); |
| test_name.append(std::get<bool>(info.param) ? "DefaultOn" : "DefaultOff"); |
| return test_name; |
| }); |