Update broken references to image assets
[chromium-blink-merge.git] / chrome / browser / safe_browsing / safe_browsing_blocking_page_test.cc
blob4d7c5109a89fac8ed227b967456f7c2fb60df9af
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/chrome_switches.h"
32 #include "chrome/common/pref_names.h"
33 #include "chrome/common/url_constants.h"
34 #include "chrome/test/base/in_process_browser_test.h"
35 #include "chrome/test/base/test_switches.h"
36 #include "chrome/test/base/ui_test_utils.h"
37 #include "components/security_interstitials/core/metrics_helper.h"
38 #include "content/public/browser/interstitial_page.h"
39 #include "content/public/browser/navigation_controller.h"
40 #include "content/public/browser/notification_types.h"
41 #include "content/public/browser/render_frame_host.h"
42 #include "content/public/browser/render_process_host.h"
43 #include "content/public/browser/render_view_host.h"
44 #include "content/public/browser/web_contents.h"
45 #include "content/public/test/browser_test_utils.h"
46 #include "content/public/test/test_browser_thread.h"
47 #include "content/public/test/test_utils.h"
48 #include "net/test/url_request/url_request_mock_http_job.h"
50 using chrome_browser_interstitials::SecurityInterstitialIDNTest;
51 using content::BrowserThread;
52 using content::InterstitialPage;
53 using content::NavigationController;
54 using content::WebContents;
56 namespace {
58 const char kEmptyPage[] = "empty.html";
59 const char kMalwarePage[] = "safe_browsing/malware.html";
60 const char kMalwareIframe[] = "safe_browsing/malware_iframe.html";
61 const char kUnrelatedUrl[] = "https://www.google.com";
63 // A SafeBrowsingDatabaseManager class that allows us to inject the malicious
64 // URLs.
65 class FakeSafeBrowsingDatabaseManager : public TestSafeBrowsingDatabaseManager {
66 public:
67 FakeSafeBrowsingDatabaseManager() {}
69 // Called on the IO thread to check if the given url is safe or not. If we
70 // can synchronously determine that the url is safe, CheckUrl returns true.
71 // Otherwise it returns false, and "client" is called asynchronously with the
72 // result when it is ready.
73 // Overrides SafeBrowsingDatabaseManager::CheckBrowseUrl.
74 bool CheckBrowseUrl(const GURL& gurl, Client* client) override {
75 if (badurls[gurl.spec()] == SB_THREAT_TYPE_SAFE)
76 return true;
78 BrowserThread::PostTask(
79 BrowserThread::IO, FROM_HERE,
80 base::Bind(&FakeSafeBrowsingDatabaseManager::OnCheckBrowseURLDone,
81 this, gurl, client));
82 return false;
85 void OnCheckBrowseURLDone(const GURL& gurl, Client* client) {
86 std::vector<SBThreatType> expected_threats;
87 // TODO(nparker): Remove ref to LocalSafeBrowsingDatabase by calling
88 // client->OnCheckBrowseUrlResult(..) directly.
89 expected_threats.push_back(SB_THREAT_TYPE_URL_MALWARE);
90 expected_threats.push_back(SB_THREAT_TYPE_URL_PHISHING);
91 expected_threats.push_back(SB_THREAT_TYPE_URL_UNWANTED);
92 LocalSafeBrowsingDatabaseManager::SafeBrowsingCheck sb_check(
93 std::vector<GURL>(1, gurl),
94 std::vector<SBFullHash>(),
95 client,
96 safe_browsing_util::MALWARE,
97 expected_threats);
98 sb_check.url_results[0] = badurls[gurl.spec()];
99 sb_check.OnSafeBrowsingResult();
102 void SetURLThreatType(const GURL& url, SBThreatType threat_type) {
103 badurls[url.spec()] = threat_type;
106 // Called during startup, so must not check-fail.
107 bool CheckExtensionIDs(const std::set<std::string>& extension_ids,
108 Client* client) override {
109 return true;
112 private:
113 ~FakeSafeBrowsingDatabaseManager() override {}
115 base::hash_map<std::string, SBThreatType> badurls;
116 DISALLOW_COPY_AND_ASSIGN(FakeSafeBrowsingDatabaseManager);
119 // A SafeBrowingUIManager class that allows intercepting malware details.
120 class FakeSafeBrowsingUIManager : public SafeBrowsingUIManager {
121 public:
122 explicit FakeSafeBrowsingUIManager(SafeBrowsingService* service) :
123 SafeBrowsingUIManager(service) { }
125 // Overrides SafeBrowsingUIManager
126 void SendSerializedMalwareDetails(const std::string& serialized) override {
127 // Notify the UI thread that we got a report.
128 BrowserThread::PostTask(
129 BrowserThread::UI,
130 FROM_HERE,
131 base::Bind(&FakeSafeBrowsingUIManager::OnMalwareDetailsDone,
132 this,
133 serialized));
136 void OnMalwareDetailsDone(const std::string& serialized) {
137 EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI));
138 report_ = serialized;
140 EXPECT_FALSE(malware_details_done_callback_.is_null());
141 if (!malware_details_done_callback_.is_null()) {
142 malware_details_done_callback_.Run();
143 malware_details_done_callback_ = base::Closure();
147 void set_malware_details_done_callback(const base::Closure& callback) {
148 EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI));
149 EXPECT_TRUE(malware_details_done_callback_.is_null());
150 malware_details_done_callback_ = callback;
153 std::string GetReport() {
154 EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI));
155 return report_;
158 protected:
159 ~FakeSafeBrowsingUIManager() override {}
161 private:
162 std::string report_;
163 base::Closure malware_details_done_callback_;
165 DISALLOW_COPY_AND_ASSIGN(FakeSafeBrowsingUIManager);
168 class FakeSafeBrowsingService : public SafeBrowsingService {
169 public:
170 FakeSafeBrowsingService()
171 : fake_database_manager_(),
172 fake_ui_manager_() { }
174 // Returned pointer has the same lifespan as the database_manager_ refcounted
175 // object.
176 FakeSafeBrowsingDatabaseManager* fake_database_manager() {
177 return fake_database_manager_;
179 // Returned pointer has the same lifespan as the ui_manager_ refcounted
180 // object.
181 FakeSafeBrowsingUIManager* fake_ui_manager() {
182 return fake_ui_manager_;
185 protected:
186 ~FakeSafeBrowsingService() override {}
188 SafeBrowsingDatabaseManager* CreateDatabaseManager() override {
189 fake_database_manager_ = new FakeSafeBrowsingDatabaseManager();
190 return fake_database_manager_;
193 SafeBrowsingUIManager* CreateUIManager() override {
194 fake_ui_manager_ = new FakeSafeBrowsingUIManager(this);
195 return fake_ui_manager_;
198 SafeBrowsingProtocolManagerDelegate* GetProtocolManagerDelegate() override {
199 // Our SafeBrowsingDatabaseManager doesn't implement this delegate.
200 return NULL;
203 private:
204 FakeSafeBrowsingDatabaseManager* fake_database_manager_;
205 FakeSafeBrowsingUIManager* fake_ui_manager_;
207 DISALLOW_COPY_AND_ASSIGN(FakeSafeBrowsingService);
210 // Factory that creates FakeSafeBrowsingService instances.
211 class TestSafeBrowsingServiceFactory : public SafeBrowsingServiceFactory {
212 public:
213 TestSafeBrowsingServiceFactory() :
214 most_recent_service_(NULL) { }
215 ~TestSafeBrowsingServiceFactory() override {}
217 SafeBrowsingService* CreateSafeBrowsingService() override {
218 most_recent_service_ = new FakeSafeBrowsingService();
219 return most_recent_service_;
222 FakeSafeBrowsingService* most_recent_service() const {
223 return most_recent_service_;
226 private:
227 FakeSafeBrowsingService* most_recent_service_;
230 // A MalwareDetails class lets us intercept calls from the renderer.
231 class FakeMalwareDetails : public MalwareDetails {
232 public:
233 FakeMalwareDetails(
234 SafeBrowsingUIManager* delegate,
235 WebContents* web_contents,
236 const SafeBrowsingUIManager::UnsafeResource& unsafe_resource)
237 : MalwareDetails(delegate, web_contents, unsafe_resource),
238 got_dom_(false),
239 waiting_(false) { }
241 void AddDOMDetails(
242 const std::vector<SafeBrowsingHostMsg_MalwareDOMDetails_Node>& params)
243 override {
244 EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
245 MalwareDetails::AddDOMDetails(params);
247 // Notify the UI thread that we got the dom details.
248 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
249 base::Bind(&FakeMalwareDetails::OnDOMDetailsDone,
250 this));
253 void WaitForDOM() {
254 if (got_dom_) {
255 return;
257 // This condition might not trigger normally, but if you add a
258 // sleep(1) in malware_dom_details it triggers :).
259 waiting_ = true;
260 content::RunMessageLoop();
261 EXPECT_TRUE(got_dom_);
264 private:
265 ~FakeMalwareDetails() override {}
267 void OnDOMDetailsDone() {
268 got_dom_ = true;
269 if (waiting_) {
270 base::MessageLoopForUI::current()->Quit();
274 // Some logic to figure out if we should wait for the dom details or not.
275 // These variables should only be accessed in the UI thread.
276 bool got_dom_;
277 bool waiting_;
280 class TestMalwareDetailsFactory : public MalwareDetailsFactory {
281 public:
282 TestMalwareDetailsFactory() : details_() { }
283 ~TestMalwareDetailsFactory() override {}
285 MalwareDetails* CreateMalwareDetails(
286 SafeBrowsingUIManager* delegate,
287 WebContents* web_contents,
288 const SafeBrowsingUIManager::UnsafeResource& unsafe_resource) override {
289 details_ = new FakeMalwareDetails(delegate, web_contents,
290 unsafe_resource);
291 return details_;
294 FakeMalwareDetails* get_details() {
295 return details_;
298 private:
299 FakeMalwareDetails* details_;
302 // A SafeBrowingBlockingPage class that lets us wait until it's hidden.
303 class TestSafeBrowsingBlockingPage : public SafeBrowsingBlockingPage {
304 public:
305 TestSafeBrowsingBlockingPage(SafeBrowsingUIManager* manager,
306 WebContents* web_contents,
307 const UnsafeResourceList& unsafe_resources)
308 : SafeBrowsingBlockingPage(manager, web_contents, unsafe_resources),
309 wait_for_delete_(false) {
310 // Don't wait the whole 3 seconds for the browser test.
311 malware_details_proceed_delay_ms_ = 100;
314 ~TestSafeBrowsingBlockingPage() override {
315 if (!wait_for_delete_)
316 return;
318 // Notify that we are gone
319 base::MessageLoopForUI::current()->Quit();
320 wait_for_delete_ = false;
323 void WaitForDelete() {
324 wait_for_delete_ = true;
325 content::RunMessageLoop();
328 // InterstitialPageDelegate methods:
329 void CommandReceived(const std::string& command) override {
330 SafeBrowsingBlockingPage::CommandReceived(command);
332 void OnProceed() override { SafeBrowsingBlockingPage::OnProceed(); }
333 void OnDontProceed() override { SafeBrowsingBlockingPage::OnDontProceed(); }
335 private:
336 bool wait_for_delete_;
339 class TestSafeBrowsingBlockingPageFactory
340 : public SafeBrowsingBlockingPageFactory {
341 public:
342 TestSafeBrowsingBlockingPageFactory() { }
343 ~TestSafeBrowsingBlockingPageFactory() override {}
345 SafeBrowsingBlockingPage* CreateSafeBrowsingPage(
346 SafeBrowsingUIManager* delegate,
347 WebContents* web_contents,
348 const SafeBrowsingBlockingPage::UnsafeResourceList& unsafe_resources)
349 override {
350 return new TestSafeBrowsingBlockingPage(delegate, web_contents,
351 unsafe_resources);
355 } // namespace
357 // Tests the safe browsing blocking page in a browser.
358 class SafeBrowsingBlockingPageBrowserTest
359 : public InProcessBrowserTest,
360 public testing::WithParamInterface<SBThreatType> {
361 public:
362 enum Visibility {
363 VISIBILITY_ERROR = -1,
364 HIDDEN = 0,
365 VISIBLE = 1
368 SafeBrowsingBlockingPageBrowserTest() {}
370 void SetUp() override {
371 SafeBrowsingService::RegisterFactory(&factory_);
372 SafeBrowsingBlockingPage::RegisterFactory(&blocking_page_factory_);
373 MalwareDetails::RegisterFactory(&details_factory_);
374 InProcessBrowserTest::SetUp();
377 void SetUpCommandLine(base::CommandLine* command_line) override {
378 command_line->AppendSwitchASCII(
379 switches::kForceFieldTrials, "UwSInterstitialStatus/On/");
382 void TearDown() override {
383 InProcessBrowserTest::TearDown();
384 SafeBrowsingBlockingPage::RegisterFactory(NULL);
385 SafeBrowsingService::RegisterFactory(NULL);
386 MalwareDetails::RegisterFactory(NULL);
389 void SetUpOnMainThread() override {
390 BrowserThread::PostTask(
391 BrowserThread::IO, FROM_HERE,
392 base::Bind(&chrome_browser_net::SetUrlRequestMocksEnabled, true));
395 void SetURLThreatType(const GURL& url, SBThreatType threat_type) {
396 FakeSafeBrowsingService* service =
397 static_cast<FakeSafeBrowsingService*>(
398 g_browser_process->safe_browsing_service());
400 ASSERT_TRUE(service);
401 service->fake_database_manager()->SetURLThreatType(url, threat_type);
404 // Adds a safebrowsing result of the current test threat to the fake
405 // safebrowsing service, navigates to that page, and returns the url.
406 GURL SetupWarningAndNavigate() {
407 GURL url = net::URLRequestMockHTTPJob::GetMockUrl(kEmptyPage);
408 SetURLThreatType(url, GetParam());
410 ui_test_utils::NavigateToURL(browser(), url);
411 EXPECT_TRUE(WaitForReady());
412 return url;
415 // Adds a safebrowsing threat result to the fake safebrowsing service,
416 // navigates to a page with an iframe containing the threat site, and returns
417 // the url of the parent page.
418 GURL SetupThreatIframeWarningAndNavigate() {
419 GURL url = net::URLRequestMockHTTPJob::GetMockUrl(kMalwarePage);
420 GURL iframe_url = net::URLRequestMockHTTPJob::GetMockUrl(kMalwareIframe);
421 SetURLThreatType(iframe_url, GetParam());
423 ui_test_utils::NavigateToURL(browser(), url);
424 EXPECT_TRUE(WaitForReady());
425 return url;
428 void SendCommand(
429 SecurityInterstitialPage::SecurityInterstitialCommands command) {
430 WebContents* contents =
431 browser()->tab_strip_model()->GetActiveWebContents();
432 // We use InterstitialPage::GetInterstitialPage(tab) instead of
433 // tab->GetInterstitialPage() because the tab doesn't have a pointer
434 // to its interstital page until it gets a command from the renderer
435 // that it has indeed displayed it -- and this sometimes happens after
436 // NavigateToURL returns.
437 SafeBrowsingBlockingPage* interstitial_page =
438 static_cast<SafeBrowsingBlockingPage*>(
439 InterstitialPage::GetInterstitialPage(contents)->
440 GetDelegateForTesting());
441 ASSERT_TRUE(interstitial_page);
442 ASSERT_EQ(SafeBrowsingBlockingPage::kTypeForTesting,
443 interstitial_page->GetTypeForTesting());
444 interstitial_page->CommandReceived(base::IntToString(command));
447 void DontProceedThroughInterstitial() {
448 WebContents* contents =
449 browser()->tab_strip_model()->GetActiveWebContents();
450 InterstitialPage* interstitial_page = InterstitialPage::GetInterstitialPage(
451 contents);
452 ASSERT_TRUE(interstitial_page);
453 interstitial_page->DontProceed();
456 void ProceedThroughInterstitial() {
457 WebContents* contents =
458 browser()->tab_strip_model()->GetActiveWebContents();
459 InterstitialPage* interstitial_page = InterstitialPage::GetInterstitialPage(
460 contents);
461 ASSERT_TRUE(interstitial_page);
462 interstitial_page->Proceed();
465 void AssertNoInterstitial(bool wait_for_delete) {
466 WebContents* contents =
467 browser()->tab_strip_model()->GetActiveWebContents();
469 if (contents->ShowingInterstitialPage() && wait_for_delete) {
470 // We'll get notified when the interstitial is deleted.
471 TestSafeBrowsingBlockingPage* page =
472 static_cast<TestSafeBrowsingBlockingPage*>(
473 contents->GetInterstitialPage()->GetDelegateForTesting());
474 ASSERT_EQ(SafeBrowsingBlockingPage::kTypeForTesting,
475 page->GetTypeForTesting());
476 page->WaitForDelete();
479 // Can't use InterstitialPage::GetInterstitialPage() because that
480 // gets updated after the TestSafeBrowsingBlockingPage destructor
481 ASSERT_FALSE(contents->ShowingInterstitialPage());
484 bool YesInterstitial() {
485 WebContents* contents =
486 browser()->tab_strip_model()->GetActiveWebContents();
487 InterstitialPage* interstitial_page = InterstitialPage::GetInterstitialPage(
488 contents);
489 return interstitial_page != NULL;
492 void SetReportSentCallback(const base::Closure& callback) {
493 factory_.most_recent_service()
494 ->fake_ui_manager()
495 ->set_malware_details_done_callback(callback);
498 std::string GetReportSent() {
499 return factory_.most_recent_service()->fake_ui_manager()->GetReport();
502 void MalwareRedirectCancelAndProceed(const std::string& open_function) {
503 GURL load_url = net::URLRequestMockHTTPJob::GetMockUrl(
504 "safe_browsing/interstitial_cancel.html");
505 GURL malware_url = net::URLRequestMockHTTPJob::GetMockUrl(kMalwarePage);
506 SetURLThreatType(malware_url, GetParam());
508 // Load the test page.
509 ui_test_utils::NavigateToURL(browser(), load_url);
510 // Trigger the safe browsing interstitial page via a redirect in
511 // "openWin()".
512 ui_test_utils::NavigateToURLWithDisposition(
513 browser(),
514 GURL("javascript:" + open_function + "()"),
515 CURRENT_TAB,
516 ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB);
517 WebContents* contents =
518 browser()->tab_strip_model()->GetActiveWebContents();
519 content::WaitForInterstitialAttach(contents);
520 // Cancel the redirect request while interstitial page is open.
521 browser()->tab_strip_model()->ActivateTabAt(0, true);
522 ui_test_utils::NavigateToURL(browser(), GURL("javascript:stopWin()"));
523 browser()->tab_strip_model()->ActivateTabAt(1, true);
524 // Simulate the user clicking "proceed", there should be no crash. Since
525 // clicking proceed may do nothing (see comment in RedirectCanceled
526 // below, and crbug.com/76460), we use SendCommand to trigger the callback
527 // directly rather than using ClickAndWaitForDetach since there might not
528 // be a notification to wait for.
529 SendCommand(SecurityInterstitialPage::CMD_PROCEED);
532 content::RenderViewHost* GetRenderViewHost() {
533 InterstitialPage* interstitial = InterstitialPage::GetInterstitialPage(
534 browser()->tab_strip_model()->GetActiveWebContents());
535 if (!interstitial)
536 return NULL;
537 return interstitial->GetMainFrame()->GetRenderViewHost();
540 bool WaitForReady() {
541 InterstitialPage* interstitial = InterstitialPage::GetInterstitialPage(
542 browser()->tab_strip_model()->GetActiveWebContents());
543 if (!interstitial)
544 return false;
545 return content::WaitForRenderFrameReady(interstitial->GetMainFrame());
548 Visibility GetVisibility(const std::string& node_id) {
549 content::RenderViewHost* rvh = GetRenderViewHost();
550 if (!rvh)
551 return VISIBILITY_ERROR;
552 scoped_ptr<base::Value> value = content::ExecuteScriptAndGetValue(
553 rvh->GetMainFrame(),
554 "var node = document.getElementById('" + node_id + "');\n"
555 "if (node)\n"
556 " node.offsetWidth > 0 && node.offsetHeight > 0;"
557 "else\n"
558 " 'node not found';\n");
559 if (!value.get())
560 return VISIBILITY_ERROR;
561 bool result = false;
562 if (!value->GetAsBoolean(&result))
563 return VISIBILITY_ERROR;
564 return result ? VISIBLE : HIDDEN;
567 bool Click(const std::string& node_id) {
568 content::RenderViewHost* rvh = GetRenderViewHost();
569 if (!rvh)
570 return false;
571 // We don't use ExecuteScriptAndGetValue for this one, since clicking
572 // the button/link may navigate away before the injected javascript can
573 // reply, hanging the test.
574 rvh->GetMainFrame()->ExecuteJavaScriptForTests(
575 base::ASCIIToUTF16(
576 "document.getElementById('" + node_id + "').click();\n"));
577 return true;
580 bool ClickAndWaitForDetach(const std::string& node_id) {
581 // We wait for interstitial_detached rather than nav_entry_committed, as
582 // going back from a main-frame malware interstitial page will not cause a
583 // nav entry committed event.
584 if (!Click(node_id))
585 return false;
586 content::WaitForInterstitialDetach(
587 browser()->tab_strip_model()->GetActiveWebContents());
588 return true;
591 void TestReportingDisabledAndDontProceed(const GURL& url) {
592 SetURLThreatType(url, GetParam());
593 ui_test_utils::NavigateToURL(browser(), url);
594 ASSERT_TRUE(WaitForReady());
596 EXPECT_EQ(HIDDEN, GetVisibility("extended-reporting-opt-in"));
597 EXPECT_EQ(HIDDEN, GetVisibility("opt-in-checkbox"));
598 EXPECT_EQ(HIDDEN, GetVisibility("proceed-link"));
599 EXPECT_TRUE(Click("details-button"));
600 EXPECT_EQ(VISIBLE, GetVisibility("help-link"));
601 EXPECT_EQ(VISIBLE, GetVisibility("proceed-link"));
603 EXPECT_TRUE(ClickAndWaitForDetach("primary-button"));
604 AssertNoInterstitial(false); // Assert the interstitial is gone
605 EXPECT_EQ(GURL(url::kAboutBlankURL), // Back to "about:blank"
606 browser()->tab_strip_model()->GetActiveWebContents()->GetURL());
609 protected:
610 TestMalwareDetailsFactory details_factory_;
612 private:
613 TestSafeBrowsingServiceFactory factory_;
614 TestSafeBrowsingBlockingPageFactory blocking_page_factory_;
616 DISALLOW_COPY_AND_ASSIGN(SafeBrowsingBlockingPageBrowserTest);
619 // TODO(linux_aura) https://crbug.com/163931
620 // TODO(win_aura) https://crbug.com/154081
621 #if defined(USE_AURA) && !defined(OS_CHROMEOS)
622 #define MAYBE_RedirectInIFrameCanceled DISABLED_RedirectInIFrameCanceled
623 #else
624 #define MAYBE_RedirectInIFrameCanceled RedirectInIFrameCanceled
625 #endif
626 IN_PROC_BROWSER_TEST_P(SafeBrowsingBlockingPageBrowserTest,
627 MAYBE_RedirectInIFrameCanceled) {
628 // 1. Test the case that redirect is a subresource.
629 MalwareRedirectCancelAndProceed("openWinIFrame");
630 // If the redirect was from subresource but canceled, "proceed" will continue
631 // with the rest of resources.
632 AssertNoInterstitial(true);
635 IN_PROC_BROWSER_TEST_P(SafeBrowsingBlockingPageBrowserTest, RedirectCanceled) {
636 // 2. Test the case that redirect is the only resource.
637 MalwareRedirectCancelAndProceed("openWin");
638 // Clicking proceed won't do anything if the main request is cancelled
639 // already. See crbug.com/76460.
640 EXPECT_TRUE(YesInterstitial());
643 IN_PROC_BROWSER_TEST_P(SafeBrowsingBlockingPageBrowserTest, DontProceed) {
644 #if defined(OS_WIN) && defined(USE_ASH)
645 // Disable this test in Metro+Ash for now (https://crbug.com/262796).
646 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
647 switches::kAshBrowserTests)) {
648 return;
650 #endif
652 SetupWarningAndNavigate();
654 EXPECT_EQ(VISIBLE, GetVisibility("primary-button"));
655 EXPECT_EQ(HIDDEN, GetVisibility("details"));
656 EXPECT_EQ(HIDDEN, GetVisibility("proceed-link"));
657 EXPECT_EQ(HIDDEN, GetVisibility("error-code"));
658 EXPECT_TRUE(Click("details-button"));
659 EXPECT_EQ(VISIBLE, GetVisibility("details"));
660 EXPECT_EQ(VISIBLE, GetVisibility("proceed-link"));
661 EXPECT_EQ(HIDDEN, GetVisibility("error-code"));
662 EXPECT_TRUE(ClickAndWaitForDetach("primary-button"));
664 AssertNoInterstitial(false); // Assert the interstitial is gone
665 EXPECT_EQ(GURL(url::kAboutBlankURL), // Back to "about:blank"
666 browser()->tab_strip_model()->GetActiveWebContents()->GetURL());
669 IN_PROC_BROWSER_TEST_P(SafeBrowsingBlockingPageBrowserTest, Proceed) {
670 GURL url = SetupWarningAndNavigate();
672 EXPECT_TRUE(ClickAndWaitForDetach("proceed-link"));
673 AssertNoInterstitial(true); // Assert the interstitial is gone.
674 EXPECT_EQ(url,
675 browser()->tab_strip_model()->GetActiveWebContents()->GetURL());
678 IN_PROC_BROWSER_TEST_P(SafeBrowsingBlockingPageBrowserTest, IframeDontProceed) {
679 #if defined(OS_WIN) && defined(USE_ASH)
680 // Disable this test in Metro+Ash for now (https://crbug.com/262796).
681 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
682 switches::kAshBrowserTests)) {
683 return;
685 #endif
687 SetupThreatIframeWarningAndNavigate();
689 EXPECT_EQ(VISIBLE, GetVisibility("primary-button"));
690 EXPECT_EQ(HIDDEN, GetVisibility("details"));
691 EXPECT_EQ(HIDDEN, GetVisibility("proceed-link"));
692 EXPECT_EQ(HIDDEN, GetVisibility("error-code"));
693 EXPECT_TRUE(Click("details-button"));
694 EXPECT_EQ(VISIBLE, GetVisibility("details"));
695 EXPECT_EQ(VISIBLE, GetVisibility("proceed-link"));
696 EXPECT_EQ(HIDDEN, GetVisibility("error-code"));
697 EXPECT_TRUE(ClickAndWaitForDetach("primary-button"));
699 AssertNoInterstitial(false); // Assert the interstitial is gone
701 EXPECT_EQ(GURL(url::kAboutBlankURL), // Back to "about:blank"
702 browser()->tab_strip_model()->GetActiveWebContents()->GetURL());
705 IN_PROC_BROWSER_TEST_P(SafeBrowsingBlockingPageBrowserTest, IframeProceed) {
706 GURL url = SetupThreatIframeWarningAndNavigate();
708 EXPECT_TRUE(ClickAndWaitForDetach("proceed-link"));
709 AssertNoInterstitial(true); // Assert the interstitial is gone
711 EXPECT_EQ(url,
712 browser()->tab_strip_model()->GetActiveWebContents()->GetURL());
715 IN_PROC_BROWSER_TEST_P(SafeBrowsingBlockingPageBrowserTest,
716 IframeOptInAndReportMalwareDetails) {
717 // The extended reporting opt-in is presented in the interstitial for malware,
718 // phishing, and UwS threats. It however only results in uploading further
719 // details about the immediate threat when facing malware threats.
720 const bool expect_malware_details = GetParam() == SB_THREAT_TYPE_URL_MALWARE;
722 scoped_refptr<content::MessageLoopRunner> malware_report_sent_runner(
723 new content::MessageLoopRunner);
724 if (expect_malware_details)
725 SetReportSentCallback(malware_report_sent_runner->QuitClosure());
727 GURL url = SetupThreatIframeWarningAndNavigate();
729 FakeMalwareDetails* fake_malware_details = details_factory_.get_details();
730 EXPECT_EQ(expect_malware_details, fake_malware_details != nullptr);
732 // If the DOM details from renderer did not already return when they are
733 // expected, wait for them.
734 if (expect_malware_details)
735 fake_malware_details->WaitForDOM();
737 EXPECT_EQ(VISIBLE, GetVisibility("extended-reporting-opt-in"));
738 EXPECT_TRUE(Click("opt-in-checkbox"));
739 EXPECT_TRUE(ClickAndWaitForDetach("proceed-link"));
740 AssertNoInterstitial(true); // Assert the interstitial is gone
742 EXPECT_TRUE(browser()->profile()->GetPrefs()->GetBoolean(
743 prefs::kSafeBrowsingExtendedReportingEnabled));
744 EXPECT_EQ(url,
745 browser()->tab_strip_model()->GetActiveWebContents()->GetURL());
747 if (expect_malware_details) {
748 malware_report_sent_runner->Run();
749 std::string serialized = GetReportSent();
750 safe_browsing::ClientMalwareReportRequest report;
751 ASSERT_TRUE(report.ParseFromString(serialized));
752 // Verify the report is complete.
753 EXPECT_TRUE(report.complete());
757 // Verifies that the "proceed anyway" link isn't available when it is disabled
758 // by the corresponding policy. Also verifies that sending the "proceed"
759 // command anyway doesn't advance to the malware site.
760 IN_PROC_BROWSER_TEST_P(SafeBrowsingBlockingPageBrowserTest, ProceedDisabled) {
761 #if defined(OS_WIN) && defined(USE_ASH)
762 // Disable this test in Metro+Ash for now (https://crbug.com/262796).
763 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
764 switches::kAshBrowserTests)) {
765 return;
767 #endif
769 // Simulate a policy disabling the "proceed anyway" link.
770 browser()->profile()->GetPrefs()->SetBoolean(
771 prefs::kSafeBrowsingProceedAnywayDisabled, true);
773 SetupWarningAndNavigate();
775 EXPECT_EQ(VISIBLE, GetVisibility("primary-button"));
776 EXPECT_EQ(HIDDEN, GetVisibility("details"));
777 EXPECT_EQ(HIDDEN, GetVisibility("proceed-link"));
778 EXPECT_EQ(HIDDEN, GetVisibility("final-paragraph"));
779 EXPECT_TRUE(Click("details-button"));
780 EXPECT_EQ(HIDDEN, GetVisibility("proceed-link"));
781 EXPECT_EQ(HIDDEN, GetVisibility("final-paragraph"));
782 SendCommand(SecurityInterstitialPage::CMD_PROCEED);
784 // The "proceed" command should go back instead, if proceeding is disabled.
785 AssertNoInterstitial(true);
786 EXPECT_EQ(GURL(url::kAboutBlankURL), // Back to "about:blank"
787 browser()->tab_strip_model()->GetActiveWebContents()->GetURL());
790 // Verifies that the reporting checkbox is hidden on non-HTTP pages.
791 // TODO(mattm): Should also verify that no report is sent, but there isn't a
792 // good way to do that in the current design.
793 IN_PROC_BROWSER_TEST_P(SafeBrowsingBlockingPageBrowserTest, ReportingDisabled) {
794 #if defined(OS_WIN) && defined(USE_ASH)
795 // Disable this test in Metro+Ash for now (https://crbug.com/262796).
796 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
797 switches::kAshBrowserTests)) {
798 return;
800 #endif
802 browser()->profile()->GetPrefs()->SetBoolean(
803 prefs::kSafeBrowsingExtendedReportingEnabled, true);
805 TestReportingDisabledAndDontProceed(
806 net::URLRequestMockHTTPJob::GetMockHttpsUrl(kEmptyPage));
809 // Verifies that the reporting checkbox is hidden when opt-in is
810 // disabled by policy.
811 IN_PROC_BROWSER_TEST_P(SafeBrowsingBlockingPageBrowserTest,
812 ReportingDisabledByPolicy) {
813 #if defined(OS_WIN) && defined(USE_ASH)
814 // Disable this test in Metro+Ash for now (https://crbug.com/262796).
815 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
816 switches::kAshBrowserTests)) {
817 return;
819 #endif
821 browser()->profile()->GetPrefs()->SetBoolean(
822 prefs::kSafeBrowsingExtendedReportingEnabled, true);
823 browser()->profile()->GetPrefs()->SetBoolean(
824 prefs::kSafeBrowsingExtendedReportingOptInAllowed, false);
826 TestReportingDisabledAndDontProceed(
827 net::URLRequestMockHTTPJob::GetMockUrl(kEmptyPage));
830 IN_PROC_BROWSER_TEST_P(SafeBrowsingBlockingPageBrowserTest, LearnMore) {
831 SetupWarningAndNavigate();
832 EXPECT_TRUE(ClickAndWaitForDetach("help-link"));
833 AssertNoInterstitial(false); // Assert the interstitial is gone
835 // We are in the help page.
836 EXPECT_EQ(
837 GetParam() == SB_THREAT_TYPE_URL_PHISHING
838 ? "/transparencyreport/safebrowsing/"
839 : "/safebrowsing/diagnostic",
840 browser()->tab_strip_model()->GetActiveWebContents()->GetURL().path());
843 IN_PROC_BROWSER_TEST_P(SafeBrowsingBlockingPageBrowserTest,
844 Histograms_DontProceed) {
845 #if defined(OS_WIN) && defined(USE_ASH)
846 // Disable this test in Metro+Ash for now (https://crbug.com/262796).
847 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
848 switches::kAshBrowserTests)) {
849 return;
851 #endif
853 base::HistogramTester histograms;
854 std::string prefix;
855 if (GetParam() == SB_THREAT_TYPE_URL_MALWARE)
856 prefix = "malware";
857 else if (GetParam() == SB_THREAT_TYPE_URL_PHISHING)
858 prefix = "phishing";
859 else if (GetParam() == SB_THREAT_TYPE_URL_UNWANTED)
860 prefix = "harmful";
861 else
862 NOTREACHED();
863 const std::string decision_histogram = "interstitial." + prefix + ".decision";
864 const std::string interaction_histogram =
865 "interstitial." + prefix + ".interaction";
867 // TODO(nparker): Check for *.from_device as well.
869 // Histograms should start off empty.
870 histograms.ExpectTotalCount(decision_histogram, 0);
871 histograms.ExpectTotalCount(interaction_histogram, 0);
873 // After navigating to the page, the totals should be set.
874 SetupWarningAndNavigate();
875 histograms.ExpectTotalCount(decision_histogram, 1);
876 histograms.ExpectBucketCount(decision_histogram,
877 security_interstitials::MetricsHelper::SHOW, 1);
878 histograms.ExpectTotalCount(interaction_histogram, 1);
879 histograms.ExpectBucketCount(
880 interaction_histogram,
881 security_interstitials::MetricsHelper::TOTAL_VISITS, 1);
883 // Decision should be recorded.
884 EXPECT_TRUE(ClickAndWaitForDetach("primary-button"));
885 AssertNoInterstitial(false); // Assert the interstitial is gone
886 histograms.ExpectTotalCount(decision_histogram, 2);
887 histograms.ExpectBucketCount(
888 decision_histogram, security_interstitials::MetricsHelper::DONT_PROCEED,
890 histograms.ExpectTotalCount(interaction_histogram, 1);
891 histograms.ExpectBucketCount(
892 interaction_histogram,
893 security_interstitials::MetricsHelper::TOTAL_VISITS, 1);
896 IN_PROC_BROWSER_TEST_P(SafeBrowsingBlockingPageBrowserTest,
897 Histograms_Proceed) {
898 base::HistogramTester histograms;
899 std::string prefix;
900 if (GetParam() == SB_THREAT_TYPE_URL_MALWARE)
901 prefix = "malware";
902 else if (GetParam() == SB_THREAT_TYPE_URL_PHISHING)
903 prefix = "phishing";
904 else if (GetParam() == SB_THREAT_TYPE_URL_UNWANTED)
905 prefix = "harmful";
906 else
907 NOTREACHED();
908 const std::string decision_histogram = "interstitial." + prefix + ".decision";
909 const std::string interaction_histogram =
910 "interstitial." + prefix + ".interaction";
912 // Histograms should start off empty.
913 histograms.ExpectTotalCount(decision_histogram, 0);
914 histograms.ExpectTotalCount(interaction_histogram, 0);
916 // After navigating to the page, the totals should be set.
917 GURL url = SetupWarningAndNavigate();
918 histograms.ExpectTotalCount(decision_histogram, 1);
919 histograms.ExpectBucketCount(decision_histogram,
920 security_interstitials::MetricsHelper::SHOW, 1);
921 histograms.ExpectTotalCount(interaction_histogram, 1);
922 histograms.ExpectBucketCount(
923 interaction_histogram,
924 security_interstitials::MetricsHelper::TOTAL_VISITS, 1);
926 // Decision should be recorded.
927 EXPECT_TRUE(ClickAndWaitForDetach("proceed-link"));
928 AssertNoInterstitial(true); // Assert the interstitial is gone.
929 histograms.ExpectTotalCount(decision_histogram, 2);
930 histograms.ExpectBucketCount(
931 decision_histogram, security_interstitials::MetricsHelper::PROCEED, 1);
932 histograms.ExpectTotalCount(interaction_histogram, 1);
933 histograms.ExpectBucketCount(
934 interaction_histogram,
935 security_interstitials::MetricsHelper::TOTAL_VISITS, 1);
938 IN_PROC_BROWSER_TEST_P(SafeBrowsingBlockingPageBrowserTest, WhitelistRevisit) {
939 GURL url = SetupWarningAndNavigate();
941 EXPECT_TRUE(ClickAndWaitForDetach("proceed-link"));
942 AssertNoInterstitial(true); // Assert the interstitial is gone.
943 EXPECT_EQ(url,
944 browser()->tab_strip_model()->GetActiveWebContents()->GetURL());
946 // Unrelated pages should not be whitelisted now.
947 ui_test_utils::NavigateToURL(browser(), GURL(kUnrelatedUrl));
948 AssertNoInterstitial(false);
950 // The whitelisted page should remain whitelisted.
951 ui_test_utils::NavigateToURL(browser(), url);
952 AssertNoInterstitial(false);
955 IN_PROC_BROWSER_TEST_P(SafeBrowsingBlockingPageBrowserTest,
956 WhitelistIframeRevisit) {
957 GURL url = SetupThreatIframeWarningAndNavigate();
959 EXPECT_TRUE(ClickAndWaitForDetach("proceed-link"));
960 AssertNoInterstitial(true); // Assert the interstitial is gone.
961 EXPECT_EQ(url,
962 browser()->tab_strip_model()->GetActiveWebContents()->GetURL());
964 // Unrelated pages should not be whitelisted now.
965 ui_test_utils::NavigateToURL(browser(), GURL(kUnrelatedUrl));
966 AssertNoInterstitial(false);
968 // The whitelisted page should remain whitelisted.
969 ui_test_utils::NavigateToURL(browser(), url);
970 AssertNoInterstitial(false);
973 IN_PROC_BROWSER_TEST_P(SafeBrowsingBlockingPageBrowserTest, WhitelistUnsaved) {
974 GURL url = SetupWarningAndNavigate();
976 // Navigate without making a decision.
977 ui_test_utils::NavigateToURL(browser(), GURL(kUnrelatedUrl));
978 AssertNoInterstitial(false);
980 // The non-whitelisted page should now show an interstitial.
981 ui_test_utils::NavigateToURL(browser(), url);
982 EXPECT_TRUE(WaitForReady());
983 EXPECT_TRUE(ClickAndWaitForDetach("proceed-link"));
984 AssertNoInterstitial(true);
987 INSTANTIATE_TEST_CASE_P(SafeBrowsingBlockingPageBrowserTestWithThreatType,
988 SafeBrowsingBlockingPageBrowserTest,
989 testing::Values(SB_THREAT_TYPE_URL_MALWARE,
990 SB_THREAT_TYPE_URL_PHISHING,
991 SB_THREAT_TYPE_URL_UNWANTED));
993 // Test that SafeBrowsingBlockingPage properly decodes IDN URLs that are
994 // displayed.
995 class SafeBrowsingBlockingPageIDNTest
996 : public SecurityInterstitialIDNTest,
997 public testing::WithParamInterface<SBThreatType> {
998 protected:
999 // SecurityInterstitialIDNTest implementation
1000 SecurityInterstitialPage* CreateInterstitial(
1001 content::WebContents* contents,
1002 const GURL& request_url) const override {
1003 SafeBrowsingService* sb_service =
1004 g_browser_process->safe_browsing_service();
1005 SafeBrowsingBlockingPage::UnsafeResource resource;
1007 resource.url = request_url;
1008 resource.is_subresource = false;
1009 resource.threat_type = GetParam();
1010 resource.render_process_host_id = contents->GetRenderProcessHost()->GetID();
1011 resource.render_view_id = contents->GetRenderViewHost()->GetRoutingID();
1012 resource.threat_source = SafeBrowsingUIManager::FROM_DEVICE;
1014 return SafeBrowsingBlockingPage::CreateBlockingPage(
1015 sb_service->ui_manager().get(), contents, resource);
1019 IN_PROC_BROWSER_TEST_P(SafeBrowsingBlockingPageIDNTest,
1020 SafeBrowsingBlockingPageDecodesIDN) {
1021 EXPECT_TRUE(VerifyIDNDecoded());
1024 INSTANTIATE_TEST_CASE_P(SafeBrowsingBlockingPageIDNTestWithThreatType,
1025 SafeBrowsingBlockingPageIDNTest,
1026 testing::Values(SB_THREAT_TYPE_URL_MALWARE,
1027 SB_THREAT_TYPE_URL_PHISHING,
1028 SB_THREAT_TYPE_URL_UNWANTED));