Refactor WebsiteSettings to operate on a SecurityInfo
[chromium-blink-merge.git] / chrome / browser / safe_browsing / safe_browsing_blocking_page_test.cc
blob99488eac1024711fbeef82d630f36a7d43070b89
1 // Copyright (c) 2012 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 // This test creates a fake safebrowsing service, where we can inject known-
6 // threat urls. It then uses a real browser to go to these urls, and sends
7 // "goback" or "proceed" commands and verifies they work.
9 #include "base/bind.h"
10 #include "base/command_line.h"
11 #include "base/prefs/pref_service.h"
12 #include "base/strings/string_number_conversions.h"
13 #include "base/strings/utf_string_conversions.h"
14 #include "base/test/histogram_tester.h"
15 #include "base/values.h"
16 #include "chrome/browser/browser_process.h"
17 #include "chrome/browser/interstitials/security_interstitial_page_test_utils.h"
18 #include "chrome/browser/net/url_request_mock_util.h"
19 #include "chrome/browser/profiles/profile.h"
20 #include "chrome/browser/safe_browsing/database_manager.h"
21 #include "chrome/browser/safe_browsing/local_database_manager.h"
22 #include "chrome/browser/safe_browsing/malware_details.h"
23 #include "chrome/browser/safe_browsing/safe_browsing_blocking_page.h"
24 #include "chrome/browser/safe_browsing/safe_browsing_service.h"
25 #include "chrome/browser/safe_browsing/safe_browsing_util.h"
26 #include "chrome/browser/safe_browsing/test_database_manager.h"
27 #include "chrome/browser/safe_browsing/ui_manager.h"
28 #include "chrome/browser/ui/browser.h"
29 #include "chrome/browser/ui/browser_tabstrip.h"
30 #include "chrome/browser/ui/tabs/tab_strip_model.h"
31 #include "chrome/common/pref_names.h"
32 #include "chrome/common/url_constants.h"
33 #include "chrome/test/base/in_process_browser_test.h"
34 #include "chrome/test/base/test_switches.h"
35 #include "chrome/test/base/ui_test_utils.h"
36 #include "components/security_interstitials/core/metrics_helper.h"
37 #include "content/public/browser/interstitial_page.h"
38 #include "content/public/browser/navigation_controller.h"
39 #include "content/public/browser/notification_types.h"
40 #include "content/public/browser/render_frame_host.h"
41 #include "content/public/browser/render_process_host.h"
42 #include "content/public/browser/render_view_host.h"
43 #include "content/public/browser/web_contents.h"
44 #include "content/public/test/browser_test_utils.h"
45 #include "content/public/test/test_browser_thread.h"
46 #include "content/public/test/test_utils.h"
47 #include "net/test/url_request/url_request_mock_http_job.h"
49 using chrome_browser_interstitials::SecurityInterstitialIDNTest;
50 using content::BrowserThread;
51 using content::InterstitialPage;
52 using content::NavigationController;
53 using content::WebContents;
55 namespace {
57 const char kEmptyPage[] = "empty.html";
58 const char kMalwarePage[] = "safe_browsing/malware.html";
59 const char kMalwareIframe[] = "safe_browsing/malware_iframe.html";
60 const char kUnrelatedUrl[] = "https://www.google.com";
62 // A SafeBrowsingDatabaseManager class that allows us to inject the malicious
63 // URLs.
64 class FakeSafeBrowsingDatabaseManager : public TestSafeBrowsingDatabaseManager {
65 public:
66 FakeSafeBrowsingDatabaseManager() {}
68 // Called on the IO thread to check if the given url is safe or not. If we
69 // can synchronously determine that the url is safe, CheckUrl returns true.
70 // Otherwise it returns false, and "client" is called asynchronously with the
71 // result when it is ready.
72 // Overrides SafeBrowsingDatabaseManager::CheckBrowseUrl.
73 bool CheckBrowseUrl(const GURL& gurl, Client* client) override {
74 if (badurls[gurl.spec()] == SB_THREAT_TYPE_SAFE)
75 return true;
77 BrowserThread::PostTask(
78 BrowserThread::IO, FROM_HERE,
79 base::Bind(&FakeSafeBrowsingDatabaseManager::OnCheckBrowseURLDone,
80 this, gurl, client));
81 return false;
84 void OnCheckBrowseURLDone(const GURL& gurl, Client* client) {
85 std::vector<SBThreatType> expected_threats;
86 // TODO(nparker): Remove ref to LocalSafeBrowsingDatabase by calling
87 // client->OnCheckBrowseUrlResult(..) directly.
88 expected_threats.push_back(SB_THREAT_TYPE_URL_MALWARE);
89 expected_threats.push_back(SB_THREAT_TYPE_URL_PHISHING);
90 expected_threats.push_back(SB_THREAT_TYPE_URL_UNWANTED);
91 LocalSafeBrowsingDatabaseManager::SafeBrowsingCheck sb_check(
92 std::vector<GURL>(1, gurl),
93 std::vector<SBFullHash>(),
94 client,
95 safe_browsing_util::MALWARE,
96 expected_threats);
97 sb_check.url_results[0] = badurls[gurl.spec()];
98 sb_check.OnSafeBrowsingResult();
101 void SetURLThreatType(const GURL& url, SBThreatType threat_type) {
102 badurls[url.spec()] = threat_type;
105 // Called during startup, so must not check-fail.
106 bool CheckExtensionIDs(const std::set<std::string>& extension_ids,
107 Client* client) override {
108 return true;
111 private:
112 ~FakeSafeBrowsingDatabaseManager() override {}
114 base::hash_map<std::string, SBThreatType> badurls;
115 DISALLOW_COPY_AND_ASSIGN(FakeSafeBrowsingDatabaseManager);
118 // A SafeBrowingUIManager class that allows intercepting malware details.
119 class FakeSafeBrowsingUIManager : public SafeBrowsingUIManager {
120 public:
121 explicit FakeSafeBrowsingUIManager(SafeBrowsingService* service) :
122 SafeBrowsingUIManager(service) { }
124 // Overrides SafeBrowsingUIManager
125 void SendSerializedMalwareDetails(const std::string& serialized) override {
126 // Notify the UI thread that we got a report.
127 BrowserThread::PostTask(
128 BrowserThread::UI,
129 FROM_HERE,
130 base::Bind(&FakeSafeBrowsingUIManager::OnMalwareDetailsDone,
131 this,
132 serialized));
135 void OnMalwareDetailsDone(const std::string& serialized) {
136 EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI));
137 report_ = serialized;
139 EXPECT_FALSE(malware_details_done_callback_.is_null());
140 if (!malware_details_done_callback_.is_null()) {
141 malware_details_done_callback_.Run();
142 malware_details_done_callback_ = base::Closure();
146 void set_malware_details_done_callback(const base::Closure& callback) {
147 EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI));
148 EXPECT_TRUE(malware_details_done_callback_.is_null());
149 malware_details_done_callback_ = callback;
152 std::string GetReport() {
153 EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI));
154 return report_;
157 protected:
158 ~FakeSafeBrowsingUIManager() override {}
160 private:
161 std::string report_;
162 base::Closure malware_details_done_callback_;
164 DISALLOW_COPY_AND_ASSIGN(FakeSafeBrowsingUIManager);
167 class FakeSafeBrowsingService : public SafeBrowsingService {
168 public:
169 FakeSafeBrowsingService()
170 : fake_database_manager_(),
171 fake_ui_manager_() { }
173 // Returned pointer has the same lifespan as the database_manager_ refcounted
174 // object.
175 FakeSafeBrowsingDatabaseManager* fake_database_manager() {
176 return fake_database_manager_;
178 // Returned pointer has the same lifespan as the ui_manager_ refcounted
179 // object.
180 FakeSafeBrowsingUIManager* fake_ui_manager() {
181 return fake_ui_manager_;
184 protected:
185 ~FakeSafeBrowsingService() override {}
187 SafeBrowsingDatabaseManager* CreateDatabaseManager() override {
188 fake_database_manager_ = new FakeSafeBrowsingDatabaseManager();
189 return fake_database_manager_;
192 SafeBrowsingUIManager* CreateUIManager() override {
193 fake_ui_manager_ = new FakeSafeBrowsingUIManager(this);
194 return fake_ui_manager_;
197 SafeBrowsingProtocolManagerDelegate* GetProtocolManagerDelegate() override {
198 // Our SafeBrowsingDatabaseManager doesn't implement this delegate.
199 return NULL;
202 private:
203 FakeSafeBrowsingDatabaseManager* fake_database_manager_;
204 FakeSafeBrowsingUIManager* fake_ui_manager_;
206 DISALLOW_COPY_AND_ASSIGN(FakeSafeBrowsingService);
209 // Factory that creates FakeSafeBrowsingService instances.
210 class TestSafeBrowsingServiceFactory : public SafeBrowsingServiceFactory {
211 public:
212 TestSafeBrowsingServiceFactory() :
213 most_recent_service_(NULL) { }
214 ~TestSafeBrowsingServiceFactory() override {}
216 SafeBrowsingService* CreateSafeBrowsingService() override {
217 most_recent_service_ = new FakeSafeBrowsingService();
218 return most_recent_service_;
221 FakeSafeBrowsingService* most_recent_service() const {
222 return most_recent_service_;
225 private:
226 FakeSafeBrowsingService* most_recent_service_;
229 // A MalwareDetails class lets us intercept calls from the renderer.
230 class FakeMalwareDetails : public MalwareDetails {
231 public:
232 FakeMalwareDetails(
233 SafeBrowsingUIManager* delegate,
234 WebContents* web_contents,
235 const SafeBrowsingUIManager::UnsafeResource& unsafe_resource)
236 : MalwareDetails(delegate, web_contents, unsafe_resource),
237 got_dom_(false),
238 waiting_(false) { }
240 void AddDOMDetails(
241 const std::vector<SafeBrowsingHostMsg_MalwareDOMDetails_Node>& params)
242 override {
243 EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
244 MalwareDetails::AddDOMDetails(params);
246 // Notify the UI thread that we got the dom details.
247 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
248 base::Bind(&FakeMalwareDetails::OnDOMDetailsDone,
249 this));
252 void WaitForDOM() {
253 if (got_dom_) {
254 return;
256 // This condition might not trigger normally, but if you add a
257 // sleep(1) in malware_dom_details it triggers :).
258 waiting_ = true;
259 content::RunMessageLoop();
260 EXPECT_TRUE(got_dom_);
263 private:
264 ~FakeMalwareDetails() override {}
266 void OnDOMDetailsDone() {
267 got_dom_ = true;
268 if (waiting_) {
269 base::MessageLoopForUI::current()->Quit();
273 // Some logic to figure out if we should wait for the dom details or not.
274 // These variables should only be accessed in the UI thread.
275 bool got_dom_;
276 bool waiting_;
279 class TestMalwareDetailsFactory : public MalwareDetailsFactory {
280 public:
281 TestMalwareDetailsFactory() : details_() { }
282 ~TestMalwareDetailsFactory() override {}
284 MalwareDetails* CreateMalwareDetails(
285 SafeBrowsingUIManager* delegate,
286 WebContents* web_contents,
287 const SafeBrowsingUIManager::UnsafeResource& unsafe_resource) override {
288 details_ = new FakeMalwareDetails(delegate, web_contents,
289 unsafe_resource);
290 return details_;
293 FakeMalwareDetails* get_details() {
294 return details_;
297 private:
298 FakeMalwareDetails* details_;
301 // A SafeBrowingBlockingPage class that lets us wait until it's hidden.
302 class TestSafeBrowsingBlockingPage : public SafeBrowsingBlockingPage {
303 public:
304 TestSafeBrowsingBlockingPage(SafeBrowsingUIManager* manager,
305 WebContents* web_contents,
306 const UnsafeResourceList& unsafe_resources)
307 : SafeBrowsingBlockingPage(manager, web_contents, unsafe_resources),
308 wait_for_delete_(false) {
309 // Don't wait the whole 3 seconds for the browser test.
310 malware_details_proceed_delay_ms_ = 100;
313 ~TestSafeBrowsingBlockingPage() override {
314 if (!wait_for_delete_)
315 return;
317 // Notify that we are gone
318 base::MessageLoopForUI::current()->Quit();
319 wait_for_delete_ = false;
322 void WaitForDelete() {
323 wait_for_delete_ = true;
324 content::RunMessageLoop();
327 // InterstitialPageDelegate methods:
328 void CommandReceived(const std::string& command) override {
329 SafeBrowsingBlockingPage::CommandReceived(command);
331 void OnProceed() override { SafeBrowsingBlockingPage::OnProceed(); }
332 void OnDontProceed() override { SafeBrowsingBlockingPage::OnDontProceed(); }
334 private:
335 bool wait_for_delete_;
338 class TestSafeBrowsingBlockingPageFactory
339 : public SafeBrowsingBlockingPageFactory {
340 public:
341 TestSafeBrowsingBlockingPageFactory() { }
342 ~TestSafeBrowsingBlockingPageFactory() override {}
344 SafeBrowsingBlockingPage* CreateSafeBrowsingPage(
345 SafeBrowsingUIManager* delegate,
346 WebContents* web_contents,
347 const SafeBrowsingBlockingPage::UnsafeResourceList& unsafe_resources)
348 override {
349 return new TestSafeBrowsingBlockingPage(delegate, web_contents,
350 unsafe_resources);
354 } // namespace
356 // Tests the safe browsing blocking page in a browser.
357 class SafeBrowsingBlockingPageBrowserTest
358 : public InProcessBrowserTest,
359 public testing::WithParamInterface<SBThreatType> {
360 public:
361 enum Visibility {
362 VISIBILITY_ERROR = -1,
363 HIDDEN = 0,
364 VISIBLE = 1
367 SafeBrowsingBlockingPageBrowserTest() {}
369 void SetUp() override {
370 SafeBrowsingService::RegisterFactory(&factory_);
371 SafeBrowsingBlockingPage::RegisterFactory(&blocking_page_factory_);
372 MalwareDetails::RegisterFactory(&details_factory_);
373 InProcessBrowserTest::SetUp();
376 void TearDown() override {
377 InProcessBrowserTest::TearDown();
378 SafeBrowsingBlockingPage::RegisterFactory(NULL);
379 SafeBrowsingService::RegisterFactory(NULL);
380 MalwareDetails::RegisterFactory(NULL);
383 void SetUpOnMainThread() override {
384 BrowserThread::PostTask(
385 BrowserThread::IO, FROM_HERE,
386 base::Bind(&chrome_browser_net::SetUrlRequestMocksEnabled, true));
389 void SetURLThreatType(const GURL& url, SBThreatType threat_type) {
390 FakeSafeBrowsingService* service =
391 static_cast<FakeSafeBrowsingService*>(
392 g_browser_process->safe_browsing_service());
394 ASSERT_TRUE(service);
395 service->fake_database_manager()->SetURLThreatType(url, threat_type);
398 // Adds a safebrowsing result of the current test threat to the fake
399 // safebrowsing service, navigates to that page, and returns the url.
400 GURL SetupWarningAndNavigate() {
401 GURL url = net::URLRequestMockHTTPJob::GetMockUrl(kEmptyPage);
402 SetURLThreatType(url, GetParam());
404 ui_test_utils::NavigateToURL(browser(), url);
405 EXPECT_TRUE(WaitForReady());
406 return url;
409 // Adds a safebrowsing threat result to the fake safebrowsing service,
410 // navigates to a page with an iframe containing the threat site, and returns
411 // the url of the parent page.
412 GURL SetupThreatIframeWarningAndNavigate() {
413 GURL url = net::URLRequestMockHTTPJob::GetMockUrl(kMalwarePage);
414 GURL iframe_url = net::URLRequestMockHTTPJob::GetMockUrl(kMalwareIframe);
415 SetURLThreatType(iframe_url, GetParam());
417 ui_test_utils::NavigateToURL(browser(), url);
418 EXPECT_TRUE(WaitForReady());
419 return url;
422 void SendCommand(
423 SecurityInterstitialPage::SecurityInterstitialCommands command) {
424 WebContents* contents =
425 browser()->tab_strip_model()->GetActiveWebContents();
426 // We use InterstitialPage::GetInterstitialPage(tab) instead of
427 // tab->GetInterstitialPage() because the tab doesn't have a pointer
428 // to its interstital page until it gets a command from the renderer
429 // that it has indeed displayed it -- and this sometimes happens after
430 // NavigateToURL returns.
431 SafeBrowsingBlockingPage* interstitial_page =
432 static_cast<SafeBrowsingBlockingPage*>(
433 InterstitialPage::GetInterstitialPage(contents)->
434 GetDelegateForTesting());
435 ASSERT_TRUE(interstitial_page);
436 ASSERT_EQ(SafeBrowsingBlockingPage::kTypeForTesting,
437 interstitial_page->GetTypeForTesting());
438 interstitial_page->CommandReceived(base::IntToString(command));
441 void DontProceedThroughInterstitial() {
442 WebContents* contents =
443 browser()->tab_strip_model()->GetActiveWebContents();
444 InterstitialPage* interstitial_page = InterstitialPage::GetInterstitialPage(
445 contents);
446 ASSERT_TRUE(interstitial_page);
447 interstitial_page->DontProceed();
450 void ProceedThroughInterstitial() {
451 WebContents* contents =
452 browser()->tab_strip_model()->GetActiveWebContents();
453 InterstitialPage* interstitial_page = InterstitialPage::GetInterstitialPage(
454 contents);
455 ASSERT_TRUE(interstitial_page);
456 interstitial_page->Proceed();
459 void AssertNoInterstitial(bool wait_for_delete) {
460 WebContents* contents =
461 browser()->tab_strip_model()->GetActiveWebContents();
463 if (contents->ShowingInterstitialPage() && wait_for_delete) {
464 // We'll get notified when the interstitial is deleted.
465 TestSafeBrowsingBlockingPage* page =
466 static_cast<TestSafeBrowsingBlockingPage*>(
467 contents->GetInterstitialPage()->GetDelegateForTesting());
468 ASSERT_EQ(SafeBrowsingBlockingPage::kTypeForTesting,
469 page->GetTypeForTesting());
470 page->WaitForDelete();
473 // Can't use InterstitialPage::GetInterstitialPage() because that
474 // gets updated after the TestSafeBrowsingBlockingPage destructor
475 ASSERT_FALSE(contents->ShowingInterstitialPage());
478 bool YesInterstitial() {
479 WebContents* contents =
480 browser()->tab_strip_model()->GetActiveWebContents();
481 InterstitialPage* interstitial_page = InterstitialPage::GetInterstitialPage(
482 contents);
483 return interstitial_page != NULL;
486 void SetReportSentCallback(const base::Closure& callback) {
487 factory_.most_recent_service()
488 ->fake_ui_manager()
489 ->set_malware_details_done_callback(callback);
492 std::string GetReportSent() {
493 return factory_.most_recent_service()->fake_ui_manager()->GetReport();
496 void MalwareRedirectCancelAndProceed(const std::string& open_function) {
497 GURL load_url = net::URLRequestMockHTTPJob::GetMockUrl(
498 "safe_browsing/interstitial_cancel.html");
499 GURL malware_url = net::URLRequestMockHTTPJob::GetMockUrl(kMalwarePage);
500 SetURLThreatType(malware_url, GetParam());
502 // Load the test page.
503 ui_test_utils::NavigateToURL(browser(), load_url);
504 // Trigger the safe browsing interstitial page via a redirect in
505 // "openWin()".
506 ui_test_utils::NavigateToURLWithDisposition(
507 browser(),
508 GURL("javascript:" + open_function + "()"),
509 CURRENT_TAB,
510 ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB);
511 WebContents* contents =
512 browser()->tab_strip_model()->GetActiveWebContents();
513 content::WaitForInterstitialAttach(contents);
514 // Cancel the redirect request while interstitial page is open.
515 browser()->tab_strip_model()->ActivateTabAt(0, true);
516 ui_test_utils::NavigateToURL(browser(), GURL("javascript:stopWin()"));
517 browser()->tab_strip_model()->ActivateTabAt(1, true);
518 // Simulate the user clicking "proceed", there should be no crash. Since
519 // clicking proceed may do nothing (see comment in RedirectCanceled
520 // below, and crbug.com/76460), we use SendCommand to trigger the callback
521 // directly rather than using ClickAndWaitForDetach since there might not
522 // be a notification to wait for.
523 SendCommand(SecurityInterstitialPage::CMD_PROCEED);
526 content::RenderViewHost* GetRenderViewHost() {
527 InterstitialPage* interstitial = InterstitialPage::GetInterstitialPage(
528 browser()->tab_strip_model()->GetActiveWebContents());
529 if (!interstitial)
530 return NULL;
531 return interstitial->GetMainFrame()->GetRenderViewHost();
534 bool WaitForReady() {
535 InterstitialPage* interstitial = InterstitialPage::GetInterstitialPage(
536 browser()->tab_strip_model()->GetActiveWebContents());
537 if (!interstitial)
538 return false;
539 return content::WaitForRenderFrameReady(interstitial->GetMainFrame());
542 Visibility GetVisibility(const std::string& node_id) {
543 content::RenderViewHost* rvh = GetRenderViewHost();
544 if (!rvh)
545 return VISIBILITY_ERROR;
546 scoped_ptr<base::Value> value = content::ExecuteScriptAndGetValue(
547 rvh->GetMainFrame(),
548 "var node = document.getElementById('" + node_id + "');\n"
549 "if (node)\n"
550 " node.offsetWidth > 0 && node.offsetHeight > 0;"
551 "else\n"
552 " 'node not found';\n");
553 if (!value.get())
554 return VISIBILITY_ERROR;
555 bool result = false;
556 if (!value->GetAsBoolean(&result))
557 return VISIBILITY_ERROR;
558 return result ? VISIBLE : HIDDEN;
561 bool Click(const std::string& node_id) {
562 content::RenderViewHost* rvh = GetRenderViewHost();
563 if (!rvh)
564 return false;
565 // We don't use ExecuteScriptAndGetValue for this one, since clicking
566 // the button/link may navigate away before the injected javascript can
567 // reply, hanging the test.
568 rvh->GetMainFrame()->ExecuteJavaScriptForTests(
569 base::ASCIIToUTF16(
570 "document.getElementById('" + node_id + "').click();\n"));
571 return true;
574 bool ClickAndWaitForDetach(const std::string& node_id) {
575 // We wait for interstitial_detached rather than nav_entry_committed, as
576 // going back from a main-frame malware interstitial page will not cause a
577 // nav entry committed event.
578 if (!Click(node_id))
579 return false;
580 content::WaitForInterstitialDetach(
581 browser()->tab_strip_model()->GetActiveWebContents());
582 return true;
585 void TestReportingDisabledAndDontProceed(const GURL& url) {
586 SetURLThreatType(url, GetParam());
587 ui_test_utils::NavigateToURL(browser(), url);
588 ASSERT_TRUE(WaitForReady());
590 EXPECT_EQ(HIDDEN, GetVisibility("extended-reporting-opt-in"));
591 EXPECT_EQ(HIDDEN, GetVisibility("opt-in-checkbox"));
592 EXPECT_EQ(HIDDEN, GetVisibility("proceed-link"));
593 EXPECT_TRUE(Click("details-button"));
594 EXPECT_EQ(VISIBLE, GetVisibility("help-link"));
595 EXPECT_EQ(VISIBLE, GetVisibility("proceed-link"));
597 EXPECT_TRUE(ClickAndWaitForDetach("primary-button"));
598 AssertNoInterstitial(false); // Assert the interstitial is gone
599 EXPECT_EQ(GURL(url::kAboutBlankURL), // Back to "about:blank"
600 browser()->tab_strip_model()->GetActiveWebContents()->GetURL());
603 protected:
604 TestMalwareDetailsFactory details_factory_;
606 private:
607 TestSafeBrowsingServiceFactory factory_;
608 TestSafeBrowsingBlockingPageFactory blocking_page_factory_;
610 DISALLOW_COPY_AND_ASSIGN(SafeBrowsingBlockingPageBrowserTest);
613 // TODO(linux_aura) https://crbug.com/163931
614 // TODO(win_aura) https://crbug.com/154081
615 #if defined(USE_AURA) && !defined(OS_CHROMEOS)
616 #define MAYBE_RedirectInIFrameCanceled DISABLED_RedirectInIFrameCanceled
617 #else
618 #define MAYBE_RedirectInIFrameCanceled RedirectInIFrameCanceled
619 #endif
620 IN_PROC_BROWSER_TEST_P(SafeBrowsingBlockingPageBrowserTest,
621 MAYBE_RedirectInIFrameCanceled) {
622 // 1. Test the case that redirect is a subresource.
623 MalwareRedirectCancelAndProceed("openWinIFrame");
624 // If the redirect was from subresource but canceled, "proceed" will continue
625 // with the rest of resources.
626 AssertNoInterstitial(true);
629 IN_PROC_BROWSER_TEST_P(SafeBrowsingBlockingPageBrowserTest, RedirectCanceled) {
630 // 2. Test the case that redirect is the only resource.
631 MalwareRedirectCancelAndProceed("openWin");
632 // Clicking proceed won't do anything if the main request is cancelled
633 // already. See crbug.com/76460.
634 EXPECT_TRUE(YesInterstitial());
637 IN_PROC_BROWSER_TEST_P(SafeBrowsingBlockingPageBrowserTest, DontProceed) {
638 #if defined(OS_WIN) && defined(USE_ASH)
639 // Disable this test in Metro+Ash for now (https://crbug.com/262796).
640 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
641 switches::kAshBrowserTests)) {
642 return;
644 #endif
646 SetupWarningAndNavigate();
648 EXPECT_EQ(VISIBLE, GetVisibility("primary-button"));
649 EXPECT_EQ(HIDDEN, GetVisibility("details"));
650 EXPECT_EQ(HIDDEN, GetVisibility("proceed-link"));
651 EXPECT_EQ(HIDDEN, GetVisibility("error-code"));
652 EXPECT_TRUE(Click("details-button"));
653 EXPECT_EQ(VISIBLE, GetVisibility("details"));
654 EXPECT_EQ(VISIBLE, GetVisibility("proceed-link"));
655 EXPECT_EQ(HIDDEN, GetVisibility("error-code"));
656 EXPECT_TRUE(ClickAndWaitForDetach("primary-button"));
658 AssertNoInterstitial(false); // Assert the interstitial is gone
659 EXPECT_EQ(GURL(url::kAboutBlankURL), // Back to "about:blank"
660 browser()->tab_strip_model()->GetActiveWebContents()->GetURL());
663 IN_PROC_BROWSER_TEST_P(SafeBrowsingBlockingPageBrowserTest, Proceed) {
664 GURL url = SetupWarningAndNavigate();
666 EXPECT_TRUE(ClickAndWaitForDetach("proceed-link"));
667 AssertNoInterstitial(true); // Assert the interstitial is gone.
668 EXPECT_EQ(url,
669 browser()->tab_strip_model()->GetActiveWebContents()->GetURL());
672 IN_PROC_BROWSER_TEST_P(SafeBrowsingBlockingPageBrowserTest, IframeDontProceed) {
673 #if defined(OS_WIN) && defined(USE_ASH)
674 // Disable this test in Metro+Ash for now (https://crbug.com/262796).
675 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
676 switches::kAshBrowserTests)) {
677 return;
679 #endif
681 SetupThreatIframeWarningAndNavigate();
683 EXPECT_EQ(VISIBLE, GetVisibility("primary-button"));
684 EXPECT_EQ(HIDDEN, GetVisibility("details"));
685 EXPECT_EQ(HIDDEN, GetVisibility("proceed-link"));
686 EXPECT_EQ(HIDDEN, GetVisibility("error-code"));
687 EXPECT_TRUE(Click("details-button"));
688 EXPECT_EQ(VISIBLE, GetVisibility("details"));
689 EXPECT_EQ(VISIBLE, GetVisibility("proceed-link"));
690 EXPECT_EQ(HIDDEN, GetVisibility("error-code"));
691 EXPECT_TRUE(ClickAndWaitForDetach("primary-button"));
693 AssertNoInterstitial(false); // Assert the interstitial is gone
695 EXPECT_EQ(GURL(url::kAboutBlankURL), // Back to "about:blank"
696 browser()->tab_strip_model()->GetActiveWebContents()->GetURL());
699 IN_PROC_BROWSER_TEST_P(SafeBrowsingBlockingPageBrowserTest, IframeProceed) {
700 GURL url = SetupThreatIframeWarningAndNavigate();
702 EXPECT_TRUE(ClickAndWaitForDetach("proceed-link"));
703 AssertNoInterstitial(true); // Assert the interstitial is gone
705 EXPECT_EQ(url,
706 browser()->tab_strip_model()->GetActiveWebContents()->GetURL());
709 IN_PROC_BROWSER_TEST_P(SafeBrowsingBlockingPageBrowserTest,
710 IframeOptInAndReportMalwareDetails) {
711 // The extended reporting opt-in is presented in the interstitial for malware,
712 // phishing, and UwS threats. It however only results in uploading further
713 // details about the immediate threat when facing malware threats.
714 const bool expect_malware_details = GetParam() == SB_THREAT_TYPE_URL_MALWARE;
716 scoped_refptr<content::MessageLoopRunner> malware_report_sent_runner(
717 new content::MessageLoopRunner);
718 if (expect_malware_details)
719 SetReportSentCallback(malware_report_sent_runner->QuitClosure());
721 GURL url = SetupThreatIframeWarningAndNavigate();
723 FakeMalwareDetails* fake_malware_details = details_factory_.get_details();
724 EXPECT_EQ(expect_malware_details, fake_malware_details != nullptr);
726 // If the DOM details from renderer did not already return when they are
727 // expected, wait for them.
728 if (expect_malware_details)
729 fake_malware_details->WaitForDOM();
731 EXPECT_EQ(VISIBLE, GetVisibility("extended-reporting-opt-in"));
732 EXPECT_TRUE(Click("opt-in-checkbox"));
733 EXPECT_TRUE(ClickAndWaitForDetach("proceed-link"));
734 AssertNoInterstitial(true); // Assert the interstitial is gone
736 EXPECT_TRUE(browser()->profile()->GetPrefs()->GetBoolean(
737 prefs::kSafeBrowsingExtendedReportingEnabled));
738 EXPECT_EQ(url,
739 browser()->tab_strip_model()->GetActiveWebContents()->GetURL());
741 if (expect_malware_details) {
742 malware_report_sent_runner->Run();
743 std::string serialized = GetReportSent();
744 safe_browsing::ClientMalwareReportRequest report;
745 ASSERT_TRUE(report.ParseFromString(serialized));
746 // Verify the report is complete.
747 EXPECT_TRUE(report.complete());
751 // Verifies that the "proceed anyway" link isn't available when it is disabled
752 // by the corresponding policy. Also verifies that sending the "proceed"
753 // command anyway doesn't advance to the malware site.
754 IN_PROC_BROWSER_TEST_P(SafeBrowsingBlockingPageBrowserTest, ProceedDisabled) {
755 #if defined(OS_WIN) && defined(USE_ASH)
756 // Disable this test in Metro+Ash for now (https://crbug.com/262796).
757 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
758 switches::kAshBrowserTests)) {
759 return;
761 #endif
763 // Simulate a policy disabling the "proceed anyway" link.
764 browser()->profile()->GetPrefs()->SetBoolean(
765 prefs::kSafeBrowsingProceedAnywayDisabled, true);
767 SetupWarningAndNavigate();
769 EXPECT_EQ(VISIBLE, GetVisibility("primary-button"));
770 EXPECT_EQ(HIDDEN, GetVisibility("details"));
771 EXPECT_EQ(HIDDEN, GetVisibility("proceed-link"));
772 EXPECT_EQ(HIDDEN, GetVisibility("final-paragraph"));
773 EXPECT_TRUE(Click("details-button"));
774 EXPECT_EQ(HIDDEN, GetVisibility("proceed-link"));
775 EXPECT_EQ(HIDDEN, GetVisibility("final-paragraph"));
776 SendCommand(SecurityInterstitialPage::CMD_PROCEED);
778 // The "proceed" command should go back instead, if proceeding is disabled.
779 AssertNoInterstitial(true);
780 EXPECT_EQ(GURL(url::kAboutBlankURL), // Back to "about:blank"
781 browser()->tab_strip_model()->GetActiveWebContents()->GetURL());
784 // Verifies that the reporting checkbox is hidden on non-HTTP pages.
785 // TODO(mattm): Should also verify that no report is sent, but there isn't a
786 // good way to do that in the current design.
787 IN_PROC_BROWSER_TEST_P(SafeBrowsingBlockingPageBrowserTest, ReportingDisabled) {
788 #if defined(OS_WIN) && defined(USE_ASH)
789 // Disable this test in Metro+Ash for now (https://crbug.com/262796).
790 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
791 switches::kAshBrowserTests)) {
792 return;
794 #endif
796 browser()->profile()->GetPrefs()->SetBoolean(
797 prefs::kSafeBrowsingExtendedReportingEnabled, true);
799 TestReportingDisabledAndDontProceed(
800 net::URLRequestMockHTTPJob::GetMockHttpsUrl(kEmptyPage));
803 // Verifies that the reporting checkbox is hidden when opt-in is
804 // disabled by policy.
805 IN_PROC_BROWSER_TEST_P(SafeBrowsingBlockingPageBrowserTest,
806 ReportingDisabledByPolicy) {
807 #if defined(OS_WIN) && defined(USE_ASH)
808 // Disable this test in Metro+Ash for now (https://crbug.com/262796).
809 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
810 switches::kAshBrowserTests)) {
811 return;
813 #endif
815 browser()->profile()->GetPrefs()->SetBoolean(
816 prefs::kSafeBrowsingExtendedReportingEnabled, true);
817 browser()->profile()->GetPrefs()->SetBoolean(
818 prefs::kSafeBrowsingExtendedReportingOptInAllowed, false);
820 TestReportingDisabledAndDontProceed(
821 net::URLRequestMockHTTPJob::GetMockUrl(kEmptyPage));
824 IN_PROC_BROWSER_TEST_P(SafeBrowsingBlockingPageBrowserTest, LearnMore) {
825 SetupWarningAndNavigate();
826 EXPECT_TRUE(ClickAndWaitForDetach("help-link"));
827 AssertNoInterstitial(false); // Assert the interstitial is gone
829 // We are in the help page.
830 EXPECT_EQ(
831 GetParam() == SB_THREAT_TYPE_URL_PHISHING
832 ? "/transparencyreport/safebrowsing/"
833 : "/safebrowsing/diagnostic",
834 browser()->tab_strip_model()->GetActiveWebContents()->GetURL().path());
837 IN_PROC_BROWSER_TEST_P(SafeBrowsingBlockingPageBrowserTest,
838 Histograms_DontProceed) {
839 #if defined(OS_WIN) && defined(USE_ASH)
840 // Disable this test in Metro+Ash for now (https://crbug.com/262796).
841 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
842 switches::kAshBrowserTests)) {
843 return;
845 #endif
847 base::HistogramTester histograms;
848 std::string prefix;
849 if (GetParam() == SB_THREAT_TYPE_URL_MALWARE)
850 prefix = "malware";
851 else if (GetParam() == SB_THREAT_TYPE_URL_PHISHING)
852 prefix = "phishing";
853 else if (GetParam() == SB_THREAT_TYPE_URL_UNWANTED)
854 prefix = "harmful";
855 else
856 NOTREACHED();
857 const std::string decision_histogram = "interstitial." + prefix + ".decision";
858 const std::string interaction_histogram =
859 "interstitial." + prefix + ".interaction";
861 // TODO(nparker): Check for *.from_device as well.
863 // Histograms should start off empty.
864 histograms.ExpectTotalCount(decision_histogram, 0);
865 histograms.ExpectTotalCount(interaction_histogram, 0);
867 // After navigating to the page, the totals should be set.
868 SetupWarningAndNavigate();
869 histograms.ExpectTotalCount(decision_histogram, 1);
870 histograms.ExpectBucketCount(decision_histogram,
871 security_interstitials::MetricsHelper::SHOW, 1);
872 histograms.ExpectTotalCount(interaction_histogram, 1);
873 histograms.ExpectBucketCount(
874 interaction_histogram,
875 security_interstitials::MetricsHelper::TOTAL_VISITS, 1);
877 // Decision should be recorded.
878 EXPECT_TRUE(ClickAndWaitForDetach("primary-button"));
879 AssertNoInterstitial(false); // Assert the interstitial is gone
880 histograms.ExpectTotalCount(decision_histogram, 2);
881 histograms.ExpectBucketCount(
882 decision_histogram, security_interstitials::MetricsHelper::DONT_PROCEED,
884 histograms.ExpectTotalCount(interaction_histogram, 1);
885 histograms.ExpectBucketCount(
886 interaction_histogram,
887 security_interstitials::MetricsHelper::TOTAL_VISITS, 1);
890 IN_PROC_BROWSER_TEST_P(SafeBrowsingBlockingPageBrowserTest,
891 Histograms_Proceed) {
892 base::HistogramTester histograms;
893 std::string prefix;
894 if (GetParam() == SB_THREAT_TYPE_URL_MALWARE)
895 prefix = "malware";
896 else if (GetParam() == SB_THREAT_TYPE_URL_PHISHING)
897 prefix = "phishing";
898 else if (GetParam() == SB_THREAT_TYPE_URL_UNWANTED)
899 prefix = "harmful";
900 else
901 NOTREACHED();
902 const std::string decision_histogram = "interstitial." + prefix + ".decision";
903 const std::string interaction_histogram =
904 "interstitial." + prefix + ".interaction";
906 // Histograms should start off empty.
907 histograms.ExpectTotalCount(decision_histogram, 0);
908 histograms.ExpectTotalCount(interaction_histogram, 0);
910 // After navigating to the page, the totals should be set.
911 GURL url = SetupWarningAndNavigate();
912 histograms.ExpectTotalCount(decision_histogram, 1);
913 histograms.ExpectBucketCount(decision_histogram,
914 security_interstitials::MetricsHelper::SHOW, 1);
915 histograms.ExpectTotalCount(interaction_histogram, 1);
916 histograms.ExpectBucketCount(
917 interaction_histogram,
918 security_interstitials::MetricsHelper::TOTAL_VISITS, 1);
920 // Decision should be recorded.
921 EXPECT_TRUE(ClickAndWaitForDetach("proceed-link"));
922 AssertNoInterstitial(true); // Assert the interstitial is gone.
923 histograms.ExpectTotalCount(decision_histogram, 2);
924 histograms.ExpectBucketCount(
925 decision_histogram, security_interstitials::MetricsHelper::PROCEED, 1);
926 histograms.ExpectTotalCount(interaction_histogram, 1);
927 histograms.ExpectBucketCount(
928 interaction_histogram,
929 security_interstitials::MetricsHelper::TOTAL_VISITS, 1);
932 IN_PROC_BROWSER_TEST_P(SafeBrowsingBlockingPageBrowserTest, WhitelistRevisit) {
933 GURL url = SetupWarningAndNavigate();
935 EXPECT_TRUE(ClickAndWaitForDetach("proceed-link"));
936 AssertNoInterstitial(true); // Assert the interstitial is gone.
937 EXPECT_EQ(url,
938 browser()->tab_strip_model()->GetActiveWebContents()->GetURL());
940 // Unrelated pages should not be whitelisted now.
941 ui_test_utils::NavigateToURL(browser(), GURL(kUnrelatedUrl));
942 AssertNoInterstitial(false);
944 // The whitelisted page should remain whitelisted.
945 ui_test_utils::NavigateToURL(browser(), url);
946 AssertNoInterstitial(false);
949 IN_PROC_BROWSER_TEST_P(SafeBrowsingBlockingPageBrowserTest,
950 WhitelistIframeRevisit) {
951 GURL url = SetupThreatIframeWarningAndNavigate();
953 EXPECT_TRUE(ClickAndWaitForDetach("proceed-link"));
954 AssertNoInterstitial(true); // Assert the interstitial is gone.
955 EXPECT_EQ(url,
956 browser()->tab_strip_model()->GetActiveWebContents()->GetURL());
958 // Unrelated pages should not be whitelisted now.
959 ui_test_utils::NavigateToURL(browser(), GURL(kUnrelatedUrl));
960 AssertNoInterstitial(false);
962 // The whitelisted page should remain whitelisted.
963 ui_test_utils::NavigateToURL(browser(), url);
964 AssertNoInterstitial(false);
967 IN_PROC_BROWSER_TEST_P(SafeBrowsingBlockingPageBrowserTest, WhitelistUnsaved) {
968 GURL url = SetupWarningAndNavigate();
970 // Navigate without making a decision.
971 ui_test_utils::NavigateToURL(browser(), GURL(kUnrelatedUrl));
972 AssertNoInterstitial(false);
974 // The non-whitelisted page should now show an interstitial.
975 ui_test_utils::NavigateToURL(browser(), url);
976 EXPECT_TRUE(WaitForReady());
977 EXPECT_TRUE(ClickAndWaitForDetach("proceed-link"));
978 AssertNoInterstitial(true);
981 INSTANTIATE_TEST_CASE_P(SafeBrowsingBlockingPageBrowserTestWithThreatType,
982 SafeBrowsingBlockingPageBrowserTest,
983 testing::Values(SB_THREAT_TYPE_URL_MALWARE,
984 SB_THREAT_TYPE_URL_PHISHING,
985 SB_THREAT_TYPE_URL_UNWANTED));
987 // Test that SafeBrowsingBlockingPage properly decodes IDN URLs that are
988 // displayed.
989 class SafeBrowsingBlockingPageIDNTest
990 : public SecurityInterstitialIDNTest,
991 public testing::WithParamInterface<SBThreatType> {
992 protected:
993 // SecurityInterstitialIDNTest implementation
994 SecurityInterstitialPage* CreateInterstitial(
995 content::WebContents* contents,
996 const GURL& request_url) const override {
997 SafeBrowsingService* sb_service =
998 g_browser_process->safe_browsing_service();
999 SafeBrowsingBlockingPage::UnsafeResource resource;
1001 resource.url = request_url;
1002 resource.is_subresource = false;
1003 resource.threat_type = GetParam();
1004 resource.render_process_host_id = contents->GetRenderProcessHost()->GetID();
1005 resource.render_view_id = contents->GetRenderViewHost()->GetRoutingID();
1006 resource.threat_source = SafeBrowsingUIManager::FROM_DEVICE;
1008 return SafeBrowsingBlockingPage::CreateBlockingPage(
1009 sb_service->ui_manager().get(), contents, resource);
1013 IN_PROC_BROWSER_TEST_P(SafeBrowsingBlockingPageIDNTest,
1014 SafeBrowsingBlockingPageDecodesIDN) {
1015 EXPECT_TRUE(VerifyIDNDecoded());
1018 INSTANTIATE_TEST_CASE_P(SafeBrowsingBlockingPageIDNTestWithThreatType,
1019 SafeBrowsingBlockingPageIDNTest,
1020 testing::Values(SB_THREAT_TYPE_URL_MALWARE,
1021 SB_THREAT_TYPE_URL_PHISHING,
1022 SB_THREAT_TYPE_URL_UNWANTED));