blob: 23bcb296d4ab9a78886202c22770a894554c70b8 [file] [log] [blame]
// 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 "chrome/browser/ui/views/intent_picker_bubble_view.h"
#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/ui/actions/chrome_action_id.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/ui_features.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/location_bar/intent_chip_button.h"
#include "chrome/browser/ui/views/location_bar/intent_chip_button_test_base.h"
#include "chrome/browser/ui/views/page_action/page_action_icon_view.h"
#include "chrome/browser/ui/views/page_action/page_action_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/link_capturing_features.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
using LinkCapturingFeatureVersion = apps::test::LinkCapturingFeatureVersion;
namespace {
std::string GetLinkCapturingTestName(
const testing::TestParamInfo<
std::tuple<std::string, LinkCapturingFeatureVersion, bool>>& info) {
std::string test_name;
test_name = std::get<std::string>(info.param);
test_name.append("_");
test_name.append(
apps::test::ToString(std::get<LinkCapturingFeatureVersion>(info.param)));
test_name.append(std::get<bool>(info.param) ? "MigrationEnabled"
: "MigrationNotEnabled");
return test_name;
}
} // namespace
class IntentPickerBrowserTest : public web_app::WebAppNavigationBrowserTest {
public:
IntentPickerBrowserTest() {
if (IsMigrationEnabled()) {
scoped_feature_list_.InitAndEnableFeatureWithParameters(
features::kPageActionsMigration,
{{features::kPageActionsMigrationIntentPicker.name, "true"}});
} else {
scoped_feature_list_.InitWithFeatures(
{}, {::features::kPageActionsMigration});
}
}
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());
// On Mac, updating the icon requires asynchronous work that is done on the
// threadpool (see `WebAppsIntentPickerDelegate::FindAllAppsForUrl()` for
// more information). Flushing the thread pool thus helps prevent flakiness
// in tests.
#if BUILDFLAG(IS_MAC)
base::ThreadPoolInstance::Get()->FlushForTesting();
#endif // BUILDFLAG(IS_MAC)
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);");
}
content::WebContents* GetWebContents() {
return browser()->tab_strip_model()->GetActiveWebContents();
}
IntentPickerBubbleView* intent_picker_bubble() {
return IntentPickerBubbleView::intent_picker_bubble();
}
// Returns a bool indicating whether the ongoing page action framework
// migration is enabled. This function provides a default implementation that
// can be overridden in tests to control the enabled state of the page action
// view.
virtual bool IsMigrationEnabled() const { return false; }
private:
base::test::ScopedFeatureList scoped_feature_list_;
};
// 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, LinkCapturingFeatureVersion, bool>>,
public IntentChipButtonTestBase {
public:
// TODO(crbug.com/40097608): Stop disabling Paint Holding.
IntentPickerIconBrowserTest() {
std::vector<base::test::FeatureRefAndParams> features_to_enable =
apps::test::GetFeaturesToEnableLinkCapturingUX(LinkCapturingVersion());
features_to_enable.push_back({blink::features::kPaintHolding, {}});
if (IsMigrationEnabled()) {
features_to_enable.push_back(
{::features::kPageActionsMigration,
{{::features::kPageActionsMigrationIntentPicker.name, "true"}}});
}
feature_list_.InitWithFeaturesAndParameters(features_to_enable, {});
}
bool IsMigrationEnabled() const override {
return std::get<bool>(GetParam());
}
LinkCapturingFeatureVersion LinkCapturingVersion() {
return std::get<LinkCapturingFeatureVersion>(GetParam());
}
std::string rel() { return std::get<std::string>(GetParam()); }
bool IsDefaultOnEnabled() {
#if BUILDFLAG(IS_CHROMEOS)
return false;
#else
return LinkCapturingVersion() == LinkCapturingFeatureVersion::kV2DefaultOn;
#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()));
EXPECT_FALSE(GetIntentChip(browser())->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.
IN_PROC_BROWSER_TEST_P(IntentPickerIconBrowserTest,
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();
EXPECT_TRUE(WaitForPageActionButtonVisible(browser()));
EXPECT_TRUE(GetIntentChip(browser())->GetVisible());
}
// Tests that the intent icon updates its visibility when switching between
// tabs.
IN_PROC_BROWSER_TEST_P(IntentPickerIconBrowserTest,
IconVisibilityAfterTabSwitching) {
InstallTestWebApp();
const GURL in_scope_url =
https_server().GetURL(GetAppUrlHost(), GetInScopeUrlPath());
const GURL out_of_scope_url =
https_server().GetURL(GetAppUrlHost(), GetOutOfScopeUrlPath());
// OpenNewTab opens a new tab and focus on the new tab.
OpenNewTab(in_scope_url, /*rel=*/rel());
EXPECT_TRUE(WaitForPageActionButtonVisible(browser()));
EXPECT_TRUE(GetIntentChip(browser())->GetVisible());
OpenNewTab(out_of_scope_url, /*rel=*/rel());
EXPECT_FALSE(GetIntentChip(browser())->GetVisible());
chrome::SelectPreviousTab(browser());
EXPECT_TRUE(WaitForPageActionButtonVisible(browser()));
EXPECT_TRUE(GetIntentChip(browser())->GetVisible());
chrome::SelectNextTab(browser());
EXPECT_FALSE(GetIntentChip(browser())->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 = GetIntentChip(browser());
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(WaitForPageActionButtonVisible(browser()));
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.
IN_PROC_BROWSER_TEST_P(IntentPickerIconBrowserTest,
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 = GetIntentChip(browser());
OpenNewTab(in_scope_url);
EXPECT_TRUE(WaitForPageActionButtonVisible(browser()));
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.
IN_PROC_BROWSER_TEST_P(IntentPickerIconBrowserTest,
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 = GetIntentChip(browser());
OpenNewTab(in_scope_url);
ASSERT_TRUE(intent_picker_view);
EXPECT_TRUE(WaitForPageActionButtonVisible(browser()));
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(&params);
}));
// 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.
IN_PROC_BROWSER_TEST_P(IntentPickerIconBrowserTest, DoNotShowIconOnErrorPages) {
InstallTestWebApp();
InstallTestWebApp("www.google.com", "/");
const GURL in_scope_url =
https_server().GetURL(GetAppUrlHost(), GetInScopeUrlPath());
views::Button* intent_picker_view = GetIntentChip(browser());
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(WaitForPageActionButtonVisible(browser()));
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(&params);
}));
// 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.
IN_PROC_BROWSER_TEST_P(IntentPickerIconBrowserTest, 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 = GetIntentChip(browser());
OpenNewTab(test_url);
EXPECT_TRUE(WaitForPageActionButtonVisible(browser()));
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(LinkCapturingFeatureVersion::kV1DefaultOff,
LinkCapturingFeatureVersion::kV2DefaultOff)
#else
testing::Values(LinkCapturingFeatureVersion::kV2DefaultOn,
LinkCapturingFeatureVersion::kV2DefaultOff)
#endif // BUILDFLAG(IS_CHROMEOS)
,
testing::Bool()),
GetLinkCapturingTestName);
class IntentPickerIconBrowserBubbleTest
: public IntentPickerBrowserTest,
public ::testing::WithParamInterface<
std::tuple<std::string, LinkCapturingFeatureVersion, bool>>,
public IntentChipButtonTestBase {
public:
// TODO(crbug.com/40097608): Stop disabling Paint Holding.
IntentPickerIconBrowserBubbleTest() {
std::vector<base::test::FeatureRefAndParams> features_to_enable =
apps::test::GetFeaturesToEnableLinkCapturingUX(LinkCapturingVersion());
if (IsMigrationEnabled()) {
features_to_enable.push_back(
{::features::kPageActionsMigration,
{{::features::kPageActionsMigrationIntentPicker.name, "true"}}});
}
feature_list_.InitWithFeaturesAndParameters(
features_to_enable, {blink::features::kPaintHolding});
}
bool IsMigrationEnabled() const override {
return std::get<bool>(GetParam());
}
LinkCapturingFeatureVersion LinkCapturingVersion() const {
return std::get<LinkCapturingFeatureVersion>(GetParam());
}
bool LinkCapturingEnabledByDefault() const {
#if BUILDFLAG(IS_CHROMEOS)
return false;
#else
return LinkCapturingVersion() == LinkCapturingFeatureVersion::kV2DefaultOn;
#endif // BUILDFLAG(IS_CHROMEOS)
}
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());
OpenNewTab(in_scope_url);
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::BrowserCreatedObserver browser_created_observer;
intent_picker_bubble()->AcceptDialog();
// Accepting the bubble should open the app.
Browser* app_browser = browser_created_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",
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 = GetIntentChip(browser());
OpenNewTab(in_scope_url);
EXPECT_TRUE(intent_picker_icon->GetVisible());
views::test::ButtonTestApi test_api(intent_picker_icon);
test_api.NotifyClick(ui::MouseEvent(
ui::EventType::kMousePressed, 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(
All,
IntentPickerIconBrowserBubbleTest,
testing::Combine(testing::Values("", "noopener", "noreferrer", "nofollow"),
#if BUILDFLAG(IS_CHROMEOS)
testing::Values(LinkCapturingFeatureVersion::kV1DefaultOff,
LinkCapturingFeatureVersion::kV2DefaultOff)
#else
testing::Values(LinkCapturingFeatureVersion::kV2DefaultOn,
LinkCapturingFeatureVersion::kV2DefaultOff)
#endif // BUILDFLAG(IS_CHROMEOS)
,
testing::Bool()),
GetLinkCapturingTestName);
// 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();
}
bool IsMigrationEnabled() const override {
return std::get<bool>(GetParam());
}
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 = GetIntentChip(browser());
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");
content::FrameTreeNodeId 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(WaitForPageActionButtonVisible(browser()));
EXPECT_TRUE(intent_picker_icon->GetVisible());
}
INSTANTIATE_TEST_SUITE_P(
All,
IntentPickerIconPrerenderingBrowserTest,
testing::Combine(testing::Values("", "noopener", "noreferrer", "nofollow"),
#if BUILDFLAG(IS_CHROMEOS)
testing::Values(LinkCapturingFeatureVersion::kV1DefaultOff,
LinkCapturingFeatureVersion::kV2DefaultOff)
#else
testing::Values(LinkCapturingFeatureVersion::kV2DefaultOff)
#endif // BUILDFLAG(IS_CHROMEOS)
,
testing::Bool()),
GetLinkCapturingTestName);
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_;
}
bool IsMigrationEnabled() const override {
return std::get<bool>(GetParam());
}
private:
content::test::FencedFrameTestHelper fenced_frame_helper_;
};
IN_PROC_BROWSER_TEST_P(IntentPickerIconFencedFrameBrowserTest,
ShouldShowIntentPickerInFencedFrame) {
InstallTestWebApp();
views::Button* intent_picker_icon = GetIntentChip(browser());
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(LinkCapturingFeatureVersion::kV1DefaultOff,
LinkCapturingFeatureVersion::kV2DefaultOff)
#else
testing::Values(LinkCapturingFeatureVersion::kV2DefaultOn,
LinkCapturingFeatureVersion::kV2DefaultOff)
#endif // BUILDFLAG(IS_CHROMEOS)
,
testing::Bool()),
GetLinkCapturingTestName);