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