summaryrefslogtreecommitdiffstats
path: root/chrome/browser/safe_browsing
diff options
context:
space:
mode:
authorjcampan@chromium.org <jcampan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-04-03 17:18:04 +0000
committerjcampan@chromium.org <jcampan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-04-03 17:18:04 +0000
commitbc0caef9b0af84365b6dd546cd21673c9790ca58 (patch)
tree54881e9c8bc957f65901a53978d18865135392dd /chrome/browser/safe_browsing
parent4e9f6be54df1f1f6f9cfe243624ef976f15d452f (diff)
downloadchromium_src-bc0caef9b0af84365b6dd546cd21673c9790ca58.zip
chromium_src-bc0caef9b0af84365b6dd546cd21673c9790ca58.tar.gz
chromium_src-bc0caef9b0af84365b6dd546cd21673c9790ca58.tar.bz2
This CL adds unit-tests for the SafeBrowsingBlockingPage class.
This required: - creating a factory to create SafeBrowsingBlockingPage instances (so unit-tests can provide their own sub-classes). - making the code posts tasks on the current message loop when there is no IO thread. This should only happen in tests scenarios where we only have 1 thread. BUG=6731 TEST=Run the unit-tests. In Chrome, navigate to pages flagged as malware (ex: ianfette.org) and make sure the safe browsing feature still works as expected. Review URL: http://codereview.chromium.org/56135 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@13088 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/safe_browsing')
-rw-r--r--chrome/browser/safe_browsing/safe_browsing_blocking_page.cc44
-rw-r--r--chrome/browser/safe_browsing/safe_browsing_blocking_page.h32
-rw-r--r--chrome/browser/safe_browsing/safe_browsing_blocking_page_unittest.cc355
-rw-r--r--chrome/browser/safe_browsing/safe_browsing_service.cc10
-rw-r--r--chrome/browser/safe_browsing/safe_browsing_service.h3
5 files changed, 427 insertions, 17 deletions
diff --git a/chrome/browser/safe_browsing/safe_browsing_blocking_page.cc b/chrome/browser/safe_browsing/safe_browsing_blocking_page.cc
index dd090c0..e87b44b 100644
--- a/chrome/browser/safe_browsing/safe_browsing_blocking_page.cc
+++ b/chrome/browser/safe_browsing/safe_browsing_blocking_page.cc
@@ -49,6 +49,30 @@ static const char* const kLearnMoreCommand = "learnMore";
static const char* const kProceedCommand = "proceed";
static const char* const kTakeMeBackCommand = "takeMeBack";
+// static
+SafeBrowsingBlockingPageFactory* SafeBrowsingBlockingPage::factory_ = NULL;
+
+// The default SafeBrowsingBlockingPageFactory. Global, made a singleton so we
+// don't leak it.
+class SafeBrowsingBlockingPageFactoryImpl
+ : public SafeBrowsingBlockingPageFactory {
+ public:
+ SafeBrowsingBlockingPage* CreateSafeBrowsingPage(
+ SafeBrowsingService* service,
+ WebContents* web_contents,
+ const SafeBrowsingBlockingPage::UnsafeResourceList& unsafe_resources) {
+ return new SafeBrowsingBlockingPage(service, web_contents,
+ unsafe_resources);
+ }
+
+ private:
+ friend struct DefaultSingletonTraits<SafeBrowsingBlockingPageFactoryImpl>;
+
+ SafeBrowsingBlockingPageFactoryImpl() { }
+
+ DISALLOW_COPY_AND_ASSIGN(SafeBrowsingBlockingPageFactoryImpl);
+};
+
SafeBrowsingBlockingPage::SafeBrowsingBlockingPage(
SafeBrowsingService* sb_service,
WebContents* web_contents,
@@ -349,8 +373,8 @@ void SafeBrowsingBlockingPage::Proceed() {
// Build an interstitial for all the unsafe resources notifications.
// Don't show it now as showing an interstitial while an interstitial is
// already showing would cause DontProceed() to be invoked.
- blocking_page = new SafeBrowsingBlockingPage(sb_service_, tab(),
- iter->second);
+ blocking_page = factory_->CreateSafeBrowsingPage(sb_service_, tab(),
+ iter->second);
unsafe_resource_map->erase(iter);
}
@@ -391,11 +415,13 @@ void SafeBrowsingBlockingPage::NotifySafeBrowsingService(
SafeBrowsingService* sb_service,
const UnsafeResourceList& unsafe_resources,
bool proceed) {
- base::Thread* io_thread = g_browser_process->io_thread();
- if (!io_thread)
- return;
+ MessageLoop* message_loop;
+ if (g_browser_process->io_thread())
+ message_loop = g_browser_process->io_thread()->message_loop();
+ else // For unit-tests, just post on the current thread.
+ message_loop = MessageLoop::current();
- io_thread->message_loop()->PostTask(FROM_HERE, NewRunnableMethod(
+ message_loop->PostTask(FROM_HERE, NewRunnableMethod(
sb_service, &SafeBrowsingService::OnBlockingPageDone, unsafe_resources,
proceed));
}
@@ -418,8 +444,12 @@ void SafeBrowsingBlockingPage::ShowBlockingPage(
// show this interstitial.
std::vector<SafeBrowsingService::UnsafeResource> resources;
resources.push_back(unsafe_resource);
+ // Set up the factory if this has not been done already (tests do that
+ // before this method is called).
+ if (!factory_)
+ factory_ = Singleton<SafeBrowsingBlockingPageFactoryImpl>::get();
SafeBrowsingBlockingPage* blocking_page =
- new SafeBrowsingBlockingPage(sb_service, web_contents, resources);
+ factory_->CreateSafeBrowsingPage(sb_service, web_contents, resources);
blocking_page->Show();
return;
}
diff --git a/chrome/browser/safe_browsing/safe_browsing_blocking_page.h b/chrome/browser/safe_browsing/safe_browsing_blocking_page.h
index 242f68f..be03a0f 100644
--- a/chrome/browser/safe_browsing/safe_browsing_blocking_page.h
+++ b/chrome/browser/safe_browsing/safe_browsing_blocking_page.h
@@ -38,9 +38,9 @@
class DictionaryValue;
class MessageLoop;
class NavigationController;
+class SafeBrowsingBlockingPageFactory;
class WebContents;
-
class SafeBrowsingBlockingPage : public InterstitialPage {
public:
virtual ~SafeBrowsingBlockingPage();
@@ -54,23 +54,29 @@ class SafeBrowsingBlockingPage : public InterstitialPage {
SafeBrowsingService* service,
const SafeBrowsingService::UnsafeResource& resource);
+ // Makes the passed |factory| the factory used to instanciate
+ // SafeBrowsingBlockingPage objects. Usefull for tests.
+ static void RegisterFactory(SafeBrowsingBlockingPageFactory* factory) {
+ factory_ = factory;
+ }
+
// InterstitialPage method:
virtual std::string GetHTMLContents();
virtual void Proceed();
virtual void DontProceed();
+ typedef std::vector<SafeBrowsingService::UnsafeResource> UnsafeResourceList;
+
protected:
// InterstitialPage method:
virtual void CommandReceived(const std::string& command);
- private:
- typedef std::vector<SafeBrowsingService::UnsafeResource> UnsafeResourceList;
-
// Don't instanciate this class directly, use ShowBlockingPage instead.
SafeBrowsingBlockingPage(SafeBrowsingService* service,
WebContents* web_contents,
const UnsafeResourceList& unsafe_resources);
+ private:
// Fills the passed dictionary with the strings passed to JS Template when
// creating the HTML.
void PopulateMultipleThreatStringDictionary(DictionaryValue* strings);
@@ -103,6 +109,8 @@ class SafeBrowsingBlockingPage : public InterstitialPage {
static bool IsMainPage(const UnsafeResourceList& unsafe_resources);
private:
+ friend class SafeBrowsingBlockingPageFactoryImpl;
+
// For reporting back user actions.
SafeBrowsingService* sb_service_;
MessageLoop* report_loop_;
@@ -117,7 +125,23 @@ class SafeBrowsingBlockingPage : public InterstitialPage {
// The list of unsafe resources this page is warning about.
UnsafeResourceList unsafe_resources_;
+ // The factory used to instanciate SafeBrowsingBlockingPage objects.
+ // Usefull for tests, so they can provide their own implementation of
+ // SafeBrowsingBlockingPage.
+ static SafeBrowsingBlockingPageFactory* factory_;
+
DISALLOW_COPY_AND_ASSIGN(SafeBrowsingBlockingPage);
};
+// Factory for creating SafeBrowsingBlockingPage. Useful for tests.
+class SafeBrowsingBlockingPageFactory {
+ public:
+ ~SafeBrowsingBlockingPageFactory() { }
+
+ virtual SafeBrowsingBlockingPage* CreateSafeBrowsingPage(
+ SafeBrowsingService* service,
+ WebContents* web_contents,
+ const SafeBrowsingBlockingPage::UnsafeResourceList& unsafe_resources) = 0;
+};
+
#endif // CHROME_BROWSER_SAFE_BROWSING_SAFE_BROWSING_BLOCKING_PAGE_H_
diff --git a/chrome/browser/safe_browsing/safe_browsing_blocking_page_unittest.cc b/chrome/browser/safe_browsing/safe_browsing_blocking_page_unittest.cc
new file mode 100644
index 0000000..45ff6f7
--- /dev/null
+++ b/chrome/browser/safe_browsing/safe_browsing_blocking_page_unittest.cc
@@ -0,0 +1,355 @@
+// Copyright (c) 2009 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.
+
+#include "chrome/browser/renderer_host/test_render_view_host.h"
+
+#include "chrome/browser/safe_browsing/safe_browsing_blocking_page.h"
+#include "chrome/browser/tab_contents/navigation_entry.h"
+#include "chrome/common/render_messages.h"
+
+static const char* kGoogleURL = "http://www.google.com/";
+static const char* kGoodURL = "http://www.goodguys.com/";
+static const char* kBadURL = "http://www.badguys.com/";
+static const char* kBadURL2 = "http://www.badguys2.com/";
+static const char* kBadURL3 = "http://www.badguys3.com/";
+
+static void InitNavigateParams(ViewHostMsg_FrameNavigate_Params* params,
+ int page_id,
+ const GURL& url) {
+ params->page_id = page_id;
+ params->url = url;
+ params->referrer = GURL::EmptyGURL();
+ params->transition = PageTransition::TYPED;
+ params->redirects = std::vector<GURL>();
+ params->should_update_history = false;
+ params->searchable_form_url = GURL::EmptyGURL();
+ params->searchable_form_element_name = std::wstring();
+ params->searchable_form_encoding = std::string();
+ params->password_form = PasswordForm();
+ params->security_info = std::string();
+ params->gesture = NavigationGestureUser;
+ params->is_post = false;
+}
+
+// A SafeBrowingBlockingPage class that does not create windows.
+class TestSafeBrowsingBlockingPage : public SafeBrowsingBlockingPage {
+ public:
+ TestSafeBrowsingBlockingPage(SafeBrowsingService* service,
+ WebContents* web_contents,
+ const UnsafeResourceList& unsafe_resources)
+ : SafeBrowsingBlockingPage(service, web_contents, unsafe_resources) {
+ }
+
+ // Overriden from InterstitialPage. Don't create a view.
+ virtual WebContentsView* CreateWebContentsView() {
+ return NULL;
+ }
+};
+
+class TestSafeBrowsingBlockingPageFactory
+ : public SafeBrowsingBlockingPageFactory {
+ public:
+ TestSafeBrowsingBlockingPageFactory() { }
+ ~TestSafeBrowsingBlockingPageFactory() { }
+
+ virtual SafeBrowsingBlockingPage* CreateSafeBrowsingPage(
+ SafeBrowsingService* service,
+ WebContents* web_contents,
+ const SafeBrowsingBlockingPage::UnsafeResourceList& unsafe_resources) {
+ return new TestSafeBrowsingBlockingPage(service, web_contents,
+ unsafe_resources);
+ }
+};
+
+class SafeBrowsingBlockingPageTest : public RenderViewHostTestHarness,
+ public SafeBrowsingService::Client {
+ public:
+ // The decision the user made.
+ enum UserResponse {
+ PENDING,
+ OK,
+ CANCEL
+ };
+
+ SafeBrowsingBlockingPageTest() {
+ ResetUserResponse();
+ service_ = new SafeBrowsingService();
+ }
+
+ virtual void SetUp() {
+ RenderViewHostTestHarness::SetUp();
+ SafeBrowsingBlockingPage::RegisterFactory(&factory_);
+ ResetUserResponse();
+ }
+
+ // SafeBrowsingService::Client implementation.
+ virtual void OnUrlCheckResult(const GURL& url,
+ SafeBrowsingService::UrlCheckResult result) {
+ }
+ virtual void OnBlockingPageComplete(bool proceed) {
+ if (proceed)
+ user_response_ = OK;
+ else
+ user_response_ = CANCEL;
+ }
+
+ void Navigate(const char* url, int page_id) {
+ ViewHostMsg_FrameNavigate_Params params;
+ InitNavigateParams(&params, page_id, GURL(url));
+ contents()->TestDidNavigate(contents_->render_view_host(), params);
+ }
+
+ void ShowInterstitial(ResourceType::Type resource_type,
+ const char* url) {
+ SafeBrowsingService::UnsafeResource resource;
+ InitResource(&resource, resource_type, GURL(url));
+ SafeBrowsingBlockingPage::ShowBlockingPage(service_, resource);
+ }
+
+ // Returns the SafeBrowsingBlockingPage currently showing or NULL if none is
+ // showing.
+ SafeBrowsingBlockingPage* GetSafeBrowsingBlockingPage() {
+ InterstitialPage* interstitial =
+ InterstitialPage::GetInterstitialPage(contents_);
+ if (!interstitial)
+ return NULL;
+ return static_cast<SafeBrowsingBlockingPage*>(interstitial);
+ }
+
+ UserResponse user_response() const { return user_response_; }
+ void ResetUserResponse() { user_response_ = PENDING; }
+
+ static void ProceedThroughInterstitial(
+ SafeBrowsingBlockingPage* sb_interstitial) {
+ sb_interstitial->Proceed();
+ // Proceed() posts a task to update the SafeBrowsingService::Client.
+ MessageLoop::current()->RunAllPending();
+ }
+
+ static void DontProceedThroughInterstitial(
+ SafeBrowsingBlockingPage* sb_interstitial) {
+ sb_interstitial->DontProceed();
+ // DontProceed() posts a task to update the SafeBrowsingService::Client.
+ MessageLoop::current()->RunAllPending();
+ }
+
+ private:
+ void InitResource(SafeBrowsingService::UnsafeResource* resource,
+ ResourceType::Type resource_type,
+ const GURL& url) {
+ resource->client = this;
+ resource->url = url;
+ resource->resource_type = resource_type;
+ resource->threat_type = SafeBrowsingService::URL_MALWARE;
+ resource->render_process_host_id = contents_->process()->pid();
+ resource->render_view_id = contents_->render_view_host()->routing_id();
+ }
+
+ UserResponse user_response_;
+ scoped_refptr<SafeBrowsingService> service_;
+ TestSafeBrowsingBlockingPageFactory factory_;
+};
+
+// Tests showing a blocking page for a malware page and not proceeding.
+TEST_F(SafeBrowsingBlockingPageTest, MalwarePageDontProceed) {
+ // Start a load.
+ controller()->LoadURL(GURL(kBadURL), GURL(), PageTransition::TYPED);
+
+ // Simulate the load causing a safe browsing interstitial to be shown.
+ ShowInterstitial(ResourceType::MAIN_FRAME, kBadURL);
+ SafeBrowsingBlockingPage* sb_interstitial = GetSafeBrowsingBlockingPage();
+ ASSERT_TRUE(sb_interstitial);
+
+ // Simulate the user clicking "don't proceed".
+ DontProceedThroughInterstitial(sb_interstitial);
+
+ // The interstitial should be gone.
+ EXPECT_EQ(CANCEL, user_response());
+ EXPECT_FALSE(GetSafeBrowsingBlockingPage());
+
+ // We did not proceed, the pending entry should be gone.
+ EXPECT_FALSE(controller()->GetPendingEntry());
+}
+
+// Tests showing a blocking page for a malware page and then proceeding.
+TEST_F(SafeBrowsingBlockingPageTest, MalwarePageProceed) {
+ // Start a load.
+ controller()->LoadURL(GURL(kBadURL), GURL(), PageTransition::TYPED);
+
+ // Simulate the load causing a safe browsing interstitial to be shown.
+ ShowInterstitial(ResourceType::MAIN_FRAME, kBadURL);
+ SafeBrowsingBlockingPage* sb_interstitial = GetSafeBrowsingBlockingPage();
+ ASSERT_TRUE(sb_interstitial);
+
+ // Simulate the user clicking "proceed".
+ ProceedThroughInterstitial(sb_interstitial);
+
+ // The interstitial is shown until the navigation commits.
+ ASSERT_TRUE(InterstitialPage::GetInterstitialPage(contents_));
+ // Commit the navigation.
+ Navigate(kBadURL, 1);
+ // The interstitial should be gone now.
+ ASSERT_FALSE(InterstitialPage::GetInterstitialPage(contents_));
+}
+
+// Tests showing a blocking page for a page that contains malware subresources
+// and not proceeding.
+TEST_F(SafeBrowsingBlockingPageTest, PageWithMalwareResourceDontProceed) {
+ // Navigate somewhere.
+ Navigate(kGoogleURL, 1);
+
+ // Navigate somewhere else.
+ Navigate(kGoodURL, 2);
+
+ // Simulate that page loading a bad-resource triggering an interstitial.
+ ShowInterstitial(ResourceType::SUB_RESOURCE, kBadURL);
+
+ SafeBrowsingBlockingPage* sb_interstitial = GetSafeBrowsingBlockingPage();
+ ASSERT_TRUE(sb_interstitial);
+
+ // Simulate the user clicking "don't proceed".
+ DontProceedThroughInterstitial(sb_interstitial);
+ EXPECT_EQ(CANCEL, user_response());
+ EXPECT_FALSE(GetSafeBrowsingBlockingPage());
+
+ // We did not proceed, we should be back to the first page, the 2nd one should
+ // have been removed from the navigation controller.
+ ASSERT_EQ(1, controller()->GetEntryCount());
+ EXPECT_EQ(kGoogleURL, controller()->GetActiveEntry()->url().spec());
+}
+
+// Tests showing a blocking page for a page that contains malware subresources
+// and proceeding.
+TEST_F(SafeBrowsingBlockingPageTest, PageWithMalwareResourceProceed) {
+ // Navigate somewhere.
+ Navigate(kGoodURL, 1);
+
+ // Simulate that page loading a bad-resource triggering an interstitial.
+ ShowInterstitial(ResourceType::SUB_RESOURCE, kBadURL);
+
+ SafeBrowsingBlockingPage* sb_interstitial = GetSafeBrowsingBlockingPage();
+ ASSERT_TRUE(sb_interstitial);
+
+ // Simulate the user clicking "proceed".
+ ProceedThroughInterstitial(sb_interstitial);
+ EXPECT_EQ(OK, user_response());
+ EXPECT_FALSE(GetSafeBrowsingBlockingPage());
+
+ // We did proceed, we should be back to showing the page.
+ ASSERT_EQ(1, controller()->GetEntryCount());
+ EXPECT_EQ(kGoodURL, controller()->GetActiveEntry()->url().spec());
+}
+
+// Tests showing a blocking page for a page that contains multiple malware
+// subresources and not proceeding. This just tests that the extra malware
+// subresources (which trigger queued interstitial pages) do not break anything.
+TEST_F(SafeBrowsingBlockingPageTest,
+ PageWithMultipleMalwareResourceDontProceed) {
+ // Navigate somewhere.
+ Navigate(kGoogleURL, 1);
+
+ // Navigate somewhere else.
+ Navigate(kGoodURL, 2);
+
+ // Simulate that page loading a bad-resource triggering an interstitial.
+ ShowInterstitial(ResourceType::SUB_RESOURCE, kBadURL);
+
+ // More bad resources loading causing more interstitials. The new
+ // interstitials should be queued.
+ ShowInterstitial(ResourceType::SUB_RESOURCE, kBadURL2);
+ ShowInterstitial(ResourceType::SUB_RESOURCE, kBadURL3);
+
+ SafeBrowsingBlockingPage* sb_interstitial = GetSafeBrowsingBlockingPage();
+ ASSERT_TRUE(sb_interstitial);
+
+ // Simulate the user clicking "don't proceed".
+ DontProceedThroughInterstitial(sb_interstitial);
+ EXPECT_EQ(CANCEL, user_response());
+ EXPECT_FALSE(GetSafeBrowsingBlockingPage());
+
+ // We did not proceed, we should be back to the first page, the 2nd one should
+ // have been removed from the navigation controller.
+ ASSERT_EQ(1, controller()->GetEntryCount());
+ EXPECT_EQ(kGoogleURL, controller()->GetActiveEntry()->url().spec());
+}
+
+// Tests showing a blocking page for a page that contains multiple malware
+// subresources and proceeding through the first interstitial, but not the next.
+TEST_F(SafeBrowsingBlockingPageTest,
+ PageWithMultipleMalwareResourceProceedThenDontProceed) {
+ // Navigate somewhere.
+ Navigate(kGoogleURL, 1);
+
+ // Navigate somewhere else.
+ Navigate(kGoodURL, 2);
+
+ // Simulate that page loading a bad-resource triggering an interstitial.
+ ShowInterstitial(ResourceType::SUB_RESOURCE, kBadURL);
+
+ // More bad resources loading causing more interstitials. The new
+ // interstitials should be queued.
+ ShowInterstitial(ResourceType::SUB_RESOURCE, kBadURL2);
+ ShowInterstitial(ResourceType::SUB_RESOURCE, kBadURL3);
+
+ SafeBrowsingBlockingPage* sb_interstitial = GetSafeBrowsingBlockingPage();
+ ASSERT_TRUE(sb_interstitial);
+
+ // Proceed through the 1st interstitial.
+ ProceedThroughInterstitial(sb_interstitial);
+ EXPECT_EQ(OK, user_response());
+
+ ResetUserResponse();
+
+ // We should land to a 2nd interstitial (aggregating all the malware resources
+ // loaded while the 1st interstitial was showing).
+ sb_interstitial = GetSafeBrowsingBlockingPage();
+ ASSERT_TRUE(sb_interstitial);
+
+ // Don't proceed through the 2nd interstitial.
+ DontProceedThroughInterstitial(sb_interstitial);
+ EXPECT_EQ(CANCEL, user_response());
+ EXPECT_FALSE(GetSafeBrowsingBlockingPage());
+
+ // We did not proceed, we should be back to the first page, the 2nd one should
+ // have been removed from the navigation controller.
+ ASSERT_EQ(1, controller()->GetEntryCount());
+ EXPECT_EQ(kGoogleURL, controller()->GetActiveEntry()->url().spec());
+}
+
+// Tests showing a blocking page for a page that contains multiple malware
+// subresources and proceeding through the multiple interstitials.
+TEST_F(SafeBrowsingBlockingPageTest, PageWithMultipleMalwareResourceProceed) {
+ // Navigate somewhere else.
+ Navigate(kGoodURL, 1);
+
+ // Simulate that page loading a bad-resource triggering an interstitial.
+ ShowInterstitial(ResourceType::SUB_RESOURCE, kBadURL);
+
+ // More bad resources loading causing more interstitials. The new
+ // interstitials should be queued.
+ ShowInterstitial(ResourceType::SUB_RESOURCE, kBadURL2);
+ ShowInterstitial(ResourceType::SUB_RESOURCE, kBadURL3);
+
+ SafeBrowsingBlockingPage* sb_interstitial = GetSafeBrowsingBlockingPage();
+ ASSERT_TRUE(sb_interstitial);
+
+ // Proceed through the 1st interstitial.
+ ProceedThroughInterstitial(sb_interstitial);
+ EXPECT_EQ(OK, user_response());
+
+ ResetUserResponse();
+
+ // We should land to a 2nd interstitial (aggregating all the malware resources
+ // loaded while the 1st interstitial was showing).
+ sb_interstitial = GetSafeBrowsingBlockingPage();
+ ASSERT_TRUE(sb_interstitial);
+
+ // Proceed through the 2nd interstitial.
+ ProceedThroughInterstitial(sb_interstitial);
+ EXPECT_EQ(OK, user_response());
+
+ // We did proceed, we should be back to the initial page.
+ ASSERT_EQ(1, controller()->GetEntryCount());
+ EXPECT_EQ(kGoodURL, controller()->GetActiveEntry()->url().spec());
+}
diff --git a/chrome/browser/safe_browsing/safe_browsing_service.cc b/chrome/browser/safe_browsing/safe_browsing_service.cc
index 47a1941..2f8f5ea 100644
--- a/chrome/browser/safe_browsing/safe_browsing_service.cc
+++ b/chrome/browser/safe_browsing/safe_browsing_service.cc
@@ -264,12 +264,14 @@ void SafeBrowsingService::DoDisplayBlockingPage(
if (!wc) {
// The tab is gone and we did not have a chance at showing the interstitial.
// Just act as "Don't Proceed" was chosen.
- base::Thread* io_thread = g_browser_process->io_thread();
- if (!io_thread)
- return;
std::vector<UnsafeResource> resources;
resources.push_back(resource);
- io_thread->message_loop()->PostTask(FROM_HERE, NewRunnableMethod(
+ MessageLoop* message_loop;
+ if (g_browser_process->io_thread())
+ message_loop = g_browser_process->io_thread()->message_loop();
+ else // For unit-tests, just post on the current thread.
+ message_loop = MessageLoop::current();
+ message_loop->PostTask(FROM_HERE, NewRunnableMethod(
this, &SafeBrowsingService::OnBlockingPageDone, resources, false));
return;
}
diff --git a/chrome/browser/safe_browsing/safe_browsing_service.h b/chrome/browser/safe_browsing/safe_browsing_service.h
index 6eba443..c280737 100644
--- a/chrome/browser/safe_browsing/safe_browsing_service.h
+++ b/chrome/browser/safe_browsing/safe_browsing_service.h
@@ -72,8 +72,7 @@ class SafeBrowsingService
// Initializes the service. io_loop is the message loop that the
// caller of this service (ResourceDispatcherHost) wants to be notified on
- // for check results. db_loop is the message loop for the thread to do
- // the database work.
+ // for check results.
void Initialize(MessageLoop* io_loop);
// Called to initialize objects that are used on the io_thread.