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