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.
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.
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
;
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
65 class FakeSafeBrowsingDatabaseManager
: public TestSafeBrowsingDatabaseManager
{
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
)
78 BrowserThread::PostTask(
79 BrowserThread::IO
, FROM_HERE
,
80 base::Bind(&FakeSafeBrowsingDatabaseManager::OnCheckBrowseURLDone
,
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
>(),
96 safe_browsing_util::MALWARE
,
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
{
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
{
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(
131 base::Bind(&FakeSafeBrowsingUIManager::OnMalwareDetailsDone
,
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
));
159 ~FakeSafeBrowsingUIManager() override
{}
163 base::Closure malware_details_done_callback_
;
165 DISALLOW_COPY_AND_ASSIGN(FakeSafeBrowsingUIManager
);
168 class FakeSafeBrowsingService
: public SafeBrowsingService
{
170 FakeSafeBrowsingService()
171 : fake_database_manager_(),
172 fake_ui_manager_() { }
174 // Returned pointer has the same lifespan as the database_manager_ refcounted
176 FakeSafeBrowsingDatabaseManager
* fake_database_manager() {
177 return fake_database_manager_
;
179 // Returned pointer has the same lifespan as the ui_manager_ refcounted
181 FakeSafeBrowsingUIManager
* fake_ui_manager() {
182 return fake_ui_manager_
;
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.
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
{
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_
;
227 FakeSafeBrowsingService
* most_recent_service_
;
230 // A MalwareDetails class lets us intercept calls from the renderer.
231 class FakeMalwareDetails
: public MalwareDetails
{
234 SafeBrowsingUIManager
* delegate
,
235 WebContents
* web_contents
,
236 const SafeBrowsingUIManager::UnsafeResource
& unsafe_resource
)
237 : MalwareDetails(delegate
, web_contents
, unsafe_resource
),
242 const std::vector
<SafeBrowsingHostMsg_MalwareDOMDetails_Node
>& params
)
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
,
257 // This condition might not trigger normally, but if you add a
258 // sleep(1) in malware_dom_details it triggers :).
260 content::RunMessageLoop();
261 EXPECT_TRUE(got_dom_
);
265 ~FakeMalwareDetails() override
{}
267 void OnDOMDetailsDone() {
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.
280 class TestMalwareDetailsFactory
: public MalwareDetailsFactory
{
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
,
294 FakeMalwareDetails
* get_details() {
299 FakeMalwareDetails
* details_
;
302 // A SafeBrowingBlockingPage class that lets us wait until it's hidden.
303 class TestSafeBrowsingBlockingPage
: public SafeBrowsingBlockingPage
{
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_
)
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(); }
336 bool wait_for_delete_
;
339 class TestSafeBrowsingBlockingPageFactory
340 : public SafeBrowsingBlockingPageFactory
{
342 TestSafeBrowsingBlockingPageFactory() { }
343 ~TestSafeBrowsingBlockingPageFactory() override
{}
345 SafeBrowsingBlockingPage
* CreateSafeBrowsingPage(
346 SafeBrowsingUIManager
* delegate
,
347 WebContents
* web_contents
,
348 const SafeBrowsingBlockingPage::UnsafeResourceList
& unsafe_resources
)
350 return new TestSafeBrowsingBlockingPage(delegate
, web_contents
,
357 // Tests the safe browsing blocking page in a browser.
358 class SafeBrowsingBlockingPageBrowserTest
359 : public InProcessBrowserTest
,
360 public testing::WithParamInterface
<SBThreatType
> {
363 VISIBILITY_ERROR
= -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());
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());
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(
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(
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(
489 return interstitial_page
!= NULL
;
492 void SetReportSentCallback(const base::Closure
& callback
) {
493 factory_
.most_recent_service()
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
512 ui_test_utils::NavigateToURLWithDisposition(
514 GURL("javascript:" + open_function
+ "()"),
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());
537 return interstitial
->GetMainFrame()->GetRenderViewHost();
540 bool WaitForReady() {
541 InterstitialPage
* interstitial
= InterstitialPage::GetInterstitialPage(
542 browser()->tab_strip_model()->GetActiveWebContents());
545 return content::WaitForRenderFrameReady(interstitial
->GetMainFrame());
548 Visibility
GetVisibility(const std::string
& node_id
) {
549 content::RenderViewHost
* rvh
= GetRenderViewHost();
551 return VISIBILITY_ERROR
;
552 scoped_ptr
<base::Value
> value
= content::ExecuteScriptAndGetValue(
554 "var node = document.getElementById('" + node_id
+ "');\n"
556 " node.offsetWidth > 0 && node.offsetHeight > 0;"
558 " 'node not found';\n");
560 return VISIBILITY_ERROR
;
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();
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(
576 "document.getElementById('" + node_id
+ "').click();\n"));
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.
586 content::WaitForInterstitialDetach(
587 browser()->tab_strip_model()->GetActiveWebContents());
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());
610 TestMalwareDetailsFactory details_factory_
;
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
624 #define MAYBE_RedirectInIFrameCanceled RedirectInIFrameCanceled
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
)) {
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.
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
)) {
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
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
));
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
)) {
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
)) {
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
)) {
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.
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
)) {
853 base::HistogramTester histograms
;
855 if (GetParam() == SB_THREAT_TYPE_URL_MALWARE
)
857 else if (GetParam() == SB_THREAT_TYPE_URL_PHISHING
)
859 else if (GetParam() == SB_THREAT_TYPE_URL_UNWANTED
)
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
;
900 if (GetParam() == SB_THREAT_TYPE_URL_MALWARE
)
902 else if (GetParam() == SB_THREAT_TYPE_URL_PHISHING
)
904 else if (GetParam() == SB_THREAT_TYPE_URL_UNWANTED
)
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.
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.
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
995 class SafeBrowsingBlockingPageIDNTest
996 : public SecurityInterstitialIDNTest
,
997 public testing::WithParamInterface
<SBThreatType
> {
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
));