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/values.h"
15 #include "chrome/browser/browser_process.h"
16 #include "chrome/browser/interstitials/security_interstitial_page_test_utils.h"
17 #include "chrome/browser/profiles/profile.h"
18 #include "chrome/browser/safe_browsing/database_manager.h"
19 #include "chrome/browser/safe_browsing/malware_details.h"
20 #include "chrome/browser/safe_browsing/safe_browsing_blocking_page.h"
21 #include "chrome/browser/safe_browsing/safe_browsing_service.h"
22 #include "chrome/browser/safe_browsing/safe_browsing_util.h"
23 #include "chrome/browser/safe_browsing/ui_manager.h"
24 #include "chrome/browser/ui/browser.h"
25 #include "chrome/browser/ui/browser_tabstrip.h"
26 #include "chrome/browser/ui/tabs/tab_strip_model.h"
27 #include "chrome/common/chrome_switches.h"
28 #include "chrome/common/pref_names.h"
29 #include "chrome/common/url_constants.h"
30 #include "chrome/test/base/in_process_browser_test.h"
31 #include "chrome/test/base/test_switches.h"
32 #include "chrome/test/base/ui_test_utils.h"
33 #include "content/public/browser/interstitial_page.h"
34 #include "content/public/browser/navigation_controller.h"
35 #include "content/public/browser/notification_types.h"
36 #include "content/public/browser/render_frame_host.h"
37 #include "content/public/browser/render_process_host.h"
38 #include "content/public/browser/render_view_host.h"
39 #include "content/public/browser/web_contents.h"
40 #include "content/public/test/browser_test_utils.h"
41 #include "content/public/test/test_browser_thread.h"
42 #include "content/public/test/test_utils.h"
44 using chrome_browser_interstitials::SecurityInterstitialIDNTest
;
45 using content::BrowserThread
;
46 using content::InterstitialPage
;
47 using content::NavigationController
;
48 using content::WebContents
;
52 const char kEmptyPage
[] = "files/empty.html";
53 const char kMalwarePage
[] = "files/safe_browsing/malware.html";
54 const char kMalwareIframe
[] = "files/safe_browsing/malware_iframe.html";
56 // A SafeBrowsingDatabaseManager class that allows us to inject the malicious
58 class FakeSafeBrowsingDatabaseManager
: public SafeBrowsingDatabaseManager
{
60 explicit FakeSafeBrowsingDatabaseManager(SafeBrowsingService
* service
)
61 : SafeBrowsingDatabaseManager(service
) { }
63 // Called on the IO thread to check if the given url is safe or not. If we
64 // can synchronously determine that the url is safe, CheckUrl returns true.
65 // Otherwise it returns false, and "client" is called asynchronously with the
66 // result when it is ready.
67 // Overrides SafeBrowsingDatabaseManager::CheckBrowseUrl.
68 bool CheckBrowseUrl(const GURL
& gurl
, Client
* client
) override
{
69 if (badurls
[gurl
.spec()] == SB_THREAT_TYPE_SAFE
)
72 BrowserThread::PostTask(
73 BrowserThread::IO
, FROM_HERE
,
74 base::Bind(&FakeSafeBrowsingDatabaseManager::OnCheckBrowseURLDone
,
79 void OnCheckBrowseURLDone(const GURL
& gurl
, Client
* client
) {
80 std::vector
<SBThreatType
> expected_threats
;
81 expected_threats
.push_back(SB_THREAT_TYPE_URL_MALWARE
);
82 expected_threats
.push_back(SB_THREAT_TYPE_URL_PHISHING
);
83 expected_threats
.push_back(SB_THREAT_TYPE_URL_UNWANTED
);
84 SafeBrowsingDatabaseManager::SafeBrowsingCheck
sb_check(
85 std::vector
<GURL
>(1, gurl
),
86 std::vector
<SBFullHash
>(),
88 safe_browsing_util::MALWARE
,
90 sb_check
.url_results
[0] = badurls
[gurl
.spec()];
91 client
->OnSafeBrowsingResult(sb_check
);
94 void SetURLThreatType(const GURL
& url
, SBThreatType threat_type
) {
95 badurls
[url
.spec()] = threat_type
;
99 ~FakeSafeBrowsingDatabaseManager() override
{}
101 base::hash_map
<std::string
, SBThreatType
> badurls
;
102 DISALLOW_COPY_AND_ASSIGN(FakeSafeBrowsingDatabaseManager
);
105 // A SafeBrowingUIManager class that allows intercepting malware details.
106 class FakeSafeBrowsingUIManager
: public SafeBrowsingUIManager
{
108 explicit FakeSafeBrowsingUIManager(SafeBrowsingService
* service
) :
109 SafeBrowsingUIManager(service
) { }
111 // Overrides SafeBrowsingUIManager
112 void SendSerializedMalwareDetails(const std::string
& serialized
) override
{
113 // Notify the UI thread that we got a report.
114 BrowserThread::PostTask(
117 base::Bind(&FakeSafeBrowsingUIManager::OnMalwareDetailsDone
,
122 void OnMalwareDetailsDone(const std::string
& serialized
) {
123 EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI
));
124 report_
= serialized
;
126 EXPECT_FALSE(malware_details_done_callback_
.is_null());
127 if (!malware_details_done_callback_
.is_null()) {
128 malware_details_done_callback_
.Run();
129 malware_details_done_callback_
= base::Closure();
133 void set_malware_details_done_callback(const base::Closure
& callback
) {
134 EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI
));
135 EXPECT_TRUE(malware_details_done_callback_
.is_null());
136 malware_details_done_callback_
= callback
;
139 std::string
GetReport() {
140 EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI
));
145 ~FakeSafeBrowsingUIManager() override
{}
149 base::Closure malware_details_done_callback_
;
151 DISALLOW_COPY_AND_ASSIGN(FakeSafeBrowsingUIManager
);
154 class FakeSafeBrowsingService
: public SafeBrowsingService
{
156 FakeSafeBrowsingService()
157 : fake_database_manager_(),
158 fake_ui_manager_() { }
160 // Returned pointer has the same lifespan as the database_manager_ refcounted
162 FakeSafeBrowsingDatabaseManager
* fake_database_manager() {
163 return fake_database_manager_
;
165 // Returned pointer has the same lifespan as the ui_manager_ refcounted
167 FakeSafeBrowsingUIManager
* fake_ui_manager() {
168 return fake_ui_manager_
;
172 ~FakeSafeBrowsingService() override
{}
174 SafeBrowsingDatabaseManager
* CreateDatabaseManager() override
{
175 fake_database_manager_
= new FakeSafeBrowsingDatabaseManager(this);
176 return fake_database_manager_
;
179 SafeBrowsingUIManager
* CreateUIManager() override
{
180 fake_ui_manager_
= new FakeSafeBrowsingUIManager(this);
181 return fake_ui_manager_
;
185 FakeSafeBrowsingDatabaseManager
* fake_database_manager_
;
186 FakeSafeBrowsingUIManager
* fake_ui_manager_
;
188 DISALLOW_COPY_AND_ASSIGN(FakeSafeBrowsingService
);
191 // Factory that creates FakeSafeBrowsingService instances.
192 class TestSafeBrowsingServiceFactory
: public SafeBrowsingServiceFactory
{
194 TestSafeBrowsingServiceFactory() :
195 most_recent_service_(NULL
) { }
196 ~TestSafeBrowsingServiceFactory() override
{}
198 SafeBrowsingService
* CreateSafeBrowsingService() override
{
199 most_recent_service_
= new FakeSafeBrowsingService();
200 return most_recent_service_
;
203 FakeSafeBrowsingService
* most_recent_service() const {
204 return most_recent_service_
;
208 FakeSafeBrowsingService
* most_recent_service_
;
211 // A MalwareDetails class lets us intercept calls from the renderer.
212 class FakeMalwareDetails
: public MalwareDetails
{
215 SafeBrowsingUIManager
* delegate
,
216 WebContents
* web_contents
,
217 const SafeBrowsingUIManager::UnsafeResource
& unsafe_resource
)
218 : MalwareDetails(delegate
, web_contents
, unsafe_resource
),
223 const std::vector
<SafeBrowsingHostMsg_MalwareDOMDetails_Node
>& params
)
225 EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO
));
226 MalwareDetails::AddDOMDetails(params
);
228 // Notify the UI thread that we got the dom details.
229 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
230 base::Bind(&FakeMalwareDetails::OnDOMDetailsDone
,
238 // This condition might not trigger normally, but if you add a
239 // sleep(1) in malware_dom_details it triggers :).
241 content::RunMessageLoop();
242 EXPECT_TRUE(got_dom_
);
246 ~FakeMalwareDetails() override
{}
248 void OnDOMDetailsDone() {
251 base::MessageLoopForUI::current()->Quit();
255 // Some logic to figure out if we should wait for the dom details or not.
256 // These variables should only be accessed in the UI thread.
261 class TestMalwareDetailsFactory
: public MalwareDetailsFactory
{
263 TestMalwareDetailsFactory() : details_() { }
264 ~TestMalwareDetailsFactory() override
{}
266 MalwareDetails
* CreateMalwareDetails(
267 SafeBrowsingUIManager
* delegate
,
268 WebContents
* web_contents
,
269 const SafeBrowsingUIManager::UnsafeResource
& unsafe_resource
) override
{
270 details_
= new FakeMalwareDetails(delegate
, web_contents
,
275 FakeMalwareDetails
* get_details() {
280 FakeMalwareDetails
* details_
;
283 // A SafeBrowingBlockingPage class that lets us wait until it's hidden.
284 class TestSafeBrowsingBlockingPage
: public SafeBrowsingBlockingPage
{
286 TestSafeBrowsingBlockingPage(SafeBrowsingUIManager
* manager
,
287 WebContents
* web_contents
,
288 const UnsafeResourceList
& unsafe_resources
)
289 : SafeBrowsingBlockingPage(manager
, web_contents
, unsafe_resources
),
290 wait_for_delete_(false) {
291 // Don't wait the whole 3 seconds for the browser test.
292 malware_details_proceed_delay_ms_
= 100;
295 ~TestSafeBrowsingBlockingPage() override
{
296 if (!wait_for_delete_
)
299 // Notify that we are gone
300 base::MessageLoopForUI::current()->Quit();
301 wait_for_delete_
= false;
304 void WaitForDelete() {
305 wait_for_delete_
= true;
306 content::RunMessageLoop();
309 // InterstitialPageDelegate methods:
310 void CommandReceived(const std::string
& command
) override
{
311 SafeBrowsingBlockingPage::CommandReceived(command
);
313 void OnProceed() override
{ SafeBrowsingBlockingPage::OnProceed(); }
314 void OnDontProceed() override
{ SafeBrowsingBlockingPage::OnDontProceed(); }
317 bool wait_for_delete_
;
320 class TestSafeBrowsingBlockingPageFactory
321 : public SafeBrowsingBlockingPageFactory
{
323 TestSafeBrowsingBlockingPageFactory() { }
324 ~TestSafeBrowsingBlockingPageFactory() override
{}
326 SafeBrowsingBlockingPage
* CreateSafeBrowsingPage(
327 SafeBrowsingUIManager
* delegate
,
328 WebContents
* web_contents
,
329 const SafeBrowsingBlockingPage::UnsafeResourceList
& unsafe_resources
)
331 return new TestSafeBrowsingBlockingPage(delegate
, web_contents
,
338 // Tests the safe browsing blocking page in a browser.
339 class SafeBrowsingBlockingPageBrowserTest
340 : public InProcessBrowserTest
,
341 public testing::WithParamInterface
<SBThreatType
> {
344 VISIBILITY_ERROR
= -1,
349 SafeBrowsingBlockingPageBrowserTest() {}
351 void SetUp() override
{
352 SafeBrowsingService::RegisterFactory(&factory_
);
353 SafeBrowsingBlockingPage::RegisterFactory(&blocking_page_factory_
);
354 MalwareDetails::RegisterFactory(&details_factory_
);
355 InProcessBrowserTest::SetUp();
358 void SetUpCommandLine(base::CommandLine
* command_line
) override
{
359 command_line
->AppendSwitchASCII(
360 switches::kForceFieldTrials
, "UwSInterstitialStatus/On/");
363 void TearDown() override
{
364 InProcessBrowserTest::TearDown();
365 SafeBrowsingBlockingPage::RegisterFactory(NULL
);
366 SafeBrowsingService::RegisterFactory(NULL
);
367 MalwareDetails::RegisterFactory(NULL
);
370 void SetUpInProcessBrowserTestFixture() override
{
371 ASSERT_TRUE(test_server()->Start());
374 void SetURLThreatType(const GURL
& url
, SBThreatType threat_type
) {
375 FakeSafeBrowsingService
* service
=
376 static_cast<FakeSafeBrowsingService
*>(
377 g_browser_process
->safe_browsing_service());
379 ASSERT_TRUE(service
);
380 service
->fake_database_manager()->SetURLThreatType(url
, threat_type
);
383 // Adds a safebrowsing result of the current test threat to the fake
384 // safebrowsing service, navigates to that page, and returns the url.
385 GURL
SetupWarningAndNavigate() {
386 GURL url
= test_server()->GetURL(kEmptyPage
);
387 SetURLThreatType(url
, GetParam());
389 ui_test_utils::NavigateToURL(browser(), url
);
390 EXPECT_TRUE(WaitForReady());
394 // Adds a safebrowsing threat result to the fake safebrowsing service,
395 // navigates to a page with an iframe containing the threat site, and returns
396 // the url of the parent page.
397 GURL
SetupThreatIframeWarningAndNavigate() {
398 GURL url
= test_server()->GetURL(kMalwarePage
);
399 GURL iframe_url
= test_server()->GetURL(kMalwareIframe
);
400 SetURLThreatType(iframe_url
, GetParam());
402 ui_test_utils::NavigateToURL(browser(), url
);
403 EXPECT_TRUE(WaitForReady());
408 SecurityInterstitialPage::SecurityInterstitialCommands command
) {
409 WebContents
* contents
=
410 browser()->tab_strip_model()->GetActiveWebContents();
411 // We use InterstitialPage::GetInterstitialPage(tab) instead of
412 // tab->GetInterstitialPage() because the tab doesn't have a pointer
413 // to its interstital page until it gets a command from the renderer
414 // that it has indeed displayed it -- and this sometimes happens after
415 // NavigateToURL returns.
416 SafeBrowsingBlockingPage
* interstitial_page
=
417 static_cast<SafeBrowsingBlockingPage
*>(
418 InterstitialPage::GetInterstitialPage(contents
)->
419 GetDelegateForTesting());
420 ASSERT_TRUE(interstitial_page
);
421 ASSERT_EQ(SafeBrowsingBlockingPage::kTypeForTesting
,
422 interstitial_page
->GetTypeForTesting());
423 interstitial_page
->CommandReceived(base::IntToString(command
));
426 void DontProceedThroughInterstitial() {
427 WebContents
* contents
=
428 browser()->tab_strip_model()->GetActiveWebContents();
429 InterstitialPage
* interstitial_page
= InterstitialPage::GetInterstitialPage(
431 ASSERT_TRUE(interstitial_page
);
432 interstitial_page
->DontProceed();
435 void ProceedThroughInterstitial() {
436 WebContents
* contents
=
437 browser()->tab_strip_model()->GetActiveWebContents();
438 InterstitialPage
* interstitial_page
= InterstitialPage::GetInterstitialPage(
440 ASSERT_TRUE(interstitial_page
);
441 interstitial_page
->Proceed();
444 void AssertNoInterstitial(bool wait_for_delete
) {
445 WebContents
* contents
=
446 browser()->tab_strip_model()->GetActiveWebContents();
448 if (contents
->ShowingInterstitialPage() && wait_for_delete
) {
449 // We'll get notified when the interstitial is deleted.
450 TestSafeBrowsingBlockingPage
* page
=
451 static_cast<TestSafeBrowsingBlockingPage
*>(
452 contents
->GetInterstitialPage()->GetDelegateForTesting());
453 ASSERT_EQ(SafeBrowsingBlockingPage::kTypeForTesting
,
454 page
->GetTypeForTesting());
455 page
->WaitForDelete();
458 // Can't use InterstitialPage::GetInterstitialPage() because that
459 // gets updated after the TestSafeBrowsingBlockingPage destructor
460 ASSERT_FALSE(contents
->ShowingInterstitialPage());
463 bool YesInterstitial() {
464 WebContents
* contents
=
465 browser()->tab_strip_model()->GetActiveWebContents();
466 InterstitialPage
* interstitial_page
= InterstitialPage::GetInterstitialPage(
468 return interstitial_page
!= NULL
;
471 void SetReportSentCallback(const base::Closure
& callback
) {
472 factory_
.most_recent_service()
474 ->set_malware_details_done_callback(callback
);
477 std::string
GetReportSent() {
478 return factory_
.most_recent_service()->fake_ui_manager()->GetReport();
481 void MalwareRedirectCancelAndProceed(const std::string
& open_function
) {
482 GURL load_url
= test_server()->GetURL(
483 "files/safe_browsing/interstitial_cancel.html");
484 GURL
malware_url("http://localhost/files/safe_browsing/malware.html");
485 SetURLThreatType(malware_url
, GetParam());
487 // Load the test page.
488 ui_test_utils::NavigateToURL(browser(), load_url
);
489 // Trigger the safe browsing interstitial page via a redirect in
491 ui_test_utils::NavigateToURLWithDisposition(
493 GURL("javascript:" + open_function
+ "()"),
495 ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB
);
496 WebContents
* contents
=
497 browser()->tab_strip_model()->GetActiveWebContents();
498 content::WaitForInterstitialAttach(contents
);
499 // Cancel the redirect request while interstitial page is open.
500 browser()->tab_strip_model()->ActivateTabAt(0, true);
501 ui_test_utils::NavigateToURL(browser(), GURL("javascript:stopWin()"));
502 browser()->tab_strip_model()->ActivateTabAt(1, true);
503 // Simulate the user clicking "proceed", there should be no crash. Since
504 // clicking proceed may do nothing (see comment in RedirectCanceled
505 // below, and crbug.com/76460), we use SendCommand to trigger the callback
506 // directly rather than using ClickAndWaitForDetach since there might not
507 // be a notification to wait for.
508 SendCommand(SecurityInterstitialPage::CMD_PROCEED
);
511 content::RenderViewHost
* GetRenderViewHost() {
512 InterstitialPage
* interstitial
= InterstitialPage::GetInterstitialPage(
513 browser()->tab_strip_model()->GetActiveWebContents());
516 return interstitial
->GetMainFrame()->GetRenderViewHost();
519 bool WaitForReady() {
520 InterstitialPage
* interstitial
= InterstitialPage::GetInterstitialPage(
521 browser()->tab_strip_model()->GetActiveWebContents());
524 return content::WaitForRenderFrameReady(interstitial
->GetMainFrame());
527 Visibility
GetVisibility(const std::string
& node_id
) {
528 content::RenderViewHost
* rvh
= GetRenderViewHost();
530 return VISIBILITY_ERROR
;
531 scoped_ptr
<base::Value
> value
= content::ExecuteScriptAndGetValue(
533 "var node = document.getElementById('" + node_id
+ "');\n"
535 " node.offsetWidth > 0 && node.offsetHeight > 0;"
537 " 'node not found';\n");
539 return VISIBILITY_ERROR
;
541 if (!value
->GetAsBoolean(&result
))
542 return VISIBILITY_ERROR
;
543 return result
? VISIBLE
: HIDDEN
;
546 bool Click(const std::string
& node_id
) {
547 content::RenderViewHost
* rvh
= GetRenderViewHost();
550 // We don't use ExecuteScriptAndGetValue for this one, since clicking
551 // the button/link may navigate away before the injected javascript can
552 // reply, hanging the test.
553 rvh
->GetMainFrame()->ExecuteJavaScript(
555 "document.getElementById('" + node_id
+ "').click();\n"));
559 bool ClickAndWaitForDetach(const std::string
& node_id
) {
560 // We wait for interstitial_detached rather than nav_entry_committed, as
561 // going back from a main-frame malware interstitial page will not cause a
562 // nav entry committed event.
565 content::WaitForInterstitialDetach(
566 browser()->tab_strip_model()->GetActiveWebContents());
571 TestMalwareDetailsFactory details_factory_
;
574 TestSafeBrowsingServiceFactory factory_
;
575 TestSafeBrowsingBlockingPageFactory blocking_page_factory_
;
577 DISALLOW_COPY_AND_ASSIGN(SafeBrowsingBlockingPageBrowserTest
);
580 // TODO(linux_aura) http://crbug.com/163931
581 // TODO(win_aura) http://crbug.com/154081
582 #if defined(USE_AURA) && !defined(OS_CHROMEOS)
583 #define MAYBE_RedirectInIFrameCanceled DISABLED_RedirectInIFrameCanceled
585 #define MAYBE_RedirectInIFrameCanceled RedirectInIFrameCanceled
587 IN_PROC_BROWSER_TEST_P(SafeBrowsingBlockingPageBrowserTest
,
588 MAYBE_RedirectInIFrameCanceled
) {
589 // 1. Test the case that redirect is a subresource.
590 MalwareRedirectCancelAndProceed("openWinIFrame");
591 // If the redirect was from subresource but canceled, "proceed" will continue
592 // with the rest of resources.
593 AssertNoInterstitial(true);
596 IN_PROC_BROWSER_TEST_P(SafeBrowsingBlockingPageBrowserTest
, RedirectCanceled
) {
597 // 2. Test the case that redirect is the only resource.
598 MalwareRedirectCancelAndProceed("openWin");
599 // Clicking proceed won't do anything if the main request is cancelled
600 // already. See crbug.com/76460.
601 EXPECT_TRUE(YesInterstitial());
604 IN_PROC_BROWSER_TEST_P(SafeBrowsingBlockingPageBrowserTest
, DontProceed
) {
605 #if defined(OS_WIN) && defined(USE_ASH)
606 // Disable this test in Metro+Ash for now (http://crbug.com/262796).
607 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
608 switches::kAshBrowserTests
))
612 SetupWarningAndNavigate();
614 EXPECT_EQ(VISIBLE
, GetVisibility("primary-button"));
615 EXPECT_EQ(HIDDEN
, GetVisibility("details"));
616 EXPECT_EQ(HIDDEN
, GetVisibility("proceed-link"));
617 EXPECT_EQ(HIDDEN
, GetVisibility("error-code"));
618 EXPECT_TRUE(Click("details-button"));
619 EXPECT_EQ(VISIBLE
, GetVisibility("details"));
620 EXPECT_EQ(VISIBLE
, GetVisibility("proceed-link"));
621 EXPECT_EQ(HIDDEN
, GetVisibility("error-code"));
622 EXPECT_TRUE(ClickAndWaitForDetach("primary-button"));
624 AssertNoInterstitial(false); // Assert the interstitial is gone
625 EXPECT_EQ(GURL(url::kAboutBlankURL
), // Back to "about:blank"
626 browser()->tab_strip_model()->GetActiveWebContents()->GetURL());
629 IN_PROC_BROWSER_TEST_P(SafeBrowsingBlockingPageBrowserTest
, Proceed
) {
630 GURL url
= SetupWarningAndNavigate();
632 EXPECT_TRUE(ClickAndWaitForDetach("proceed-link"));
633 AssertNoInterstitial(true); // Assert the interstitial is gone.
635 browser()->tab_strip_model()->GetActiveWebContents()->GetURL());
638 IN_PROC_BROWSER_TEST_P(SafeBrowsingBlockingPageBrowserTest
, IframeDontProceed
) {
639 #if defined(OS_WIN) && defined(USE_ASH)
640 // Disable this test in Metro+Ash for now (http://crbug.com/262796).
641 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
642 switches::kAshBrowserTests
))
646 SetupThreatIframeWarningAndNavigate();
648 EXPECT_EQ(VISIBLE
, GetVisibility("primary-button"));
649 EXPECT_EQ(HIDDEN
, GetVisibility("details"));
650 EXPECT_EQ(HIDDEN
, GetVisibility("proceed-link"));
651 EXPECT_EQ(HIDDEN
, GetVisibility("error-code"));
652 EXPECT_TRUE(Click("details-button"));
653 EXPECT_EQ(VISIBLE
, GetVisibility("details"));
654 EXPECT_EQ(VISIBLE
, GetVisibility("proceed-link"));
655 EXPECT_EQ(HIDDEN
, GetVisibility("error-code"));
656 EXPECT_TRUE(ClickAndWaitForDetach("primary-button"));
658 AssertNoInterstitial(false); // Assert the interstitial is gone
660 EXPECT_EQ(GURL(url::kAboutBlankURL
), // Back to "about:blank"
661 browser()->tab_strip_model()->GetActiveWebContents()->GetURL());
664 IN_PROC_BROWSER_TEST_P(SafeBrowsingBlockingPageBrowserTest
, IframeProceed
) {
665 GURL url
= SetupThreatIframeWarningAndNavigate();
667 EXPECT_TRUE(ClickAndWaitForDetach("proceed-link"));
668 AssertNoInterstitial(true); // Assert the interstitial is gone
671 browser()->tab_strip_model()->GetActiveWebContents()->GetURL());
674 IN_PROC_BROWSER_TEST_P(SafeBrowsingBlockingPageBrowserTest
,
675 IframeOptInAndReportMalwareDetails
) {
676 // The extended reporting opt-in is presented in the interstitial for malware,
677 // phishing, and UwS threats. It however only results in uploading further
678 // details about the immediate threat when facing malware threats.
679 const bool expect_malware_details
= GetParam() == SB_THREAT_TYPE_URL_MALWARE
;
681 scoped_refptr
<content::MessageLoopRunner
> malware_report_sent_runner(
682 new content::MessageLoopRunner
);
683 if (expect_malware_details
)
684 SetReportSentCallback(malware_report_sent_runner
->QuitClosure());
686 GURL url
= SetupThreatIframeWarningAndNavigate();
688 FakeMalwareDetails
* fake_malware_details
= details_factory_
.get_details();
689 EXPECT_EQ(expect_malware_details
, fake_malware_details
!= nullptr);
691 // If the DOM details from renderer did not already return when they are
692 // expected, wait for them.
693 if (expect_malware_details
)
694 fake_malware_details
->WaitForDOM();
696 EXPECT_EQ(VISIBLE
, GetVisibility("extended-reporting-opt-in"));
697 EXPECT_TRUE(Click("opt-in-checkbox"));
698 EXPECT_TRUE(ClickAndWaitForDetach("proceed-link"));
699 AssertNoInterstitial(true); // Assert the interstitial is gone
701 EXPECT_TRUE(browser()->profile()->GetPrefs()->GetBoolean(
702 prefs::kSafeBrowsingExtendedReportingEnabled
));
704 browser()->tab_strip_model()->GetActiveWebContents()->GetURL());
706 if (expect_malware_details
) {
707 malware_report_sent_runner
->Run();
708 std::string serialized
= GetReportSent();
709 safe_browsing::ClientMalwareReportRequest report
;
710 ASSERT_TRUE(report
.ParseFromString(serialized
));
711 // Verify the report is complete.
712 EXPECT_TRUE(report
.complete());
716 // Verifies that the "proceed anyway" link isn't available when it is disabled
717 // by the corresponding policy. Also verifies that sending the "proceed"
718 // command anyway doesn't advance to the malware site.
719 IN_PROC_BROWSER_TEST_P(SafeBrowsingBlockingPageBrowserTest
, ProceedDisabled
) {
720 #if defined(OS_WIN) && defined(USE_ASH)
721 // Disable this test in Metro+Ash for now (http://crbug.com/262796).
722 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
723 switches::kAshBrowserTests
))
727 // Simulate a policy disabling the "proceed anyway" link.
728 browser()->profile()->GetPrefs()->SetBoolean(
729 prefs::kSafeBrowsingProceedAnywayDisabled
, true);
731 SetupWarningAndNavigate();
733 EXPECT_EQ(VISIBLE
, GetVisibility("primary-button"));
734 EXPECT_EQ(HIDDEN
, GetVisibility("details"));
735 EXPECT_EQ(HIDDEN
, GetVisibility("proceed-link"));
736 EXPECT_EQ(HIDDEN
, GetVisibility("final-paragraph"));
737 EXPECT_TRUE(Click("details-button"));
738 EXPECT_EQ(HIDDEN
, GetVisibility("proceed-link"));
739 EXPECT_EQ(HIDDEN
, GetVisibility("final-paragraph"));
740 SendCommand(SecurityInterstitialPage::CMD_PROCEED
);
742 // The "proceed" command should go back instead, if proceeding is disabled.
743 AssertNoInterstitial(true);
744 EXPECT_EQ(GURL(url::kAboutBlankURL
), // Back to "about:blank"
745 browser()->tab_strip_model()->GetActiveWebContents()->GetURL());
748 // Verifies that the reporting checkbox is hidden on non-HTTP pages.
749 // TODO(mattm): Should also verify that no report is sent, but there isn't a
750 // good way to do that in the current design.
751 IN_PROC_BROWSER_TEST_P(SafeBrowsingBlockingPageBrowserTest
, ReportingDisabled
) {
752 #if defined(OS_WIN) && defined(USE_ASH)
753 // Disable this test in Metro+Ash for now (http://crbug.com/262796).
754 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
755 switches::kAshBrowserTests
))
759 browser()->profile()->GetPrefs()->SetBoolean(
760 prefs::kSafeBrowsingExtendedReportingEnabled
, true);
762 net::SpawnedTestServer
https_server(
763 net::SpawnedTestServer::TYPE_HTTPS
, net::SpawnedTestServer::kLocalhost
,
764 base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
765 ASSERT_TRUE(https_server
.Start());
766 GURL url
= https_server
.GetURL(kEmptyPage
);
767 SetURLThreatType(url
, GetParam());
768 ui_test_utils::NavigateToURL(browser(), url
);
769 ASSERT_TRUE(WaitForReady());
771 EXPECT_EQ(HIDDEN
, GetVisibility("extended-reporting-opt-in"));
772 EXPECT_EQ(HIDDEN
, GetVisibility("opt-in-checkbox"));
773 EXPECT_EQ(HIDDEN
, GetVisibility("proceed-link"));
774 EXPECT_TRUE(Click("details-button"));
775 EXPECT_EQ(VISIBLE
, GetVisibility("help-link"));
776 EXPECT_EQ(VISIBLE
, GetVisibility("proceed-link"));
778 EXPECT_TRUE(ClickAndWaitForDetach("primary-button"));
779 AssertNoInterstitial(false); // Assert the interstitial is gone
780 EXPECT_EQ(GURL(url::kAboutBlankURL
), // Back to "about:blank"
781 browser()->tab_strip_model()->GetActiveWebContents()->GetURL());
784 IN_PROC_BROWSER_TEST_P(SafeBrowsingBlockingPageBrowserTest
, LearnMore
) {
785 SetupWarningAndNavigate();
786 EXPECT_TRUE(ClickAndWaitForDetach("help-link"));
787 AssertNoInterstitial(false); // Assert the interstitial is gone
789 // We are in the help page.
791 GetParam() == SB_THREAT_TYPE_URL_PHISHING
792 ? "/transparencyreport/safebrowsing/"
793 : "/safebrowsing/diagnostic",
794 browser()->tab_strip_model()->GetActiveWebContents()->GetURL().path());
797 INSTANTIATE_TEST_CASE_P(SafeBrowsingBlockingPageBrowserTestWithThreatType
,
798 SafeBrowsingBlockingPageBrowserTest
,
799 testing::Values(SB_THREAT_TYPE_URL_MALWARE
,
800 SB_THREAT_TYPE_URL_PHISHING
,
801 SB_THREAT_TYPE_URL_UNWANTED
));
803 // Test that SafeBrowsingBlockingPage properly decodes IDN URLs that are
805 class SafeBrowsingBlockingPageIDNTest
806 : public SecurityInterstitialIDNTest
,
807 public testing::WithParamInterface
<SBThreatType
> {
809 // SecurityInterstitialIDNTest implementation
810 SecurityInterstitialPage
* CreateInterstitial(
811 content::WebContents
* contents
,
812 const GURL
& request_url
) const override
{
813 SafeBrowsingService
* sb_service
=
814 g_browser_process
->safe_browsing_service();
815 SafeBrowsingBlockingPage::UnsafeResource resource
;
817 resource
.url
= request_url
;
818 resource
.is_subresource
= false;
819 resource
.threat_type
= GetParam();
820 resource
.render_process_host_id
= contents
->GetRenderProcessHost()->GetID();
821 resource
.render_view_id
= contents
->GetRenderViewHost()->GetRoutingID();
823 return SafeBrowsingBlockingPage::CreateBlockingPage(
824 sb_service
->ui_manager().get(), contents
, resource
);
828 IN_PROC_BROWSER_TEST_P(SafeBrowsingBlockingPageIDNTest
,
829 SafeBrowsingBlockingPageDecodesIDN
) {
830 EXPECT_TRUE(VerifyIDNDecoded());
833 INSTANTIATE_TEST_CASE_P(SafeBrowsingBlockingPageIDNTestWithThreatType
,
834 SafeBrowsingBlockingPageIDNTest
,
835 testing::Values(SB_THREAT_TYPE_URL_MALWARE
,
836 SB_THREAT_TYPE_URL_PHISHING
,
837 SB_THREAT_TYPE_URL_UNWANTED
));