1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "components/blocked_content/popup_tracker.h"
6
7 #include <memory>
8 #include <string>
9
10 #include "base/path_service.h"
11 #include "base/supports_user_data.h"
12 #include "base/test/metrics/histogram_tester.h"
13 #include "build/build_config.h"
14 #include "chrome/browser/profiles/profile.h"
15 #include "chrome/browser/safe_browsing/test_safe_browsing_database_helper.h"
16 #include "chrome/browser/ui/browser.h"
17 #include "chrome/browser/ui/browser_finder.h"
18 #include "chrome/browser/ui/browser_list.h"
19 #include "chrome/browser/ui/tabs/tab_strip_model.h"
20 #include "chrome/common/chrome_paths.h"
21 #include "chrome/test/base/in_process_browser_test.h"
22 #include "chrome/test/base/ui_test_utils.h"
23 #include "components/blocked_content/popup_blocker_tab_helper.h"
24 #include "components/content_settings/browser/page_specific_content_settings.h"
25 #include "components/safe_browsing/core/db/v4_embedded_test_server_util.h"
26 #include "components/safe_browsing/core/db/v4_test_util.h"
27 #include "components/ukm/test_ukm_recorder.h"
28 #include "content/public/browser/web_contents.h"
29 #include "content/public/test/browser_test.h"
30 #include "content/public/test/browser_test_utils.h"
31 #include "content/public/test/test_navigation_observer.h"
32 #include "content/public/test/test_utils.h"
33 #include "net/dns/mock_host_resolver.h"
34 #include "net/test/embedded_test_server/embedded_test_server.h"
35 #include "services/metrics/public/cpp/ukm_builders.h"
36 #include "testing/gtest/include/gtest/gtest.h"
37 #include "ui/base/window_open_disposition.h"
38 #include "ui/events/keycodes/dom/dom_code.h"
39 #include "ui/events/keycodes/dom/dom_key.h"
40 #include "ui/events/keycodes/keyboard_codes.h"
41
42 namespace {
43 const char kPopupFirstDocumentEngagement[] =
44 "ContentSettings.Popups.FirstDocumentEngagementTime2";
45 const char kPopupEngagement[] = "ContentSettings.Popups.EngagementTime";
46 const char kPopupGestureClose[] =
47 "ContentSettings.Popups.EngagementTime.GestureClose";
48
49 const char kUkmEngagementTime[] = "EngagementTime";
50 const char kUkmUserInitiatedClose[] = "UserInitiatedClose";
51 const char kUkmTrusted[] = "Trusted";
52 const char kUkmNumInteractions[] = "NumInteractions";
53 const char kUkmSafeBrowsingStatus[] = "SafeBrowsingStatus";
54 const char kUkmWindowOpenDisposition[] = "WindowOpenDisposition";
55 const char kUkmNumActivationInteractions[] = "NumActivationInteractions";
56 const char kUkmNumGestureScrollBeginInteractions[] =
57 "NumGestureScrollBeginInteractions";
58 const char kUkmRedirectCount[] = "RedirectCount";
59 } // namespace
60
61 using UkmEntry = ukm::builders::Popup_Closed;
62
63 class PopupTrackerBrowserTest : public InProcessBrowserTest {
64 public:
PopupTrackerBrowserTest()65 PopupTrackerBrowserTest() {}
~PopupTrackerBrowserTest()66 ~PopupTrackerBrowserTest() override {}
67
SetUpOnMainThread()68 void SetUpOnMainThread() override {
69 ASSERT_TRUE(embedded_test_server()->Start());
70 }
71
PreRunTestOnMainThread()72 void PreRunTestOnMainThread() override {
73 InProcessBrowserTest::PreRunTestOnMainThread();
74 test_ukm_recorder_ = std::make_unique<ukm::TestAutoSetUkmRecorder>();
75 }
76
77 protected:
78 enum UserClosedPopup { kTrue, kFalse };
79
GetNumPopupUkmEntries() const80 size_t GetNumPopupUkmEntries() const {
81 return test_ukm_recorder_->GetEntriesByName(UkmEntry::kEntryName).size();
82 }
83
ExpectAndGetEntry(const GURL & expected_url)84 const ukm::mojom::UkmEntry* ExpectAndGetEntry(const GURL& expected_url) {
85 const auto& entries =
86 test_ukm_recorder_->GetEntriesByName(UkmEntry::kEntryName);
87 EXPECT_EQ(1u, entries.size());
88 const auto* entry = entries[0];
89 test_ukm_recorder_->ExpectEntrySourceHasUrl(entry, expected_url);
90 EXPECT_TRUE(test_ukm_recorder_->EntryHasMetric(entry, kUkmEngagementTime));
91 return entry;
92 }
93
94 std::unique_ptr<ukm::TestAutoSetUkmRecorder> test_ukm_recorder_;
95 };
96
IN_PROC_BROWSER_TEST_F(PopupTrackerBrowserTest,NoPopup_NoTracker)97 IN_PROC_BROWSER_TEST_F(PopupTrackerBrowserTest, NoPopup_NoTracker) {
98 base::HistogramTester tester;
99 ui_test_utils::NavigateToURL(browser(),
100 embedded_test_server()->GetURL("/title1.html"));
101 EXPECT_FALSE(blocked_content::PopupTracker::FromWebContents(
102 browser()->tab_strip_model()->GetActiveWebContents()));
103
104 tester.ExpectTotalCount(kPopupFirstDocumentEngagement, 0);
105 tester.ExpectTotalCount(kPopupEngagement, 0);
106 tester.ExpectTotalCount(kPopupGestureClose, 0);
107
108 EXPECT_EQ(0u, GetNumPopupUkmEntries());
109 }
110
IN_PROC_BROWSER_TEST_F(PopupTrackerBrowserTest,WindowOpenPopup_HasTracker_GestureClose)111 IN_PROC_BROWSER_TEST_F(PopupTrackerBrowserTest,
112 WindowOpenPopup_HasTracker_GestureClose) {
113 base::HistogramTester tester;
114 const GURL first_url = embedded_test_server()->GetURL("/title1.html");
115 ui_test_utils::NavigateToURL(browser(), first_url);
116
117 content::TestNavigationObserver navigation_observer(nullptr, 1);
118 navigation_observer.StartWatchingNewWebContents();
119
120 EXPECT_TRUE(content::ExecuteScript(
121 browser()->tab_strip_model()->GetActiveWebContents(),
122 "window.open('/title1.html')"));
123 navigation_observer.Wait();
124
125 EXPECT_EQ(2, browser()->tab_strip_model()->count());
126 EXPECT_TRUE(blocked_content::PopupTracker::FromWebContents(
127 browser()->tab_strip_model()->GetActiveWebContents()));
128
129 // Close the popup and check metric.
130 int active_index = browser()->tab_strip_model()->active_index();
131 content::WebContentsDestroyedWatcher destroyed_watcher(
132 browser()->tab_strip_model()->GetWebContentsAt(active_index));
133 browser()->tab_strip_model()->CloseWebContentsAt(
134 active_index, TabStripModel::CLOSE_USER_GESTURE);
135 destroyed_watcher.Wait();
136
137 tester.ExpectTotalCount(kPopupFirstDocumentEngagement, 1);
138 tester.ExpectTotalCount(kPopupEngagement, 1);
139 tester.ExpectTotalCount(kPopupGestureClose, 1);
140
141 auto* entry = ExpectAndGetEntry(first_url);
142 test_ukm_recorder_->ExpectEntryMetric(entry, kUkmUserInitiatedClose, 1u);
143 test_ukm_recorder_->ExpectEntryMetric(entry, kUkmTrusted, 0u);
144 test_ukm_recorder_->ExpectEntryMetric(entry, kUkmNumInteractions, 0u);
145 test_ukm_recorder_->ExpectEntryMetric(entry, kUkmNumActivationInteractions,
146 0u);
147 test_ukm_recorder_->ExpectEntryMetric(
148 entry, kUkmNumGestureScrollBeginInteractions, 0u);
149 }
150
IN_PROC_BROWSER_TEST_F(PopupTrackerBrowserTest,WindowOpenPopup_WithInteraction)151 IN_PROC_BROWSER_TEST_F(PopupTrackerBrowserTest,
152 WindowOpenPopup_WithInteraction) {
153 base::HistogramTester tester;
154 const GURL first_url = embedded_test_server()->GetURL("/title1.html");
155 ui_test_utils::NavigateToURL(browser(), first_url);
156
157 content::TestNavigationObserver navigation_observer(nullptr, 1);
158 navigation_observer.StartWatchingNewWebContents();
159
160 EXPECT_TRUE(content::ExecuteScript(
161 browser()->tab_strip_model()->GetActiveWebContents(),
162 "window.open('/title1.html')"));
163 navigation_observer.Wait();
164
165 EXPECT_EQ(2, browser()->tab_strip_model()->count());
166 content::WebContents* popup =
167 browser()->tab_strip_model()->GetActiveWebContents();
168 EXPECT_TRUE(blocked_content::PopupTracker::FromWebContents(popup));
169
170 // Perform some user gestures on the page.
171 content::SimulateMouseClick(popup, 0, blink::WebMouseEvent::Button::kLeft);
172 content::SimulateMouseClick(popup, 0, blink::WebMouseEvent::Button::kLeft);
173 content::SimulateGestureScrollSequence(popup, gfx::Point(100, 100),
174 gfx::Vector2dF(0, 15));
175
176 // Close the popup and check metric.
177 int active_index = browser()->tab_strip_model()->active_index();
178 content::WebContentsDestroyedWatcher destroyed_watcher(popup);
179 browser()->tab_strip_model()->CloseWebContentsAt(
180 active_index, TabStripModel::CLOSE_USER_GESTURE);
181 destroyed_watcher.Wait();
182
183 tester.ExpectTotalCount(kPopupFirstDocumentEngagement, 1);
184 tester.ExpectTotalCount(kPopupEngagement, 1);
185 tester.ExpectTotalCount(kPopupGestureClose, 1);
186
187 auto* entry = ExpectAndGetEntry(first_url);
188 test_ukm_recorder_->ExpectEntryMetric(entry, kUkmUserInitiatedClose, 1u);
189 test_ukm_recorder_->ExpectEntryMetric(entry, kUkmTrusted, 0u);
190 test_ukm_recorder_->ExpectEntryMetric(entry, kUkmNumInteractions, 3u);
191 test_ukm_recorder_->ExpectEntryMetric(entry, kUkmNumActivationInteractions,
192 2u);
193 test_ukm_recorder_->ExpectEntryMetric(
194 entry, kUkmNumGestureScrollBeginInteractions, 1u);
195 }
196
197 // OpenURLFromTab goes through a different code path than traditional popups
198 // that use window.open(). Make sure the tracker is created in those cases.
IN_PROC_BROWSER_TEST_F(PopupTrackerBrowserTest,ControlClick_HasTracker)199 IN_PROC_BROWSER_TEST_F(PopupTrackerBrowserTest, ControlClick_HasTracker) {
200 base::HistogramTester tester;
201 const GURL url = embedded_test_server()->GetURL(
202 "/popup_blocker/popup-simulated-click-on-anchor.html");
203 ui_test_utils::NavigateToURL(browser(), url);
204
205 // Mac uses command instead of control for the new tab action.
206 bool is_mac = false;
207 #if defined(OS_MAC)
208 is_mac = true;
209 #endif
210
211 content::TestNavigationObserver navigation_observer(nullptr, 1);
212 navigation_observer.StartWatchingNewWebContents();
213
214 SimulateKeyPress(browser()->tab_strip_model()->GetActiveWebContents(),
215 ui::DomKey::ENTER, ui::DomCode::ENTER, ui::VKEY_RETURN,
216 !is_mac /* control */, false /* shift */, false /* alt */,
217 is_mac /* command */);
218 navigation_observer.Wait();
219
220 EXPECT_EQ(1u, chrome::GetBrowserCount(browser()->profile()));
221 content::WebContents* new_contents =
222 browser()->tab_strip_model()->GetWebContentsAt(1);
223 EXPECT_TRUE(blocked_content::PopupTracker::FromWebContents(new_contents));
224
225 // Close the popup and check metric.
226 content::WebContentsDestroyedWatcher destroyed_watcher(new_contents);
227 BrowserList::CloseAllBrowsersWithProfile(
228 Profile::FromBrowserContext(new_contents->GetBrowserContext()));
229 destroyed_watcher.Wait();
230
231 tester.ExpectTotalCount(kPopupFirstDocumentEngagement, 1);
232 tester.ExpectTotalCount(kPopupEngagement, 1);
233
234 auto* entry = ExpectAndGetEntry(url);
235 test_ukm_recorder_->ExpectEntryMetric(entry, kUkmUserInitiatedClose, 0u);
236 test_ukm_recorder_->ExpectEntryMetric(entry, kUkmTrusted, 1u);
237 test_ukm_recorder_->ExpectEntryMetric(entry, kUkmNumInteractions, 0u);
238 test_ukm_recorder_->ExpectEntryMetric(entry, kUkmNumActivationInteractions,
239 0u);
240 test_ukm_recorder_->ExpectEntryMetric(
241 entry, kUkmNumGestureScrollBeginInteractions, 0u);
242 }
243
IN_PROC_BROWSER_TEST_F(PopupTrackerBrowserTest,ShiftClick_HasTracker)244 IN_PROC_BROWSER_TEST_F(PopupTrackerBrowserTest, ShiftClick_HasTracker) {
245 base::HistogramTester tester;
246 const GURL url = embedded_test_server()->GetURL(
247 "/popup_blocker/popup-simulated-click-on-anchor.html");
248 ui_test_utils::NavigateToURL(browser(), url);
249
250 content::TestNavigationObserver navigation_observer(nullptr, 1);
251 navigation_observer.StartWatchingNewWebContents();
252
253 SimulateKeyPress(browser()->tab_strip_model()->GetActiveWebContents(),
254 ui::DomKey::ENTER, ui::DomCode::ENTER, ui::VKEY_RETURN,
255 false /* control */, true /* shift */, false /* alt */,
256 false /* command */);
257 navigation_observer.Wait();
258
259 EXPECT_EQ(2u, chrome::GetBrowserCount(browser()->profile()));
260 content::WebContents* new_contents = BrowserList::GetInstance()
261 ->GetLastActive()
262 ->tab_strip_model()
263 ->GetActiveWebContents();
264 EXPECT_TRUE(blocked_content::PopupTracker::FromWebContents(new_contents));
265
266 // Close the popup and check metric.
267 content::WebContentsDestroyedWatcher destroyed_watcher(new_contents);
268 BrowserList::CloseAllBrowsersWithProfile(
269 Profile::FromBrowserContext(new_contents->GetBrowserContext()));
270 destroyed_watcher.Wait();
271
272 tester.ExpectTotalCount(kPopupFirstDocumentEngagement, 1);
273 tester.ExpectTotalCount(kPopupEngagement, 1);
274
275 auto* entry = ExpectAndGetEntry(url);
276 test_ukm_recorder_->ExpectEntryMetric(entry, kUkmUserInitiatedClose, 0u);
277 test_ukm_recorder_->ExpectEntryMetric(entry, kUkmTrusted, 1u);
278 test_ukm_recorder_->ExpectEntryMetric(entry, kUkmNumInteractions, 0u);
279 test_ukm_recorder_->ExpectEntryMetric(entry, kUkmNumActivationInteractions,
280 0u);
281 test_ukm_recorder_->ExpectEntryMetric(
282 entry, kUkmNumGestureScrollBeginInteractions, 0u);
283 }
284
IN_PROC_BROWSER_TEST_F(PopupTrackerBrowserTest,AllowlistedPopup_HasTracker)285 IN_PROC_BROWSER_TEST_F(PopupTrackerBrowserTest, AllowlistedPopup_HasTracker) {
286 base::HistogramTester tester;
287 const GURL url =
288 embedded_test_server()->GetURL("/popup_blocker/popup-window-open.html");
289 content::WebContents* web_contents =
290 browser()->tab_strip_model()->GetActiveWebContents();
291
292 // Is blocked by the popup blocker.
293 ui_test_utils::NavigateToURL(browser(), url);
294 EXPECT_TRUE(content_settings::PageSpecificContentSettings::GetForFrame(
295 web_contents->GetMainFrame())
296 ->IsContentBlocked(ContentSettingsType::POPUPS));
297
298 // Click through to open the popup.
299 content::TestNavigationObserver navigation_observer(nullptr, 1);
300 navigation_observer.StartWatchingNewWebContents();
301 auto* popup_blocker =
302 blocked_content::PopupBlockerTabHelper::FromWebContents(web_contents);
303 popup_blocker->ShowBlockedPopup(
304 popup_blocker->GetBlockedPopupRequests().begin()->first,
305 WindowOpenDisposition::NEW_FOREGROUND_TAB);
306 navigation_observer.Wait();
307
308 // Close the popup and check metric.
309 content::WebContentsDestroyedWatcher destroyed_watcher(
310 browser()->tab_strip_model()->GetActiveWebContents());
311 browser()->tab_strip_model()->CloseAllTabs();
312 destroyed_watcher.Wait();
313
314 tester.ExpectTotalCount(kPopupFirstDocumentEngagement, 1);
315 tester.ExpectTotalCount(kPopupEngagement, 1);
316
317 auto* entry = ExpectAndGetEntry(url);
318 test_ukm_recorder_->ExpectEntryMetric(entry, kUkmUserInitiatedClose, 0u);
319 test_ukm_recorder_->ExpectEntryMetric(entry, kUkmTrusted, 1u);
320 test_ukm_recorder_->ExpectEntryMetric(entry, kUkmNumInteractions, 0u);
321 test_ukm_recorder_->ExpectEntryMetric(entry, kUkmNumActivationInteractions,
322 0u);
323 test_ukm_recorder_->ExpectEntryMetric(
324 entry, kUkmNumGestureScrollBeginInteractions, 0u);
325 }
326
IN_PROC_BROWSER_TEST_F(PopupTrackerBrowserTest,NoOpener_NoTracker)327 IN_PROC_BROWSER_TEST_F(PopupTrackerBrowserTest, NoOpener_NoTracker) {
328 const GURL url = embedded_test_server()->GetURL("/title1.html");
329 ui_test_utils::NavigateToURLWithDisposition(
330 browser(), url, WindowOpenDisposition::NEW_FOREGROUND_TAB,
331 ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP);
332
333 content::WebContents* new_contents =
334 browser()->tab_strip_model()->GetWebContentsAt(1);
335
336 EXPECT_FALSE(blocked_content::PopupTracker::FromWebContents(new_contents));
337 EXPECT_EQ(0u, GetNumPopupUkmEntries());
338 }
339
340 // Tests for the subresource_filter popup blocker.
341 class SafeBrowsingPopupTrackerBrowserTest : public PopupTrackerBrowserTest {
342 public:
343 SafeBrowsingPopupTrackerBrowserTest() = default;
344 ~SafeBrowsingPopupTrackerBrowserTest() override = default;
345
SetUp()346 void SetUp() override {
347 database_helper_ = CreateTestDatabase();
348 PopupTrackerBrowserTest::SetUp();
349 }
350
SetUpOnMainThread()351 void SetUpOnMainThread() override {
352 base::FilePath test_data_dir;
353 base::PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir);
354 embedded_test_server()->ServeFilesFromDirectory(test_data_dir);
355 host_resolver()->AddRule("*", "127.0.0.1");
356 content::SetupCrossSiteRedirector(embedded_test_server());
357
358 ASSERT_TRUE(embedded_test_server()->Start());
359 }
360
TearDown()361 void TearDown() override {
362 InProcessBrowserTest::TearDown();
363 database_helper_.reset();
364 }
365
CreateTestDatabase()366 virtual std::unique_ptr<TestSafeBrowsingDatabaseHelper> CreateTestDatabase() {
367 std::vector<safe_browsing::ListIdentifier> list_ids = {
368 safe_browsing::GetUrlSubresourceFilterId()};
369 return std::make_unique<TestSafeBrowsingDatabaseHelper>(
370 std::make_unique<safe_browsing::TestV4GetHashProtocolManagerFactory>(),
371 std::move(list_ids));
372 }
373
ConfigureAsList(const GURL & url,const safe_browsing::ListIdentifier & list_identifier)374 void ConfigureAsList(const GURL& url,
375 const safe_browsing::ListIdentifier& list_identifier) {
376 safe_browsing::ThreatMetadata metadata;
377 database_helper_->AddFullHashToDbAndFullHashCache(url, list_identifier,
378 metadata);
379 }
380
database_helper()381 TestSafeBrowsingDatabaseHelper* database_helper() {
382 return database_helper_.get();
383 }
384
385 private:
386 std::unique_ptr<TestSafeBrowsingDatabaseHelper> database_helper_;
387
388 DISALLOW_COPY_AND_ASSIGN(SafeBrowsingPopupTrackerBrowserTest);
389 };
390
391 // Pop-ups closed before navigation has finished will receive no safe browsing
392 // status.
IN_PROC_BROWSER_TEST_F(SafeBrowsingPopupTrackerBrowserTest,PopupClosedBeforeNavigationFinished_LoggedAsNoValue)393 IN_PROC_BROWSER_TEST_F(SafeBrowsingPopupTrackerBrowserTest,
394 PopupClosedBeforeNavigationFinished_LoggedAsNoValue) {
395 const GURL first_url = embedded_test_server()->GetURL("/title1.html");
396 ui_test_utils::NavigateToURL(browser(), first_url);
397
398 const GURL unsafe_url = embedded_test_server()->GetURL("/slow");
399 ConfigureAsList(unsafe_url, safe_browsing::GetUrlSocEngId());
400
401 content::TestNavigationObserver navigation_observer(nullptr, 1);
402 navigation_observer.StartWatchingNewWebContents();
403
404 EXPECT_TRUE(
405 content::ExecJs(browser()->tab_strip_model()->GetActiveWebContents(),
406 "window.open('/slow?1000')"));
407
408 EXPECT_EQ(2, browser()->tab_strip_model()->count());
409 content::WebContents* popup =
410 browser()->tab_strip_model()->GetActiveWebContents();
411 EXPECT_TRUE(blocked_content::PopupTracker::FromWebContents(popup));
412
413 // Close the popup and check metric.
414 int active_index = browser()->tab_strip_model()->active_index();
415 content::WebContentsDestroyedWatcher destroyed_watcher(popup);
416 browser()->tab_strip_model()->CloseWebContentsAt(
417 active_index, TabStripModel::CLOSE_USER_GESTURE);
418 destroyed_watcher.Wait();
419
420 auto* entry = ExpectAndGetEntry(first_url);
421 test_ukm_recorder_->ExpectEntryMetric(
422 entry, kUkmSafeBrowsingStatus,
423 static_cast<int>(
424 blocked_content::PopupTracker::PopupSafeBrowsingStatus::kNoValue));
425 }
426
IN_PROC_BROWSER_TEST_F(SafeBrowsingPopupTrackerBrowserTest,SafePopup_LoggedAsSafe)427 IN_PROC_BROWSER_TEST_F(SafeBrowsingPopupTrackerBrowserTest,
428 SafePopup_LoggedAsSafe) {
429 const GURL first_url = embedded_test_server()->GetURL("/title1.html");
430 ui_test_utils::NavigateToURL(browser(), first_url);
431
432 content::TestNavigationObserver navigation_observer(nullptr, 1);
433 navigation_observer.StartWatchingNewWebContents();
434
435 const GURL second_url = embedded_test_server()->GetURL("/title2.html");
436 EXPECT_TRUE(
437 content::ExecJs(browser()->tab_strip_model()->GetActiveWebContents(),
438 "window.open('/title2.html')"));
439 navigation_observer.Wait();
440
441 EXPECT_EQ(2, browser()->tab_strip_model()->count());
442 content::WebContents* popup =
443 browser()->tab_strip_model()->GetActiveWebContents();
444 EXPECT_TRUE(blocked_content::PopupTracker::FromWebContents(popup));
445
446 // Close the popup and check metric.
447 int active_index = browser()->tab_strip_model()->active_index();
448 content::WebContentsDestroyedWatcher destroyed_watcher(popup);
449 browser()->tab_strip_model()->CloseWebContentsAt(
450 active_index, TabStripModel::CLOSE_USER_GESTURE);
451 destroyed_watcher.Wait();
452
453 auto* entry = ExpectAndGetEntry(first_url);
454 test_ukm_recorder_->ExpectEntryMetric(
455 entry, kUkmSafeBrowsingStatus,
456 static_cast<int>(
457 blocked_content::PopupTracker::PopupSafeBrowsingStatus::kSafe));
458 }
459
IN_PROC_BROWSER_TEST_F(SafeBrowsingPopupTrackerBrowserTest,PhishingPopup_LoggedAsUnsafe)460 IN_PROC_BROWSER_TEST_F(SafeBrowsingPopupTrackerBrowserTest,
461 PhishingPopup_LoggedAsUnsafe) {
462 const GURL first_url = embedded_test_server()->GetURL("/title1.html");
463 ui_test_utils::NavigateToURL(browser(), first_url);
464
465 // Associate each domain with a separate safe browsing ListIdentifier to
466 // exercise the set of lists.
467 std::vector<std::pair<std::string, safe_browsing::ListIdentifier>>
468 domain_list_pairs = {
469 {"a.com", safe_browsing::GetUrlSocEngId()},
470 {"b.com", safe_browsing::GetUrlSubresourceFilterId()}};
471
472 // For each pair, configure the local safe browsing database and open a
473 // pop-up to the url.
474 for (const auto& domain_list_pair : domain_list_pairs) {
475 const GURL unsafe_url =
476 embedded_test_server()->GetURL(domain_list_pair.first, "/title2.html");
477 ConfigureAsList(unsafe_url, domain_list_pair.second);
478
479 content::TestNavigationObserver navigation_observer(nullptr, 1);
480 navigation_observer.StartWatchingNewWebContents();
481
482 EXPECT_TRUE(
483 content::ExecJs(browser()->tab_strip_model()->GetActiveWebContents(),
484 "window.open('" + unsafe_url.spec() + "')"));
485 navigation_observer.Wait();
486
487 EXPECT_EQ(2, browser()->tab_strip_model()->count());
488 content::WebContents* popup =
489 browser()->tab_strip_model()->GetActiveWebContents();
490 EXPECT_TRUE(blocked_content::PopupTracker::FromWebContents(popup));
491
492 // Close the popup and check metric.
493 int active_index = browser()->tab_strip_model()->active_index();
494 content::WebContentsDestroyedWatcher destroyed_watcher(popup);
495 browser()->tab_strip_model()->CloseWebContentsAt(
496 active_index, TabStripModel::CLOSE_USER_GESTURE);
497 destroyed_watcher.Wait();
498 }
499
500 // The URL should have 4 pop-up entries with an unsafe safe browsing status.
501 auto entries = test_ukm_recorder_->GetEntriesByName(
502 ukm::builders::Popup_Closed::kEntryName);
503 EXPECT_EQ(2u, entries.size());
504 for (auto* entry : entries) {
505 test_ukm_recorder_->ExpectEntryMetric(
506 entry, kUkmSafeBrowsingStatus,
507 static_cast<int>(
508 blocked_content::PopupTracker::PopupSafeBrowsingStatus::kUnsafe));
509 }
510 }
511
IN_PROC_BROWSER_TEST_F(PopupTrackerBrowserTest,PopupInTab_IsWindowFalse)512 IN_PROC_BROWSER_TEST_F(PopupTrackerBrowserTest, PopupInTab_IsWindowFalse) {
513 const GURL first_url = embedded_test_server()->GetURL("/title1.html");
514 ui_test_utils::NavigateToURL(browser(), first_url);
515
516 content::TestNavigationObserver navigation_observer(nullptr, 1);
517 navigation_observer.StartWatchingNewWebContents();
518
519 EXPECT_TRUE(
520 content::ExecJs(browser()->tab_strip_model()->GetActiveWebContents(),
521 "window.open('/title1.html')"));
522 navigation_observer.Wait();
523
524 EXPECT_EQ(2, browser()->tab_strip_model()->count());
525 content::WebContents* popup =
526 browser()->tab_strip_model()->GetActiveWebContents();
527 EXPECT_TRUE(blocked_content::PopupTracker::FromWebContents(popup));
528
529 // Close the popup and check metric.
530 int active_index = browser()->tab_strip_model()->active_index();
531 content::WebContentsDestroyedWatcher destroyed_watcher(popup);
532 browser()->tab_strip_model()->CloseWebContentsAt(
533 active_index, TabStripModel::CLOSE_USER_GESTURE);
534 destroyed_watcher.Wait();
535
536 auto* entry = ExpectAndGetEntry(first_url);
537 test_ukm_recorder_->ExpectEntryMetric(
538 entry, kUkmWindowOpenDisposition,
539 static_cast<int>(WindowOpenDisposition::NEW_FOREGROUND_TAB));
540 }
541
IN_PROC_BROWSER_TEST_F(PopupTrackerBrowserTest,PopupInWindow_IsWindowTrue)542 IN_PROC_BROWSER_TEST_F(PopupTrackerBrowserTest, PopupInWindow_IsWindowTrue) {
543 const GURL first_url = embedded_test_server()->GetURL("/title1.html");
544 ui_test_utils::NavigateToURL(browser(), first_url);
545
546 content::TestNavigationObserver navigation_observer(nullptr, 1);
547 navigation_observer.StartWatchingNewWebContents();
548 EXPECT_TRUE(content::ExecJs(
549 browser()->tab_strip_model()->GetActiveWebContents(),
550 "window.open('/title1.html', 'new_window', "
551 "'location=yes,height=570,width=520,scrollbars=yes,status=yes')"));
552 navigation_observer.Wait();
553 EXPECT_EQ(2u, chrome::GetTotalBrowserCount());
554
555 Browser* created_browser = chrome::FindLastActive();
556
557 EXPECT_EQ(1, created_browser->tab_strip_model()->count());
558 content::WebContents* popup =
559 created_browser->tab_strip_model()->GetActiveWebContents();
560 EXPECT_TRUE(blocked_content::PopupTracker::FromWebContents(popup));
561
562 // Close the popup and check metric.
563 int active_index = created_browser->tab_strip_model()->active_index();
564 content::WebContentsDestroyedWatcher destroyed_watcher(popup);
565 created_browser->tab_strip_model()->CloseWebContentsAt(
566 active_index, TabStripModel::CLOSE_USER_GESTURE);
567 destroyed_watcher.Wait();
568
569 auto* entry = ExpectAndGetEntry(first_url);
570 test_ukm_recorder_->ExpectEntryMetric(
571 entry, kUkmWindowOpenDisposition,
572 static_cast<int>(WindowOpenDisposition::NEW_POPUP));
573 }
574
575 // TODO(crbug.com/1146598): Test is flaky on Lacros.
576 #if BUILDFLAG(IS_LACROS)
577 #define MAYBE_PopupNoRedirect_RedirectCountZero DISABLED_PopupNoRedirect_RedirectCountZero
578 #else
579 #define MAYBE_PopupNoRedirect_RedirectCountZero PopupNoRedirect_RedirectCountZero
580 #endif
IN_PROC_BROWSER_TEST_F(PopupTrackerBrowserTest,MAYBE_PopupNoRedirect_RedirectCountZero)581 IN_PROC_BROWSER_TEST_F(PopupTrackerBrowserTest,
582 MAYBE_PopupNoRedirect_RedirectCountZero) {
583 const GURL first_url = embedded_test_server()->GetURL("/title1.html");
584 ui_test_utils::NavigateToURL(browser(), first_url);
585
586 content::TestNavigationObserver navigation_observer(nullptr, 1);
587 navigation_observer.StartWatchingNewWebContents();
588 EXPECT_TRUE(content::ExecJs(
589 browser()->tab_strip_model()->GetActiveWebContents(),
590 "window.open('/title1.html', 'new_window', "
591 "'location=yes,height=570,width=520,scrollbars=yes,status=yes')"));
592 navigation_observer.Wait();
593 EXPECT_EQ(2u, chrome::GetTotalBrowserCount());
594
595 Browser* created_browser = chrome::FindLastActive();
596
597 EXPECT_EQ(1, created_browser->tab_strip_model()->count());
598 content::WebContents* popup =
599 created_browser->tab_strip_model()->GetActiveWebContents();
600 EXPECT_TRUE(blocked_content::PopupTracker::FromWebContents(popup));
601
602 // Close the popup and check that the pop up did not redirect.
603 int active_index = created_browser->tab_strip_model()->active_index();
604 content::WebContentsDestroyedWatcher destroyed_watcher(popup);
605 created_browser->tab_strip_model()->CloseWebContentsAt(
606 active_index, TabStripModel::CLOSE_USER_GESTURE);
607 destroyed_watcher.Wait();
608
609 auto* entry = ExpectAndGetEntry(first_url);
610 test_ukm_recorder_->ExpectEntryMetric(entry, kUkmRedirectCount, 0);
611 }
612
IN_PROC_BROWSER_TEST_F(PopupTrackerBrowserTest,PopupRedirectsTwice_RedirectCountTwo)613 IN_PROC_BROWSER_TEST_F(PopupTrackerBrowserTest,
614 PopupRedirectsTwice_RedirectCountTwo) {
615 const GURL first_url = embedded_test_server()->GetURL("/title1.html");
616 ui_test_utils::NavigateToURL(browser(), first_url);
617
618 content::TestNavigationObserver navigation_observer(nullptr, 1);
619 navigation_observer.StartWatchingNewWebContents();
620
621 // Redirect the popup using /server-redirect twice.
622 EXPECT_TRUE(content::ExecJs(
623 browser()->tab_strip_model()->GetActiveWebContents(),
624 "window.open('/server-redirect?/server-redirect?/title1.html',"
625 "'new_window', 'location=yes,height=570,width=520,scrollbars=yes,"
626 "status=yes')"));
627 navigation_observer.Wait();
628 EXPECT_EQ(2u, chrome::GetTotalBrowserCount());
629
630 Browser* created_browser = chrome::FindLastActive();
631
632 EXPECT_EQ(1, created_browser->tab_strip_model()->count());
633 content::WebContents* popup =
634 created_browser->tab_strip_model()->GetActiveWebContents();
635 EXPECT_TRUE(blocked_content::PopupTracker::FromWebContents(popup));
636
637 // Close the popup and check metric.
638 int active_index = created_browser->tab_strip_model()->active_index();
639 content::WebContentsDestroyedWatcher destroyed_watcher(popup);
640 created_browser->tab_strip_model()->CloseWebContentsAt(
641 active_index, TabStripModel::CLOSE_USER_GESTURE);
642 destroyed_watcher.Wait();
643
644 auto* entry = ExpectAndGetEntry(first_url);
645 test_ukm_recorder_->ExpectEntryMetric(entry, kUkmRedirectCount, 2);
646 }
647
IN_PROC_BROWSER_TEST_F(PopupTrackerBrowserTest,PopupJavascriptRenavigation_RedirectCountZero)648 IN_PROC_BROWSER_TEST_F(PopupTrackerBrowserTest,
649 PopupJavascriptRenavigation_RedirectCountZero) {
650 const GURL first_url = embedded_test_server()->GetURL("/title1.html");
651 ui_test_utils::NavigateToURL(browser(), first_url);
652
653 content::TestNavigationObserver navigation_observer(nullptr, 1);
654 navigation_observer.StartWatchingNewWebContents();
655
656 // Redirect the popup using /server-redirect twice.
657 EXPECT_TRUE(content::ExecJs(
658 browser()->tab_strip_model()->GetActiveWebContents(),
659 "var w = window.open('',"
660 "'new_window', 'location=yes,height=570,width=520,scrollbars=yes,"
661 "status=yes'); "
662 "w.location = '/title1.html'"));
663 navigation_observer.Wait();
664 EXPECT_EQ(2u, chrome::GetTotalBrowserCount());
665
666 Browser* created_browser = chrome::FindLastActive();
667
668 EXPECT_EQ(1, created_browser->tab_strip_model()->count());
669 content::WebContents* popup =
670 created_browser->tab_strip_model()->GetActiveWebContents();
671 EXPECT_TRUE(blocked_content::PopupTracker::FromWebContents(popup));
672
673 // Close the popup and check metric.
674 int active_index = created_browser->tab_strip_model()->active_index();
675 content::WebContentsDestroyedWatcher destroyed_watcher(popup);
676 created_browser->tab_strip_model()->CloseWebContentsAt(
677 active_index, TabStripModel::CLOSE_USER_GESTURE);
678 destroyed_watcher.Wait();
679
680 auto* entry = ExpectAndGetEntry(first_url);
681 test_ukm_recorder_->ExpectEntryMetric(entry, kUkmRedirectCount, 0);
682 }
683