No dual_mode on Win10+ shortcuts.
[chromium-blink-merge.git] / chrome / browser / safe_browsing / safe_browsing_blocking_page_test.cc
blob19b1715499eac43aaf79c7c192ec06cfe6a717d6
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/values.h"
15 #include "chrome/browser/browser_process.h"
16 #include "chrome/browser/interstitials/security_interstitial_page_test_utils.h"
17 #include "chrome/browser/net/url_request_mock_util.h"
18 #include "chrome/browser/profiles/profile.h"
19 #include "chrome/browser/safe_browsing/database_manager.h"
20 #include "chrome/browser/safe_browsing/local_database_manager.h"
21 #include "chrome/browser/safe_browsing/malware_details.h"
22 #include "chrome/browser/safe_browsing/safe_browsing_blocking_page.h"
23 #include "chrome/browser/safe_browsing/safe_browsing_service.h"
24 #include "chrome/browser/safe_browsing/safe_browsing_util.h"
25 #include "chrome/browser/safe_browsing/test_database_manager.h"
26 #include "chrome/browser/safe_browsing/ui_manager.h"
27 #include "chrome/browser/ui/browser.h"
28 #include "chrome/browser/ui/browser_tabstrip.h"
29 #include "chrome/browser/ui/tabs/tab_strip_model.h"
30 #include "chrome/common/chrome_switches.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 "content/public/browser/interstitial_page.h"
37 #include "content/public/browser/navigation_controller.h"
38 #include "content/public/browser/notification_types.h"
39 #include "content/public/browser/render_frame_host.h"
40 #include "content/public/browser/render_process_host.h"
41 #include "content/public/browser/render_view_host.h"
42 #include "content/public/browser/web_contents.h"
43 #include "content/public/test/browser_test_utils.h"
44 #include "content/public/test/test_browser_thread.h"
45 #include "content/public/test/test_utils.h"
46 #include "net/test/url_request/url_request_mock_http_job.h"
48 using chrome_browser_interstitials::SecurityInterstitialIDNTest;
49 using content::BrowserThread;
50 using content::InterstitialPage;
51 using content::NavigationController;
52 using content::WebContents;
54 namespace {
56 const char kEmptyPage[] = "empty.html";
57 const char kMalwarePage[] = "safe_browsing/malware.html";
58 const char kMalwareIframe[] = "safe_browsing/malware_iframe.html";
60 // A SafeBrowsingDatabaseManager class that allows us to inject the malicious
61 // URLs.
62 class FakeSafeBrowsingDatabaseManager : public TestSafeBrowsingDatabaseManager {
63 public:
64 FakeSafeBrowsingDatabaseManager() {}
66 // Called on the IO thread to check if the given url is safe or not. If we
67 // can synchronously determine that the url is safe, CheckUrl returns true.
68 // Otherwise it returns false, and "client" is called asynchronously with the
69 // result when it is ready.
70 // Overrides SafeBrowsingDatabaseManager::CheckBrowseUrl.
71 bool CheckBrowseUrl(const GURL& gurl, Client* client) override {
72 if (badurls[gurl.spec()] == SB_THREAT_TYPE_SAFE)
73 return true;
75 BrowserThread::PostTask(
76 BrowserThread::IO, FROM_HERE,
77 base::Bind(&FakeSafeBrowsingDatabaseManager::OnCheckBrowseURLDone,
78 this, gurl, client));
79 return false;
82 void OnCheckBrowseURLDone(const GURL& gurl, Client* client) {
83 std::vector<SBThreatType> expected_threats;
84 // TODO(nparker): Remove ref to LocalSafeBrowsingDatabase by calling
85 // client->OnCheckBrowseUrlResult(..) directly.
86 expected_threats.push_back(SB_THREAT_TYPE_URL_MALWARE);
87 expected_threats.push_back(SB_THREAT_TYPE_URL_PHISHING);
88 expected_threats.push_back(SB_THREAT_TYPE_URL_UNWANTED);
89 LocalSafeBrowsingDatabaseManager::SafeBrowsingCheck sb_check(
90 std::vector<GURL>(1, gurl),
91 std::vector<SBFullHash>(),
92 client,
93 safe_browsing_util::MALWARE,
94 expected_threats);
95 sb_check.url_results[0] = badurls[gurl.spec()];
96 sb_check.OnSafeBrowsingResult();
99 void SetURLThreatType(const GURL& url, SBThreatType threat_type) {
100 badurls[url.spec()] = threat_type;
103 // Called during startup, so must not check-fail.
104 bool CheckExtensionIDs(const std::set<std::string>& extension_ids,
105 Client* client) override {
106 return true;
109 private:
110 ~FakeSafeBrowsingDatabaseManager() override {}
112 base::hash_map<std::string, SBThreatType> badurls;
113 DISALLOW_COPY_AND_ASSIGN(FakeSafeBrowsingDatabaseManager);
116 // A SafeBrowingUIManager class that allows intercepting malware details.
117 class FakeSafeBrowsingUIManager : public SafeBrowsingUIManager {
118 public:
119 explicit FakeSafeBrowsingUIManager(SafeBrowsingService* service) :
120 SafeBrowsingUIManager(service) { }
122 // Overrides SafeBrowsingUIManager
123 void SendSerializedMalwareDetails(const std::string& serialized) override {
124 // Notify the UI thread that we got a report.
125 BrowserThread::PostTask(
126 BrowserThread::UI,
127 FROM_HERE,
128 base::Bind(&FakeSafeBrowsingUIManager::OnMalwareDetailsDone,
129 this,
130 serialized));
133 void OnMalwareDetailsDone(const std::string& serialized) {
134 EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI));
135 report_ = serialized;
137 EXPECT_FALSE(malware_details_done_callback_.is_null());
138 if (!malware_details_done_callback_.is_null()) {
139 malware_details_done_callback_.Run();
140 malware_details_done_callback_ = base::Closure();
144 void set_malware_details_done_callback(const base::Closure& callback) {
145 EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI));
146 EXPECT_TRUE(malware_details_done_callback_.is_null());
147 malware_details_done_callback_ = callback;
150 std::string GetReport() {
151 EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI));
152 return report_;
155 protected:
156 ~FakeSafeBrowsingUIManager() override {}
158 private:
159 std::string report_;
160 base::Closure malware_details_done_callback_;
162 DISALLOW_COPY_AND_ASSIGN(FakeSafeBrowsingUIManager);
165 class FakeSafeBrowsingService : public SafeBrowsingService {
166 public:
167 FakeSafeBrowsingService()
168 : fake_database_manager_(),
169 fake_ui_manager_() { }
171 // Returned pointer has the same lifespan as the database_manager_ refcounted
172 // object.
173 FakeSafeBrowsingDatabaseManager* fake_database_manager() {
174 return fake_database_manager_;
176 // Returned pointer has the same lifespan as the ui_manager_ refcounted
177 // object.
178 FakeSafeBrowsingUIManager* fake_ui_manager() {
179 return fake_ui_manager_;
182 protected:
183 ~FakeSafeBrowsingService() override {}
185 SafeBrowsingDatabaseManager* CreateDatabaseManager() override {
186 fake_database_manager_ = new FakeSafeBrowsingDatabaseManager();
187 return fake_database_manager_;
190 SafeBrowsingUIManager* CreateUIManager() override {
191 fake_ui_manager_ = new FakeSafeBrowsingUIManager(this);
192 return fake_ui_manager_;
195 SafeBrowsingProtocolManagerDelegate* GetProtocolManagerDelegate() override {
196 // Our SafeBrowsingDatabaseManager doesn't implement this delegate.
197 return NULL;
200 private:
201 FakeSafeBrowsingDatabaseManager* fake_database_manager_;
202 FakeSafeBrowsingUIManager* fake_ui_manager_;
204 DISALLOW_COPY_AND_ASSIGN(FakeSafeBrowsingService);
207 // Factory that creates FakeSafeBrowsingService instances.
208 class TestSafeBrowsingServiceFactory : public SafeBrowsingServiceFactory {
209 public:
210 TestSafeBrowsingServiceFactory() :
211 most_recent_service_(NULL) { }
212 ~TestSafeBrowsingServiceFactory() override {}
214 SafeBrowsingService* CreateSafeBrowsingService() override {
215 most_recent_service_ = new FakeSafeBrowsingService();
216 return most_recent_service_;
219 FakeSafeBrowsingService* most_recent_service() const {
220 return most_recent_service_;
223 private:
224 FakeSafeBrowsingService* most_recent_service_;
227 // A MalwareDetails class lets us intercept calls from the renderer.
228 class FakeMalwareDetails : public MalwareDetails {
229 public:
230 FakeMalwareDetails(
231 SafeBrowsingUIManager* delegate,
232 WebContents* web_contents,
233 const SafeBrowsingUIManager::UnsafeResource& unsafe_resource)
234 : MalwareDetails(delegate, web_contents, unsafe_resource),
235 got_dom_(false),
236 waiting_(false) { }
238 void AddDOMDetails(
239 const std::vector<SafeBrowsingHostMsg_MalwareDOMDetails_Node>& params)
240 override {
241 EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
242 MalwareDetails::AddDOMDetails(params);
244 // Notify the UI thread that we got the dom details.
245 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
246 base::Bind(&FakeMalwareDetails::OnDOMDetailsDone,
247 this));
250 void WaitForDOM() {
251 if (got_dom_) {
252 return;
254 // This condition might not trigger normally, but if you add a
255 // sleep(1) in malware_dom_details it triggers :).
256 waiting_ = true;
257 content::RunMessageLoop();
258 EXPECT_TRUE(got_dom_);
261 private:
262 ~FakeMalwareDetails() override {}
264 void OnDOMDetailsDone() {
265 got_dom_ = true;
266 if (waiting_) {
267 base::MessageLoopForUI::current()->Quit();
271 // Some logic to figure out if we should wait for the dom details or not.
272 // These variables should only be accessed in the UI thread.
273 bool got_dom_;
274 bool waiting_;
277 class TestMalwareDetailsFactory : public MalwareDetailsFactory {
278 public:
279 TestMalwareDetailsFactory() : details_() { }
280 ~TestMalwareDetailsFactory() override {}
282 MalwareDetails* CreateMalwareDetails(
283 SafeBrowsingUIManager* delegate,
284 WebContents* web_contents,
285 const SafeBrowsingUIManager::UnsafeResource& unsafe_resource) override {
286 details_ = new FakeMalwareDetails(delegate, web_contents,
287 unsafe_resource);
288 return details_;
291 FakeMalwareDetails* get_details() {
292 return details_;
295 private:
296 FakeMalwareDetails* details_;
299 // A SafeBrowingBlockingPage class that lets us wait until it's hidden.
300 class TestSafeBrowsingBlockingPage : public SafeBrowsingBlockingPage {
301 public:
302 TestSafeBrowsingBlockingPage(SafeBrowsingUIManager* manager,
303 WebContents* web_contents,
304 const UnsafeResourceList& unsafe_resources)
305 : SafeBrowsingBlockingPage(manager, web_contents, unsafe_resources),
306 wait_for_delete_(false) {
307 // Don't wait the whole 3 seconds for the browser test.
308 malware_details_proceed_delay_ms_ = 100;
311 ~TestSafeBrowsingBlockingPage() override {
312 if (!wait_for_delete_)
313 return;
315 // Notify that we are gone
316 base::MessageLoopForUI::current()->Quit();
317 wait_for_delete_ = false;
320 void WaitForDelete() {
321 wait_for_delete_ = true;
322 content::RunMessageLoop();
325 // InterstitialPageDelegate methods:
326 void CommandReceived(const std::string& command) override {
327 SafeBrowsingBlockingPage::CommandReceived(command);
329 void OnProceed() override { SafeBrowsingBlockingPage::OnProceed(); }
330 void OnDontProceed() override { SafeBrowsingBlockingPage::OnDontProceed(); }
332 private:
333 bool wait_for_delete_;
336 class TestSafeBrowsingBlockingPageFactory
337 : public SafeBrowsingBlockingPageFactory {
338 public:
339 TestSafeBrowsingBlockingPageFactory() { }
340 ~TestSafeBrowsingBlockingPageFactory() override {}
342 SafeBrowsingBlockingPage* CreateSafeBrowsingPage(
343 SafeBrowsingUIManager* delegate,
344 WebContents* web_contents,
345 const SafeBrowsingBlockingPage::UnsafeResourceList& unsafe_resources)
346 override {
347 return new TestSafeBrowsingBlockingPage(delegate, web_contents,
348 unsafe_resources);
352 } // namespace
354 // Tests the safe browsing blocking page in a browser.
355 class SafeBrowsingBlockingPageBrowserTest
356 : public InProcessBrowserTest,
357 public testing::WithParamInterface<SBThreatType> {
358 public:
359 enum Visibility {
360 VISIBILITY_ERROR = -1,
361 HIDDEN = 0,
362 VISIBLE = 1
365 SafeBrowsingBlockingPageBrowserTest() {}
367 void SetUp() override {
368 SafeBrowsingService::RegisterFactory(&factory_);
369 SafeBrowsingBlockingPage::RegisterFactory(&blocking_page_factory_);
370 MalwareDetails::RegisterFactory(&details_factory_);
371 InProcessBrowserTest::SetUp();
374 void SetUpCommandLine(base::CommandLine* command_line) override {
375 command_line->AppendSwitchASCII(
376 switches::kForceFieldTrials, "UwSInterstitialStatus/On/");
379 void TearDown() override {
380 InProcessBrowserTest::TearDown();
381 SafeBrowsingBlockingPage::RegisterFactory(NULL);
382 SafeBrowsingService::RegisterFactory(NULL);
383 MalwareDetails::RegisterFactory(NULL);
386 void SetUpOnMainThread() override {
387 BrowserThread::PostTask(
388 BrowserThread::IO, FROM_HERE,
389 base::Bind(&chrome_browser_net::SetUrlRequestMocksEnabled, true));
392 void SetURLThreatType(const GURL& url, SBThreatType threat_type) {
393 FakeSafeBrowsingService* service =
394 static_cast<FakeSafeBrowsingService*>(
395 g_browser_process->safe_browsing_service());
397 ASSERT_TRUE(service);
398 service->fake_database_manager()->SetURLThreatType(url, threat_type);
401 // Adds a safebrowsing result of the current test threat to the fake
402 // safebrowsing service, navigates to that page, and returns the url.
403 GURL SetupWarningAndNavigate() {
404 GURL url = net::URLRequestMockHTTPJob::GetMockUrl(kEmptyPage);
405 SetURLThreatType(url, GetParam());
407 ui_test_utils::NavigateToURL(browser(), url);
408 EXPECT_TRUE(WaitForReady());
409 return url;
412 // Adds a safebrowsing threat result to the fake safebrowsing service,
413 // navigates to a page with an iframe containing the threat site, and returns
414 // the url of the parent page.
415 GURL SetupThreatIframeWarningAndNavigate() {
416 GURL url = net::URLRequestMockHTTPJob::GetMockUrl(kMalwarePage);
417 GURL iframe_url = net::URLRequestMockHTTPJob::GetMockUrl(kMalwareIframe);
418 SetURLThreatType(iframe_url, GetParam());
420 ui_test_utils::NavigateToURL(browser(), url);
421 EXPECT_TRUE(WaitForReady());
422 return url;
425 void SendCommand(
426 SecurityInterstitialPage::SecurityInterstitialCommands command) {
427 WebContents* contents =
428 browser()->tab_strip_model()->GetActiveWebContents();
429 // We use InterstitialPage::GetInterstitialPage(tab) instead of
430 // tab->GetInterstitialPage() because the tab doesn't have a pointer
431 // to its interstital page until it gets a command from the renderer
432 // that it has indeed displayed it -- and this sometimes happens after
433 // NavigateToURL returns.
434 SafeBrowsingBlockingPage* interstitial_page =
435 static_cast<SafeBrowsingBlockingPage*>(
436 InterstitialPage::GetInterstitialPage(contents)->
437 GetDelegateForTesting());
438 ASSERT_TRUE(interstitial_page);
439 ASSERT_EQ(SafeBrowsingBlockingPage::kTypeForTesting,
440 interstitial_page->GetTypeForTesting());
441 interstitial_page->CommandReceived(base::IntToString(command));
444 void DontProceedThroughInterstitial() {
445 WebContents* contents =
446 browser()->tab_strip_model()->GetActiveWebContents();
447 InterstitialPage* interstitial_page = InterstitialPage::GetInterstitialPage(
448 contents);
449 ASSERT_TRUE(interstitial_page);
450 interstitial_page->DontProceed();
453 void ProceedThroughInterstitial() {
454 WebContents* contents =
455 browser()->tab_strip_model()->GetActiveWebContents();
456 InterstitialPage* interstitial_page = InterstitialPage::GetInterstitialPage(
457 contents);
458 ASSERT_TRUE(interstitial_page);
459 interstitial_page->Proceed();
462 void AssertNoInterstitial(bool wait_for_delete) {
463 WebContents* contents =
464 browser()->tab_strip_model()->GetActiveWebContents();
466 if (contents->ShowingInterstitialPage() && wait_for_delete) {
467 // We'll get notified when the interstitial is deleted.
468 TestSafeBrowsingBlockingPage* page =
469 static_cast<TestSafeBrowsingBlockingPage*>(
470 contents->GetInterstitialPage()->GetDelegateForTesting());
471 ASSERT_EQ(SafeBrowsingBlockingPage::kTypeForTesting,
472 page->GetTypeForTesting());
473 page->WaitForDelete();
476 // Can't use InterstitialPage::GetInterstitialPage() because that
477 // gets updated after the TestSafeBrowsingBlockingPage destructor
478 ASSERT_FALSE(contents->ShowingInterstitialPage());
481 bool YesInterstitial() {
482 WebContents* contents =
483 browser()->tab_strip_model()->GetActiveWebContents();
484 InterstitialPage* interstitial_page = InterstitialPage::GetInterstitialPage(
485 contents);
486 return interstitial_page != NULL;
489 void SetReportSentCallback(const base::Closure& callback) {
490 factory_.most_recent_service()
491 ->fake_ui_manager()
492 ->set_malware_details_done_callback(callback);
495 std::string GetReportSent() {
496 return factory_.most_recent_service()->fake_ui_manager()->GetReport();
499 void MalwareRedirectCancelAndProceed(const std::string& open_function) {
500 GURL load_url = net::URLRequestMockHTTPJob::GetMockUrl(
501 "safe_browsing/interstitial_cancel.html");
502 GURL malware_url = net::URLRequestMockHTTPJob::GetMockUrl(kMalwarePage);
503 SetURLThreatType(malware_url, GetParam());
505 // Load the test page.
506 ui_test_utils::NavigateToURL(browser(), load_url);
507 // Trigger the safe browsing interstitial page via a redirect in
508 // "openWin()".
509 ui_test_utils::NavigateToURLWithDisposition(
510 browser(),
511 GURL("javascript:" + open_function + "()"),
512 CURRENT_TAB,
513 ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB);
514 WebContents* contents =
515 browser()->tab_strip_model()->GetActiveWebContents();
516 content::WaitForInterstitialAttach(contents);
517 // Cancel the redirect request while interstitial page is open.
518 browser()->tab_strip_model()->ActivateTabAt(0, true);
519 ui_test_utils::NavigateToURL(browser(), GURL("javascript:stopWin()"));
520 browser()->tab_strip_model()->ActivateTabAt(1, true);
521 // Simulate the user clicking "proceed", there should be no crash. Since
522 // clicking proceed may do nothing (see comment in RedirectCanceled
523 // below, and crbug.com/76460), we use SendCommand to trigger the callback
524 // directly rather than using ClickAndWaitForDetach since there might not
525 // be a notification to wait for.
526 SendCommand(SecurityInterstitialPage::CMD_PROCEED);
529 content::RenderViewHost* GetRenderViewHost() {
530 InterstitialPage* interstitial = InterstitialPage::GetInterstitialPage(
531 browser()->tab_strip_model()->GetActiveWebContents());
532 if (!interstitial)
533 return NULL;
534 return interstitial->GetMainFrame()->GetRenderViewHost();
537 bool WaitForReady() {
538 InterstitialPage* interstitial = InterstitialPage::GetInterstitialPage(
539 browser()->tab_strip_model()->GetActiveWebContents());
540 if (!interstitial)
541 return false;
542 return content::WaitForRenderFrameReady(interstitial->GetMainFrame());
545 Visibility GetVisibility(const std::string& node_id) {
546 content::RenderViewHost* rvh = GetRenderViewHost();
547 if (!rvh)
548 return VISIBILITY_ERROR;
549 scoped_ptr<base::Value> value = content::ExecuteScriptAndGetValue(
550 rvh->GetMainFrame(),
551 "var node = document.getElementById('" + node_id + "');\n"
552 "if (node)\n"
553 " node.offsetWidth > 0 && node.offsetHeight > 0;"
554 "else\n"
555 " 'node not found';\n");
556 if (!value.get())
557 return VISIBILITY_ERROR;
558 bool result = false;
559 if (!value->GetAsBoolean(&result))
560 return VISIBILITY_ERROR;
561 return result ? VISIBLE : HIDDEN;
564 bool Click(const std::string& node_id) {
565 content::RenderViewHost* rvh = GetRenderViewHost();
566 if (!rvh)
567 return false;
568 // We don't use ExecuteScriptAndGetValue for this one, since clicking
569 // the button/link may navigate away before the injected javascript can
570 // reply, hanging the test.
571 rvh->GetMainFrame()->ExecuteJavaScriptForTests(
572 base::ASCIIToUTF16(
573 "document.getElementById('" + node_id + "').click();\n"));
574 return true;
577 bool ClickAndWaitForDetach(const std::string& node_id) {
578 // We wait for interstitial_detached rather than nav_entry_committed, as
579 // going back from a main-frame malware interstitial page will not cause a
580 // nav entry committed event.
581 if (!Click(node_id))
582 return false;
583 content::WaitForInterstitialDetach(
584 browser()->tab_strip_model()->GetActiveWebContents());
585 return true;
588 void TestReportingDisabledAndDontProceed(const GURL& url) {
589 SetURLThreatType(url, GetParam());
590 ui_test_utils::NavigateToURL(browser(), url);
591 ASSERT_TRUE(WaitForReady());
593 EXPECT_EQ(HIDDEN, GetVisibility("extended-reporting-opt-in"));
594 EXPECT_EQ(HIDDEN, GetVisibility("opt-in-checkbox"));
595 EXPECT_EQ(HIDDEN, GetVisibility("proceed-link"));
596 EXPECT_TRUE(Click("details-button"));
597 EXPECT_EQ(VISIBLE, GetVisibility("help-link"));
598 EXPECT_EQ(VISIBLE, GetVisibility("proceed-link"));
600 EXPECT_TRUE(ClickAndWaitForDetach("primary-button"));
601 AssertNoInterstitial(false); // Assert the interstitial is gone
602 EXPECT_EQ(GURL(url::kAboutBlankURL), // Back to "about:blank"
603 browser()->tab_strip_model()->GetActiveWebContents()->GetURL());
606 protected:
607 TestMalwareDetailsFactory details_factory_;
609 private:
610 TestSafeBrowsingServiceFactory factory_;
611 TestSafeBrowsingBlockingPageFactory blocking_page_factory_;
613 DISALLOW_COPY_AND_ASSIGN(SafeBrowsingBlockingPageBrowserTest);
616 // TODO(linux_aura) http://crbug.com/163931
617 // TODO(win_aura) http://crbug.com/154081
618 #if defined(USE_AURA) && !defined(OS_CHROMEOS)
619 #define MAYBE_RedirectInIFrameCanceled DISABLED_RedirectInIFrameCanceled
620 #else
621 #define MAYBE_RedirectInIFrameCanceled RedirectInIFrameCanceled
622 #endif
623 IN_PROC_BROWSER_TEST_P(SafeBrowsingBlockingPageBrowserTest,
624 MAYBE_RedirectInIFrameCanceled) {
625 // 1. Test the case that redirect is a subresource.
626 MalwareRedirectCancelAndProceed("openWinIFrame");
627 // If the redirect was from subresource but canceled, "proceed" will continue
628 // with the rest of resources.
629 AssertNoInterstitial(true);
632 IN_PROC_BROWSER_TEST_P(SafeBrowsingBlockingPageBrowserTest, RedirectCanceled) {
633 // 2. Test the case that redirect is the only resource.
634 MalwareRedirectCancelAndProceed("openWin");
635 // Clicking proceed won't do anything if the main request is cancelled
636 // already. See crbug.com/76460.
637 EXPECT_TRUE(YesInterstitial());
640 IN_PROC_BROWSER_TEST_P(SafeBrowsingBlockingPageBrowserTest, DontProceed) {
641 #if defined(OS_WIN) && defined(USE_ASH)
642 // Disable this test in Metro+Ash for now (http://crbug.com/262796).
643 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
644 switches::kAshBrowserTests))
645 return;
646 #endif
648 SetupWarningAndNavigate();
650 EXPECT_EQ(VISIBLE, GetVisibility("primary-button"));
651 EXPECT_EQ(HIDDEN, GetVisibility("details"));
652 EXPECT_EQ(HIDDEN, GetVisibility("proceed-link"));
653 EXPECT_EQ(HIDDEN, GetVisibility("error-code"));
654 EXPECT_TRUE(Click("details-button"));
655 EXPECT_EQ(VISIBLE, GetVisibility("details"));
656 EXPECT_EQ(VISIBLE, GetVisibility("proceed-link"));
657 EXPECT_EQ(HIDDEN, GetVisibility("error-code"));
658 EXPECT_TRUE(ClickAndWaitForDetach("primary-button"));
660 AssertNoInterstitial(false); // Assert the interstitial is gone
661 EXPECT_EQ(GURL(url::kAboutBlankURL), // Back to "about:blank"
662 browser()->tab_strip_model()->GetActiveWebContents()->GetURL());
665 IN_PROC_BROWSER_TEST_P(SafeBrowsingBlockingPageBrowserTest, Proceed) {
666 GURL url = SetupWarningAndNavigate();
668 EXPECT_TRUE(ClickAndWaitForDetach("proceed-link"));
669 AssertNoInterstitial(true); // Assert the interstitial is gone.
670 EXPECT_EQ(url,
671 browser()->tab_strip_model()->GetActiveWebContents()->GetURL());
674 IN_PROC_BROWSER_TEST_P(SafeBrowsingBlockingPageBrowserTest, IframeDontProceed) {
675 #if defined(OS_WIN) && defined(USE_ASH)
676 // Disable this test in Metro+Ash for now (http://crbug.com/262796).
677 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
678 switches::kAshBrowserTests))
679 return;
680 #endif
682 SetupThreatIframeWarningAndNavigate();
684 EXPECT_EQ(VISIBLE, GetVisibility("primary-button"));
685 EXPECT_EQ(HIDDEN, GetVisibility("details"));
686 EXPECT_EQ(HIDDEN, GetVisibility("proceed-link"));
687 EXPECT_EQ(HIDDEN, GetVisibility("error-code"));
688 EXPECT_TRUE(Click("details-button"));
689 EXPECT_EQ(VISIBLE, GetVisibility("details"));
690 EXPECT_EQ(VISIBLE, GetVisibility("proceed-link"));
691 EXPECT_EQ(HIDDEN, GetVisibility("error-code"));
692 EXPECT_TRUE(ClickAndWaitForDetach("primary-button"));
694 AssertNoInterstitial(false); // Assert the interstitial is gone
696 EXPECT_EQ(GURL(url::kAboutBlankURL), // Back to "about:blank"
697 browser()->tab_strip_model()->GetActiveWebContents()->GetURL());
700 IN_PROC_BROWSER_TEST_P(SafeBrowsingBlockingPageBrowserTest, IframeProceed) {
701 GURL url = SetupThreatIframeWarningAndNavigate();
703 EXPECT_TRUE(ClickAndWaitForDetach("proceed-link"));
704 AssertNoInterstitial(true); // Assert the interstitial is gone
706 EXPECT_EQ(url,
707 browser()->tab_strip_model()->GetActiveWebContents()->GetURL());
710 IN_PROC_BROWSER_TEST_P(SafeBrowsingBlockingPageBrowserTest,
711 IframeOptInAndReportMalwareDetails) {
712 // The extended reporting opt-in is presented in the interstitial for malware,
713 // phishing, and UwS threats. It however only results in uploading further
714 // details about the immediate threat when facing malware threats.
715 const bool expect_malware_details = GetParam() == SB_THREAT_TYPE_URL_MALWARE;
717 scoped_refptr<content::MessageLoopRunner> malware_report_sent_runner(
718 new content::MessageLoopRunner);
719 if (expect_malware_details)
720 SetReportSentCallback(malware_report_sent_runner->QuitClosure());
722 GURL url = SetupThreatIframeWarningAndNavigate();
724 FakeMalwareDetails* fake_malware_details = details_factory_.get_details();
725 EXPECT_EQ(expect_malware_details, fake_malware_details != nullptr);
727 // If the DOM details from renderer did not already return when they are
728 // expected, wait for them.
729 if (expect_malware_details)
730 fake_malware_details->WaitForDOM();
732 EXPECT_EQ(VISIBLE, GetVisibility("extended-reporting-opt-in"));
733 EXPECT_TRUE(Click("opt-in-checkbox"));
734 EXPECT_TRUE(ClickAndWaitForDetach("proceed-link"));
735 AssertNoInterstitial(true); // Assert the interstitial is gone
737 EXPECT_TRUE(browser()->profile()->GetPrefs()->GetBoolean(
738 prefs::kSafeBrowsingExtendedReportingEnabled));
739 EXPECT_EQ(url,
740 browser()->tab_strip_model()->GetActiveWebContents()->GetURL());
742 if (expect_malware_details) {
743 malware_report_sent_runner->Run();
744 std::string serialized = GetReportSent();
745 safe_browsing::ClientMalwareReportRequest report;
746 ASSERT_TRUE(report.ParseFromString(serialized));
747 // Verify the report is complete.
748 EXPECT_TRUE(report.complete());
752 // Verifies that the "proceed anyway" link isn't available when it is disabled
753 // by the corresponding policy. Also verifies that sending the "proceed"
754 // command anyway doesn't advance to the malware site.
755 IN_PROC_BROWSER_TEST_P(SafeBrowsingBlockingPageBrowserTest, ProceedDisabled) {
756 #if defined(OS_WIN) && defined(USE_ASH)
757 // Disable this test in Metro+Ash for now (http://crbug.com/262796).
758 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
759 switches::kAshBrowserTests))
760 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 (http://crbug.com/262796).
790 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
791 switches::kAshBrowserTests))
792 return;
793 #endif
795 browser()->profile()->GetPrefs()->SetBoolean(
796 prefs::kSafeBrowsingExtendedReportingEnabled, true);
798 TestReportingDisabledAndDontProceed(
799 net::URLRequestMockHTTPJob::GetMockHttpsUrl(kEmptyPage));
802 // Verifies that the reporting checkbox is hidden when opt-in is
803 // disabled by policy.
804 IN_PROC_BROWSER_TEST_P(SafeBrowsingBlockingPageBrowserTest,
805 ReportingDisabledByPolicy) {
806 #if defined(OS_WIN) && defined(USE_ASH)
807 // Disable this test in Metro+Ash for now (http://crbug.com/262796).
808 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
809 switches::kAshBrowserTests))
810 return;
811 #endif
813 browser()->profile()->GetPrefs()->SetBoolean(
814 prefs::kSafeBrowsingExtendedReportingEnabled, true);
815 browser()->profile()->GetPrefs()->SetBoolean(
816 prefs::kSafeBrowsingExtendedReportingOptInAllowed, false);
818 TestReportingDisabledAndDontProceed(
819 net::URLRequestMockHTTPJob::GetMockUrl(kEmptyPage));
822 IN_PROC_BROWSER_TEST_P(SafeBrowsingBlockingPageBrowserTest, LearnMore) {
823 SetupWarningAndNavigate();
824 EXPECT_TRUE(ClickAndWaitForDetach("help-link"));
825 AssertNoInterstitial(false); // Assert the interstitial is gone
827 // We are in the help page.
828 EXPECT_EQ(
829 GetParam() == SB_THREAT_TYPE_URL_PHISHING
830 ? "/transparencyreport/safebrowsing/"
831 : "/safebrowsing/diagnostic",
832 browser()->tab_strip_model()->GetActiveWebContents()->GetURL().path());
835 INSTANTIATE_TEST_CASE_P(SafeBrowsingBlockingPageBrowserTestWithThreatType,
836 SafeBrowsingBlockingPageBrowserTest,
837 testing::Values(SB_THREAT_TYPE_URL_MALWARE,
838 SB_THREAT_TYPE_URL_PHISHING,
839 SB_THREAT_TYPE_URL_UNWANTED));
841 // Test that SafeBrowsingBlockingPage properly decodes IDN URLs that are
842 // displayed.
843 class SafeBrowsingBlockingPageIDNTest
844 : public SecurityInterstitialIDNTest,
845 public testing::WithParamInterface<SBThreatType> {
846 protected:
847 // SecurityInterstitialIDNTest implementation
848 SecurityInterstitialPage* CreateInterstitial(
849 content::WebContents* contents,
850 const GURL& request_url) const override {
851 SafeBrowsingService* sb_service =
852 g_browser_process->safe_browsing_service();
853 SafeBrowsingBlockingPage::UnsafeResource resource;
855 resource.url = request_url;
856 resource.is_subresource = false;
857 resource.threat_type = GetParam();
858 resource.render_process_host_id = contents->GetRenderProcessHost()->GetID();
859 resource.render_view_id = contents->GetRenderViewHost()->GetRoutingID();
861 return SafeBrowsingBlockingPage::CreateBlockingPage(
862 sb_service->ui_manager().get(), contents, resource);
866 IN_PROC_BROWSER_TEST_P(SafeBrowsingBlockingPageIDNTest,
867 SafeBrowsingBlockingPageDecodesIDN) {
868 EXPECT_TRUE(VerifyIDNDecoded());
871 INSTANTIATE_TEST_CASE_P(SafeBrowsingBlockingPageIDNTestWithThreatType,
872 SafeBrowsingBlockingPageIDNTest,
873 testing::Values(SB_THREAT_TYPE_URL_MALWARE,
874 SB_THREAT_TYPE_URL_PHISHING,
875 SB_THREAT_TYPE_URL_UNWANTED));