1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 // 5 // This test creates a fake safebrowsing service, where we can inject 6 // malware and phishing urls. It then uses a real browser to go to 7 // these urls, and sends "goback" or "proceed" commands and verifies 8 // they work. 9 10 #include "base/bind.h" 11 #include "base/command_line.h" 12 #include "base/prefs/pref_service.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/profiles/profile.h" 17 #include "chrome/browser/safe_browsing/database_manager.h" 18 #include "chrome/browser/safe_browsing/malware_details.h" 19 #include "chrome/browser/safe_browsing/safe_browsing_blocking_page.h" 20 #include "chrome/browser/safe_browsing/safe_browsing_service.h" 21 #include "chrome/browser/safe_browsing/safe_browsing_util.h" 22 #include "chrome/browser/safe_browsing/ui_manager.h" 23 #include "chrome/browser/ui/browser.h" 24 #include "chrome/browser/ui/browser_tabstrip.h" 25 #include "chrome/browser/ui/tabs/tab_strip_model.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/test_browser_thread.h" 38 #include "content/public/test/test_utils.h" 39 40 using content::BrowserThread; 41 using content::InterstitialPage; 42 using content::NavigationController; 43 using content::WebContents; 44 45 namespace { 46 47 const char kEmptyPage[] = "files/empty.html"; 48 const char kMalwarePage[] = "files/safe_browsing/malware.html"; 49 const char kMalwareIframe[] = "files/safe_browsing/malware_iframe.html"; 50 51 class InterstitialObserver : public content::WebContentsObserver { 52 public: 53 InterstitialObserver(content::WebContents* web_contents, 54 const base::Closure& attach_callback, 55 const base::Closure& detach_callback) 56 : WebContentsObserver(web_contents), 57 attach_callback_(attach_callback), 58 detach_callback_(detach_callback) { 59 } 60 61 virtual void DidAttachInterstitialPage() OVERRIDE { 62 attach_callback_.Run(); 63 } 64 65 virtual void DidDetachInterstitialPage() OVERRIDE { 66 detach_callback_.Run(); 67 } 68 69 private: 70 base::Closure attach_callback_; 71 base::Closure detach_callback_; 72 73 DISALLOW_COPY_AND_ASSIGN(InterstitialObserver); 74 }; 75 76 // A SafeBrowsingDatabaseManager class that allows us to inject the malicious 77 // URLs. 78 class FakeSafeBrowsingDatabaseManager : public SafeBrowsingDatabaseManager { 79 public: 80 explicit FakeSafeBrowsingDatabaseManager(SafeBrowsingService* service) 81 : SafeBrowsingDatabaseManager(service) { } 82 83 // Called on the IO thread to check if the given url is safe or not. If we 84 // can synchronously determine that the url is safe, CheckUrl returns true. 85 // Otherwise it returns false, and "client" is called asynchronously with the 86 // result when it is ready. 87 // Overrides SafeBrowsingDatabaseManager::CheckBrowseUrl. 88 virtual bool CheckBrowseUrl(const GURL& gurl, Client* client) OVERRIDE { 89 if (badurls[gurl.spec()] == SB_THREAT_TYPE_SAFE) 90 return true; 91 92 BrowserThread::PostTask( 93 BrowserThread::IO, FROM_HERE, 94 base::Bind(&FakeSafeBrowsingDatabaseManager::OnCheckBrowseURLDone, 95 this, gurl, client)); 96 return false; 97 } 98 99 void OnCheckBrowseURLDone(const GURL& gurl, Client* client) { 100 std::vector<SBThreatType> expected_threats; 101 expected_threats.push_back(SB_THREAT_TYPE_URL_MALWARE); 102 expected_threats.push_back(SB_THREAT_TYPE_URL_PHISHING); 103 SafeBrowsingDatabaseManager::SafeBrowsingCheck sb_check( 104 std::vector<GURL>(1, gurl), 105 std::vector<SBFullHash>(), 106 client, 107 safe_browsing_util::MALWARE, 108 expected_threats); 109 sb_check.url_results[0] = badurls[gurl.spec()]; 110 client->OnSafeBrowsingResult(sb_check); 111 } 112 113 void SetURLThreatType(const GURL& url, SBThreatType threat_type) { 114 badurls[url.spec()] = threat_type; 115 } 116 117 private: 118 virtual ~FakeSafeBrowsingDatabaseManager() {} 119 120 base::hash_map<std::string, SBThreatType> badurls; 121 DISALLOW_COPY_AND_ASSIGN(FakeSafeBrowsingDatabaseManager); 122 }; 123 124 // A SafeBrowingUIManager class that allows intercepting malware details. 125 class FakeSafeBrowsingUIManager : public SafeBrowsingUIManager { 126 public: 127 explicit FakeSafeBrowsingUIManager(SafeBrowsingService* service) : 128 SafeBrowsingUIManager(service) { } 129 130 // Overrides SafeBrowsingUIManager 131 virtual void SendSerializedMalwareDetails( 132 const std::string& serialized) OVERRIDE { 133 // Notify the UI thread that we got a report. 134 BrowserThread::PostTask( 135 BrowserThread::UI, 136 FROM_HERE, 137 base::Bind(&FakeSafeBrowsingUIManager::OnMalwareDetailsDone, 138 this, 139 serialized)); 140 } 141 142 void OnMalwareDetailsDone(const std::string& serialized) { 143 EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI)); 144 report_ = serialized; 145 146 EXPECT_FALSE(malware_details_done_callback_.is_null()); 147 if (!malware_details_done_callback_.is_null()) { 148 malware_details_done_callback_.Run(); 149 malware_details_done_callback_ = base::Closure(); 150 } 151 } 152 153 void set_malware_details_done_callback(const base::Closure& callback) { 154 EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI)); 155 EXPECT_TRUE(malware_details_done_callback_.is_null()); 156 malware_details_done_callback_ = callback; 157 } 158 159 std::string GetReport() { 160 EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI)); 161 return report_; 162 } 163 164 protected: 165 virtual ~FakeSafeBrowsingUIManager() { } 166 167 private: 168 std::string report_; 169 base::Closure malware_details_done_callback_; 170 171 DISALLOW_COPY_AND_ASSIGN(FakeSafeBrowsingUIManager); 172 }; 173 174 class FakeSafeBrowsingService : public SafeBrowsingService { 175 public: 176 FakeSafeBrowsingService() 177 : fake_database_manager_(), 178 fake_ui_manager_() { } 179 180 // Returned pointer has the same lifespan as the database_manager_ refcounted 181 // object. 182 FakeSafeBrowsingDatabaseManager* fake_database_manager() { 183 return fake_database_manager_; 184 } 185 // Returned pointer has the same lifespan as the ui_manager_ refcounted 186 // object. 187 FakeSafeBrowsingUIManager* fake_ui_manager() { 188 return fake_ui_manager_; 189 } 190 191 protected: 192 virtual ~FakeSafeBrowsingService() { } 193 194 virtual SafeBrowsingDatabaseManager* CreateDatabaseManager() OVERRIDE { 195 fake_database_manager_ = new FakeSafeBrowsingDatabaseManager(this); 196 return fake_database_manager_; 197 } 198 199 virtual SafeBrowsingUIManager* CreateUIManager() OVERRIDE { 200 fake_ui_manager_ = new FakeSafeBrowsingUIManager(this); 201 return fake_ui_manager_; 202 } 203 204 private: 205 FakeSafeBrowsingDatabaseManager* fake_database_manager_; 206 FakeSafeBrowsingUIManager* fake_ui_manager_; 207 208 DISALLOW_COPY_AND_ASSIGN(FakeSafeBrowsingService); 209 }; 210 211 // Factory that creates FakeSafeBrowsingService instances. 212 class TestSafeBrowsingServiceFactory : public SafeBrowsingServiceFactory { 213 public: 214 TestSafeBrowsingServiceFactory() : 215 most_recent_service_(NULL) { } 216 virtual ~TestSafeBrowsingServiceFactory() { } 217 218 virtual SafeBrowsingService* CreateSafeBrowsingService() OVERRIDE { 219 most_recent_service_ = new FakeSafeBrowsingService(); 220 return most_recent_service_; 221 } 222 223 FakeSafeBrowsingService* most_recent_service() const { 224 return most_recent_service_; 225 } 226 227 private: 228 FakeSafeBrowsingService* most_recent_service_; 229 }; 230 231 // A MalwareDetails class lets us intercept calls from the renderer. 232 class FakeMalwareDetails : public MalwareDetails { 233 public: 234 FakeMalwareDetails( 235 SafeBrowsingUIManager* delegate, 236 WebContents* web_contents, 237 const SafeBrowsingUIManager::UnsafeResource& unsafe_resource) 238 : MalwareDetails(delegate, web_contents, unsafe_resource), 239 got_dom_(false), 240 waiting_(false) { } 241 242 virtual void AddDOMDetails( 243 const std::vector<SafeBrowsingHostMsg_MalwareDOMDetails_Node>& params) 244 OVERRIDE { 245 EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO)); 246 MalwareDetails::AddDOMDetails(params); 247 248 // Notify the UI thread that we got the dom details. 249 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, 250 base::Bind(&FakeMalwareDetails::OnDOMDetailsDone, 251 this)); 252 } 253 254 void WaitForDOM() { 255 if (got_dom_) { 256 return; 257 } 258 // This condition might not trigger normally, but if you add a 259 // sleep(1) in malware_dom_details it triggers :). 260 waiting_ = true; 261 content::RunMessageLoop(); 262 EXPECT_TRUE(got_dom_); 263 } 264 265 private: 266 virtual ~FakeMalwareDetails() {} 267 268 void OnDOMDetailsDone() { 269 got_dom_ = true; 270 if (waiting_) { 271 base::MessageLoopForUI::current()->Quit(); 272 } 273 } 274 275 // Some logic to figure out if we should wait for the dom details or not. 276 // These variables should only be accessed in the UI thread. 277 bool got_dom_; 278 bool waiting_; 279 }; 280 281 class TestMalwareDetailsFactory : public MalwareDetailsFactory { 282 public: 283 TestMalwareDetailsFactory() : details_() { } 284 virtual ~TestMalwareDetailsFactory() { } 285 286 virtual MalwareDetails* CreateMalwareDetails( 287 SafeBrowsingUIManager* delegate, 288 WebContents* web_contents, 289 const SafeBrowsingUIManager::UnsafeResource& unsafe_resource) OVERRIDE { 290 details_ = new FakeMalwareDetails(delegate, web_contents, 291 unsafe_resource); 292 return details_; 293 } 294 295 FakeMalwareDetails* get_details() { 296 return details_; 297 } 298 299 private: 300 FakeMalwareDetails* details_; 301 }; 302 303 // A SafeBrowingBlockingPage class that lets us wait until it's hidden. 304 class TestSafeBrowsingBlockingPage : public SafeBrowsingBlockingPage { 305 public: 306 TestSafeBrowsingBlockingPage(SafeBrowsingUIManager* manager, 307 WebContents* web_contents, 308 const UnsafeResourceList& unsafe_resources) 309 : SafeBrowsingBlockingPage(manager, web_contents, unsafe_resources), 310 wait_for_delete_(false) { 311 // Don't wait the whole 3 seconds for the browser test. 312 malware_details_proceed_delay_ms_ = 100; 313 } 314 315 virtual ~TestSafeBrowsingBlockingPage() { 316 if (!wait_for_delete_) 317 return; 318 319 // Notify that we are gone 320 base::MessageLoopForUI::current()->Quit(); 321 wait_for_delete_ = false; 322 } 323 324 void WaitForDelete() { 325 wait_for_delete_ = true; 326 content::RunMessageLoop(); 327 } 328 329 // InterstitialPageDelegate methods: 330 virtual void CommandReceived(const std::string& command) OVERRIDE { 331 SafeBrowsingBlockingPage::CommandReceived(command); 332 } 333 virtual void OnProceed() OVERRIDE { 334 SafeBrowsingBlockingPage::OnProceed(); 335 } 336 virtual void OnDontProceed() OVERRIDE { 337 SafeBrowsingBlockingPage::OnDontProceed(); 338 } 339 340 private: 341 bool wait_for_delete_; 342 }; 343 344 class TestSafeBrowsingBlockingPageFactory 345 : public SafeBrowsingBlockingPageFactory { 346 public: 347 TestSafeBrowsingBlockingPageFactory() { } 348 virtual ~TestSafeBrowsingBlockingPageFactory() { } 349 350 virtual SafeBrowsingBlockingPage* CreateSafeBrowsingPage( 351 SafeBrowsingUIManager* delegate, 352 WebContents* web_contents, 353 const SafeBrowsingBlockingPage::UnsafeResourceList& unsafe_resources) 354 OVERRIDE { 355 return new TestSafeBrowsingBlockingPage(delegate, web_contents, 356 unsafe_resources); 357 } 358 }; 359 360 } // namespace 361 362 // Tests the safe browsing blocking page in a browser. 363 class SafeBrowsingBlockingPageBrowserTest 364 : public InProcessBrowserTest, 365 public testing::WithParamInterface<int> { 366 public: 367 enum Visibility { 368 VISIBILITY_ERROR = -1, 369 HIDDEN = 0, 370 VISIBLE = 1 371 }; 372 373 SafeBrowsingBlockingPageBrowserTest() { 374 } 375 376 virtual void SetUp() OVERRIDE { 377 SafeBrowsingService::RegisterFactory(&factory_); 378 SafeBrowsingBlockingPage::RegisterFactory(&blocking_page_factory_); 379 MalwareDetails::RegisterFactory(&details_factory_); 380 InProcessBrowserTest::SetUp(); 381 } 382 383 virtual void TearDown() OVERRIDE { 384 InProcessBrowserTest::TearDown(); 385 SafeBrowsingBlockingPage::RegisterFactory(NULL); 386 SafeBrowsingService::RegisterFactory(NULL); 387 MalwareDetails::RegisterFactory(NULL); 388 } 389 390 virtual void SetUpInProcessBrowserTestFixture() OVERRIDE { 391 ASSERT_TRUE(test_server()->Start()); 392 } 393 394 void SetURLThreatType(const GURL& url, SBThreatType threat_type) { 395 FakeSafeBrowsingService* service = 396 static_cast<FakeSafeBrowsingService*>( 397 g_browser_process->safe_browsing_service()); 398 399 ASSERT_TRUE(service); 400 service->fake_database_manager()->SetURLThreatType(url, threat_type); 401 } 402 403 // Adds a safebrowsing result of type |threat_type| to the fake safebrowsing 404 // service, navigates to that page, and returns the url. 405 GURL SetupWarningAndNavigate(SBThreatType threat_type) { 406 GURL url = test_server()->GetURL(kEmptyPage); 407 SetURLThreatType(url, threat_type); 408 409 ui_test_utils::NavigateToURL(browser(), url); 410 EXPECT_TRUE(WaitForReady()); 411 return url; 412 } 413 414 // Adds a safebrowsing malware result to the fake safebrowsing service, 415 // navigates to a page with an iframe containing the malware site, and 416 // returns the url of the parent page. 417 GURL SetupMalwareIframeWarningAndNavigate() { 418 GURL url = test_server()->GetURL(kMalwarePage); 419 GURL iframe_url = test_server()->GetURL(kMalwareIframe); 420 SetURLThreatType(iframe_url, SB_THREAT_TYPE_URL_MALWARE); 421 422 ui_test_utils::NavigateToURL(browser(), url); 423 EXPECT_TRUE(WaitForReady()); 424 return url; 425 } 426 427 void SendCommand(const std::string& command) { 428 WebContents* contents = 429 browser()->tab_strip_model()->GetActiveWebContents(); 430 // We use InterstitialPage::GetInterstitialPage(tab) instead of 431 // tab->GetInterstitialPage() because the tab doesn't have a pointer 432 // to its interstital page until it gets a command from the renderer 433 // that it has indeed displayed it -- and this sometimes happens after 434 // NavigateToURL returns. 435 SafeBrowsingBlockingPage* interstitial_page = 436 static_cast<SafeBrowsingBlockingPage*>( 437 InterstitialPage::GetInterstitialPage(contents)-> 438 GetDelegateForTesting()); 439 ASSERT_TRUE(interstitial_page); 440 interstitial_page->CommandReceived(command); 441 } 442 443 void DontProceedThroughInterstitial() { 444 WebContents* contents = 445 browser()->tab_strip_model()->GetActiveWebContents(); 446 InterstitialPage* interstitial_page = InterstitialPage::GetInterstitialPage( 447 contents); 448 ASSERT_TRUE(interstitial_page); 449 interstitial_page->DontProceed(); 450 } 451 452 void ProceedThroughInterstitial() { 453 WebContents* contents = 454 browser()->tab_strip_model()->GetActiveWebContents(); 455 InterstitialPage* interstitial_page = InterstitialPage::GetInterstitialPage( 456 contents); 457 ASSERT_TRUE(interstitial_page); 458 interstitial_page->Proceed(); 459 } 460 461 void AssertNoInterstitial(bool wait_for_delete) { 462 WebContents* contents = 463 browser()->tab_strip_model()->GetActiveWebContents(); 464 465 if (contents->ShowingInterstitialPage() && wait_for_delete) { 466 // We'll get notified when the interstitial is deleted. 467 TestSafeBrowsingBlockingPage* page = 468 static_cast<TestSafeBrowsingBlockingPage*>( 469 contents->GetInterstitialPage()->GetDelegateForTesting()); 470 page->WaitForDelete(); 471 } 472 473 // Can't use InterstitialPage::GetInterstitialPage() because that 474 // gets updated after the TestSafeBrowsingBlockingPage destructor 475 ASSERT_FALSE(contents->ShowingInterstitialPage()); 476 } 477 478 bool YesInterstitial() { 479 WebContents* contents = 480 browser()->tab_strip_model()->GetActiveWebContents(); 481 InterstitialPage* interstitial_page = InterstitialPage::GetInterstitialPage( 482 contents); 483 return interstitial_page != NULL; 484 } 485 486 void WaitForInterstitial() { 487 WebContents* contents = 488 browser()->tab_strip_model()->GetActiveWebContents(); 489 scoped_refptr<content::MessageLoopRunner> loop_runner( 490 new content::MessageLoopRunner); 491 InterstitialObserver observer(contents, 492 loop_runner->QuitClosure(), 493 base::Closure()); 494 if (!InterstitialPage::GetInterstitialPage(contents)) 495 loop_runner->Run(); 496 } 497 498 void SetReportSentCallback(const base::Closure& callback) { 499 factory_.most_recent_service() 500 ->fake_ui_manager() 501 ->set_malware_details_done_callback(callback); 502 } 503 504 std::string GetReportSent() { 505 return factory_.most_recent_service()->fake_ui_manager()->GetReport(); 506 } 507 508 void MalwareRedirectCancelAndProceed(const std::string& open_function) { 509 GURL load_url = test_server()->GetURL( 510 "files/safe_browsing/interstitial_cancel.html"); 511 GURL malware_url("http://localhost/files/safe_browsing/malware.html"); 512 SetURLThreatType(malware_url, SB_THREAT_TYPE_URL_MALWARE); 513 514 // Load the test page. 515 ui_test_utils::NavigateToURL(browser(), load_url); 516 // Trigger the safe browsing interstitial page via a redirect in 517 // "openWin()". 518 ui_test_utils::NavigateToURLWithDisposition( 519 browser(), 520 GURL("javascript:" + open_function + "()"), 521 CURRENT_TAB, 522 ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB); 523 WaitForInterstitial(); 524 // Cancel the redirect request while interstitial page is open. 525 browser()->tab_strip_model()->ActivateTabAt(0, true); 526 ui_test_utils::NavigateToURLWithDisposition( 527 browser(), 528 GURL("javascript:stopWin()"), 529 CURRENT_TAB, 530 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); 531 browser()->tab_strip_model()->ActivateTabAt(1, true); 532 // Simulate the user clicking "proceed", there should be no crash. Since 533 // clicking proceed may do nothing (see comment in MalwareRedirectCanceled 534 // below, and crbug.com/76460), we use SendCommand to trigger the callback 535 // directly rather than using ClickAndWaitForDetach since there might not 536 // be a notification to wait for. 537 SendCommand("\"proceed\""); 538 } 539 540 content::RenderViewHost* GetRenderViewHost() { 541 InterstitialPage* interstitial = InterstitialPage::GetInterstitialPage( 542 browser()->tab_strip_model()->GetActiveWebContents()); 543 if (!interstitial) 544 return NULL; 545 return interstitial->GetRenderViewHostForTesting(); 546 } 547 548 bool WaitForReady() { 549 content::RenderViewHost* rvh = GetRenderViewHost(); 550 if (!rvh) 551 return false; 552 // Wait until all <script> tags have executed, including jstemplate. 553 // TODO(joaodasilva): it would be nice to avoid the busy loop, though in 554 // practice it spins at most once or twice. 555 std::string ready_state; 556 do { 557 scoped_ptr<base::Value> value = content::ExecuteScriptAndGetValue( 558 rvh->GetMainFrame(), "document.readyState"); 559 if (!value.get() || !value->GetAsString(&ready_state)) 560 return false; 561 } while (ready_state != "complete"); 562 return true; 563 } 564 565 Visibility GetVisibility(const std::string& node_id) { 566 content::RenderViewHost* rvh = GetRenderViewHost(); 567 if (!rvh) 568 return VISIBILITY_ERROR; 569 scoped_ptr<base::Value> value = content::ExecuteScriptAndGetValue( 570 rvh->GetMainFrame(), 571 "var node = document.getElementById('" + node_id + "');\n" 572 "if (node)\n" 573 " node.offsetWidth > 0 && node.offsetHeight > 0;" 574 "else\n" 575 " 'node not found';\n"); 576 if (!value.get()) 577 return VISIBILITY_ERROR; 578 bool result = false; 579 if (!value->GetAsBoolean(&result)) 580 return VISIBILITY_ERROR; 581 return result ? VISIBLE : HIDDEN; 582 } 583 584 bool Click(const std::string& node_id) { 585 content::RenderViewHost* rvh = GetRenderViewHost(); 586 if (!rvh) 587 return false; 588 // We don't use ExecuteScriptAndGetValue for this one, since clicking 589 // the button/link may navigate away before the injected javascript can 590 // reply, hanging the test. 591 rvh->GetMainFrame()->ExecuteJavaScript( 592 base::ASCIIToUTF16( 593 "document.getElementById('" + node_id + "').click();\n")); 594 return true; 595 } 596 597 bool ClickAndWaitForDetach(const std::string& node_id) { 598 // We wait for interstitial_detached rather than nav_entry_committed, as 599 // going back from a main-frame malware interstitial page will not cause a 600 // nav entry committed event. 601 scoped_refptr<content::MessageLoopRunner> loop_runner( 602 new content::MessageLoopRunner); 603 InterstitialObserver observer( 604 browser()->tab_strip_model()->GetActiveWebContents(), 605 base::Closure(), 606 loop_runner->QuitClosure()); 607 if (!Click(node_id)) 608 return false; 609 loop_runner->Run(); 610 return true; 611 } 612 613 protected: 614 TestMalwareDetailsFactory details_factory_; 615 616 private: 617 TestSafeBrowsingServiceFactory factory_; 618 TestSafeBrowsingBlockingPageFactory blocking_page_factory_; 619 620 DISALLOW_COPY_AND_ASSIGN(SafeBrowsingBlockingPageBrowserTest); 621 }; 622 623 // TODO(linux_aura) http://crbug.com/163931 624 // TODO(win_aura) http://crbug.com/154081 625 #if defined(USE_AURA) && !defined(OS_CHROMEOS) 626 #define MAYBE_MalwareRedirectInIFrameCanceled DISABLED_MalwareRedirectInIFrameCanceled 627 #else 628 #define MAYBE_MalwareRedirectInIFrameCanceled MalwareRedirectInIFrameCanceled 629 #endif 630 IN_PROC_BROWSER_TEST_F(SafeBrowsingBlockingPageBrowserTest, 631 MAYBE_MalwareRedirectInIFrameCanceled) { 632 // 1. Test the case that redirect is a subresource. 633 MalwareRedirectCancelAndProceed("openWinIFrame"); 634 // If the redirect was from subresource but canceled, "proceed" will continue 635 // with the rest of resources. 636 AssertNoInterstitial(true); 637 } 638 639 IN_PROC_BROWSER_TEST_F(SafeBrowsingBlockingPageBrowserTest, 640 MalwareRedirectCanceled) { 641 // 2. Test the case that redirect is the only resource. 642 MalwareRedirectCancelAndProceed("openWin"); 643 // Clicking proceed won't do anything if the main request is cancelled 644 // already. See crbug.com/76460. 645 EXPECT_TRUE(YesInterstitial()); 646 } 647 648 IN_PROC_BROWSER_TEST_F(SafeBrowsingBlockingPageBrowserTest, 649 MalwareDontProceed) { 650 #if defined(OS_WIN) && defined(USE_ASH) 651 // Disable this test in Metro+Ash for now (http://crbug.com/262796). 652 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests)) 653 return; 654 #endif 655 656 SetupWarningAndNavigate(SB_THREAT_TYPE_URL_MALWARE); 657 658 EXPECT_EQ(VISIBLE, GetVisibility("primary-button")); 659 EXPECT_EQ(HIDDEN, GetVisibility("details")); 660 EXPECT_EQ(HIDDEN, GetVisibility("proceed-link")); 661 EXPECT_EQ(HIDDEN, GetVisibility("error-code")); 662 EXPECT_TRUE(Click("details-button")); 663 EXPECT_EQ(VISIBLE, GetVisibility("details")); 664 EXPECT_EQ(VISIBLE, GetVisibility("proceed-link")); 665 EXPECT_EQ(HIDDEN, GetVisibility("error-code")); 666 EXPECT_TRUE(ClickAndWaitForDetach("primary-button")); 667 668 AssertNoInterstitial(false); // Assert the interstitial is gone 669 EXPECT_EQ(GURL(url::kAboutBlankURL), // Back to "about:blank" 670 browser()->tab_strip_model()->GetActiveWebContents()->GetURL()); 671 } 672 673 IN_PROC_BROWSER_TEST_F(SafeBrowsingBlockingPageBrowserTest, 674 HarmfulDontProceed) { 675 #if defined(OS_WIN) && defined(USE_ASH) 676 // Disable this test in Metro+Ash for now (http://crbug.com/262796). 677 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests)) 678 return; 679 #endif 680 681 SetupWarningAndNavigate(SB_THREAT_TYPE_URL_HARMFUL); 682 683 EXPECT_EQ(VISIBLE, GetVisibility("primary-button")); 684 EXPECT_EQ(HIDDEN, GetVisibility("details")); 685 EXPECT_EQ(HIDDEN, GetVisibility("proceed-link")); 686 EXPECT_EQ(HIDDEN, GetVisibility("error-code")); 687 EXPECT_TRUE(Click("details-button")); 688 EXPECT_EQ(VISIBLE, GetVisibility("details")); 689 EXPECT_EQ(VISIBLE, GetVisibility("proceed-link")); 690 EXPECT_EQ(HIDDEN, GetVisibility("error-code")); 691 EXPECT_TRUE(ClickAndWaitForDetach("primary-button")); 692 693 AssertNoInterstitial(false); // Assert the interstitial is gone 694 EXPECT_EQ(GURL(url::kAboutBlankURL), // Back to "about:blank" 695 browser()->tab_strip_model()->GetActiveWebContents()->GetURL()); 696 } 697 698 IN_PROC_BROWSER_TEST_F(SafeBrowsingBlockingPageBrowserTest, MalwareProceed) { 699 GURL url = SetupWarningAndNavigate(SB_THREAT_TYPE_URL_MALWARE); 700 701 EXPECT_TRUE(ClickAndWaitForDetach("proceed-link")); 702 AssertNoInterstitial(true); // Assert the interstitial is gone. 703 EXPECT_EQ(url, 704 browser()->tab_strip_model()->GetActiveWebContents()->GetURL()); 705 } 706 707 IN_PROC_BROWSER_TEST_F(SafeBrowsingBlockingPageBrowserTest, HarmfulProceed) { 708 GURL url = SetupWarningAndNavigate(SB_THREAT_TYPE_URL_HARMFUL); 709 710 EXPECT_TRUE(ClickAndWaitForDetach("proceed-link")); 711 AssertNoInterstitial(true); // Assert the interstitial is gone. 712 EXPECT_EQ(url, 713 browser()->tab_strip_model()->GetActiveWebContents()->GetURL()); 714 } 715 716 IN_PROC_BROWSER_TEST_F(SafeBrowsingBlockingPageBrowserTest, 717 MalwareIframeDontProceed) { 718 #if defined(OS_WIN) && defined(USE_ASH) 719 // Disable this test in Metro+Ash for now (http://crbug.com/262796). 720 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests)) 721 return; 722 #endif 723 724 SetupMalwareIframeWarningAndNavigate(); 725 726 EXPECT_EQ(VISIBLE, GetVisibility("primary-button")); 727 EXPECT_EQ(HIDDEN, GetVisibility("details")); 728 EXPECT_EQ(HIDDEN, GetVisibility("proceed-link")); 729 EXPECT_EQ(HIDDEN, GetVisibility("error-code")); 730 EXPECT_TRUE(Click("details-button")); 731 EXPECT_EQ(VISIBLE, GetVisibility("details")); 732 EXPECT_EQ(VISIBLE, GetVisibility("proceed-link")); 733 EXPECT_EQ(HIDDEN, GetVisibility("error-code")); 734 EXPECT_TRUE(ClickAndWaitForDetach("primary-button")); 735 736 AssertNoInterstitial(false); // Assert the interstitial is gone 737 738 EXPECT_EQ(GURL(url::kAboutBlankURL), // Back to "about:blank" 739 browser()->tab_strip_model()->GetActiveWebContents()->GetURL()); 740 } 741 742 IN_PROC_BROWSER_TEST_F(SafeBrowsingBlockingPageBrowserTest, 743 MalwareIframeProceed) { 744 GURL url = SetupMalwareIframeWarningAndNavigate(); 745 746 EXPECT_TRUE(ClickAndWaitForDetach("proceed-link")); 747 AssertNoInterstitial(true); // Assert the interstitial is gone 748 749 EXPECT_EQ(url, 750 browser()->tab_strip_model()->GetActiveWebContents()->GetURL()); 751 } 752 753 IN_PROC_BROWSER_TEST_F(SafeBrowsingBlockingPageBrowserTest, 754 MalwareIframeReportDetails) { 755 scoped_refptr<content::MessageLoopRunner> malware_report_sent_runner( 756 new content::MessageLoopRunner); 757 SetReportSentCallback(malware_report_sent_runner->QuitClosure()); 758 759 GURL url = SetupMalwareIframeWarningAndNavigate(); 760 761 // If the DOM details from renderer did not already return, wait for them. 762 details_factory_.get_details()->WaitForDOM(); 763 764 EXPECT_TRUE(Click("opt-in-checkbox")); 765 EXPECT_TRUE(ClickAndWaitForDetach("proceed-link")); 766 AssertNoInterstitial(true); // Assert the interstitial is gone 767 768 ASSERT_TRUE(browser()->profile()->GetPrefs()->GetBoolean( 769 prefs::kSafeBrowsingExtendedReportingEnabled)); 770 EXPECT_EQ(url, 771 browser()->tab_strip_model()->GetActiveWebContents()->GetURL()); 772 773 malware_report_sent_runner->Run(); 774 std::string serialized = GetReportSent(); 775 safe_browsing::ClientMalwareReportRequest report; 776 ASSERT_TRUE(report.ParseFromString(serialized)); 777 // Verify the report is complete. 778 EXPECT_TRUE(report.complete()); 779 } 780 781 // Verifies that the "proceed anyway" link isn't available when it is disabled 782 // by the corresponding policy. Also verifies that sending the "proceed" 783 // command anyway doesn't advance to the malware site. 784 IN_PROC_BROWSER_TEST_F(SafeBrowsingBlockingPageBrowserTest, ProceedDisabled) { 785 #if defined(OS_WIN) && defined(USE_ASH) 786 // Disable this test in Metro+Ash for now (http://crbug.com/262796). 787 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests)) 788 return; 789 #endif 790 791 // Simulate a policy disabling the "proceed anyway" link. 792 browser()->profile()->GetPrefs()->SetBoolean( 793 prefs::kSafeBrowsingProceedAnywayDisabled, true); 794 795 SetupWarningAndNavigate(SB_THREAT_TYPE_URL_MALWARE); 796 797 EXPECT_EQ(VISIBLE, GetVisibility("primary-button")); 798 EXPECT_EQ(HIDDEN, GetVisibility("details")); 799 EXPECT_EQ(HIDDEN, GetVisibility("proceed-link")); 800 EXPECT_EQ(HIDDEN, GetVisibility("final-paragraph")); 801 EXPECT_TRUE(Click("details-button")); 802 EXPECT_EQ(HIDDEN, GetVisibility("proceed-link")); 803 EXPECT_EQ(HIDDEN, GetVisibility("final-paragraph")); 804 SendCommand("proceed"); 805 806 // The "proceed" command should go back instead, if proceeding is disabled. 807 AssertNoInterstitial(true); 808 EXPECT_EQ(GURL(url::kAboutBlankURL), // Back to "about:blank" 809 browser()->tab_strip_model()->GetActiveWebContents()->GetURL()); 810 } 811 812 // Verifies that the reporting checkbox is hidden on non-HTTP pages. 813 // TODO(mattm): Should also verify that no report is sent, but there isn't a 814 // good way to do that in the current design. 815 IN_PROC_BROWSER_TEST_F(SafeBrowsingBlockingPageBrowserTest, 816 ReportingDisabled) { 817 #if defined(OS_WIN) && defined(USE_ASH) 818 // Disable this test in Metro+Ash for now (http://crbug.com/262796). 819 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests)) 820 return; 821 #endif 822 823 browser()->profile()->GetPrefs()->SetBoolean( 824 prefs::kSafeBrowsingExtendedReportingEnabled, true); 825 826 net::SpawnedTestServer https_server( 827 net::SpawnedTestServer::TYPE_HTTPS, net::SpawnedTestServer::kLocalhost, 828 base::FilePath(FILE_PATH_LITERAL("chrome/test/data"))); 829 ASSERT_TRUE(https_server.Start()); 830 GURL url = https_server.GetURL(kEmptyPage); 831 SetURLThreatType(url, SB_THREAT_TYPE_URL_MALWARE); 832 ui_test_utils::NavigateToURL(browser(), url); 833 ASSERT_TRUE(WaitForReady()); 834 835 EXPECT_EQ(HIDDEN, GetVisibility("malware-opt-in")); 836 EXPECT_EQ(HIDDEN, GetVisibility("opt-in-checkbox")); 837 EXPECT_EQ(HIDDEN, GetVisibility("proceed-link")); 838 EXPECT_TRUE(Click("details-button")); 839 EXPECT_EQ(VISIBLE, GetVisibility("help-link")); 840 EXPECT_EQ(VISIBLE, GetVisibility("proceed-link")); 841 842 EXPECT_TRUE(ClickAndWaitForDetach("primary-button")); 843 AssertNoInterstitial(false); // Assert the interstitial is gone 844 EXPECT_EQ(GURL(url::kAboutBlankURL), // Back to "about:blank" 845 browser()->tab_strip_model()->GetActiveWebContents()->GetURL()); 846 } 847 848 IN_PROC_BROWSER_TEST_F(SafeBrowsingBlockingPageBrowserTest, 849 PhishingDontProceed) { 850 #if defined(OS_WIN) && defined(USE_ASH) 851 // Disable this test in Metro+Ash for now (http://crbug.com/262796). 852 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests)) 853 return; 854 #endif 855 856 SetupWarningAndNavigate(SB_THREAT_TYPE_URL_PHISHING); 857 858 EXPECT_EQ(VISIBLE, GetVisibility("primary-button")); 859 EXPECT_EQ(HIDDEN, GetVisibility("details")); 860 EXPECT_EQ(HIDDEN, GetVisibility("proceed-link")); 861 EXPECT_EQ(HIDDEN, GetVisibility("error-code")); 862 EXPECT_TRUE(Click("details-button")); 863 EXPECT_EQ(VISIBLE, GetVisibility("details")); 864 EXPECT_EQ(VISIBLE, GetVisibility("proceed-link")); 865 EXPECT_EQ(HIDDEN, GetVisibility("error-code")); 866 EXPECT_TRUE(ClickAndWaitForDetach("primary-button")); 867 868 AssertNoInterstitial(false); // Assert the interstitial is gone 869 EXPECT_EQ(GURL(url::kAboutBlankURL), // We are back to "about:blank". 870 browser()->tab_strip_model()->GetActiveWebContents()->GetURL()); 871 } 872 873 IN_PROC_BROWSER_TEST_F(SafeBrowsingBlockingPageBrowserTest, PhishingProceed) { 874 GURL url = SetupWarningAndNavigate(SB_THREAT_TYPE_URL_PHISHING); 875 EXPECT_TRUE(ClickAndWaitForDetach("proceed-link")); 876 AssertNoInterstitial(true); // Assert the interstitial is gone 877 EXPECT_EQ(url, 878 browser()->tab_strip_model()->GetActiveWebContents()->GetURL()); 879 } 880 881 IN_PROC_BROWSER_TEST_F(SafeBrowsingBlockingPageBrowserTest, PhishingLearnMore) { 882 SetupWarningAndNavigate(SB_THREAT_TYPE_URL_PHISHING); 883 EXPECT_TRUE(ClickAndWaitForDetach("help-link")); 884 AssertNoInterstitial(false); // Assert the interstitial is gone 885 886 // We are in the help page. 887 EXPECT_EQ( 888 "/transparencyreport/safebrowsing/", 889 browser()->tab_strip_model()->GetActiveWebContents()->GetURL().path()); 890 } 891