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";
62 // A SafeBrowsingDatabaseManager class that allows us to inject the malicious
64 class FakeSafeBrowsingDatabaseManager
: public TestSafeBrowsingDatabaseManager
{
66 FakeSafeBrowsingDatabaseManager() {}
68 // Called on the IO thread to check if the given url is safe or not. If we
69 // can synchronously determine that the url is safe, CheckUrl returns true.
70 // Otherwise it returns false, and "client" is called asynchronously with the
71 // result when it is ready.
72 // Overrides SafeBrowsingDatabaseManager::CheckBrowseUrl.
73 bool CheckBrowseUrl(const GURL
& gurl
, Client
* client
) override
{
74 if (badurls
[gurl
.spec()] == SB_THREAT_TYPE_SAFE
)
77 BrowserThread::PostTask(
78 BrowserThread::IO
, FROM_HERE
,
79 base::Bind(&FakeSafeBrowsingDatabaseManager::OnCheckBrowseURLDone
,
84 void OnCheckBrowseURLDone(const GURL
& gurl
, Client
* client
) {
85 std::vector
<SBThreatType
> expected_threats
;
86 // TODO(nparker): Remove ref to LocalSafeBrowsingDatabase by calling
87 // client->OnCheckBrowseUrlResult(..) directly.
88 expected_threats
.push_back(SB_THREAT_TYPE_URL_MALWARE
);
89 expected_threats
.push_back(SB_THREAT_TYPE_URL_PHISHING
);
90 expected_threats
.push_back(SB_THREAT_TYPE_URL_UNWANTED
);
91 LocalSafeBrowsingDatabaseManager::SafeBrowsingCheck
sb_check(
92 std::vector
<GURL
>(1, gurl
),
93 std::vector
<SBFullHash
>(),
95 safe_browsing_util::MALWARE
,
97 sb_check
.url_results
[0] = badurls
[gurl
.spec()];
98 sb_check
.OnSafeBrowsingResult();
101 void SetURLThreatType(const GURL
& url
, SBThreatType threat_type
) {
102 badurls
[url
.spec()] = threat_type
;
105 // Called during startup, so must not check-fail.
106 bool CheckExtensionIDs(const std::set
<std::string
>& extension_ids
,
107 Client
* client
) override
{
112 ~FakeSafeBrowsingDatabaseManager() override
{}
114 base::hash_map
<std::string
, SBThreatType
> badurls
;
115 DISALLOW_COPY_AND_ASSIGN(FakeSafeBrowsingDatabaseManager
);
118 // A SafeBrowingUIManager class that allows intercepting malware details.
119 class FakeSafeBrowsingUIManager
: public SafeBrowsingUIManager
{
121 explicit FakeSafeBrowsingUIManager(SafeBrowsingService
* service
) :
122 SafeBrowsingUIManager(service
) { }
124 // Overrides SafeBrowsingUIManager
125 void SendSerializedMalwareDetails(const std::string
& serialized
) override
{
126 // Notify the UI thread that we got a report.
127 BrowserThread::PostTask(
130 base::Bind(&FakeSafeBrowsingUIManager::OnMalwareDetailsDone
,
135 void OnMalwareDetailsDone(const std::string
& serialized
) {
136 EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI
));
137 report_
= serialized
;
139 EXPECT_FALSE(malware_details_done_callback_
.is_null());
140 if (!malware_details_done_callback_
.is_null()) {
141 malware_details_done_callback_
.Run();
142 malware_details_done_callback_
= base::Closure();
146 void set_malware_details_done_callback(const base::Closure
& callback
) {
147 EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI
));
148 EXPECT_TRUE(malware_details_done_callback_
.is_null());
149 malware_details_done_callback_
= callback
;
152 std::string
GetReport() {
153 EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI
));
158 ~FakeSafeBrowsingUIManager() override
{}
162 base::Closure malware_details_done_callback_
;
164 DISALLOW_COPY_AND_ASSIGN(FakeSafeBrowsingUIManager
);
167 class FakeSafeBrowsingService
: public SafeBrowsingService
{
169 FakeSafeBrowsingService()
170 : fake_database_manager_(),
171 fake_ui_manager_() { }
173 // Returned pointer has the same lifespan as the database_manager_ refcounted
175 FakeSafeBrowsingDatabaseManager
* fake_database_manager() {
176 return fake_database_manager_
;
178 // Returned pointer has the same lifespan as the ui_manager_ refcounted
180 FakeSafeBrowsingUIManager
* fake_ui_manager() {
181 return fake_ui_manager_
;
185 ~FakeSafeBrowsingService() override
{}
187 SafeBrowsingDatabaseManager
* CreateDatabaseManager() override
{
188 fake_database_manager_
= new FakeSafeBrowsingDatabaseManager();
189 return fake_database_manager_
;
192 SafeBrowsingUIManager
* CreateUIManager() override
{
193 fake_ui_manager_
= new FakeSafeBrowsingUIManager(this);
194 return fake_ui_manager_
;
197 SafeBrowsingProtocolManagerDelegate
* GetProtocolManagerDelegate() override
{
198 // Our SafeBrowsingDatabaseManager doesn't implement this delegate.
203 FakeSafeBrowsingDatabaseManager
* fake_database_manager_
;
204 FakeSafeBrowsingUIManager
* fake_ui_manager_
;
206 DISALLOW_COPY_AND_ASSIGN(FakeSafeBrowsingService
);
209 // Factory that creates FakeSafeBrowsingService instances.
210 class TestSafeBrowsingServiceFactory
: public SafeBrowsingServiceFactory
{
212 TestSafeBrowsingServiceFactory() :
213 most_recent_service_(NULL
) { }
214 ~TestSafeBrowsingServiceFactory() override
{}
216 SafeBrowsingService
* CreateSafeBrowsingService() override
{
217 most_recent_service_
= new FakeSafeBrowsingService();
218 return most_recent_service_
;
221 FakeSafeBrowsingService
* most_recent_service() const {
222 return most_recent_service_
;
226 FakeSafeBrowsingService
* most_recent_service_
;
229 // A MalwareDetails class lets us intercept calls from the renderer.
230 class FakeMalwareDetails
: public MalwareDetails
{
233 SafeBrowsingUIManager
* delegate
,
234 WebContents
* web_contents
,
235 const SafeBrowsingUIManager::UnsafeResource
& unsafe_resource
)
236 : MalwareDetails(delegate
, web_contents
, unsafe_resource
),
241 const std::vector
<SafeBrowsingHostMsg_MalwareDOMDetails_Node
>& params
)
243 EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO
));
244 MalwareDetails::AddDOMDetails(params
);
246 // Notify the UI thread that we got the dom details.
247 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
248 base::Bind(&FakeMalwareDetails::OnDOMDetailsDone
,
256 // This condition might not trigger normally, but if you add a
257 // sleep(1) in malware_dom_details it triggers :).
259 content::RunMessageLoop();
260 EXPECT_TRUE(got_dom_
);
264 ~FakeMalwareDetails() override
{}
266 void OnDOMDetailsDone() {
269 base::MessageLoopForUI::current()->Quit();
273 // Some logic to figure out if we should wait for the dom details or not.
274 // These variables should only be accessed in the UI thread.
279 class TestMalwareDetailsFactory
: public MalwareDetailsFactory
{
281 TestMalwareDetailsFactory() : details_() { }
282 ~TestMalwareDetailsFactory() override
{}
284 MalwareDetails
* CreateMalwareDetails(
285 SafeBrowsingUIManager
* delegate
,
286 WebContents
* web_contents
,
287 const SafeBrowsingUIManager::UnsafeResource
& unsafe_resource
) override
{
288 details_
= new FakeMalwareDetails(delegate
, web_contents
,
293 FakeMalwareDetails
* get_details() {
298 FakeMalwareDetails
* details_
;
301 // A SafeBrowingBlockingPage class that lets us wait until it's hidden.
302 class TestSafeBrowsingBlockingPage
: public SafeBrowsingBlockingPage
{
304 TestSafeBrowsingBlockingPage(SafeBrowsingUIManager
* manager
,
305 WebContents
* web_contents
,
306 const UnsafeResourceList
& unsafe_resources
)
307 : SafeBrowsingBlockingPage(manager
, web_contents
, unsafe_resources
),
308 wait_for_delete_(false) {
309 // Don't wait the whole 3 seconds for the browser test.
310 malware_details_proceed_delay_ms_
= 100;
313 ~TestSafeBrowsingBlockingPage() override
{
314 if (!wait_for_delete_
)
317 // Notify that we are gone
318 base::MessageLoopForUI::current()->Quit();
319 wait_for_delete_
= false;
322 void WaitForDelete() {
323 wait_for_delete_
= true;
324 content::RunMessageLoop();
327 // InterstitialPageDelegate methods:
328 void CommandReceived(const std::string
& command
) override
{
329 SafeBrowsingBlockingPage::CommandReceived(command
);
331 void OnProceed() override
{ SafeBrowsingBlockingPage::OnProceed(); }
332 void OnDontProceed() override
{ SafeBrowsingBlockingPage::OnDontProceed(); }
335 bool wait_for_delete_
;
338 class TestSafeBrowsingBlockingPageFactory
339 : public SafeBrowsingBlockingPageFactory
{
341 TestSafeBrowsingBlockingPageFactory() { }
342 ~TestSafeBrowsingBlockingPageFactory() override
{}
344 SafeBrowsingBlockingPage
* CreateSafeBrowsingPage(
345 SafeBrowsingUIManager
* delegate
,
346 WebContents
* web_contents
,
347 const SafeBrowsingBlockingPage::UnsafeResourceList
& unsafe_resources
)
349 return new TestSafeBrowsingBlockingPage(delegate
, web_contents
,
356 // Tests the safe browsing blocking page in a browser.
357 class SafeBrowsingBlockingPageBrowserTest
358 : public InProcessBrowserTest
,
359 public testing::WithParamInterface
<SBThreatType
> {
362 VISIBILITY_ERROR
= -1,
367 SafeBrowsingBlockingPageBrowserTest() {}
369 void SetUp() override
{
370 SafeBrowsingService::RegisterFactory(&factory_
);
371 SafeBrowsingBlockingPage::RegisterFactory(&blocking_page_factory_
);
372 MalwareDetails::RegisterFactory(&details_factory_
);
373 InProcessBrowserTest::SetUp();
376 void SetUpCommandLine(base::CommandLine
* command_line
) override
{
377 command_line
->AppendSwitchASCII(
378 switches::kForceFieldTrials
, "UwSInterstitialStatus/On/");
381 void TearDown() override
{
382 InProcessBrowserTest::TearDown();
383 SafeBrowsingBlockingPage::RegisterFactory(NULL
);
384 SafeBrowsingService::RegisterFactory(NULL
);
385 MalwareDetails::RegisterFactory(NULL
);
388 void SetUpOnMainThread() override
{
389 BrowserThread::PostTask(
390 BrowserThread::IO
, FROM_HERE
,
391 base::Bind(&chrome_browser_net::SetUrlRequestMocksEnabled
, true));
394 void SetURLThreatType(const GURL
& url
, SBThreatType threat_type
) {
395 FakeSafeBrowsingService
* service
=
396 static_cast<FakeSafeBrowsingService
*>(
397 g_browser_process
->safe_browsing_service());
399 ASSERT_TRUE(service
);
400 service
->fake_database_manager()->SetURLThreatType(url
, threat_type
);
403 // Adds a safebrowsing result of the current test threat to the fake
404 // safebrowsing service, navigates to that page, and returns the url.
405 GURL
SetupWarningAndNavigate() {
406 GURL url
= net::URLRequestMockHTTPJob::GetMockUrl(kEmptyPage
);
407 SetURLThreatType(url
, GetParam());
409 ui_test_utils::NavigateToURL(browser(), url
);
410 EXPECT_TRUE(WaitForReady());
414 // Adds a safebrowsing threat result to the fake safebrowsing service,
415 // navigates to a page with an iframe containing the threat site, and returns
416 // the url of the parent page.
417 GURL
SetupThreatIframeWarningAndNavigate() {
418 GURL url
= net::URLRequestMockHTTPJob::GetMockUrl(kMalwarePage
);
419 GURL iframe_url
= net::URLRequestMockHTTPJob::GetMockUrl(kMalwareIframe
);
420 SetURLThreatType(iframe_url
, GetParam());
422 ui_test_utils::NavigateToURL(browser(), url
);
423 EXPECT_TRUE(WaitForReady());
428 SecurityInterstitialPage::SecurityInterstitialCommands command
) {
429 WebContents
* contents
=
430 browser()->tab_strip_model()->GetActiveWebContents();
431 // We use InterstitialPage::GetInterstitialPage(tab) instead of
432 // tab->GetInterstitialPage() because the tab doesn't have a pointer
433 // to its interstital page until it gets a command from the renderer
434 // that it has indeed displayed it -- and this sometimes happens after
435 // NavigateToURL returns.
436 SafeBrowsingBlockingPage
* interstitial_page
=
437 static_cast<SafeBrowsingBlockingPage
*>(
438 InterstitialPage::GetInterstitialPage(contents
)->
439 GetDelegateForTesting());
440 ASSERT_TRUE(interstitial_page
);
441 ASSERT_EQ(SafeBrowsingBlockingPage::kTypeForTesting
,
442 interstitial_page
->GetTypeForTesting());
443 interstitial_page
->CommandReceived(base::IntToString(command
));
446 void DontProceedThroughInterstitial() {
447 WebContents
* contents
=
448 browser()->tab_strip_model()->GetActiveWebContents();
449 InterstitialPage
* interstitial_page
= InterstitialPage::GetInterstitialPage(
451 ASSERT_TRUE(interstitial_page
);
452 interstitial_page
->DontProceed();
455 void ProceedThroughInterstitial() {
456 WebContents
* contents
=
457 browser()->tab_strip_model()->GetActiveWebContents();
458 InterstitialPage
* interstitial_page
= InterstitialPage::GetInterstitialPage(
460 ASSERT_TRUE(interstitial_page
);
461 interstitial_page
->Proceed();
464 void AssertNoInterstitial(bool wait_for_delete
) {
465 WebContents
* contents
=
466 browser()->tab_strip_model()->GetActiveWebContents();
468 if (contents
->ShowingInterstitialPage() && wait_for_delete
) {
469 // We'll get notified when the interstitial is deleted.
470 TestSafeBrowsingBlockingPage
* page
=
471 static_cast<TestSafeBrowsingBlockingPage
*>(
472 contents
->GetInterstitialPage()->GetDelegateForTesting());
473 ASSERT_EQ(SafeBrowsingBlockingPage::kTypeForTesting
,
474 page
->GetTypeForTesting());
475 page
->WaitForDelete();
478 // Can't use InterstitialPage::GetInterstitialPage() because that
479 // gets updated after the TestSafeBrowsingBlockingPage destructor
480 ASSERT_FALSE(contents
->ShowingInterstitialPage());
483 bool YesInterstitial() {
484 WebContents
* contents
=
485 browser()->tab_strip_model()->GetActiveWebContents();
486 InterstitialPage
* interstitial_page
= InterstitialPage::GetInterstitialPage(
488 return interstitial_page
!= NULL
;
491 void SetReportSentCallback(const base::Closure
& callback
) {
492 factory_
.most_recent_service()
494 ->set_malware_details_done_callback(callback
);
497 std::string
GetReportSent() {
498 return factory_
.most_recent_service()->fake_ui_manager()->GetReport();
501 void MalwareRedirectCancelAndProceed(const std::string
& open_function
) {
502 GURL load_url
= net::URLRequestMockHTTPJob::GetMockUrl(
503 "safe_browsing/interstitial_cancel.html");
504 GURL malware_url
= net::URLRequestMockHTTPJob::GetMockUrl(kMalwarePage
);
505 SetURLThreatType(malware_url
, GetParam());
507 // Load the test page.
508 ui_test_utils::NavigateToURL(browser(), load_url
);
509 // Trigger the safe browsing interstitial page via a redirect in
511 ui_test_utils::NavigateToURLWithDisposition(
513 GURL("javascript:" + open_function
+ "()"),
515 ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB
);
516 WebContents
* contents
=
517 browser()->tab_strip_model()->GetActiveWebContents();
518 content::WaitForInterstitialAttach(contents
);
519 // Cancel the redirect request while interstitial page is open.
520 browser()->tab_strip_model()->ActivateTabAt(0, true);
521 ui_test_utils::NavigateToURL(browser(), GURL("javascript:stopWin()"));
522 browser()->tab_strip_model()->ActivateTabAt(1, true);
523 // Simulate the user clicking "proceed", there should be no crash. Since
524 // clicking proceed may do nothing (see comment in RedirectCanceled
525 // below, and crbug.com/76460), we use SendCommand to trigger the callback
526 // directly rather than using ClickAndWaitForDetach since there might not
527 // be a notification to wait for.
528 SendCommand(SecurityInterstitialPage::CMD_PROCEED
);
531 content::RenderViewHost
* GetRenderViewHost() {
532 InterstitialPage
* interstitial
= InterstitialPage::GetInterstitialPage(
533 browser()->tab_strip_model()->GetActiveWebContents());
536 return interstitial
->GetMainFrame()->GetRenderViewHost();
539 bool WaitForReady() {
540 InterstitialPage
* interstitial
= InterstitialPage::GetInterstitialPage(
541 browser()->tab_strip_model()->GetActiveWebContents());
544 return content::WaitForRenderFrameReady(interstitial
->GetMainFrame());
547 Visibility
GetVisibility(const std::string
& node_id
) {
548 content::RenderViewHost
* rvh
= GetRenderViewHost();
550 return VISIBILITY_ERROR
;
551 scoped_ptr
<base::Value
> value
= content::ExecuteScriptAndGetValue(
553 "var node = document.getElementById('" + node_id
+ "');\n"
555 " node.offsetWidth > 0 && node.offsetHeight > 0;"
557 " 'node not found';\n");
559 return VISIBILITY_ERROR
;
561 if (!value
->GetAsBoolean(&result
))
562 return VISIBILITY_ERROR
;
563 return result
? VISIBLE
: HIDDEN
;
566 bool Click(const std::string
& node_id
) {
567 content::RenderViewHost
* rvh
= GetRenderViewHost();
570 // We don't use ExecuteScriptAndGetValue for this one, since clicking
571 // the button/link may navigate away before the injected javascript can
572 // reply, hanging the test.
573 rvh
->GetMainFrame()->ExecuteJavaScriptForTests(
575 "document.getElementById('" + node_id
+ "').click();\n"));
579 bool ClickAndWaitForDetach(const std::string
& node_id
) {
580 // We wait for interstitial_detached rather than nav_entry_committed, as
581 // going back from a main-frame malware interstitial page will not cause a
582 // nav entry committed event.
585 content::WaitForInterstitialDetach(
586 browser()->tab_strip_model()->GetActiveWebContents());
590 void TestReportingDisabledAndDontProceed(const GURL
& url
) {
591 SetURLThreatType(url
, GetParam());
592 ui_test_utils::NavigateToURL(browser(), url
);
593 ASSERT_TRUE(WaitForReady());
595 EXPECT_EQ(HIDDEN
, GetVisibility("extended-reporting-opt-in"));
596 EXPECT_EQ(HIDDEN
, GetVisibility("opt-in-checkbox"));
597 EXPECT_EQ(HIDDEN
, GetVisibility("proceed-link"));
598 EXPECT_TRUE(Click("details-button"));
599 EXPECT_EQ(VISIBLE
, GetVisibility("help-link"));
600 EXPECT_EQ(VISIBLE
, GetVisibility("proceed-link"));
602 EXPECT_TRUE(ClickAndWaitForDetach("primary-button"));
603 AssertNoInterstitial(false); // Assert the interstitial is gone
604 EXPECT_EQ(GURL(url::kAboutBlankURL
), // Back to "about:blank"
605 browser()->tab_strip_model()->GetActiveWebContents()->GetURL());
609 TestMalwareDetailsFactory details_factory_
;
612 TestSafeBrowsingServiceFactory factory_
;
613 TestSafeBrowsingBlockingPageFactory blocking_page_factory_
;
615 DISALLOW_COPY_AND_ASSIGN(SafeBrowsingBlockingPageBrowserTest
);
618 // TODO(linux_aura) https://crbug.com/163931
619 // TODO(win_aura) https://crbug.com/154081
620 #if defined(USE_AURA) && !defined(OS_CHROMEOS)
621 #define MAYBE_RedirectInIFrameCanceled DISABLED_RedirectInIFrameCanceled
623 #define MAYBE_RedirectInIFrameCanceled RedirectInIFrameCanceled
625 IN_PROC_BROWSER_TEST_P(SafeBrowsingBlockingPageBrowserTest
,
626 MAYBE_RedirectInIFrameCanceled
) {
627 // 1. Test the case that redirect is a subresource.
628 MalwareRedirectCancelAndProceed("openWinIFrame");
629 // If the redirect was from subresource but canceled, "proceed" will continue
630 // with the rest of resources.
631 AssertNoInterstitial(true);
634 IN_PROC_BROWSER_TEST_P(SafeBrowsingBlockingPageBrowserTest
, RedirectCanceled
) {
635 // 2. Test the case that redirect is the only resource.
636 MalwareRedirectCancelAndProceed("openWin");
637 // Clicking proceed won't do anything if the main request is cancelled
638 // already. See crbug.com/76460.
639 EXPECT_TRUE(YesInterstitial());
642 IN_PROC_BROWSER_TEST_P(SafeBrowsingBlockingPageBrowserTest
, DontProceed
) {
643 #if defined(OS_WIN) && defined(USE_ASH)
644 // Disable this test in Metro+Ash for now (https://crbug.com/262796).
645 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
646 switches::kAshBrowserTests
)) {
651 SetupWarningAndNavigate();
653 EXPECT_EQ(VISIBLE
, GetVisibility("primary-button"));
654 EXPECT_EQ(HIDDEN
, GetVisibility("details"));
655 EXPECT_EQ(HIDDEN
, GetVisibility("proceed-link"));
656 EXPECT_EQ(HIDDEN
, GetVisibility("error-code"));
657 EXPECT_TRUE(Click("details-button"));
658 EXPECT_EQ(VISIBLE
, GetVisibility("details"));
659 EXPECT_EQ(VISIBLE
, GetVisibility("proceed-link"));
660 EXPECT_EQ(HIDDEN
, GetVisibility("error-code"));
661 EXPECT_TRUE(ClickAndWaitForDetach("primary-button"));
663 AssertNoInterstitial(false); // Assert the interstitial is gone
664 EXPECT_EQ(GURL(url::kAboutBlankURL
), // Back to "about:blank"
665 browser()->tab_strip_model()->GetActiveWebContents()->GetURL());
668 IN_PROC_BROWSER_TEST_P(SafeBrowsingBlockingPageBrowserTest
, Proceed
) {
669 GURL url
= SetupWarningAndNavigate();
671 EXPECT_TRUE(ClickAndWaitForDetach("proceed-link"));
672 AssertNoInterstitial(true); // Assert the interstitial is gone.
674 browser()->tab_strip_model()->GetActiveWebContents()->GetURL());
677 IN_PROC_BROWSER_TEST_P(SafeBrowsingBlockingPageBrowserTest
, IframeDontProceed
) {
678 #if defined(OS_WIN) && defined(USE_ASH)
679 // Disable this test in Metro+Ash for now (https://crbug.com/262796).
680 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
681 switches::kAshBrowserTests
)) {
686 SetupThreatIframeWarningAndNavigate();
688 EXPECT_EQ(VISIBLE
, GetVisibility("primary-button"));
689 EXPECT_EQ(HIDDEN
, GetVisibility("details"));
690 EXPECT_EQ(HIDDEN
, GetVisibility("proceed-link"));
691 EXPECT_EQ(HIDDEN
, GetVisibility("error-code"));
692 EXPECT_TRUE(Click("details-button"));
693 EXPECT_EQ(VISIBLE
, GetVisibility("details"));
694 EXPECT_EQ(VISIBLE
, GetVisibility("proceed-link"));
695 EXPECT_EQ(HIDDEN
, GetVisibility("error-code"));
696 EXPECT_TRUE(ClickAndWaitForDetach("primary-button"));
698 AssertNoInterstitial(false); // Assert the interstitial is gone
700 EXPECT_EQ(GURL(url::kAboutBlankURL
), // Back to "about:blank"
701 browser()->tab_strip_model()->GetActiveWebContents()->GetURL());
704 IN_PROC_BROWSER_TEST_P(SafeBrowsingBlockingPageBrowserTest
, IframeProceed
) {
705 GURL url
= SetupThreatIframeWarningAndNavigate();
707 EXPECT_TRUE(ClickAndWaitForDetach("proceed-link"));
708 AssertNoInterstitial(true); // Assert the interstitial is gone
711 browser()->tab_strip_model()->GetActiveWebContents()->GetURL());
714 IN_PROC_BROWSER_TEST_P(SafeBrowsingBlockingPageBrowserTest
,
715 IframeOptInAndReportMalwareDetails
) {
716 // The extended reporting opt-in is presented in the interstitial for malware,
717 // phishing, and UwS threats. It however only results in uploading further
718 // details about the immediate threat when facing malware threats.
719 const bool expect_malware_details
= GetParam() == SB_THREAT_TYPE_URL_MALWARE
;
721 scoped_refptr
<content::MessageLoopRunner
> malware_report_sent_runner(
722 new content::MessageLoopRunner
);
723 if (expect_malware_details
)
724 SetReportSentCallback(malware_report_sent_runner
->QuitClosure());
726 GURL url
= SetupThreatIframeWarningAndNavigate();
728 FakeMalwareDetails
* fake_malware_details
= details_factory_
.get_details();
729 EXPECT_EQ(expect_malware_details
, fake_malware_details
!= nullptr);
731 // If the DOM details from renderer did not already return when they are
732 // expected, wait for them.
733 if (expect_malware_details
)
734 fake_malware_details
->WaitForDOM();
736 EXPECT_EQ(VISIBLE
, GetVisibility("extended-reporting-opt-in"));
737 EXPECT_TRUE(Click("opt-in-checkbox"));
738 EXPECT_TRUE(ClickAndWaitForDetach("proceed-link"));
739 AssertNoInterstitial(true); // Assert the interstitial is gone
741 EXPECT_TRUE(browser()->profile()->GetPrefs()->GetBoolean(
742 prefs::kSafeBrowsingExtendedReportingEnabled
));
744 browser()->tab_strip_model()->GetActiveWebContents()->GetURL());
746 if (expect_malware_details
) {
747 malware_report_sent_runner
->Run();
748 std::string serialized
= GetReportSent();
749 safe_browsing::ClientMalwareReportRequest report
;
750 ASSERT_TRUE(report
.ParseFromString(serialized
));
751 // Verify the report is complete.
752 EXPECT_TRUE(report
.complete());
756 // Verifies that the "proceed anyway" link isn't available when it is disabled
757 // by the corresponding policy. Also verifies that sending the "proceed"
758 // command anyway doesn't advance to the malware site.
759 IN_PROC_BROWSER_TEST_P(SafeBrowsingBlockingPageBrowserTest
, ProceedDisabled
) {
760 #if defined(OS_WIN) && defined(USE_ASH)
761 // Disable this test in Metro+Ash for now (https://crbug.com/262796).
762 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
763 switches::kAshBrowserTests
)) {
768 // Simulate a policy disabling the "proceed anyway" link.
769 browser()->profile()->GetPrefs()->SetBoolean(
770 prefs::kSafeBrowsingProceedAnywayDisabled
, true);
772 SetupWarningAndNavigate();
774 EXPECT_EQ(VISIBLE
, GetVisibility("primary-button"));
775 EXPECT_EQ(HIDDEN
, GetVisibility("details"));
776 EXPECT_EQ(HIDDEN
, GetVisibility("proceed-link"));
777 EXPECT_EQ(HIDDEN
, GetVisibility("final-paragraph"));
778 EXPECT_TRUE(Click("details-button"));
779 EXPECT_EQ(HIDDEN
, GetVisibility("proceed-link"));
780 EXPECT_EQ(HIDDEN
, GetVisibility("final-paragraph"));
781 SendCommand(SecurityInterstitialPage::CMD_PROCEED
);
783 // The "proceed" command should go back instead, if proceeding is disabled.
784 AssertNoInterstitial(true);
785 EXPECT_EQ(GURL(url::kAboutBlankURL
), // Back to "about:blank"
786 browser()->tab_strip_model()->GetActiveWebContents()->GetURL());
789 // Verifies that the reporting checkbox is hidden on non-HTTP pages.
790 // TODO(mattm): Should also verify that no report is sent, but there isn't a
791 // good way to do that in the current design.
792 IN_PROC_BROWSER_TEST_P(SafeBrowsingBlockingPageBrowserTest
, ReportingDisabled
) {
793 #if defined(OS_WIN) && defined(USE_ASH)
794 // Disable this test in Metro+Ash for now (https://crbug.com/262796).
795 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
796 switches::kAshBrowserTests
)) {
801 browser()->profile()->GetPrefs()->SetBoolean(
802 prefs::kSafeBrowsingExtendedReportingEnabled
, true);
804 TestReportingDisabledAndDontProceed(
805 net::URLRequestMockHTTPJob::GetMockHttpsUrl(kEmptyPage
));
808 // Verifies that the reporting checkbox is hidden when opt-in is
809 // disabled by policy.
810 IN_PROC_BROWSER_TEST_P(SafeBrowsingBlockingPageBrowserTest
,
811 ReportingDisabledByPolicy
) {
812 #if defined(OS_WIN) && defined(USE_ASH)
813 // Disable this test in Metro+Ash for now (https://crbug.com/262796).
814 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
815 switches::kAshBrowserTests
)) {
820 browser()->profile()->GetPrefs()->SetBoolean(
821 prefs::kSafeBrowsingExtendedReportingEnabled
, true);
822 browser()->profile()->GetPrefs()->SetBoolean(
823 prefs::kSafeBrowsingExtendedReportingOptInAllowed
, false);
825 TestReportingDisabledAndDontProceed(
826 net::URLRequestMockHTTPJob::GetMockUrl(kEmptyPage
));
829 IN_PROC_BROWSER_TEST_P(SafeBrowsingBlockingPageBrowserTest
, LearnMore
) {
830 SetupWarningAndNavigate();
831 EXPECT_TRUE(ClickAndWaitForDetach("help-link"));
832 AssertNoInterstitial(false); // Assert the interstitial is gone
834 // We are in the help page.
836 GetParam() == SB_THREAT_TYPE_URL_PHISHING
837 ? "/transparencyreport/safebrowsing/"
838 : "/safebrowsing/diagnostic",
839 browser()->tab_strip_model()->GetActiveWebContents()->GetURL().path());
842 IN_PROC_BROWSER_TEST_P(SafeBrowsingBlockingPageBrowserTest
,
843 Histograms_DontProceed
) {
844 #if defined(OS_WIN) && defined(USE_ASH)
845 // Disable this test in Metro+Ash for now (https://crbug.com/262796).
846 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
847 switches::kAshBrowserTests
)) {
852 base::HistogramTester histograms
;
854 if (GetParam() == SB_THREAT_TYPE_URL_MALWARE
)
856 else if (GetParam() == SB_THREAT_TYPE_URL_PHISHING
)
858 else if (GetParam() == SB_THREAT_TYPE_URL_UNWANTED
)
862 const std::string decision_histogram
= "interstitial." + prefix
+ ".decision";
863 const std::string interaction_histogram
=
864 "interstitial." + prefix
+ ".interaction";
866 // Histograms should start off empty.
867 histograms
.ExpectTotalCount(decision_histogram
, 0);
868 histograms
.ExpectTotalCount(interaction_histogram
, 0);
870 // After navigating to the page, the totals should be set.
871 SetupWarningAndNavigate();
872 histograms
.ExpectTotalCount(decision_histogram
, 1);
873 histograms
.ExpectBucketCount(decision_histogram
,
874 security_interstitials::MetricsHelper::SHOW
, 1);
875 histograms
.ExpectTotalCount(interaction_histogram
, 1);
876 histograms
.ExpectBucketCount(
877 interaction_histogram
,
878 security_interstitials::MetricsHelper::TOTAL_VISITS
, 1);
880 // Decision should be recorded.
881 EXPECT_TRUE(ClickAndWaitForDetach("primary-button"));
882 AssertNoInterstitial(false); // Assert the interstitial is gone
883 histograms
.ExpectTotalCount(decision_histogram
, 2);
884 histograms
.ExpectBucketCount(
885 decision_histogram
, security_interstitials::MetricsHelper::DONT_PROCEED
,
887 histograms
.ExpectTotalCount(interaction_histogram
, 1);
888 histograms
.ExpectBucketCount(
889 interaction_histogram
,
890 security_interstitials::MetricsHelper::TOTAL_VISITS
, 1);
893 IN_PROC_BROWSER_TEST_P(SafeBrowsingBlockingPageBrowserTest
,
894 Histograms_Proceed
) {
895 base::HistogramTester histograms
;
897 if (GetParam() == SB_THREAT_TYPE_URL_MALWARE
)
899 else if (GetParam() == SB_THREAT_TYPE_URL_PHISHING
)
901 else if (GetParam() == SB_THREAT_TYPE_URL_UNWANTED
)
905 const std::string decision_histogram
= "interstitial." + prefix
+ ".decision";
906 const std::string interaction_histogram
=
907 "interstitial." + prefix
+ ".interaction";
909 // Histograms should start off empty.
910 histograms
.ExpectTotalCount(decision_histogram
, 0);
911 histograms
.ExpectTotalCount(interaction_histogram
, 0);
913 // After navigating to the page, the totals should be set.
914 GURL url
= SetupWarningAndNavigate();
915 histograms
.ExpectTotalCount(decision_histogram
, 1);
916 histograms
.ExpectBucketCount(decision_histogram
,
917 security_interstitials::MetricsHelper::SHOW
, 1);
918 histograms
.ExpectTotalCount(interaction_histogram
, 1);
919 histograms
.ExpectBucketCount(
920 interaction_histogram
,
921 security_interstitials::MetricsHelper::TOTAL_VISITS
, 1);
923 // Decision should be recorded.
924 EXPECT_TRUE(ClickAndWaitForDetach("proceed-link"));
925 AssertNoInterstitial(true); // Assert the interstitial is gone.
926 histograms
.ExpectTotalCount(decision_histogram
, 2);
927 histograms
.ExpectBucketCount(
928 decision_histogram
, security_interstitials::MetricsHelper::PROCEED
, 1);
929 histograms
.ExpectTotalCount(interaction_histogram
, 1);
930 histograms
.ExpectBucketCount(
931 interaction_histogram
,
932 security_interstitials::MetricsHelper::TOTAL_VISITS
, 1);
935 INSTANTIATE_TEST_CASE_P(SafeBrowsingBlockingPageBrowserTestWithThreatType
,
936 SafeBrowsingBlockingPageBrowserTest
,
937 testing::Values(SB_THREAT_TYPE_URL_MALWARE
,
938 SB_THREAT_TYPE_URL_PHISHING
,
939 SB_THREAT_TYPE_URL_UNWANTED
));
941 // Test that SafeBrowsingBlockingPage properly decodes IDN URLs that are
943 class SafeBrowsingBlockingPageIDNTest
944 : public SecurityInterstitialIDNTest
,
945 public testing::WithParamInterface
<SBThreatType
> {
947 // SecurityInterstitialIDNTest implementation
948 SecurityInterstitialPage
* CreateInterstitial(
949 content::WebContents
* contents
,
950 const GURL
& request_url
) const override
{
951 SafeBrowsingService
* sb_service
=
952 g_browser_process
->safe_browsing_service();
953 SafeBrowsingBlockingPage::UnsafeResource resource
;
955 resource
.url
= request_url
;
956 resource
.is_subresource
= false;
957 resource
.threat_type
= GetParam();
958 resource
.render_process_host_id
= contents
->GetRenderProcessHost()->GetID();
959 resource
.render_view_id
= contents
->GetRenderViewHost()->GetRoutingID();
961 return SafeBrowsingBlockingPage::CreateBlockingPage(
962 sb_service
->ui_manager().get(), contents
, resource
);
966 IN_PROC_BROWSER_TEST_P(SafeBrowsingBlockingPageIDNTest
,
967 SafeBrowsingBlockingPageDecodesIDN
) {
968 EXPECT_TRUE(VerifyIDNDecoded());
971 INSTANTIATE_TEST_CASE_P(SafeBrowsingBlockingPageIDNTestWithThreatType
,
972 SafeBrowsingBlockingPageIDNTest
,
973 testing::Values(SB_THREAT_TYPE_URL_MALWARE
,
974 SB_THREAT_TYPE_URL_PHISHING
,
975 SB_THREAT_TYPE_URL_UNWANTED
));