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 #include <list>
      6 
      7 #include "base/prefs/pref_service.h"
      8 #include "base/run_loop.h"
      9 #include "chrome/browser/profiles/profile.h"
     10 #include "chrome/browser/safe_browsing/malware_details.h"
     11 #include "chrome/browser/safe_browsing/safe_browsing_blocking_page.h"
     12 #include "chrome/browser/safe_browsing/safe_browsing_service.h"
     13 #include "chrome/browser/safe_browsing/ui_manager.h"
     14 #include "chrome/common/pref_names.h"
     15 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
     16 #include "content/public/browser/interstitial_page.h"
     17 #include "content/public/browser/navigation_entry.h"
     18 #include "content/public/browser/render_process_host.h"
     19 #include "content/public/browser/web_contents.h"
     20 #include "content/public/test/web_contents_tester.h"
     21 
     22 using content::InterstitialPage;
     23 using content::NavigationEntry;
     24 using content::WebContents;
     25 using content::WebContentsTester;
     26 
     27 static const char* kGoogleURL = "http://www.google.com/";
     28 static const char* kGoodURL = "http://www.goodguys.com/";
     29 static const char* kBadURL = "http://www.badguys.com/";
     30 static const char* kBadURL2 = "http://www.badguys2.com/";
     31 static const char* kBadURL3 = "http://www.badguys3.com/";
     32 
     33 namespace {
     34 
     35 // A SafeBrowingBlockingPage class that does not create windows.
     36 class TestSafeBrowsingBlockingPage : public SafeBrowsingBlockingPage {
     37  public:
     38   TestSafeBrowsingBlockingPage(SafeBrowsingUIManager* manager,
     39                                  WebContents* web_contents,
     40                                  const UnsafeResourceList& unsafe_resources)
     41       : SafeBrowsingBlockingPage(manager, web_contents, unsafe_resources) {
     42     // Don't delay details at all for the unittest.
     43     malware_details_proceed_delay_ms_ = 0;
     44     DontCreateViewForTesting();
     45   }
     46 };
     47 
     48 class TestSafeBrowsingUIManager: public SafeBrowsingUIManager {
     49  public:
     50   explicit TestSafeBrowsingUIManager(SafeBrowsingService* service)
     51       : SafeBrowsingUIManager(service) {
     52   }
     53 
     54   virtual void SendSerializedMalwareDetails(
     55       const std::string& serialized) OVERRIDE {
     56     details_.push_back(serialized);
     57   }
     58 
     59   std::list<std::string>* GetDetails() {
     60     return &details_;
     61   }
     62 
     63  private:
     64   virtual ~TestSafeBrowsingUIManager() {}
     65 
     66   std::list<std::string> details_;
     67 };
     68 
     69 class TestSafeBrowsingBlockingPageFactory
     70     : public SafeBrowsingBlockingPageFactory {
     71  public:
     72   TestSafeBrowsingBlockingPageFactory() { }
     73   virtual ~TestSafeBrowsingBlockingPageFactory() { }
     74 
     75   virtual SafeBrowsingBlockingPage* CreateSafeBrowsingPage(
     76       SafeBrowsingUIManager* manager,
     77       WebContents* web_contents,
     78       const SafeBrowsingBlockingPage::UnsafeResourceList& unsafe_resources)
     79       OVERRIDE {
     80     return new TestSafeBrowsingBlockingPage(manager, web_contents,
     81                                               unsafe_resources);
     82   }
     83 };
     84 
     85 }  // namespace
     86 
     87 class SafeBrowsingBlockingPageTest : public ChromeRenderViewHostTestHarness {
     88  public:
     89   // The decision the user made.
     90   enum UserResponse {
     91     PENDING,
     92     OK,
     93     CANCEL
     94   };
     95 
     96   SafeBrowsingBlockingPageTest() {
     97     ResetUserResponse();
     98     // The safe browsing UI manager does not need a service for this test.
     99     ui_manager_ = new TestSafeBrowsingUIManager(NULL);
    100   }
    101 
    102   virtual void SetUp() OVERRIDE {
    103     ChromeRenderViewHostTestHarness::SetUp();
    104     SafeBrowsingBlockingPage::RegisterFactory(&factory_);
    105     ResetUserResponse();
    106   }
    107 
    108   virtual void TearDown() OVERRIDE {
    109     // Release the UI manager before the BrowserThreads are destroyed.
    110     ui_manager_ = NULL;
    111     SafeBrowsingBlockingPage::RegisterFactory(NULL);
    112     // Clean up singleton reference (crbug.com/110594).
    113     MalwareDetails::RegisterFactory(NULL);
    114     ChromeRenderViewHostTestHarness::TearDown();
    115   }
    116 
    117   void OnBlockingPageComplete(bool proceed) {
    118     if (proceed)
    119       user_response_ = OK;
    120     else
    121       user_response_ = CANCEL;
    122   }
    123 
    124   void Navigate(const char* url, int page_id) {
    125     WebContentsTester::For(web_contents())->TestDidNavigate(
    126         web_contents()->GetMainFrame(), page_id, GURL(url),
    127         ui::PAGE_TRANSITION_TYPED);
    128   }
    129 
    130   void GoBack(bool is_cross_site) {
    131     NavigationEntry* entry =
    132         web_contents()->GetController().GetEntryAtOffset(-1);
    133     ASSERT_TRUE(entry);
    134     web_contents()->GetController().GoBack();
    135 
    136     // The pending RVH should commit for cross-site navigations.
    137     content::RenderFrameHost* rfh = is_cross_site ?
    138         WebContentsTester::For(web_contents())->GetPendingMainFrame() :
    139         web_contents()->GetMainFrame();
    140     WebContentsTester::For(web_contents())->TestDidNavigate(
    141         rfh,
    142         entry->GetPageID(),
    143         GURL(entry->GetURL()),
    144         ui::PAGE_TRANSITION_TYPED);
    145   }
    146 
    147   void ShowInterstitial(bool is_subresource, const char* url) {
    148     SafeBrowsingUIManager::UnsafeResource resource;
    149     InitResource(&resource, is_subresource, GURL(url));
    150     SafeBrowsingBlockingPage::ShowBlockingPage(ui_manager_.get(), resource);
    151   }
    152 
    153   // Returns the SafeBrowsingBlockingPage currently showing or NULL if none is
    154   // showing.
    155   SafeBrowsingBlockingPage* GetSafeBrowsingBlockingPage() {
    156     InterstitialPage* interstitial =
    157         InterstitialPage::GetInterstitialPage(web_contents());
    158     if (!interstitial)
    159       return NULL;
    160     return  static_cast<SafeBrowsingBlockingPage*>(
    161         interstitial->GetDelegateForTesting());
    162   }
    163 
    164   UserResponse user_response() const { return user_response_; }
    165   void ResetUserResponse() { user_response_ = PENDING; }
    166 
    167   static void ProceedThroughInterstitial(
    168       SafeBrowsingBlockingPage* sb_interstitial) {
    169     sb_interstitial->interstitial_page_->Proceed();
    170     // Proceed() posts a task to update the SafeBrowsingService::Client.
    171     base::RunLoop().RunUntilIdle();
    172   }
    173 
    174   static void DontProceedThroughInterstitial(
    175       SafeBrowsingBlockingPage* sb_interstitial) {
    176     sb_interstitial->interstitial_page_->DontProceed();
    177     // DontProceed() posts a task to update the SafeBrowsingService::Client.
    178     base::RunLoop().RunUntilIdle();
    179   }
    180 
    181   void DontProceedThroughSubresourceInterstitial(
    182       SafeBrowsingBlockingPage* sb_interstitial) {
    183     // CommandReceived(kTakeMeBackCommand) does a back navigation for
    184     // subresource interstitials.
    185     GoBack(false);
    186     // DontProceed() posts a task to update the SafeBrowsingService::Client.
    187     base::RunLoop().RunUntilIdle();
    188   }
    189 
    190   scoped_refptr<TestSafeBrowsingUIManager> ui_manager_;
    191 
    192  private:
    193   void InitResource(SafeBrowsingUIManager::UnsafeResource* resource,
    194                     bool is_subresource,
    195                     const GURL& url) {
    196     resource->callback =
    197         base::Bind(&SafeBrowsingBlockingPageTest::OnBlockingPageComplete,
    198                    base::Unretained(this));
    199     resource->url = url;
    200     resource->is_subresource = is_subresource;
    201     resource->threat_type = SB_THREAT_TYPE_URL_MALWARE;
    202     resource->render_process_host_id =
    203         web_contents()->GetRenderProcessHost()->GetID();
    204     resource->render_view_id =
    205         web_contents()->GetRenderViewHost()->GetRoutingID();
    206   }
    207 
    208   UserResponse user_response_;
    209   TestSafeBrowsingBlockingPageFactory factory_;
    210 };
    211 
    212 
    213 // Tests showing a blocking page for a malware page and not proceeding.
    214 TEST_F(SafeBrowsingBlockingPageTest, MalwarePageDontProceed) {
    215   // Enable malware details.
    216   Profile* profile = Profile::FromBrowserContext(
    217       web_contents()->GetBrowserContext());
    218   profile->GetPrefs()->SetBoolean(
    219       prefs::kSafeBrowsingExtendedReportingEnabled, true);
    220 
    221   // Start a load.
    222   controller().LoadURL(GURL(kBadURL), content::Referrer(),
    223                        ui::PAGE_TRANSITION_TYPED, std::string());
    224 
    225 
    226   // Simulate the load causing a safe browsing interstitial to be shown.
    227   ShowInterstitial(false, kBadURL);
    228   SafeBrowsingBlockingPage* sb_interstitial =
    229       GetSafeBrowsingBlockingPage();
    230   ASSERT_TRUE(sb_interstitial);
    231 
    232   base::RunLoop().RunUntilIdle();
    233 
    234   // Simulate the user clicking "don't proceed".
    235   DontProceedThroughInterstitial(sb_interstitial);
    236 
    237   // The interstitial should be gone.
    238   EXPECT_EQ(CANCEL, user_response());
    239   EXPECT_FALSE(GetSafeBrowsingBlockingPage());
    240 
    241   // We did not proceed, the pending entry should be gone.
    242   EXPECT_FALSE(controller().GetPendingEntry());
    243 
    244   // A report should have been sent.
    245   EXPECT_EQ(1u, ui_manager_->GetDetails()->size());
    246   ui_manager_->GetDetails()->clear();
    247 }
    248 
    249 // Tests showing a blocking page for a malware page and then proceeding.
    250 TEST_F(SafeBrowsingBlockingPageTest, MalwarePageProceed) {
    251   // Enable malware reports.
    252   Profile* profile = Profile::FromBrowserContext(
    253       web_contents()->GetBrowserContext());
    254   profile->GetPrefs()->SetBoolean(
    255       prefs::kSafeBrowsingExtendedReportingEnabled, true);
    256 
    257   // Start a load.
    258   controller().LoadURL(GURL(kBadURL), content::Referrer(),
    259                        ui::PAGE_TRANSITION_TYPED, std::string());
    260 
    261   // Simulate the load causing a safe browsing interstitial to be shown.
    262   ShowInterstitial(false, kBadURL);
    263   SafeBrowsingBlockingPage* sb_interstitial =
    264       GetSafeBrowsingBlockingPage();
    265   ASSERT_TRUE(sb_interstitial);
    266 
    267   // Simulate the user clicking "proceed".
    268   ProceedThroughInterstitial(sb_interstitial);
    269 
    270   // The interstitial is shown until the navigation commits.
    271   ASSERT_TRUE(InterstitialPage::GetInterstitialPage(web_contents()));
    272   // Commit the navigation.
    273   Navigate(kBadURL, 1);
    274   // The interstitial should be gone now.
    275   ASSERT_FALSE(InterstitialPage::GetInterstitialPage(web_contents()));
    276 
    277   // A report should have been sent.
    278   EXPECT_EQ(1u, ui_manager_->GetDetails()->size());
    279   ui_manager_->GetDetails()->clear();
    280 }
    281 
    282 // Tests showing a blocking page for a page that contains malware subresources
    283 // and not proceeding.
    284 TEST_F(SafeBrowsingBlockingPageTest, PageWithMalwareResourceDontProceed) {
    285   // Enable malware reports.
    286   Profile* profile = Profile::FromBrowserContext(
    287       web_contents()->GetBrowserContext());
    288   profile->GetPrefs()->SetBoolean(
    289       prefs::kSafeBrowsingExtendedReportingEnabled, true);
    290 
    291   // Navigate somewhere.
    292   Navigate(kGoogleURL, 1);
    293 
    294   // Navigate somewhere else.
    295   Navigate(kGoodURL, 2);
    296 
    297   // Simulate that page loading a bad-resource triggering an interstitial.
    298   ShowInterstitial(true, kBadURL);
    299 
    300   SafeBrowsingBlockingPage* sb_interstitial =
    301       GetSafeBrowsingBlockingPage();
    302   ASSERT_TRUE(sb_interstitial);
    303 
    304   // Simulate the user clicking "don't proceed".
    305   DontProceedThroughSubresourceInterstitial(sb_interstitial);
    306   EXPECT_EQ(CANCEL, user_response());
    307   EXPECT_FALSE(GetSafeBrowsingBlockingPage());
    308 
    309   // We did not proceed, we should be back to the first page, the 2nd one should
    310   // have been removed from the navigation controller.
    311   ASSERT_EQ(1, controller().GetEntryCount());
    312   EXPECT_EQ(kGoogleURL, controller().GetActiveEntry()->GetURL().spec());
    313 
    314   // A report should have been sent.
    315   EXPECT_EQ(1u, ui_manager_->GetDetails()->size());
    316   ui_manager_->GetDetails()->clear();
    317 }
    318 
    319 // Tests showing a blocking page for a page that contains malware subresources
    320 // and proceeding.
    321 TEST_F(SafeBrowsingBlockingPageTest, PageWithMalwareResourceProceed) {
    322   // Enable malware reports.
    323   Profile* profile = Profile::FromBrowserContext(
    324       web_contents()->GetBrowserContext());
    325   profile->GetPrefs()->SetBoolean(
    326       prefs::kSafeBrowsingExtendedReportingEnabled, true);
    327 
    328   // Navigate somewhere.
    329   Navigate(kGoodURL, 1);
    330 
    331   // Simulate that page loading a bad-resource triggering an interstitial.
    332   ShowInterstitial(true, kBadURL);
    333 
    334   SafeBrowsingBlockingPage* sb_interstitial =
    335       GetSafeBrowsingBlockingPage();
    336   ASSERT_TRUE(sb_interstitial);
    337 
    338   // Simulate the user clicking "proceed".
    339   ProceedThroughInterstitial(sb_interstitial);
    340   EXPECT_EQ(OK, user_response());
    341   EXPECT_FALSE(GetSafeBrowsingBlockingPage());
    342 
    343   // We did proceed, we should be back to showing the page.
    344   ASSERT_EQ(1, controller().GetEntryCount());
    345   EXPECT_EQ(kGoodURL, controller().GetActiveEntry()->GetURL().spec());
    346 
    347   // A report should have been sent.
    348   EXPECT_EQ(1u, ui_manager_->GetDetails()->size());
    349   ui_manager_->GetDetails()->clear();
    350 }
    351 
    352 // Tests showing a blocking page for a page that contains multiple malware
    353 // subresources and not proceeding.  This just tests that the extra malware
    354 // subresources (which trigger queued interstitial pages) do not break anything.
    355 TEST_F(SafeBrowsingBlockingPageTest,
    356        PageWithMultipleMalwareResourceDontProceed) {
    357   // Enable malware reports.
    358   Profile* profile = Profile::FromBrowserContext(
    359       web_contents()->GetBrowserContext());
    360   profile->GetPrefs()->SetBoolean(
    361       prefs::kSafeBrowsingExtendedReportingEnabled, true);
    362 
    363   // Navigate somewhere.
    364   Navigate(kGoogleURL, 1);
    365 
    366   // Navigate somewhere else.
    367   Navigate(kGoodURL, 2);
    368 
    369   // Simulate that page loading a bad-resource triggering an interstitial.
    370   ShowInterstitial(true, kBadURL);
    371 
    372   // More bad resources loading causing more interstitials. The new
    373   // interstitials should be queued.
    374   ShowInterstitial(true, kBadURL2);
    375   ShowInterstitial(true, kBadURL3);
    376 
    377   SafeBrowsingBlockingPage* sb_interstitial =
    378       GetSafeBrowsingBlockingPage();
    379   ASSERT_TRUE(sb_interstitial);
    380 
    381   // Simulate the user clicking "don't proceed".
    382   DontProceedThroughSubresourceInterstitial(sb_interstitial);
    383   EXPECT_EQ(CANCEL, user_response());
    384   EXPECT_FALSE(GetSafeBrowsingBlockingPage());
    385 
    386   // We did not proceed, we should be back to the first page, the 2nd one should
    387   // have been removed from the navigation controller.
    388   ASSERT_EQ(1, controller().GetEntryCount());
    389   EXPECT_EQ(kGoogleURL, controller().GetActiveEntry()->GetURL().spec());
    390 
    391   // A report should have been sent.
    392   EXPECT_EQ(1u, ui_manager_->GetDetails()->size());
    393   ui_manager_->GetDetails()->clear();
    394 }
    395 
    396 // Tests showing a blocking page for a page that contains multiple malware
    397 // subresources and proceeding through the first interstitial, but not the next.
    398 TEST_F(SafeBrowsingBlockingPageTest,
    399        PageWithMultipleMalwareResourceProceedThenDontProceed) {
    400   // Enable malware reports.
    401   Profile* profile = Profile::FromBrowserContext(
    402       web_contents()->GetBrowserContext());
    403   profile->GetPrefs()->SetBoolean(
    404       prefs::kSafeBrowsingExtendedReportingEnabled, true);
    405 
    406   // Navigate somewhere.
    407   Navigate(kGoogleURL, 1);
    408 
    409   // Navigate somewhere else.
    410   Navigate(kGoodURL, 2);
    411 
    412   // Simulate that page loading a bad-resource triggering an interstitial.
    413   ShowInterstitial(true, kBadURL);
    414 
    415   // More bad resources loading causing more interstitials. The new
    416   // interstitials should be queued.
    417   ShowInterstitial(true, kBadURL2);
    418   ShowInterstitial(true, kBadURL3);
    419 
    420   SafeBrowsingBlockingPage* sb_interstitial =
    421       GetSafeBrowsingBlockingPage();
    422   ASSERT_TRUE(sb_interstitial);
    423 
    424   // Proceed through the 1st interstitial.
    425   ProceedThroughInterstitial(sb_interstitial);
    426   EXPECT_EQ(OK, user_response());
    427 
    428   // A report should have been sent.
    429   EXPECT_EQ(1u, ui_manager_->GetDetails()->size());
    430   ui_manager_->GetDetails()->clear();
    431 
    432   ResetUserResponse();
    433 
    434   // We should land to a 2nd interstitial (aggregating all the malware resources
    435   // loaded while the 1st interstitial was showing).
    436   sb_interstitial = GetSafeBrowsingBlockingPage();
    437   ASSERT_TRUE(sb_interstitial);
    438 
    439   // Don't proceed through the 2nd interstitial.
    440   DontProceedThroughSubresourceInterstitial(sb_interstitial);
    441   EXPECT_EQ(CANCEL, user_response());
    442   EXPECT_FALSE(GetSafeBrowsingBlockingPage());
    443 
    444   // We did not proceed, we should be back to the first page, the 2nd one should
    445   // have been removed from the navigation controller.
    446   ASSERT_EQ(1, controller().GetEntryCount());
    447   EXPECT_EQ(kGoogleURL, controller().GetActiveEntry()->GetURL().spec());
    448 
    449   // No report should have been sent -- we don't create a report the
    450   // second time.
    451   EXPECT_EQ(0u, ui_manager_->GetDetails()->size());
    452   ui_manager_->GetDetails()->clear();
    453 }
    454 
    455 // Tests showing a blocking page for a page that contains multiple malware
    456 // subresources and proceeding through the multiple interstitials.
    457 TEST_F(SafeBrowsingBlockingPageTest,
    458     PageWithMultipleMalwareResourceProceed) {
    459   // Enable malware reports.
    460   Profile* profile = Profile::FromBrowserContext(
    461       web_contents()->GetBrowserContext());
    462   profile->GetPrefs()->SetBoolean(
    463       prefs::kSafeBrowsingExtendedReportingEnabled, true);
    464 
    465   // Navigate somewhere else.
    466   Navigate(kGoodURL, 1);
    467 
    468   // Simulate that page loading a bad-resource triggering an interstitial.
    469   ShowInterstitial(true, kBadURL);
    470 
    471   // More bad resources loading causing more interstitials. The new
    472   // interstitials should be queued.
    473   ShowInterstitial(true, kBadURL2);
    474   ShowInterstitial(true, kBadURL3);
    475 
    476   SafeBrowsingBlockingPage* sb_interstitial =
    477       GetSafeBrowsingBlockingPage();
    478   ASSERT_TRUE(sb_interstitial);
    479 
    480   // Proceed through the 1st interstitial.
    481   ProceedThroughInterstitial(sb_interstitial);
    482   EXPECT_EQ(OK, user_response());
    483 
    484   // A report should have been sent.
    485   EXPECT_EQ(1u, ui_manager_->GetDetails()->size());
    486   ui_manager_->GetDetails()->clear();
    487 
    488   ResetUserResponse();
    489 
    490   // We should land to a 2nd interstitial (aggregating all the malware resources
    491   // loaded while the 1st interstitial was showing).
    492   sb_interstitial = GetSafeBrowsingBlockingPage();
    493   ASSERT_TRUE(sb_interstitial);
    494 
    495   // Proceed through the 2nd interstitial.
    496   ProceedThroughInterstitial(sb_interstitial);
    497   EXPECT_EQ(OK, user_response());
    498 
    499   // We did proceed, we should be back to the initial page.
    500   ASSERT_EQ(1, controller().GetEntryCount());
    501   EXPECT_EQ(kGoodURL, controller().GetActiveEntry()->GetURL().spec());
    502 
    503   // No report should have been sent -- we don't create a report the
    504   // second time.
    505   EXPECT_EQ(0u, ui_manager_->GetDetails()->size());
    506   ui_manager_->GetDetails()->clear();
    507 }
    508 
    509 // Tests showing a blocking page then navigating back and forth to make sure the
    510 // controller entries are OK.  http://crbug.com/17627
    511 TEST_F(SafeBrowsingBlockingPageTest, NavigatingBackAndForth) {
    512   // Enable malware reports.
    513   Profile* profile = Profile::FromBrowserContext(
    514       web_contents()->GetBrowserContext());
    515   profile->GetPrefs()->SetBoolean(
    516       prefs::kSafeBrowsingExtendedReportingEnabled, true);
    517 
    518   // Navigate somewhere.
    519   Navigate(kGoodURL, 1);
    520 
    521   // Now navigate to a bad page triggerring an interstitial.
    522   controller().LoadURL(GURL(kBadURL), content::Referrer(),
    523                        ui::PAGE_TRANSITION_TYPED, std::string());
    524   ShowInterstitial(false, kBadURL);
    525   SafeBrowsingBlockingPage* sb_interstitial =
    526       GetSafeBrowsingBlockingPage();
    527   ASSERT_TRUE(sb_interstitial);
    528 
    529   // Proceed, then navigate back.
    530   ProceedThroughInterstitial(sb_interstitial);
    531   Navigate(kBadURL, 2);  // Commit the navigation.
    532   GoBack(true);
    533 
    534   // We are back on the good page.
    535   sb_interstitial = GetSafeBrowsingBlockingPage();
    536   ASSERT_FALSE(sb_interstitial);
    537   ASSERT_EQ(2, controller().GetEntryCount());
    538   EXPECT_EQ(kGoodURL, controller().GetActiveEntry()->GetURL().spec());
    539 
    540   // Navigate forward to the malware URL.
    541   web_contents()->GetController().GoForward();
    542   ShowInterstitial(false, kBadURL);
    543   sb_interstitial = GetSafeBrowsingBlockingPage();
    544   ASSERT_TRUE(sb_interstitial);
    545 
    546   // Let's proceed and make sure everything is OK (bug 17627).
    547   ProceedThroughInterstitial(sb_interstitial);
    548   Navigate(kBadURL, 2);  // Commit the navigation.
    549   sb_interstitial = GetSafeBrowsingBlockingPage();
    550   ASSERT_FALSE(sb_interstitial);
    551   ASSERT_EQ(2, controller().GetEntryCount());
    552   EXPECT_EQ(kBadURL, controller().GetActiveEntry()->GetURL().spec());
    553 
    554   // Two reports should have been sent.
    555   EXPECT_EQ(2u, ui_manager_->GetDetails()->size());
    556   ui_manager_->GetDetails()->clear();
    557 }
    558 
    559 // Tests that calling "don't proceed" after "proceed" has been called doesn't
    560 // cause problems. http://crbug.com/30079
    561 TEST_F(SafeBrowsingBlockingPageTest, ProceedThenDontProceed) {
    562   // Enable malware reports.
    563   Profile* profile = Profile::FromBrowserContext(
    564       web_contents()->GetBrowserContext());
    565   profile->GetPrefs()->SetBoolean(
    566       prefs::kSafeBrowsingExtendedReportingEnabled, true);
    567 
    568   // Start a load.
    569   controller().LoadURL(GURL(kBadURL), content::Referrer(),
    570                        ui::PAGE_TRANSITION_TYPED, std::string());
    571 
    572   // Simulate the load causing a safe browsing interstitial to be shown.
    573   ShowInterstitial(false, kBadURL);
    574   SafeBrowsingBlockingPage* sb_interstitial =
    575       GetSafeBrowsingBlockingPage();
    576   ASSERT_TRUE(sb_interstitial);
    577 
    578   base::RunLoop().RunUntilIdle();
    579 
    580   // Simulate the user clicking "proceed" then "don't proceed" (before the
    581   // interstitial is shown).
    582   sb_interstitial->interstitial_page_->Proceed();
    583   sb_interstitial->interstitial_page_->DontProceed();
    584   // Proceed() and DontProceed() post a task to update the
    585   // SafeBrowsingService::Client.
    586   base::RunLoop().RunUntilIdle();
    587 
    588   // The interstitial should be gone.
    589   EXPECT_EQ(OK, user_response());
    590   EXPECT_FALSE(GetSafeBrowsingBlockingPage());
    591 
    592   // Only one report should have been sent.
    593   EXPECT_EQ(1u, ui_manager_->GetDetails()->size());
    594   ui_manager_->GetDetails()->clear();
    595 }
    596 
    597 // Tests showing a blocking page for a malware page with reports disabled.
    598 TEST_F(SafeBrowsingBlockingPageTest, MalwareReportsDisabled) {
    599   // Disable malware reports.
    600   Profile* profile = Profile::FromBrowserContext(
    601       web_contents()->GetBrowserContext());
    602   profile->GetPrefs()->SetBoolean(
    603       prefs::kSafeBrowsingExtendedReportingEnabled, false);
    604 
    605   // Start a load.
    606   controller().LoadURL(GURL(kBadURL), content::Referrer(),
    607                        ui::PAGE_TRANSITION_TYPED, std::string());
    608 
    609   // Simulate the load causing a safe browsing interstitial to be shown.
    610   ShowInterstitial(false, kBadURL);
    611   SafeBrowsingBlockingPage* sb_interstitial =
    612       GetSafeBrowsingBlockingPage();
    613   ASSERT_TRUE(sb_interstitial);
    614 
    615   base::RunLoop().RunUntilIdle();
    616 
    617   // Simulate the user clicking "don't proceed".
    618   DontProceedThroughInterstitial(sb_interstitial);
    619 
    620   // The interstitial should be gone.
    621   EXPECT_EQ(CANCEL, user_response());
    622   EXPECT_FALSE(GetSafeBrowsingBlockingPage());
    623 
    624   // We did not proceed, the pending entry should be gone.
    625   EXPECT_FALSE(controller().GetPendingEntry());
    626 
    627   // No report should have been sent.
    628   EXPECT_EQ(0u, ui_manager_->GetDetails()->size());
    629   ui_manager_->GetDetails()->clear();
    630 }
    631 
    632 // Test that toggling the checkbox has the anticipated effects.
    633 TEST_F(SafeBrowsingBlockingPageTest, MalwareReportsToggling) {
    634   // Disable malware reports.
    635   Profile* profile = Profile::FromBrowserContext(
    636       web_contents()->GetBrowserContext());
    637   profile->GetPrefs()->SetBoolean(
    638       prefs::kSafeBrowsingExtendedReportingEnabled, false);
    639 
    640   // Start a load.
    641   controller().LoadURL(GURL(kBadURL), content::Referrer(),
    642                        ui::PAGE_TRANSITION_TYPED, std::string());
    643 
    644   // Simulate the load causing a safe browsing interstitial to be shown.
    645   ShowInterstitial(false, kBadURL);
    646   SafeBrowsingBlockingPage* sb_interstitial =
    647       GetSafeBrowsingBlockingPage();
    648   ASSERT_TRUE(sb_interstitial);
    649 
    650   base::RunLoop().RunUntilIdle();
    651 
    652   EXPECT_FALSE(profile->GetPrefs()->GetBoolean(
    653       prefs::kSafeBrowsingExtendedReportingEnabled));
    654 
    655   // Simulate the user check the report agreement checkbox.
    656   sb_interstitial->SetReportingPreference(true);
    657 
    658   EXPECT_TRUE(profile->GetPrefs()->GetBoolean(
    659       prefs::kSafeBrowsingExtendedReportingEnabled));
    660 
    661   // Simulate the user uncheck the report agreement checkbox.
    662   sb_interstitial->SetReportingPreference(false);
    663 
    664   EXPECT_FALSE(profile->GetPrefs()->GetBoolean(
    665       prefs::kSafeBrowsingExtendedReportingEnabled));
    666 }
    667