blob: c8265664c848f310e86d9b05d862ee78e00d3fe2 [file] [log] [blame]
// 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 "components/blocked_content/popup_tracker.h"
#include <memory>
#include <string>
#include "base/command_line.h"
#include "base/path_service.h"
#include "base/supports_user_data.h"
#include "base/test/metrics/histogram_tester.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/safe_browsing/test_safe_browsing_database_helper.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/ui_test_utils.h"
#include "components/blocked_content/popup_blocker_tab_helper.h"
#include "components/content_settings/browser/page_specific_content_settings.h"
#include "components/safe_browsing/core/browser/db/v4_embedded_test_server_util.h"
#include "components/safe_browsing/core/browser/db/v4_test_util.h"
#include "components/ukm/test_ukm_recorder.h"
#include "content/public/browser/web_contents.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/prerender_test_util.h"
#include "content/public/test/test_navigation_observer.h"
#include "content/public/test/test_utils.h"
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "services/metrics/public/cpp/ukm_builders.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/window_open_disposition.h"
#include "ui/events/keycodes/dom/dom_code.h"
#include "ui/events/keycodes/dom/dom_key.h"
#include "ui/events/keycodes/keyboard_codes.h"
#if BUILDFLAG(IS_LINUX)
#include "ui/ozone/public/ozone_switches.h"
#endif
namespace {
const char kPopupFirstDocumentEngagement[] =
"ContentSettings.Popups.FirstDocumentEngagementTime2";
const char kPopupEngagement[] = "ContentSettings.Popups.EngagementTime";
const char kPopupGestureClose[] =
"ContentSettings.Popups.EngagementTime.GestureClose";
const char kUkmEngagementTime[] = "EngagementTime";
const char kUkmUserInitiatedClose[] = "UserInitiatedClose";
const char kUkmTrusted[] = "Trusted";
const char kUkmNumInteractions[] = "NumInteractions";
const char kUkmSafeBrowsingStatus[] = "SafeBrowsingStatus";
const char kUkmWindowOpenDisposition[] = "WindowOpenDisposition";
const char kUkmNumActivationInteractions[] = "NumActivationInteractions";
const char kUkmNumGestureScrollBeginInteractions[] =
"NumGestureScrollBeginInteractions";
const char kUkmRedirectCount[] = "RedirectCount";
} // namespace
using UkmEntry = ukm::builders::Popup_Closed;
class PopupTrackerBrowserTest : public InProcessBrowserTest {
public:
PopupTrackerBrowserTest() {}
~PopupTrackerBrowserTest() override {}
void SetUpOnMainThread() override {
ASSERT_TRUE(embedded_test_server()->Start());
}
void PreRunTestOnMainThread() override {
InProcessBrowserTest::PreRunTestOnMainThread();
test_ukm_recorder_ = std::make_unique<ukm::TestAutoSetUkmRecorder>();
}
protected:
enum UserClosedPopup { kTrue, kFalse };
size_t GetNumPopupUkmEntries() const {
return test_ukm_recorder_->GetEntriesByName(UkmEntry::kEntryName).size();
}
const ukm::mojom::UkmEntry* ExpectAndGetEntry(const GURL& expected_url) {
const auto& entries =
test_ukm_recorder_->GetEntriesByName(UkmEntry::kEntryName);
EXPECT_EQ(1u, entries.size());
const auto* entry = entries[0];
test_ukm_recorder_->ExpectEntrySourceHasUrl(entry, expected_url);
EXPECT_TRUE(test_ukm_recorder_->EntryHasMetric(entry, kUkmEngagementTime));
return entry;
}
std::unique_ptr<ukm::TestAutoSetUkmRecorder> test_ukm_recorder_;
};
IN_PROC_BROWSER_TEST_F(PopupTrackerBrowserTest, NoPopup_NoTracker) {
base::HistogramTester tester;
ASSERT_TRUE(ui_test_utils::NavigateToURL(
browser(), embedded_test_server()->GetURL("/title1.html")));
EXPECT_FALSE(blocked_content::PopupTracker::FromWebContents(
browser()->tab_strip_model()->GetActiveWebContents()));
tester.ExpectTotalCount(kPopupFirstDocumentEngagement, 0);
tester.ExpectTotalCount(kPopupEngagement, 0);
tester.ExpectTotalCount(kPopupGestureClose, 0);
EXPECT_EQ(0u, GetNumPopupUkmEntries());
}
IN_PROC_BROWSER_TEST_F(PopupTrackerBrowserTest,
WindowOpenPopup_HasTracker_GestureClose) {
base::HistogramTester tester;
const GURL first_url = embedded_test_server()->GetURL("/title1.html");
ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), first_url));
content::TestNavigationObserver navigation_observer(nullptr, 1);
navigation_observer.StartWatchingNewWebContents();
EXPECT_TRUE(content::ExecuteScript(
browser()->tab_strip_model()->GetActiveWebContents(),
"window.open('/title1.html')"));
navigation_observer.Wait();
EXPECT_EQ(2, browser()->tab_strip_model()->count());
EXPECT_TRUE(blocked_content::PopupTracker::FromWebContents(
browser()->tab_strip_model()->GetActiveWebContents()));
// Close the popup and check metric.
int active_index = browser()->tab_strip_model()->active_index();
content::WebContentsDestroyedWatcher destroyed_watcher(
browser()->tab_strip_model()->GetWebContentsAt(active_index));
browser()->tab_strip_model()->CloseWebContentsAt(
active_index, TabStripModel::CLOSE_USER_GESTURE);
destroyed_watcher.Wait();
tester.ExpectTotalCount(kPopupFirstDocumentEngagement, 1);
tester.ExpectTotalCount(kPopupEngagement, 1);
tester.ExpectTotalCount(kPopupGestureClose, 1);
auto* entry = ExpectAndGetEntry(first_url);
test_ukm_recorder_->ExpectEntryMetric(entry, kUkmUserInitiatedClose, 1u);
test_ukm_recorder_->ExpectEntryMetric(entry, kUkmTrusted, 0u);
test_ukm_recorder_->ExpectEntryMetric(entry, kUkmNumInteractions, 0u);
test_ukm_recorder_->ExpectEntryMetric(entry, kUkmNumActivationInteractions,
0u);
test_ukm_recorder_->ExpectEntryMetric(
entry, kUkmNumGestureScrollBeginInteractions, 0u);
}
IN_PROC_BROWSER_TEST_F(PopupTrackerBrowserTest,
WindowOpenPopup_WithInteraction) {
base::HistogramTester tester;
const GURL first_url = embedded_test_server()->GetURL("/title1.html");
ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), first_url));
content::TestNavigationObserver navigation_observer(nullptr, 1);
navigation_observer.StartWatchingNewWebContents();
EXPECT_TRUE(content::ExecuteScript(
browser()->tab_strip_model()->GetActiveWebContents(),
"window.open('/title1.html')"));
navigation_observer.Wait();
EXPECT_EQ(2, browser()->tab_strip_model()->count());
content::WebContents* popup =
browser()->tab_strip_model()->GetActiveWebContents();
EXPECT_TRUE(blocked_content::PopupTracker::FromWebContents(popup));
// Perform some user gestures on the page.
content::SimulateMouseClick(popup, 0, blink::WebMouseEvent::Button::kLeft);
content::SimulateMouseClick(popup, 0, blink::WebMouseEvent::Button::kLeft);
content::SimulateGestureScrollSequence(popup, gfx::Point(100, 100),
gfx::Vector2dF(0, 15));
// Close the popup and check metric.
int active_index = browser()->tab_strip_model()->active_index();
content::WebContentsDestroyedWatcher destroyed_watcher(popup);
browser()->tab_strip_model()->CloseWebContentsAt(
active_index, TabStripModel::CLOSE_USER_GESTURE);
destroyed_watcher.Wait();
tester.ExpectTotalCount(kPopupFirstDocumentEngagement, 1);
tester.ExpectTotalCount(kPopupEngagement, 1);
tester.ExpectTotalCount(kPopupGestureClose, 1);
auto* entry = ExpectAndGetEntry(first_url);
test_ukm_recorder_->ExpectEntryMetric(entry, kUkmUserInitiatedClose, 1u);
test_ukm_recorder_->ExpectEntryMetric(entry, kUkmTrusted, 0u);
test_ukm_recorder_->ExpectEntryMetric(entry, kUkmNumInteractions, 3u);
test_ukm_recorder_->ExpectEntryMetric(entry, kUkmNumActivationInteractions,
2u);
test_ukm_recorder_->ExpectEntryMetric(
entry, kUkmNumGestureScrollBeginInteractions, 1u);
}
// OpenURLFromTab goes through a different code path than traditional popups
// that use window.open(). Make sure the tracker is created in those cases.
// Disabled due to flakiness. See crbug.com/1186441.
IN_PROC_BROWSER_TEST_F(PopupTrackerBrowserTest, DISABLED_ControlClick_HasTracker) {
base::HistogramTester tester;
const GURL url = embedded_test_server()->GetURL(
"/popup_blocker/popup-simulated-click-on-anchor.html");
ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url));
// Mac uses command instead of control for the new tab action.
bool is_mac = false;
#if BUILDFLAG(IS_MAC)
is_mac = true;
#endif
content::TestNavigationObserver navigation_observer(nullptr, 1);
navigation_observer.StartWatchingNewWebContents();
SimulateKeyPress(browser()->tab_strip_model()->GetActiveWebContents(),
ui::DomKey::ENTER, ui::DomCode::ENTER, ui::VKEY_RETURN,
!is_mac /* control */, false /* shift */, false /* alt */,
is_mac /* command */);
navigation_observer.Wait();
EXPECT_EQ(1u, chrome::GetBrowserCount(browser()->profile()));
content::WebContents* new_contents =
browser()->tab_strip_model()->GetWebContentsAt(1);
EXPECT_TRUE(blocked_content::PopupTracker::FromWebContents(new_contents));
// Close the popup and check metric.
content::WebContentsDestroyedWatcher destroyed_watcher(new_contents);
BrowserList::CloseAllBrowsersWithProfile(
Profile::FromBrowserContext(new_contents->GetBrowserContext()));
destroyed_watcher.Wait();
tester.ExpectTotalCount(kPopupFirstDocumentEngagement, 1);
tester.ExpectTotalCount(kPopupEngagement, 1);
auto* entry = ExpectAndGetEntry(url);
test_ukm_recorder_->ExpectEntryMetric(entry, kUkmUserInitiatedClose, 0u);
test_ukm_recorder_->ExpectEntryMetric(entry, kUkmTrusted, 1u);
test_ukm_recorder_->ExpectEntryMetric(entry, kUkmNumInteractions, 0u);
test_ukm_recorder_->ExpectEntryMetric(entry, kUkmNumActivationInteractions,
0u);
test_ukm_recorder_->ExpectEntryMetric(
entry, kUkmNumGestureScrollBeginInteractions, 0u);
}
// Disabled due to flakiness. See crbug.com/1186441.
IN_PROC_BROWSER_TEST_F(PopupTrackerBrowserTest, DISABLED_ShiftClick_HasTracker) {
base::HistogramTester tester;
const GURL url = embedded_test_server()->GetURL(
"/popup_blocker/popup-simulated-click-on-anchor.html");
ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url));
content::TestNavigationObserver navigation_observer(nullptr, 1);
navigation_observer.StartWatchingNewWebContents();
SimulateKeyPress(browser()->tab_strip_model()->GetActiveWebContents(),
ui::DomKey::ENTER, ui::DomCode::ENTER, ui::VKEY_RETURN,
false /* control */, true /* shift */, false /* alt */,
false /* command */);
navigation_observer.Wait();
EXPECT_EQ(2u, chrome::GetBrowserCount(browser()->profile()));
content::WebContents* new_contents = BrowserList::GetInstance()
->GetLastActive()
->tab_strip_model()
->GetActiveWebContents();
EXPECT_TRUE(blocked_content::PopupTracker::FromWebContents(new_contents));
// Close the popup and check metric.
content::WebContentsDestroyedWatcher destroyed_watcher(new_contents);
BrowserList::CloseAllBrowsersWithProfile(
Profile::FromBrowserContext(new_contents->GetBrowserContext()));
destroyed_watcher.Wait();
tester.ExpectTotalCount(kPopupFirstDocumentEngagement, 1);
tester.ExpectTotalCount(kPopupEngagement, 1);
auto* entry = ExpectAndGetEntry(url);
test_ukm_recorder_->ExpectEntryMetric(entry, kUkmUserInitiatedClose, 0u);
test_ukm_recorder_->ExpectEntryMetric(entry, kUkmTrusted, 1u);
test_ukm_recorder_->ExpectEntryMetric(entry, kUkmNumInteractions, 0u);
test_ukm_recorder_->ExpectEntryMetric(entry, kUkmNumActivationInteractions,
0u);
test_ukm_recorder_->ExpectEntryMetric(
entry, kUkmNumGestureScrollBeginInteractions, 0u);
}
IN_PROC_BROWSER_TEST_F(PopupTrackerBrowserTest, AllowlistedPopup_HasTracker) {
base::HistogramTester tester;
const GURL url =
embedded_test_server()->GetURL("/popup_blocker/popup-window-open.html");
content::WebContents* web_contents =
browser()->tab_strip_model()->GetActiveWebContents();
// Is blocked by the popup blocker.
ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url));
EXPECT_TRUE(content_settings::PageSpecificContentSettings::GetForFrame(
web_contents->GetPrimaryMainFrame())
->IsContentBlocked(ContentSettingsType::POPUPS));
// Click through to open the popup.
content::TestNavigationObserver navigation_observer(nullptr, 1);
navigation_observer.StartWatchingNewWebContents();
auto* popup_blocker =
blocked_content::PopupBlockerTabHelper::FromWebContents(web_contents);
popup_blocker->ShowBlockedPopup(
popup_blocker->GetBlockedPopupRequests().begin()->first,
WindowOpenDisposition::NEW_FOREGROUND_TAB);
navigation_observer.Wait();
// Close the popup and check metric.
content::WebContentsDestroyedWatcher destroyed_watcher(
browser()->tab_strip_model()->GetActiveWebContents());
browser()->tab_strip_model()->CloseAllTabs();
destroyed_watcher.Wait();
tester.ExpectTotalCount(kPopupFirstDocumentEngagement, 1);
tester.ExpectTotalCount(kPopupEngagement, 1);
auto* entry = ExpectAndGetEntry(url);
test_ukm_recorder_->ExpectEntryMetric(entry, kUkmUserInitiatedClose, 0u);
test_ukm_recorder_->ExpectEntryMetric(entry, kUkmTrusted, 1u);
test_ukm_recorder_->ExpectEntryMetric(entry, kUkmNumInteractions, 0u);
test_ukm_recorder_->ExpectEntryMetric(entry, kUkmNumActivationInteractions,
0u);
test_ukm_recorder_->ExpectEntryMetric(
entry, kUkmNumGestureScrollBeginInteractions, 0u);
}
IN_PROC_BROWSER_TEST_F(PopupTrackerBrowserTest, NoOpener_NoTracker) {
const GURL url = embedded_test_server()->GetURL("/title1.html");
ui_test_utils::NavigateToURLWithDisposition(
browser(), url, WindowOpenDisposition::NEW_FOREGROUND_TAB,
ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP);
content::WebContents* new_contents =
browser()->tab_strip_model()->GetWebContentsAt(1);
EXPECT_FALSE(blocked_content::PopupTracker::FromWebContents(new_contents));
EXPECT_EQ(0u, GetNumPopupUkmEntries());
}
// Tests for the subresource_filter popup blocker.
class SafeBrowsingPopupTrackerBrowserTest : public PopupTrackerBrowserTest {
public:
SafeBrowsingPopupTrackerBrowserTest() = default;
SafeBrowsingPopupTrackerBrowserTest(
const SafeBrowsingPopupTrackerBrowserTest&) = delete;
SafeBrowsingPopupTrackerBrowserTest& operator=(
const SafeBrowsingPopupTrackerBrowserTest&) = delete;
~SafeBrowsingPopupTrackerBrowserTest() override = default;
void SetUp() override {
database_helper_ = CreateTestDatabase();
PopupTrackerBrowserTest::SetUp();
}
void SetUpOnMainThread() override {
base::FilePath test_data_dir;
base::PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir);
embedded_test_server()->ServeFilesFromDirectory(test_data_dir);
host_resolver()->AddRule("*", "127.0.0.1");
content::SetupCrossSiteRedirector(embedded_test_server());
ASSERT_TRUE(embedded_test_server()->Start());
}
void TearDown() override {
InProcessBrowserTest::TearDown();
database_helper_.reset();
}
virtual std::unique_ptr<TestSafeBrowsingDatabaseHelper> CreateTestDatabase() {
std::vector<safe_browsing::ListIdentifier> list_ids = {
safe_browsing::GetUrlSubresourceFilterId()};
return std::make_unique<TestSafeBrowsingDatabaseHelper>(
std::make_unique<safe_browsing::TestV4GetHashProtocolManagerFactory>(),
std::move(list_ids));
}
void ConfigureAsList(const GURL& url,
const safe_browsing::ListIdentifier& list_identifier) {
safe_browsing::ThreatMetadata metadata;
database_helper_->AddFullHashToDbAndFullHashCache(url, list_identifier,
metadata);
}
TestSafeBrowsingDatabaseHelper* database_helper() {
return database_helper_.get();
}
private:
std::unique_ptr<TestSafeBrowsingDatabaseHelper> database_helper_;
};
// Pop-ups closed before navigation has finished will receive no safe browsing
// status.
IN_PROC_BROWSER_TEST_F(SafeBrowsingPopupTrackerBrowserTest,
PopupClosedBeforeNavigationFinished_LoggedAsNoValue) {
const GURL first_url = embedded_test_server()->GetURL("/title1.html");
ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), first_url));
const GURL unsafe_url = embedded_test_server()->GetURL("/slow");
ConfigureAsList(unsafe_url, safe_browsing::GetUrlSocEngId());
content::TestNavigationObserver navigation_observer(nullptr, 1);
navigation_observer.StartWatchingNewWebContents();
EXPECT_TRUE(
content::ExecJs(browser()->tab_strip_model()->GetActiveWebContents(),
"window.open('/slow?1000')"));
EXPECT_EQ(2, browser()->tab_strip_model()->count());
content::WebContents* popup =
browser()->tab_strip_model()->GetActiveWebContents();
EXPECT_TRUE(blocked_content::PopupTracker::FromWebContents(popup));
// Close the popup and check metric.
int active_index = browser()->tab_strip_model()->active_index();
content::WebContentsDestroyedWatcher destroyed_watcher(popup);
browser()->tab_strip_model()->CloseWebContentsAt(
active_index, TabStripModel::CLOSE_USER_GESTURE);
destroyed_watcher.Wait();
auto* entry = ExpectAndGetEntry(first_url);
test_ukm_recorder_->ExpectEntryMetric(
entry, kUkmSafeBrowsingStatus,
static_cast<int>(
blocked_content::PopupTracker::PopupSafeBrowsingStatus::kNoValue));
}
IN_PROC_BROWSER_TEST_F(SafeBrowsingPopupTrackerBrowserTest,
SafePopup_LoggedAsSafe) {
const GURL first_url = embedded_test_server()->GetURL("/title1.html");
ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), first_url));
content::TestNavigationObserver navigation_observer(nullptr, 1);
navigation_observer.StartWatchingNewWebContents();
const GURL second_url = embedded_test_server()->GetURL("/title2.html");
EXPECT_TRUE(
content::ExecJs(browser()->tab_strip_model()->GetActiveWebContents(),
"window.open('/title2.html')"));
navigation_observer.Wait();
EXPECT_EQ(2, browser()->tab_strip_model()->count());
content::WebContents* popup =
browser()->tab_strip_model()->GetActiveWebContents();
EXPECT_TRUE(blocked_content::PopupTracker::FromWebContents(popup));
// Close the popup and check metric.
int active_index = browser()->tab_strip_model()->active_index();
content::WebContentsDestroyedWatcher destroyed_watcher(popup);
browser()->tab_strip_model()->CloseWebContentsAt(
active_index, TabStripModel::CLOSE_USER_GESTURE);
destroyed_watcher.Wait();
auto* entry = ExpectAndGetEntry(first_url);
test_ukm_recorder_->ExpectEntryMetric(
entry, kUkmSafeBrowsingStatus,
static_cast<int>(
blocked_content::PopupTracker::PopupSafeBrowsingStatus::kSafe));
}
IN_PROC_BROWSER_TEST_F(SafeBrowsingPopupTrackerBrowserTest,
PhishingPopup_LoggedAsUnsafe) {
const GURL first_url = embedded_test_server()->GetURL("/title1.html");
ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), first_url));
// Associate each domain with a separate safe browsing ListIdentifier to
// exercise the set of lists.
std::vector<std::pair<std::string, safe_browsing::ListIdentifier>>
domain_list_pairs = {
{"a.com", safe_browsing::GetUrlSocEngId()},
{"b.com", safe_browsing::GetUrlSubresourceFilterId()}};
// For each pair, configure the local safe browsing database and open a
// pop-up to the url.
for (const auto& domain_list_pair : domain_list_pairs) {
const GURL unsafe_url =
embedded_test_server()->GetURL(domain_list_pair.first, "/title2.html");
ConfigureAsList(unsafe_url, domain_list_pair.second);
content::TestNavigationObserver navigation_observer(nullptr, 1);
navigation_observer.StartWatchingNewWebContents();
EXPECT_TRUE(
content::ExecJs(browser()->tab_strip_model()->GetActiveWebContents(),
"window.open('" + unsafe_url.spec() + "')"));
navigation_observer.Wait();
EXPECT_EQ(2, browser()->tab_strip_model()->count());
content::WebContents* popup =
browser()->tab_strip_model()->GetActiveWebContents();
EXPECT_TRUE(blocked_content::PopupTracker::FromWebContents(popup));
// Close the popup and check metric.
int active_index = browser()->tab_strip_model()->active_index();
content::WebContentsDestroyedWatcher destroyed_watcher(popup);
browser()->tab_strip_model()->CloseWebContentsAt(
active_index, TabStripModel::CLOSE_USER_GESTURE);
destroyed_watcher.Wait();
}
// The URL should have 4 pop-up entries with an unsafe safe browsing status.
auto entries = test_ukm_recorder_->GetEntriesByName(
ukm::builders::Popup_Closed::kEntryName);
EXPECT_EQ(2u, entries.size());
for (auto* entry : entries) {
test_ukm_recorder_->ExpectEntryMetric(
entry, kUkmSafeBrowsingStatus,
static_cast<int>(
blocked_content::PopupTracker::PopupSafeBrowsingStatus::kUnsafe));
}
}
IN_PROC_BROWSER_TEST_F(PopupTrackerBrowserTest, PopupInTab_IsWindowFalse) {
const GURL first_url = embedded_test_server()->GetURL("/title1.html");
ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), first_url));
content::TestNavigationObserver navigation_observer(nullptr, 1);
navigation_observer.StartWatchingNewWebContents();
EXPECT_TRUE(
content::ExecJs(browser()->tab_strip_model()->GetActiveWebContents(),
"window.open('/title1.html')"));
navigation_observer.Wait();
EXPECT_EQ(2, browser()->tab_strip_model()->count());
content::WebContents* popup =
browser()->tab_strip_model()->GetActiveWebContents();
EXPECT_TRUE(blocked_content::PopupTracker::FromWebContents(popup));
// Close the popup and check metric.
int active_index = browser()->tab_strip_model()->active_index();
content::WebContentsDestroyedWatcher destroyed_watcher(popup);
browser()->tab_strip_model()->CloseWebContentsAt(
active_index, TabStripModel::CLOSE_USER_GESTURE);
destroyed_watcher.Wait();
auto* entry = ExpectAndGetEntry(first_url);
test_ukm_recorder_->ExpectEntryMetric(
entry, kUkmWindowOpenDisposition,
static_cast<int>(WindowOpenDisposition::NEW_FOREGROUND_TAB));
}
// TODO(crbug.com/1178846): Test is flaky on Linux.
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
#define MAYBE_PopupInWindow_IsWindowTrue DISABLED_PopupInWindow_IsWindowTrue
#else
#define MAYBE_PopupInWindow_IsWindowTrue PopupInWindow_IsWindowTrue
#endif
IN_PROC_BROWSER_TEST_F(PopupTrackerBrowserTest,
MAYBE_PopupInWindow_IsWindowTrue) {
const GURL first_url = embedded_test_server()->GetURL("/title1.html");
ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), first_url));
content::TestNavigationObserver navigation_observer(nullptr, 1);
navigation_observer.StartWatchingNewWebContents();
EXPECT_TRUE(content::ExecJs(
browser()->tab_strip_model()->GetActiveWebContents(),
"window.open('/title1.html', 'new_window', "
"'location=yes,height=570,width=520,scrollbars=yes,status=yes')"));
navigation_observer.Wait();
EXPECT_EQ(2u, chrome::GetTotalBrowserCount());
Browser* created_browser = chrome::FindLastActive();
EXPECT_EQ(1, created_browser->tab_strip_model()->count());
content::WebContents* popup =
created_browser->tab_strip_model()->GetActiveWebContents();
EXPECT_TRUE(blocked_content::PopupTracker::FromWebContents(popup));
// Close the popup and check metric.
int active_index = created_browser->tab_strip_model()->active_index();
content::WebContentsDestroyedWatcher destroyed_watcher(popup);
created_browser->tab_strip_model()->CloseWebContentsAt(
active_index, TabStripModel::CLOSE_USER_GESTURE);
destroyed_watcher.Wait();
auto* entry = ExpectAndGetEntry(first_url);
test_ukm_recorder_->ExpectEntryMetric(
entry, kUkmWindowOpenDisposition,
static_cast<int>(WindowOpenDisposition::NEW_POPUP));
}
// TODO(crbug.com/1146598): Test is flaky on Lacros, Linux Ozone Wayland.
#if BUILDFLAG(IS_CHROMEOS_LACROS) || BUILDFLAG(IS_LINUX)
#define MAYBE_PopupNoRedirect_RedirectCountZero DISABLED_PopupNoRedirect_RedirectCountZero
#else
#define MAYBE_PopupNoRedirect_RedirectCountZero PopupNoRedirect_RedirectCountZero
#endif
IN_PROC_BROWSER_TEST_F(PopupTrackerBrowserTest,
MAYBE_PopupNoRedirect_RedirectCountZero) {
const GURL first_url = embedded_test_server()->GetURL("/title1.html");
ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), first_url));
content::TestNavigationObserver navigation_observer(nullptr, 1);
navigation_observer.StartWatchingNewWebContents();
EXPECT_TRUE(content::ExecJs(
browser()->tab_strip_model()->GetActiveWebContents(),
"window.open('/title1.html', 'new_window', "
"'location=yes,height=570,width=520,scrollbars=yes,status=yes')"));
navigation_observer.Wait();
EXPECT_EQ(2u, chrome::GetTotalBrowserCount());
Browser* created_browser = chrome::FindLastActive();
EXPECT_EQ(1, created_browser->tab_strip_model()->count());
content::WebContents* popup =
created_browser->tab_strip_model()->GetActiveWebContents();
EXPECT_TRUE(blocked_content::PopupTracker::FromWebContents(popup));
// Close the popup and check that the pop up did not redirect.
int active_index = created_browser->tab_strip_model()->active_index();
content::WebContentsDestroyedWatcher destroyed_watcher(popup);
created_browser->tab_strip_model()->CloseWebContentsAt(
active_index, TabStripModel::CLOSE_USER_GESTURE);
destroyed_watcher.Wait();
auto* entry = ExpectAndGetEntry(first_url);
test_ukm_recorder_->ExpectEntryMetric(entry, kUkmRedirectCount, 0);
}
// TODO(crbug.com/1179235): Test is flaky on Lacros.
#if BUILDFLAG(IS_CHROMEOS_LACROS)
#define MAYBE_PopupRedirectsTwice_RedirectCountTwo \
DISABLED_PopupRedirectsTwice_RedirectCountTwo
#else
#define MAYBE_PopupRedirectsTwice_RedirectCountTwo \
PopupRedirectsTwice_RedirectCountTwo
#endif
IN_PROC_BROWSER_TEST_F(PopupTrackerBrowserTest,
MAYBE_PopupRedirectsTwice_RedirectCountTwo) {
#if BUILDFLAG(IS_LINUX)
{
auto* command_line = base::CommandLine::ForCurrentProcess();
if (command_line->HasSwitch(switches::kOzonePlatform) &&
command_line->GetSwitchValueASCII(switches::kOzonePlatform) ==
"wayland") {
// TODO(crbug.com/1179235): Test is flaky on Linux Wayland configuration.
GTEST_SKIP() << "Flaky on Linux Wayland";
}
}
#endif
const GURL first_url = embedded_test_server()->GetURL("/title1.html");
ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), first_url));
content::TestNavigationObserver navigation_observer(nullptr, 1);
navigation_observer.StartWatchingNewWebContents();
// Redirect the popup using /server-redirect twice.
EXPECT_TRUE(content::ExecJs(
browser()->tab_strip_model()->GetActiveWebContents(),
"window.open('/server-redirect?/server-redirect?/title1.html',"
"'new_window', 'location=yes,height=570,width=520,scrollbars=yes,"
"status=yes')"));
navigation_observer.Wait();
EXPECT_EQ(2u, chrome::GetTotalBrowserCount());
Browser* created_browser = chrome::FindLastActive();
EXPECT_EQ(1, created_browser->tab_strip_model()->count());
content::WebContents* popup =
created_browser->tab_strip_model()->GetActiveWebContents();
EXPECT_TRUE(blocked_content::PopupTracker::FromWebContents(popup));
// Close the popup and check metric.
int active_index = created_browser->tab_strip_model()->active_index();
content::WebContentsDestroyedWatcher destroyed_watcher(popup);
created_browser->tab_strip_model()->CloseWebContentsAt(
active_index, TabStripModel::CLOSE_USER_GESTURE);
destroyed_watcher.Wait();
auto* entry = ExpectAndGetEntry(first_url);
test_ukm_recorder_->ExpectEntryMetric(entry, kUkmRedirectCount, 2);
}
// TODO(crbug.com/1179859): Test is flaky on Windows, Linux and Lacros.
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_CHROMEOS_LACROS)
#define MAYBE_PopupJavascriptRenavigation_RedirectCountZero \
DISABLED_PopupJavascriptRenavigation_RedirectCountZero
#else
#define MAYBE_PopupJavascriptRenavigation_RedirectCountZero \
PopupJavascriptRenavigation_RedirectCountZero
#endif
IN_PROC_BROWSER_TEST_F(PopupTrackerBrowserTest,
MAYBE_PopupJavascriptRenavigation_RedirectCountZero) {
const GURL first_url = embedded_test_server()->GetURL("/title1.html");
ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), first_url));
content::TestNavigationObserver navigation_observer(nullptr, 1);
navigation_observer.StartWatchingNewWebContents();
// Redirect the popup using /server-redirect twice.
EXPECT_TRUE(content::ExecJs(
browser()->tab_strip_model()->GetActiveWebContents(),
"var w = window.open('',"
"'new_window', 'location=yes,height=570,width=520,scrollbars=yes,"
"status=yes'); "
"w.location = '/title1.html'"));
navigation_observer.Wait();
EXPECT_EQ(2u, chrome::GetTotalBrowserCount());
Browser* created_browser = chrome::FindLastActive();
EXPECT_EQ(1, created_browser->tab_strip_model()->count());
content::WebContents* popup =
created_browser->tab_strip_model()->GetActiveWebContents();
EXPECT_TRUE(blocked_content::PopupTracker::FromWebContents(popup));
// Close the popup and check metric.
int active_index = created_browser->tab_strip_model()->active_index();
content::WebContentsDestroyedWatcher destroyed_watcher(popup);
created_browser->tab_strip_model()->CloseWebContentsAt(
active_index, TabStripModel::CLOSE_USER_GESTURE);
destroyed_watcher.Wait();
auto* entry = ExpectAndGetEntry(first_url);
test_ukm_recorder_->ExpectEntryMetric(entry, kUkmRedirectCount, 0);
}
class PopupTrackerPrerenderBrowserTest : public PopupTrackerBrowserTest {
public:
PopupTrackerPrerenderBrowserTest()
: prerender_helper_(
base::BindRepeating(&PopupTrackerPrerenderBrowserTest::web_contents,
base::Unretained(this))) {}
~PopupTrackerPrerenderBrowserTest() override = default;
protected:
content::test::PrerenderTestHelper* prerender_helper() {
return &prerender_helper_;
}
content::WebContents* web_contents() {
return browser()->tab_strip_model()->GetActiveWebContents();
}
private:
content::test::PrerenderTestHelper prerender_helper_;
};
// Test that a navigation of the prerender page shouldn't affect recording UKM
// of PopupTracker.
IN_PROC_BROWSER_TEST_F(PopupTrackerPrerenderBrowserTest,
DoNotAffectRecordingUKMByPrerender) {
const GURL first_url = embedded_test_server()->GetURL("/title1.html");
ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), first_url));
// Load a prerender url in the popup window.
const GURL prerender_url = embedded_test_server()->GetURL("/empty.html");
EXPECT_TRUE(content::ExecuteScript(
browser()->tab_strip_model()->GetActiveWebContents(),
"window.open('/popup_blocker/popup-simple-prerender.html')"));
prerender_helper()->WaitForPrerenderLoadCompletion(prerender_url);
EXPECT_EQ(2, browser()->tab_strip_model()->count());
auto* popup_tracker = blocked_content::PopupTracker::FromWebContents(
browser()->tab_strip_model()->GetActiveWebContents());
EXPECT_NE(popup_tracker, nullptr);
// The PopupTracker should not treat a prerender navigation as a navigation
// away from the first document. So, the |first_load_visible_time_| in
// PopupTracker should be empty and not be used for the recording UKM.
EXPECT_FALSE(popup_tracker->has_first_load_visible_time_for_testing());
}