diff options
Diffstat (limited to 'chrome/browser/safe_browsing')
7 files changed, 327 insertions, 9 deletions
diff --git a/chrome/browser/safe_browsing/bloom_filter.h b/chrome/browser/safe_browsing/bloom_filter.h index fd69c0d..60cb4fc 100644 --- a/chrome/browser/safe_browsing/bloom_filter.h +++ b/chrome/browser/safe_browsing/bloom_filter.h @@ -58,7 +58,7 @@ class BloomFilter : public base::RefCountedThreadSafe<BloomFilter> { // Force a maximum size on the bloom filter to avoid using too much memory // (in bytes). - static const int kBloomFilterMaxSize = 2 * 1024 * 1024; + static const int kBloomFilterMaxSize = 3 * 1024 * 1024; // Use the above constants to calculate an appropriate size to pass // to the BloomFilter constructor based on the intended |key_count|. diff --git a/chrome/browser/safe_browsing/safe_browsing_blocking_page.cc b/chrome/browser/safe_browsing/safe_browsing_blocking_page.cc index d158b11..2601023 100644 --- a/chrome/browser/safe_browsing/safe_browsing_blocking_page.cc +++ b/chrome/browser/safe_browsing/safe_browsing_blocking_page.cc @@ -11,6 +11,7 @@ #include "app/l10n_util.h" #include "app/resource_bundle.h" #include "base/i18n/rtl.h" +#include "base/singleton.h" #include "base/string_number_conversions.h" #include "base/utf_string_conversions.h" #include "base/values.h" @@ -293,8 +294,7 @@ void SafeBrowsingBlockingPage::PopulatePhishingStringDictionary( l10n_util::GetString(IDS_SAFE_BROWSING_PHISHING_HEADLINE), l10n_util::GetStringF(IDS_SAFE_BROWSING_PHISHING_DESCRIPTION1, UTF8ToWide(url().host())), - l10n_util::GetStringF(IDS_SAFE_BROWSING_PHISHING_DESCRIPTION2, - UTF8ToWide(url().host())), + l10n_util::GetString(IDS_SAFE_BROWSING_PHISHING_DESCRIPTION2), L""); strings->SetString("continue_button", diff --git a/chrome/browser/safe_browsing/safe_browsing_blocking_page.h b/chrome/browser/safe_browsing/safe_browsing_blocking_page.h index 96d8bca..7e7cb22 100644 --- a/chrome/browser/safe_browsing/safe_browsing_blocking_page.h +++ b/chrome/browser/safe_browsing/safe_browsing_blocking_page.h @@ -68,6 +68,8 @@ class SafeBrowsingBlockingPage : public InterstitialPage { typedef std::vector<SafeBrowsingService::UnsafeResource> UnsafeResourceList; protected: + friend class SafeBrowsingBlockingPageTest; + // InterstitialPage method: virtual void CommandReceived(const std::string& command); diff --git a/chrome/browser/safe_browsing/safe_browsing_blocking_page_test.cc b/chrome/browser/safe_browsing/safe_browsing_blocking_page_test.cc new file mode 100644 index 0000000..fa30068 --- /dev/null +++ b/chrome/browser/safe_browsing/safe_browsing_blocking_page_test.cc @@ -0,0 +1,261 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// This test creates a fake safebrowsing service, where we can inject +// malware and phishing urls. It then uses a real browser to go to +// these urls, and sends "goback" or "proceed" commands and verifies +// they work. + +#include "chrome/browser/browser_process.h" +#include "chrome/browser/browser_thread.h" +#include "chrome/browser/renderer_host/render_process_host.h" +#include "chrome/browser/renderer_host/resource_dispatcher_host.h" +#include "chrome/browser/safe_browsing/safe_browsing_service.h" +#include "chrome/browser/safe_browsing/safe_browsing_blocking_page.h" +#include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/tab_contents/tab_contents_view.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/common/url_constants.h" +#include "chrome/test/in_process_browser_test.h" +#include "chrome/test/ui_test_utils.h" + +// A SafeBrowingService class that allows us to inject the malicious URLs. +class FakeSafeBrowsingService : public SafeBrowsingService { + public: + FakeSafeBrowsingService() {} + + virtual ~FakeSafeBrowsingService() {} + + // Called on the IO thread to check if the given url is safe or not. If we + // can synchronously determine that the url is safe, CheckUrl returns true. + // Otherwise it returns false, and "client" is called asynchronously with the + // result when it is ready. + // Overrides SafeBrowsingService::CheckUrl. + virtual bool CheckUrl(const GURL& gurl, Client* client) { + const std::string& url = gurl.spec(); + if (badurls[url] == URL_SAFE) + return true; + + BrowserThread::PostTask( + BrowserThread::IO, FROM_HERE, + NewRunnableMethod(this, &FakeSafeBrowsingService::OnCheckDone, + url, client)); + return false; + } + + void OnCheckDone(std::string url, Client* client) { + client->OnUrlCheckResult(GURL(url), badurls[url]); + } + + void AddURLResult(const GURL& url, UrlCheckResult checkresult) { + badurls[url.spec()] = checkresult; + } + + private: + base::hash_map<std::string, UrlCheckResult> badurls; +}; + +// Factory that creates FakeSafeBrowsingService instances. +class TestSafeBrowsingServiceFactory : public SafeBrowsingServiceFactory { + public: + TestSafeBrowsingServiceFactory() { } + virtual ~TestSafeBrowsingServiceFactory() { } + + virtual SafeBrowsingService* CreateSafeBrowsingService() { + return new FakeSafeBrowsingService(); + } +}; + +// Tests the safe browsing blocking page in a browser. +class SafeBrowsingBlockingPageTest : public InProcessBrowserTest, + public SafeBrowsingService::Client { + public: + SafeBrowsingBlockingPageTest() { + } + + virtual void SetUp() { + SafeBrowsingService::RegisterFactory(&factory); + InProcessBrowserTest::SetUp(); + } + + virtual void TearDown() { + InProcessBrowserTest::TearDown(); + SafeBrowsingService::RegisterFactory(NULL); + } + + virtual void SetUpInProcessBrowserTestFixture() { + ASSERT_TRUE(test_server()->Start()); + } + + // SafeBrowsingService::Client implementation. + virtual void OnUrlCheckResult(const GURL& url, + SafeBrowsingService::UrlCheckResult result) { + } + virtual void OnBlockingPageComplete(bool proceed) { + } + + void AddURLResult(const GURL& url, + SafeBrowsingService::UrlCheckResult checkresult) { + FakeSafeBrowsingService* service = + static_cast<FakeSafeBrowsingService*>( + g_browser_process->resource_dispatcher_host()-> + safe_browsing_service()); + + ASSERT_TRUE(service != NULL); + service->AddURLResult(url, checkresult); + } + + void SendCommand(const std::string& command) { + TabContents* contents = browser()->GetSelectedTabContents(); + SafeBrowsingBlockingPage* interstitial_page = + static_cast<SafeBrowsingBlockingPage*>( + contents->interstitial_page()); + ASSERT_TRUE(interstitial_page); + interstitial_page->CommandReceived(command); + } + + void DontProceedThroughInterstitial() { + TabContents* contents = browser()->GetSelectedTabContents(); + InterstitialPage* interstitial_page = contents->interstitial_page(); + ASSERT_TRUE(interstitial_page); + interstitial_page->DontProceed(); + } + + void ProceedThroughInterstitial() { + TabContents* contents = browser()->GetSelectedTabContents(); + InterstitialPage* interstitial_page = contents->interstitial_page(); + ASSERT_TRUE(interstitial_page); + interstitial_page->Proceed(); + } + + void AssertNoInterstitial() { + TabContents* contents = browser()->GetSelectedTabContents(); + InterstitialPage* interstitial_page = contents->interstitial_page(); + ASSERT_FALSE(interstitial_page); + } + + void WaitForNavigation() { + NavigationController* controller = + &browser()->GetSelectedTabContents()->controller(); + ui_test_utils::WaitForNavigation(controller); + } + + private: + TestSafeBrowsingServiceFactory factory; + + DISALLOW_COPY_AND_ASSIGN(SafeBrowsingBlockingPageTest); +}; + +namespace { + +const char kEmptyPage[] = "files/empty.html"; +const char kMalwarePage[] = "files/safe_browsing/malware.html"; +const char kMalwareIframe[] = "files/safe_browsing/malware_iframe.html"; + +IN_PROC_BROWSER_TEST_F(SafeBrowsingBlockingPageTest, MalwareDontProceed) { + GURL url = test_server()->GetURL(kEmptyPage); + AddURLResult(url, SafeBrowsingService::URL_MALWARE); + + ui_test_utils::NavigateToURL(browser(), url); + + SendCommand("\"takeMeBack\""); // Simulate the user clicking "back" + AssertNoInterstitial(); // Assert the interstitial is gone + EXPECT_EQ(GURL(chrome::kAboutBlankURL), // Back to "about:blank" + browser()->GetSelectedTabContents()->GetURL()); +} + +IN_PROC_BROWSER_TEST_F(SafeBrowsingBlockingPageTest, MalwareProceed) { + GURL url = test_server()->GetURL(kEmptyPage); + AddURLResult(url, SafeBrowsingService::URL_MALWARE); + + ui_test_utils::NavigateToURL(browser(), url); + + SendCommand("\"proceed\""); // Simulate the user clicking "proceed" + WaitForNavigation(); // Wait until we finish the navigation. + AssertNoInterstitial(); // Assert the interstitial is gone. + EXPECT_EQ(url, browser()->GetSelectedTabContents()->GetURL()); +} + +IN_PROC_BROWSER_TEST_F(SafeBrowsingBlockingPageTest, PhishingDontProceed) { + GURL url = test_server()->GetURL(kEmptyPage); + AddURLResult(url, SafeBrowsingService::URL_PHISHING); + + ui_test_utils::NavigateToURL(browser(), url); + + SendCommand("\"takeMeBack\""); // Simulate the user clicking "proceed" + AssertNoInterstitial(); // Assert the interstitial is gone + EXPECT_EQ(GURL(chrome::kAboutBlankURL), // We are back to "about:blank". + browser()->GetSelectedTabContents()->GetURL()); +} + +IN_PROC_BROWSER_TEST_F(SafeBrowsingBlockingPageTest, PhishingProceed) { + GURL url = test_server()->GetURL(kEmptyPage); + AddURLResult(url, SafeBrowsingService::URL_PHISHING); + + ui_test_utils::NavigateToURL(browser(), url); + + SendCommand("\"proceed\""); // Simulate the user clicking "proceed". + WaitForNavigation(); // Wait until we finish the navigation. + AssertNoInterstitial(); // Assert the interstitial is gone + EXPECT_EQ(url, browser()->GetSelectedTabContents()->GetURL()); +} + +IN_PROC_BROWSER_TEST_F(SafeBrowsingBlockingPageTest, PhishingReportError) { + GURL url = test_server()->GetURL(kEmptyPage); + AddURLResult(url, SafeBrowsingService::URL_PHISHING); + + ui_test_utils::NavigateToURL(browser(), url); + + SendCommand("\"reportError\""); // Simulate the user clicking "report error" + WaitForNavigation(); // Wait until we finish the navigation. + AssertNoInterstitial(); // Assert the interstitial is gone + + // We are in the error reporting page. + EXPECT_EQ("/safebrowsing/report_error/", + browser()->GetSelectedTabContents()->GetURL().path()); +} + +IN_PROC_BROWSER_TEST_F(SafeBrowsingBlockingPageTest, PhishingLearnMore) { + GURL url = test_server()->GetURL(kEmptyPage); + AddURLResult(url, SafeBrowsingService::URL_PHISHING); + + ui_test_utils::NavigateToURL(browser(), url); + + SendCommand("\"learnMore\""); // Simulate the user clicking "learn more" + WaitForNavigation(); // Wait until we finish the navigation. + AssertNoInterstitial(); // Assert the interstitial is gone + + // We are in the help page. + EXPECT_EQ("/support/bin/answer.py", + browser()->GetSelectedTabContents()->GetURL().path()); +} + +IN_PROC_BROWSER_TEST_F(SafeBrowsingBlockingPageTest, MalwareIframeDontProceed) { + GURL url = test_server()->GetURL(kMalwarePage); + GURL iframe_url = test_server()->GetURL(kMalwareIframe); + AddURLResult(iframe_url, SafeBrowsingService::URL_MALWARE); + + ui_test_utils::NavigateToURL(browser(), url); + + SendCommand("\"takeMeBack\""); // Simulate the user clicking "back" + AssertNoInterstitial(); // Assert the interstitial is gone + + EXPECT_EQ(GURL(chrome::kAboutBlankURL), // Back to "about:blank" + browser()->GetSelectedTabContents()->GetURL()); +} + +IN_PROC_BROWSER_TEST_F(SafeBrowsingBlockingPageTest, MalwareIframeProceed) { + GURL url = test_server()->GetURL(kMalwarePage); + GURL iframe_url = test_server()->GetURL(kMalwareIframe); + AddURLResult(iframe_url, SafeBrowsingService::URL_MALWARE); + + ui_test_utils::NavigateToURL(browser(), url); + + SendCommand("\"proceed\""); // Simulate the user clicking "proceed" + AssertNoInterstitial(); // Assert the interstitial is gone + + EXPECT_EQ(url, browser()->GetSelectedTabContents()->GetURL()); +} + +} // namespace diff --git a/chrome/browser/safe_browsing/safe_browsing_blocking_page_unittest.cc b/chrome/browser/safe_browsing/safe_browsing_blocking_page_unittest.cc index f0670e4..60f1043 100644 --- a/chrome/browser/safe_browsing/safe_browsing_blocking_page_unittest.cc +++ b/chrome/browser/safe_browsing/safe_browsing_blocking_page_unittest.cc @@ -61,7 +61,7 @@ class SafeBrowsingBlockingPageTest : public RenderViewHostTestHarness, : ui_thread_(BrowserThread::UI, MessageLoop::current()), io_thread_(BrowserThread::IO, MessageLoop::current()) { ResetUserResponse(); - service_ = new SafeBrowsingService(); + service_ = SafeBrowsingService::CreateSafeBrowsingService(); } virtual void SetUp() { diff --git a/chrome/browser/safe_browsing/safe_browsing_service.cc b/chrome/browser/safe_browsing/safe_browsing_service.cc index aac28cd..dbb28f1 100644 --- a/chrome/browser/safe_browsing/safe_browsing_service.cc +++ b/chrome/browser/safe_browsing/safe_browsing_service.cc @@ -7,6 +7,7 @@ #include "base/callback.h" #include "base/command_line.h" #include "base/path_service.h" +#include "base/singleton.h" #include "base/string_util.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/browser_thread.h" @@ -49,6 +50,25 @@ static Profile* GetDefaultProfile() { return profile_manager->GetDefaultProfile(user_data_dir); } +// static +SafeBrowsingServiceFactory* SafeBrowsingService::factory_ = NULL; + +// The default SafeBrowsingServiceFactory. Global, made a singleton so we +// don't leak it. +class SafeBrowsingServiceFactoryImpl : public SafeBrowsingServiceFactory { + public: + virtual SafeBrowsingService* CreateSafeBrowsingService() { + return new SafeBrowsingService(); + } + + private: + friend struct DefaultSingletonTraits<SafeBrowsingServiceFactoryImpl>; + + SafeBrowsingServiceFactoryImpl() { } + + DISALLOW_COPY_AND_ASSIGN(SafeBrowsingServiceFactoryImpl); +}; + struct SafeBrowsingService::WhiteListedEntry { int render_process_host_id; int render_view_id; @@ -74,6 +94,13 @@ SafeBrowsingService::SafeBrowsingCheck::SafeBrowsingCheck() SafeBrowsingService::SafeBrowsingCheck::~SafeBrowsingCheck() {} +/* static */ +SafeBrowsingService* SafeBrowsingService::CreateSafeBrowsingService() { + if (!factory_) + factory_ = Singleton<SafeBrowsingServiceFactoryImpl>::get(); + return factory_->CreateSafeBrowsingService(); +} + SafeBrowsingService::SafeBrowsingService() : database_(NULL), protocol_manager_(NULL), diff --git a/chrome/browser/safe_browsing/safe_browsing_service.h b/chrome/browser/safe_browsing/safe_browsing_service.h index acecf4e..78e1cde 100644 --- a/chrome/browser/safe_browsing/safe_browsing_service.h +++ b/chrome/browser/safe_browsing/safe_browsing_service.h @@ -26,6 +26,7 @@ class PrefService; class SafeBrowsingDatabase; class SafeBrowsingProtocolManager; +class SafeBrowsingServiceFactory; class URLRequestContextGetter; namespace base { @@ -88,8 +89,14 @@ class SafeBrowsingService DISALLOW_COPY_AND_ASSIGN(SafeBrowsingCheck); }; - // Creates the safe browsing service. Need to initialize before using. - SafeBrowsingService(); + // Makes the passed |factory| the factory used to instanciate + // a SafeBrowsingService. Useful for tests. + static void RegisterFactory(SafeBrowsingServiceFactory* factory) { + factory_ = factory; + } + + // Create an instance of the safe browsing service. + static SafeBrowsingService* CreateSafeBrowsingService(); // Called on the UI thread to initialize the service. void Initialize(); @@ -104,7 +111,7 @@ class SafeBrowsingService // can synchronously determine that the url is safe, CheckUrl returns true. // Otherwise it returns false, and "client" is called asynchronously with the // result when it is ready. - bool CheckUrl(const GURL& url, Client* client); + virtual bool CheckUrl(const GURL& url, Client* client); // Called on the IO thread to cancel a pending check if the result is no // longer needed. @@ -174,7 +181,15 @@ class SafeBrowsingService // the current page is 'safe'. void LogPauseDelay(base::TimeDelta time); + protected: + // Creates the safe browsing service. Need to initialize before using. + SafeBrowsingService(); + + virtual ~SafeBrowsingService(); + private: + friend class SafeBrowsingServiceFactoryImpl; + typedef std::set<SafeBrowsingCheck*> CurrentChecks; typedef std::vector<SafeBrowsingCheck*> GetHashRequestors; typedef base::hash_map<SBPrefix, GetHashRequestors> GetHashRequests; @@ -192,8 +207,6 @@ class SafeBrowsingService friend class base::RefCountedThreadSafe<SafeBrowsingService>; friend class SafeBrowsingServiceTest; - ~SafeBrowsingService(); - // Called to initialize objects that are used on the io_thread. void OnIOInitialize(const std::string& client_key, const std::string& wrapped_key, @@ -281,6 +294,11 @@ class SafeBrowsingService bool is_subresource, UrlCheckResult threat_type); + // The factory used to instanciate a SafeBrowsingService object. + // Useful for tests, so they can provide their own implementation of + // SafeBrowsingService. + static SafeBrowsingServiceFactory* factory_; + CurrentChecks checks_; // Used for issuing only one GetHash request for a given prefix. @@ -325,4 +343,14 @@ class SafeBrowsingService DISALLOW_COPY_AND_ASSIGN(SafeBrowsingService); }; +// Factory for creating SafeBrowsingService. Useful for tests. +class SafeBrowsingServiceFactory { + public: + SafeBrowsingServiceFactory() { } + virtual ~SafeBrowsingServiceFactory() { } + virtual SafeBrowsingService* CreateSafeBrowsingService() = 0; + private: + DISALLOW_COPY_AND_ASSIGN(SafeBrowsingServiceFactory); +}; + #endif // CHROME_BROWSER_SAFE_BROWSING_SAFE_BROWSING_SERVICE_H_ |