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/utf_string_conversions.h"
13 #include "base/values.h"
14 #include "chrome/browser/browser_process.h"
15 #include "chrome/browser/profiles/profile.h"
16 #include "chrome/browser/safe_browsing/database_manager.h"
17 #include "chrome/browser/safe_browsing/malware_details.h"
18 #include "chrome/browser/safe_browsing/safe_browsing_blocking_page.h"
19 #include "chrome/browser/safe_browsing/safe_browsing_service.h"
20 #include "chrome/browser/safe_browsing/safe_browsing_util.h"
21 #include "chrome/browser/safe_browsing/ui_manager.h"
22 #include "chrome/browser/ui/browser.h"
23 #include "chrome/browser/ui/browser_tabstrip.h"
24 #include "chrome/browser/ui/tabs/tab_strip_model.h"
25 #include "chrome/common/chrome_switches.h"
26 #include "chrome/common/pref_names.h"
27 #include "chrome/common/url_constants.h"
28 #include "chrome/test/base/in_process_browser_test.h"
29 #include "chrome/test/base/test_switches.h"
30 #include "chrome/test/base/ui_test_utils.h"
31 #include "content/public/browser/interstitial_page.h"
32 #include "content/public/browser/navigation_controller.h"
33 #include "content/public/browser/notification_types.h"
34 #include "content/public/browser/render_frame_host.h"
35 #include "content/public/browser/render_view_host.h"
36 #include "content/public/browser/web_contents.h"
37 #include "content/public/test/browser_test_utils.h"
38 #include "content/public/test/test_browser_thread.h"
39 #include "content/public/test/test_utils.h"
41 using content::BrowserThread
;
42 using content::InterstitialPage
;
43 using content::NavigationController
;
44 using content::WebContents
;
48 const char kEmptyPage
[] = "files/empty.html";
49 const char kMalwarePage
[] = "files/safe_browsing/malware.html";
50 const char kMalwareIframe
[] = "files/safe_browsing/malware_iframe.html";
52 // A SafeBrowsingDatabaseManager class that allows us to inject the malicious
54 class FakeSafeBrowsingDatabaseManager
: public SafeBrowsingDatabaseManager
{
56 explicit FakeSafeBrowsingDatabaseManager(SafeBrowsingService
* service
)
57 : SafeBrowsingDatabaseManager(service
) { }
59 // Called on the IO thread to check if the given url is safe or not. If we
60 // can synchronously determine that the url is safe, CheckUrl returns true.
61 // Otherwise it returns false, and "client" is called asynchronously with the
62 // result when it is ready.
63 // Overrides SafeBrowsingDatabaseManager::CheckBrowseUrl.
64 bool CheckBrowseUrl(const GURL
& gurl
, Client
* client
) override
{
65 if (badurls
[gurl
.spec()] == SB_THREAT_TYPE_SAFE
)
68 BrowserThread::PostTask(
69 BrowserThread::IO
, FROM_HERE
,
70 base::Bind(&FakeSafeBrowsingDatabaseManager::OnCheckBrowseURLDone
,
75 void OnCheckBrowseURLDone(const GURL
& gurl
, Client
* client
) {
76 std::vector
<SBThreatType
> expected_threats
;
77 expected_threats
.push_back(SB_THREAT_TYPE_URL_MALWARE
);
78 expected_threats
.push_back(SB_THREAT_TYPE_URL_PHISHING
);
79 expected_threats
.push_back(SB_THREAT_TYPE_URL_UNWANTED
);
80 SafeBrowsingDatabaseManager::SafeBrowsingCheck
sb_check(
81 std::vector
<GURL
>(1, gurl
),
82 std::vector
<SBFullHash
>(),
84 safe_browsing_util::MALWARE
,
86 sb_check
.url_results
[0] = badurls
[gurl
.spec()];
87 client
->OnSafeBrowsingResult(sb_check
);
90 void SetURLThreatType(const GURL
& url
, SBThreatType threat_type
) {
91 badurls
[url
.spec()] = threat_type
;
95 ~FakeSafeBrowsingDatabaseManager() override
{}
97 base::hash_map
<std::string
, SBThreatType
> badurls
;
98 DISALLOW_COPY_AND_ASSIGN(FakeSafeBrowsingDatabaseManager
);
101 // A SafeBrowingUIManager class that allows intercepting malware details.
102 class FakeSafeBrowsingUIManager
: public SafeBrowsingUIManager
{
104 explicit FakeSafeBrowsingUIManager(SafeBrowsingService
* service
) :
105 SafeBrowsingUIManager(service
) { }
107 // Overrides SafeBrowsingUIManager
108 void SendSerializedMalwareDetails(const std::string
& serialized
) override
{
109 // Notify the UI thread that we got a report.
110 BrowserThread::PostTask(
113 base::Bind(&FakeSafeBrowsingUIManager::OnMalwareDetailsDone
,
118 void OnMalwareDetailsDone(const std::string
& serialized
) {
119 EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI
));
120 report_
= serialized
;
122 EXPECT_FALSE(malware_details_done_callback_
.is_null());
123 if (!malware_details_done_callback_
.is_null()) {
124 malware_details_done_callback_
.Run();
125 malware_details_done_callback_
= base::Closure();
129 void set_malware_details_done_callback(const base::Closure
& callback
) {
130 EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI
));
131 EXPECT_TRUE(malware_details_done_callback_
.is_null());
132 malware_details_done_callback_
= callback
;
135 std::string
GetReport() {
136 EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI
));
141 ~FakeSafeBrowsingUIManager() override
{}
145 base::Closure malware_details_done_callback_
;
147 DISALLOW_COPY_AND_ASSIGN(FakeSafeBrowsingUIManager
);
150 class FakeSafeBrowsingService
: public SafeBrowsingService
{
152 FakeSafeBrowsingService()
153 : fake_database_manager_(),
154 fake_ui_manager_() { }
156 // Returned pointer has the same lifespan as the database_manager_ refcounted
158 FakeSafeBrowsingDatabaseManager
* fake_database_manager() {
159 return fake_database_manager_
;
161 // Returned pointer has the same lifespan as the ui_manager_ refcounted
163 FakeSafeBrowsingUIManager
* fake_ui_manager() {
164 return fake_ui_manager_
;
168 ~FakeSafeBrowsingService() override
{}
170 SafeBrowsingDatabaseManager
* CreateDatabaseManager() override
{
171 fake_database_manager_
= new FakeSafeBrowsingDatabaseManager(this);
172 return fake_database_manager_
;
175 SafeBrowsingUIManager
* CreateUIManager() override
{
176 fake_ui_manager_
= new FakeSafeBrowsingUIManager(this);
177 return fake_ui_manager_
;
181 FakeSafeBrowsingDatabaseManager
* fake_database_manager_
;
182 FakeSafeBrowsingUIManager
* fake_ui_manager_
;
184 DISALLOW_COPY_AND_ASSIGN(FakeSafeBrowsingService
);
187 // Factory that creates FakeSafeBrowsingService instances.
188 class TestSafeBrowsingServiceFactory
: public SafeBrowsingServiceFactory
{
190 TestSafeBrowsingServiceFactory() :
191 most_recent_service_(NULL
) { }
192 ~TestSafeBrowsingServiceFactory() override
{}
194 SafeBrowsingService
* CreateSafeBrowsingService() override
{
195 most_recent_service_
= new FakeSafeBrowsingService();
196 return most_recent_service_
;
199 FakeSafeBrowsingService
* most_recent_service() const {
200 return most_recent_service_
;
204 FakeSafeBrowsingService
* most_recent_service_
;
207 // A MalwareDetails class lets us intercept calls from the renderer.
208 class FakeMalwareDetails
: public MalwareDetails
{
211 SafeBrowsingUIManager
* delegate
,
212 WebContents
* web_contents
,
213 const SafeBrowsingUIManager::UnsafeResource
& unsafe_resource
)
214 : MalwareDetails(delegate
, web_contents
, unsafe_resource
),
219 const std::vector
<SafeBrowsingHostMsg_MalwareDOMDetails_Node
>& params
)
221 EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO
));
222 MalwareDetails::AddDOMDetails(params
);
224 // Notify the UI thread that we got the dom details.
225 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
226 base::Bind(&FakeMalwareDetails::OnDOMDetailsDone
,
234 // This condition might not trigger normally, but if you add a
235 // sleep(1) in malware_dom_details it triggers :).
237 content::RunMessageLoop();
238 EXPECT_TRUE(got_dom_
);
242 ~FakeMalwareDetails() override
{}
244 void OnDOMDetailsDone() {
247 base::MessageLoopForUI::current()->Quit();
251 // Some logic to figure out if we should wait for the dom details or not.
252 // These variables should only be accessed in the UI thread.
257 class TestMalwareDetailsFactory
: public MalwareDetailsFactory
{
259 TestMalwareDetailsFactory() : details_() { }
260 ~TestMalwareDetailsFactory() override
{}
262 MalwareDetails
* CreateMalwareDetails(
263 SafeBrowsingUIManager
* delegate
,
264 WebContents
* web_contents
,
265 const SafeBrowsingUIManager::UnsafeResource
& unsafe_resource
) override
{
266 details_
= new FakeMalwareDetails(delegate
, web_contents
,
271 FakeMalwareDetails
* get_details() {
276 FakeMalwareDetails
* details_
;
279 // A SafeBrowingBlockingPage class that lets us wait until it's hidden.
280 class TestSafeBrowsingBlockingPage
: public SafeBrowsingBlockingPage
{
282 TestSafeBrowsingBlockingPage(SafeBrowsingUIManager
* manager
,
283 WebContents
* web_contents
,
284 const UnsafeResourceList
& unsafe_resources
)
285 : SafeBrowsingBlockingPage(manager
, web_contents
, unsafe_resources
),
286 wait_for_delete_(false) {
287 // Don't wait the whole 3 seconds for the browser test.
288 malware_details_proceed_delay_ms_
= 100;
291 ~TestSafeBrowsingBlockingPage() override
{
292 if (!wait_for_delete_
)
295 // Notify that we are gone
296 base::MessageLoopForUI::current()->Quit();
297 wait_for_delete_
= false;
300 void WaitForDelete() {
301 wait_for_delete_
= true;
302 content::RunMessageLoop();
305 // InterstitialPageDelegate methods:
306 void CommandReceived(const std::string
& command
) override
{
307 SafeBrowsingBlockingPage::CommandReceived(command
);
309 void OnProceed() override
{ SafeBrowsingBlockingPage::OnProceed(); }
310 void OnDontProceed() override
{ SafeBrowsingBlockingPage::OnDontProceed(); }
313 bool wait_for_delete_
;
316 class TestSafeBrowsingBlockingPageFactory
317 : public SafeBrowsingBlockingPageFactory
{
319 TestSafeBrowsingBlockingPageFactory() { }
320 ~TestSafeBrowsingBlockingPageFactory() override
{}
322 SafeBrowsingBlockingPage
* CreateSafeBrowsingPage(
323 SafeBrowsingUIManager
* delegate
,
324 WebContents
* web_contents
,
325 const SafeBrowsingBlockingPage::UnsafeResourceList
& unsafe_resources
)
327 return new TestSafeBrowsingBlockingPage(delegate
, web_contents
,
334 // Tests the safe browsing blocking page in a browser.
335 class SafeBrowsingBlockingPageBrowserTest
336 : public InProcessBrowserTest
,
337 public testing::WithParamInterface
<SBThreatType
> {
340 VISIBILITY_ERROR
= -1,
345 SafeBrowsingBlockingPageBrowserTest() {}
347 void SetUp() override
{
348 SafeBrowsingService::RegisterFactory(&factory_
);
349 SafeBrowsingBlockingPage::RegisterFactory(&blocking_page_factory_
);
350 MalwareDetails::RegisterFactory(&details_factory_
);
351 InProcessBrowserTest::SetUp();
354 void SetUpCommandLine(base::CommandLine
* command_line
) override
{
355 command_line
->AppendSwitchASCII(
356 switches::kForceFieldTrials
, "UwSInterstitialStatus/On/");
359 void TearDown() override
{
360 InProcessBrowserTest::TearDown();
361 SafeBrowsingBlockingPage::RegisterFactory(NULL
);
362 SafeBrowsingService::RegisterFactory(NULL
);
363 MalwareDetails::RegisterFactory(NULL
);
366 void SetUpInProcessBrowserTestFixture() override
{
367 ASSERT_TRUE(test_server()->Start());
370 void SetURLThreatType(const GURL
& url
, SBThreatType threat_type
) {
371 FakeSafeBrowsingService
* service
=
372 static_cast<FakeSafeBrowsingService
*>(
373 g_browser_process
->safe_browsing_service());
375 ASSERT_TRUE(service
);
376 service
->fake_database_manager()->SetURLThreatType(url
, threat_type
);
379 // Adds a safebrowsing result of the current test threat to the fake
380 // safebrowsing service, navigates to that page, and returns the url.
381 GURL
SetupWarningAndNavigate() {
382 GURL url
= test_server()->GetURL(kEmptyPage
);
383 SetURLThreatType(url
, GetParam());
385 ui_test_utils::NavigateToURL(browser(), url
);
386 EXPECT_TRUE(WaitForReady());
390 // Adds a safebrowsing threat result to the fake safebrowsing service,
391 // navigates to a page with an iframe containing the threat site, and returns
392 // the url of the parent page.
393 GURL
SetupThreatIframeWarningAndNavigate() {
394 GURL url
= test_server()->GetURL(kMalwarePage
);
395 GURL iframe_url
= test_server()->GetURL(kMalwareIframe
);
396 SetURLThreatType(iframe_url
, GetParam());
398 ui_test_utils::NavigateToURL(browser(), url
);
399 EXPECT_TRUE(WaitForReady());
403 void SendCommand(const std::string
& command
) {
404 WebContents
* contents
=
405 browser()->tab_strip_model()->GetActiveWebContents();
406 // We use InterstitialPage::GetInterstitialPage(tab) instead of
407 // tab->GetInterstitialPage() because the tab doesn't have a pointer
408 // to its interstital page until it gets a command from the renderer
409 // that it has indeed displayed it -- and this sometimes happens after
410 // NavigateToURL returns.
411 SafeBrowsingBlockingPage
* interstitial_page
=
412 static_cast<SafeBrowsingBlockingPage
*>(
413 InterstitialPage::GetInterstitialPage(contents
)->
414 GetDelegateForTesting());
415 ASSERT_TRUE(interstitial_page
);
416 ASSERT_EQ(SafeBrowsingBlockingPage::kTypeForTesting
,
417 interstitial_page
->GetTypeForTesting());
418 interstitial_page
->CommandReceived(command
);
421 void DontProceedThroughInterstitial() {
422 WebContents
* contents
=
423 browser()->tab_strip_model()->GetActiveWebContents();
424 InterstitialPage
* interstitial_page
= InterstitialPage::GetInterstitialPage(
426 ASSERT_TRUE(interstitial_page
);
427 interstitial_page
->DontProceed();
430 void ProceedThroughInterstitial() {
431 WebContents
* contents
=
432 browser()->tab_strip_model()->GetActiveWebContents();
433 InterstitialPage
* interstitial_page
= InterstitialPage::GetInterstitialPage(
435 ASSERT_TRUE(interstitial_page
);
436 interstitial_page
->Proceed();
439 void AssertNoInterstitial(bool wait_for_delete
) {
440 WebContents
* contents
=
441 browser()->tab_strip_model()->GetActiveWebContents();
443 if (contents
->ShowingInterstitialPage() && wait_for_delete
) {
444 // We'll get notified when the interstitial is deleted.
445 TestSafeBrowsingBlockingPage
* page
=
446 static_cast<TestSafeBrowsingBlockingPage
*>(
447 contents
->GetInterstitialPage()->GetDelegateForTesting());
448 ASSERT_EQ(SafeBrowsingBlockingPage::kTypeForTesting
,
449 page
->GetTypeForTesting());
450 page
->WaitForDelete();
453 // Can't use InterstitialPage::GetInterstitialPage() because that
454 // gets updated after the TestSafeBrowsingBlockingPage destructor
455 ASSERT_FALSE(contents
->ShowingInterstitialPage());
458 bool YesInterstitial() {
459 WebContents
* contents
=
460 browser()->tab_strip_model()->GetActiveWebContents();
461 InterstitialPage
* interstitial_page
= InterstitialPage::GetInterstitialPage(
463 return interstitial_page
!= NULL
;
466 void SetReportSentCallback(const base::Closure
& callback
) {
467 factory_
.most_recent_service()
469 ->set_malware_details_done_callback(callback
);
472 std::string
GetReportSent() {
473 return factory_
.most_recent_service()->fake_ui_manager()->GetReport();
476 void MalwareRedirectCancelAndProceed(const std::string
& open_function
) {
477 GURL load_url
= test_server()->GetURL(
478 "files/safe_browsing/interstitial_cancel.html");
479 GURL
malware_url("http://localhost/files/safe_browsing/malware.html");
480 SetURLThreatType(malware_url
, GetParam());
482 // Load the test page.
483 ui_test_utils::NavigateToURL(browser(), load_url
);
484 // Trigger the safe browsing interstitial page via a redirect in
486 ui_test_utils::NavigateToURLWithDisposition(
488 GURL("javascript:" + open_function
+ "()"),
490 ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB
);
491 WebContents
* contents
=
492 browser()->tab_strip_model()->GetActiveWebContents();
493 content::WaitForInterstitialAttach(contents
);
494 // Cancel the redirect request while interstitial page is open.
495 browser()->tab_strip_model()->ActivateTabAt(0, true);
496 ui_test_utils::NavigateToURL(browser(), GURL("javascript:stopWin()"));
497 browser()->tab_strip_model()->ActivateTabAt(1, true);
498 // Simulate the user clicking "proceed", there should be no crash. Since
499 // clicking proceed may do nothing (see comment in RedirectCanceled
500 // below, and crbug.com/76460), we use SendCommand to trigger the callback
501 // directly rather than using ClickAndWaitForDetach since there might not
502 // be a notification to wait for.
503 SendCommand("\"proceed\"");
506 content::RenderViewHost
* GetRenderViewHost() {
507 InterstitialPage
* interstitial
= InterstitialPage::GetInterstitialPage(
508 browser()->tab_strip_model()->GetActiveWebContents());
511 return interstitial
->GetMainFrame()->GetRenderViewHost();
514 bool WaitForReady() {
515 InterstitialPage
* interstitial
= InterstitialPage::GetInterstitialPage(
516 browser()->tab_strip_model()->GetActiveWebContents());
519 return content::WaitForRenderFrameReady(interstitial
->GetMainFrame());
522 Visibility
GetVisibility(const std::string
& node_id
) {
523 content::RenderViewHost
* rvh
= GetRenderViewHost();
525 return VISIBILITY_ERROR
;
526 scoped_ptr
<base::Value
> value
= content::ExecuteScriptAndGetValue(
528 "var node = document.getElementById('" + node_id
+ "');\n"
530 " node.offsetWidth > 0 && node.offsetHeight > 0;"
532 " 'node not found';\n");
534 return VISIBILITY_ERROR
;
536 if (!value
->GetAsBoolean(&result
))
537 return VISIBILITY_ERROR
;
538 return result
? VISIBLE
: HIDDEN
;
541 bool Click(const std::string
& node_id
) {
542 content::RenderViewHost
* rvh
= GetRenderViewHost();
545 // We don't use ExecuteScriptAndGetValue for this one, since clicking
546 // the button/link may navigate away before the injected javascript can
547 // reply, hanging the test.
548 rvh
->GetMainFrame()->ExecuteJavaScript(
550 "document.getElementById('" + node_id
+ "').click();\n"));
554 bool ClickAndWaitForDetach(const std::string
& node_id
) {
555 // We wait for interstitial_detached rather than nav_entry_committed, as
556 // going back from a main-frame malware interstitial page will not cause a
557 // nav entry committed event.
560 content::WaitForInterstitialDetach(
561 browser()->tab_strip_model()->GetActiveWebContents());
566 TestMalwareDetailsFactory details_factory_
;
569 TestSafeBrowsingServiceFactory factory_
;
570 TestSafeBrowsingBlockingPageFactory blocking_page_factory_
;
572 DISALLOW_COPY_AND_ASSIGN(SafeBrowsingBlockingPageBrowserTest
);
575 // TODO(linux_aura) http://crbug.com/163931
576 // TODO(win_aura) http://crbug.com/154081
577 #if defined(USE_AURA) && !defined(OS_CHROMEOS)
578 #define MAYBE_RedirectInIFrameCanceled DISABLED_RedirectInIFrameCanceled
580 #define MAYBE_RedirectInIFrameCanceled RedirectInIFrameCanceled
582 IN_PROC_BROWSER_TEST_P(SafeBrowsingBlockingPageBrowserTest
,
583 MAYBE_RedirectInIFrameCanceled
) {
584 // 1. Test the case that redirect is a subresource.
585 MalwareRedirectCancelAndProceed("openWinIFrame");
586 // If the redirect was from subresource but canceled, "proceed" will continue
587 // with the rest of resources.
588 AssertNoInterstitial(true);
591 IN_PROC_BROWSER_TEST_P(SafeBrowsingBlockingPageBrowserTest
, RedirectCanceled
) {
592 // 2. Test the case that redirect is the only resource.
593 MalwareRedirectCancelAndProceed("openWin");
594 // Clicking proceed won't do anything if the main request is cancelled
595 // already. See crbug.com/76460.
596 EXPECT_TRUE(YesInterstitial());
599 IN_PROC_BROWSER_TEST_P(SafeBrowsingBlockingPageBrowserTest
, DontProceed
) {
600 #if defined(OS_WIN) && defined(USE_ASH)
601 // Disable this test in Metro+Ash for now (http://crbug.com/262796).
602 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
603 switches::kAshBrowserTests
))
607 SetupWarningAndNavigate();
609 EXPECT_EQ(VISIBLE
, GetVisibility("primary-button"));
610 EXPECT_EQ(HIDDEN
, GetVisibility("details"));
611 EXPECT_EQ(HIDDEN
, GetVisibility("proceed-link"));
612 EXPECT_EQ(HIDDEN
, GetVisibility("error-code"));
613 EXPECT_TRUE(Click("details-button"));
614 EXPECT_EQ(VISIBLE
, GetVisibility("details"));
615 EXPECT_EQ(VISIBLE
, GetVisibility("proceed-link"));
616 EXPECT_EQ(HIDDEN
, GetVisibility("error-code"));
617 EXPECT_TRUE(ClickAndWaitForDetach("primary-button"));
619 AssertNoInterstitial(false); // Assert the interstitial is gone
620 EXPECT_EQ(GURL(url::kAboutBlankURL
), // Back to "about:blank"
621 browser()->tab_strip_model()->GetActiveWebContents()->GetURL());
624 IN_PROC_BROWSER_TEST_P(SafeBrowsingBlockingPageBrowserTest
, Proceed
) {
625 GURL url
= SetupWarningAndNavigate();
627 EXPECT_TRUE(ClickAndWaitForDetach("proceed-link"));
628 AssertNoInterstitial(true); // Assert the interstitial is gone.
630 browser()->tab_strip_model()->GetActiveWebContents()->GetURL());
633 IN_PROC_BROWSER_TEST_P(SafeBrowsingBlockingPageBrowserTest
, IframeDontProceed
) {
634 #if defined(OS_WIN) && defined(USE_ASH)
635 // Disable this test in Metro+Ash for now (http://crbug.com/262796).
636 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
637 switches::kAshBrowserTests
))
641 SetupThreatIframeWarningAndNavigate();
643 EXPECT_EQ(VISIBLE
, GetVisibility("primary-button"));
644 EXPECT_EQ(HIDDEN
, GetVisibility("details"));
645 EXPECT_EQ(HIDDEN
, GetVisibility("proceed-link"));
646 EXPECT_EQ(HIDDEN
, GetVisibility("error-code"));
647 EXPECT_TRUE(Click("details-button"));
648 EXPECT_EQ(VISIBLE
, GetVisibility("details"));
649 EXPECT_EQ(VISIBLE
, GetVisibility("proceed-link"));
650 EXPECT_EQ(HIDDEN
, GetVisibility("error-code"));
651 EXPECT_TRUE(ClickAndWaitForDetach("primary-button"));
653 AssertNoInterstitial(false); // Assert the interstitial is gone
655 EXPECT_EQ(GURL(url::kAboutBlankURL
), // Back to "about:blank"
656 browser()->tab_strip_model()->GetActiveWebContents()->GetURL());
659 IN_PROC_BROWSER_TEST_P(SafeBrowsingBlockingPageBrowserTest
, IframeProceed
) {
660 GURL url
= SetupThreatIframeWarningAndNavigate();
662 EXPECT_TRUE(ClickAndWaitForDetach("proceed-link"));
663 AssertNoInterstitial(true); // Assert the interstitial is gone
666 browser()->tab_strip_model()->GetActiveWebContents()->GetURL());
669 IN_PROC_BROWSER_TEST_P(SafeBrowsingBlockingPageBrowserTest
,
670 IframeOptInAndReportMalwareDetails
) {
671 // The extended reporting opt-in is presented in the interstitial for malware,
672 // phishing, and UwS threats. It however only results in uploading further
673 // details about the immediate threat when facing malware threats.
674 const bool expect_malware_details
= GetParam() == SB_THREAT_TYPE_URL_MALWARE
;
676 scoped_refptr
<content::MessageLoopRunner
> malware_report_sent_runner(
677 new content::MessageLoopRunner
);
678 if (expect_malware_details
)
679 SetReportSentCallback(malware_report_sent_runner
->QuitClosure());
681 GURL url
= SetupThreatIframeWarningAndNavigate();
683 FakeMalwareDetails
* fake_malware_details
= details_factory_
.get_details();
684 EXPECT_EQ(expect_malware_details
, fake_malware_details
!= nullptr);
686 // If the DOM details from renderer did not already return when they are
687 // expected, wait for them.
688 if (expect_malware_details
)
689 fake_malware_details
->WaitForDOM();
691 EXPECT_EQ(VISIBLE
, GetVisibility("malware-opt-in"));
692 EXPECT_TRUE(Click("opt-in-checkbox"));
693 EXPECT_TRUE(ClickAndWaitForDetach("proceed-link"));
694 AssertNoInterstitial(true); // Assert the interstitial is gone
696 EXPECT_TRUE(browser()->profile()->GetPrefs()->GetBoolean(
697 prefs::kSafeBrowsingExtendedReportingEnabled
));
699 browser()->tab_strip_model()->GetActiveWebContents()->GetURL());
701 if (expect_malware_details
) {
702 malware_report_sent_runner
->Run();
703 std::string serialized
= GetReportSent();
704 safe_browsing::ClientMalwareReportRequest report
;
705 ASSERT_TRUE(report
.ParseFromString(serialized
));
706 // Verify the report is complete.
707 EXPECT_TRUE(report
.complete());
711 // Verifies that the "proceed anyway" link isn't available when it is disabled
712 // by the corresponding policy. Also verifies that sending the "proceed"
713 // command anyway doesn't advance to the malware site.
714 IN_PROC_BROWSER_TEST_P(SafeBrowsingBlockingPageBrowserTest
, ProceedDisabled
) {
715 #if defined(OS_WIN) && defined(USE_ASH)
716 // Disable this test in Metro+Ash for now (http://crbug.com/262796).
717 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
718 switches::kAshBrowserTests
))
722 // Simulate a policy disabling the "proceed anyway" link.
723 browser()->profile()->GetPrefs()->SetBoolean(
724 prefs::kSafeBrowsingProceedAnywayDisabled
, true);
726 SetupWarningAndNavigate();
728 EXPECT_EQ(VISIBLE
, GetVisibility("primary-button"));
729 EXPECT_EQ(HIDDEN
, GetVisibility("details"));
730 EXPECT_EQ(HIDDEN
, GetVisibility("proceed-link"));
731 EXPECT_EQ(HIDDEN
, GetVisibility("final-paragraph"));
732 EXPECT_TRUE(Click("details-button"));
733 EXPECT_EQ(HIDDEN
, GetVisibility("proceed-link"));
734 EXPECT_EQ(HIDDEN
, GetVisibility("final-paragraph"));
735 SendCommand("proceed");
737 // The "proceed" command should go back instead, if proceeding is disabled.
738 AssertNoInterstitial(true);
739 EXPECT_EQ(GURL(url::kAboutBlankURL
), // Back to "about:blank"
740 browser()->tab_strip_model()->GetActiveWebContents()->GetURL());
743 // Verifies that the reporting checkbox is hidden on non-HTTP pages.
744 // TODO(mattm): Should also verify that no report is sent, but there isn't a
745 // good way to do that in the current design.
746 IN_PROC_BROWSER_TEST_P(SafeBrowsingBlockingPageBrowserTest
, ReportingDisabled
) {
747 #if defined(OS_WIN) && defined(USE_ASH)
748 // Disable this test in Metro+Ash for now (http://crbug.com/262796).
749 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
750 switches::kAshBrowserTests
))
754 browser()->profile()->GetPrefs()->SetBoolean(
755 prefs::kSafeBrowsingExtendedReportingEnabled
, true);
757 net::SpawnedTestServer
https_server(
758 net::SpawnedTestServer::TYPE_HTTPS
, net::SpawnedTestServer::kLocalhost
,
759 base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
760 ASSERT_TRUE(https_server
.Start());
761 GURL url
= https_server
.GetURL(kEmptyPage
);
762 SetURLThreatType(url
, GetParam());
763 ui_test_utils::NavigateToURL(browser(), url
);
764 ASSERT_TRUE(WaitForReady());
766 EXPECT_EQ(HIDDEN
, GetVisibility("malware-opt-in"));
767 EXPECT_EQ(HIDDEN
, GetVisibility("opt-in-checkbox"));
768 EXPECT_EQ(HIDDEN
, GetVisibility("proceed-link"));
769 EXPECT_TRUE(Click("details-button"));
770 EXPECT_EQ(VISIBLE
, GetVisibility("help-link"));
771 EXPECT_EQ(VISIBLE
, GetVisibility("proceed-link"));
773 EXPECT_TRUE(ClickAndWaitForDetach("primary-button"));
774 AssertNoInterstitial(false); // Assert the interstitial is gone
775 EXPECT_EQ(GURL(url::kAboutBlankURL
), // Back to "about:blank"
776 browser()->tab_strip_model()->GetActiveWebContents()->GetURL());
779 IN_PROC_BROWSER_TEST_P(SafeBrowsingBlockingPageBrowserTest
, LearnMore
) {
780 SetupWarningAndNavigate();
781 EXPECT_TRUE(ClickAndWaitForDetach("help-link"));
782 AssertNoInterstitial(false); // Assert the interstitial is gone
784 // We are in the help page.
786 GetParam() == SB_THREAT_TYPE_URL_PHISHING
787 ? "/transparencyreport/safebrowsing/"
788 : "/safebrowsing/diagnostic",
789 browser()->tab_strip_model()->GetActiveWebContents()->GetURL().path());
792 INSTANTIATE_TEST_CASE_P(SafeBrowsingBlockingPageBrowserTestWithThreatType
,
793 SafeBrowsingBlockingPageBrowserTest
,
794 testing::Values(SB_THREAT_TYPE_URL_MALWARE
,
795 SB_THREAT_TYPE_URL_PHISHING
,
796 SB_THREAT_TYPE_URL_UNWANTED
));