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