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