summaryrefslogtreecommitdiffstats
path: root/chrome/browser
diff options
context:
space:
mode:
authornoelutz@google.com <noelutz@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2011-03-21 21:51:50 +0000
committernoelutz@google.com <noelutz@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2011-03-21 21:51:50 +0000
commit1fd6dccfc0bd2383005181c52635ff5b90dbae78 (patch)
treeef7501ecb808d57de2c597345021fc81b9d79880 /chrome/browser
parent8d9df902248d087ea563a196f00b8221babb2bf0 (diff)
downloadchromium_src-1fd6dccfc0bd2383005181c52635ff5b90dbae78.zip
chromium_src-1fd6dccfc0bd2383005181c52635ff5b90dbae78.tar.gz
chromium_src-1fd6dccfc0bd2383005181c52635ff5b90dbae78.tar.bz2
Integrate the csd-whitelist with the rest of the client-side
phishing detection code. BUG= TEST=ClientSideDetectionHostTest Committed: http://src.chromium.org/viewvc/chrome?view=rev&revision=78635 Committed: http://src.chromium.org/viewvc/chrome?view=rev&revision=78818 Review URL: http://codereview.chromium.org/6670053 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@78929 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
-rw-r--r--chrome/browser/safe_browsing/client_side_detection_host.cc146
-rw-r--r--chrome/browser/safe_browsing/client_side_detection_host.h4
-rw-r--r--chrome/browser/safe_browsing/client_side_detection_host_unittest.cc214
-rw-r--r--chrome/browser/safe_browsing/safe_browsing_service.h2
4 files changed, 244 insertions, 122 deletions
diff --git a/chrome/browser/safe_browsing/client_side_detection_host.cc b/chrome/browser/safe_browsing/client_side_detection_host.cc
index 1812572..8771ab9 100644
--- a/chrome/browser/safe_browsing/client_side_detection_host.cc
+++ b/chrome/browser/safe_browsing/client_side_detection_host.cc
@@ -9,6 +9,7 @@
#include "base/command_line.h"
#include "base/logging.h"
#include "base/metrics/histogram.h"
+#include "base/ref_counted.h"
#include "base/task.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/safe_browsing/client_side_detection_service.h"
@@ -32,46 +33,37 @@ namespace safe_browsing {
// This class is instantiated each time a new toplevel URL loads, and
// asynchronously checks whether the phishing classifier should run for this
// URL. If so, it notifies the renderer with a StartPhishingDetection IPC.
-// Objects of this class must have a shorter lifetime than |tab_contents|,
-// |service|, and |host|. This is currently enforced because |tab_contents|
-// owns |host| which owns this.
-class ClientSideDetectionHost::ShouldClassifyUrlRequest {
+// Objects of this class are ref-counted and will be destroyed once nobody
+// uses it anymore. If |tab_contents|, |csd_service| or |host| go away you need
+// to call Cancel(). We keep the |sb_service| alive in a ref pointer for as
+// long as it takes.
+class ClientSideDetectionHost::ShouldClassifyUrlRequest
+ : public base::RefCountedThreadSafe<
+ ClientSideDetectionHost::ShouldClassifyUrlRequest> {
public:
ShouldClassifyUrlRequest(const ViewHostMsg_FrameNavigate_Params& params,
TabContents* tab_contents,
- ClientSideDetectionService* service,
+ ClientSideDetectionService* csd_service,
+ SafeBrowsingService* sb_service,
ClientSideDetectionHost* host)
- : params_(params),
+ : canceled_(false),
+ params_(params),
tab_contents_(tab_contents),
- service_(service),
- host_(host),
- ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) {
+ csd_service_(csd_service),
+ sb_service_(sb_service),
+ host_(host) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK(tab_contents_);
- DCHECK(service_);
+ DCHECK(csd_service_);
+ DCHECK(sb_service_);
DCHECK(host_);
}
- ~ShouldClassifyUrlRequest() {
- // TODO(gcasto): Uncomment this once we can delete this object on the UI
- // thread in testing.
- // DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- }
-
void Start() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- // For consistency, always run the pre-classification checks
- // asynchronously.
- BrowserThread::PostTask(BrowserThread::UI,
- FROM_HERE,
- method_factory_.NewRunnableMethod(
- &ShouldClassifyUrlRequest::Run));
- }
-
- private:
- void Run() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ // We first start by doing the proxy and local IP check
+ // synchronously because they are fast and they run on the UI thread.
// Don't run the phishing classifier if the URL came from a private
// network, since we don't want to ping back in this case. We also need
@@ -83,7 +75,7 @@ class ClientSideDetectionHost::ShouldClassifyUrlRequest {
UMA_HISTOGRAM_COUNTS("SBClientPhishing.NoClassifyProxyFetch", 1);
return;
}
- if (service_->IsPrivateIPAddress(params_.socket_address.host())) {
+ if (csd_service_->IsPrivateIPAddress(params_.socket_address.host())) {
VLOG(1) << "Skipping phishing classification for URL: " << params_.url
<< " because of hosting on private IP: "
<< params_.socket_address.host();
@@ -91,9 +83,59 @@ class ClientSideDetectionHost::ShouldClassifyUrlRequest {
return;
}
+ // We lookup the csd-whitelist before we lookup the cache because
+ // a URL may have recently been whitelisted. If the URL matches
+ // the csd-whitelist we won't start classification. The
+ // csd-whitelist check has to be done on the IO thread because it
+ // uses the SafeBrowsing service class.
+ BrowserThread::PostTask(
+ BrowserThread::IO,
+ FROM_HERE,
+ NewRunnableMethod(this,
+ &ShouldClassifyUrlRequest::CheckCsdWhitelist,
+ params_.url));
+ }
+
+ void Cancel() {
+ canceled_ = true;
+ // Just to make sure we don't do anything stupid we reset all these
+ // pointers except for the safebrowsing service class which may be
+ // accessed by CheckCsdWhitelist().
+ tab_contents_ = NULL;
+ csd_service_ = NULL;
+ host_ = NULL;
+ }
+
+ private:
+ friend class base::RefCountedThreadSafe<
+ ClientSideDetectionHost::ShouldClassifyUrlRequest>;
+ // The destructor can be called either from the UI or the IO thread.
+ virtual ~ShouldClassifyUrlRequest() { }
+
+ void CheckCsdWhitelist(GURL url) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ if (!sb_service_ || sb_service_->MatchCsdWhitelistUrl(url)) {
+ // We're done. There is no point in going back to the UI thread.
+ UMA_HISTOGRAM_COUNTS("SBClientPhishing.MatchCsdWhitelist", 1);
+ return;
+ }
+
+ BrowserThread::PostTask(
+ BrowserThread::UI,
+ FROM_HERE,
+ NewRunnableMethod(this,
+ &ShouldClassifyUrlRequest::CheckCache));
+ }
+
+ void CheckCache() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ if (canceled_) {
+ return;
+ }
+
// If result is cached, we don't want to run classification again
bool is_phishing;
- if (service_->GetValidCachedResult(params_.url, &is_phishing)) {
+ if (csd_service_->GetValidCachedResult(params_.url, &is_phishing)) {
VLOG(1) << "Satisfying request for " << params_.url << " from cache";
UMA_HISTOGRAM_COUNTS("SBClientPhishing.RequestSatisfiedFromCache", 1);
// Since we are already on the UI thread, this is safe.
@@ -105,11 +147,11 @@ class ClientSideDetectionHost::ShouldClassifyUrlRequest {
// limit for urls in the cache. We don't want to start classifying
// too many pages as phishing, but for those that we already think are
// phishing we want to give ourselves a chance to fix false positives.
- if (service_->IsInCache(params_.url)) {
+ if (csd_service_->IsInCache(params_.url)) {
VLOG(1) << "Reporting limit skipped for " << params_.url
<< " as it was in the cache.";
UMA_HISTOGRAM_COUNTS("SBClientPhishing.ReportLimitSkipped", 1);
- } else if (service_->OverReportLimit()) {
+ } else if (csd_service_->OverReportLimit()) {
VLOG(1) << "Too many report phishing requests sent recently, "
<< "not running classification for " << params_.url;
UMA_HISTOGRAM_COUNTS("SBClientPhishing.TooManyReports", 1);
@@ -117,17 +159,23 @@ class ClientSideDetectionHost::ShouldClassifyUrlRequest {
}
// Everything checks out, so start classification.
- // |tab_contents_| is safe to call as we will be destructed before it is.
+ // |tab_contents_| is safe to call as we will be destructed
+ // before it is.
RenderViewHost* rvh = tab_contents_->render_view_host();
rvh->Send(new ViewMsg_StartPhishingDetection(
rvh->routing_id(), params_.url));
}
+ // No need to protect |canceled_| with a lock because it is only read and
+ // written by the UI thread.
+ bool canceled_;
ViewHostMsg_FrameNavigate_Params params_;
TabContents* tab_contents_;
- ClientSideDetectionService* service_;
+ ClientSideDetectionService* csd_service_;
+ // We keep a ref pointer here just to make sure the service class stays alive
+ // long enough.
+ scoped_refptr<SafeBrowsingService> sb_service_;
ClientSideDetectionHost* host_;
- ScopedRunnableMethodFactory<ShouldClassifyUrlRequest> method_factory_;
DISALLOW_COPY_AND_ASSIGN(ShouldClassifyUrlRequest);
};
@@ -160,10 +208,10 @@ class CsdClient : public SafeBrowsingService::Client {
ClientSideDetectionHost::ClientSideDetectionHost(TabContents* tab)
: TabContentsObserver(tab),
- service_(g_browser_process->safe_browsing_detection_service()),
+ csd_service_(g_browser_process->safe_browsing_detection_service()),
cb_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
DCHECK(tab);
- // Note: service_ and sb_service_ might be NULL.
+ // Note: csd_service_ and sb_service_ might be NULL.
ResourceDispatcherHost* resource =
g_browser_process->resource_dispatcher_host();
if (resource) {
@@ -172,6 +220,10 @@ ClientSideDetectionHost::ClientSideDetectionHost(TabContents* tab)
}
ClientSideDetectionHost::~ClientSideDetectionHost() {
+ // Tell any pending classification request that it is being canceled.
+ if (classification_request_.get()) {
+ classification_request_->Cancel();
+ }
}
bool ClientSideDetectionHost::OnMessageReceived(const IPC::Message& message) {
@@ -205,10 +257,18 @@ void ClientSideDetectionHost::DidNavigateMainFramePostCommit(
// interstial.
cb_factory_.RevokeAll();
- if (service_) {
+ if (csd_service_) {
+ // Cancel any pending classification request.
+ if (classification_request_.get()) {
+ classification_request_->Cancel();
+ }
+
// Notify the renderer if it should classify this URL.
- classification_request_.reset(
- new ShouldClassifyUrlRequest(params, tab_contents(), service_, this));
+ classification_request_ = new ShouldClassifyUrlRequest(params,
+ tab_contents(),
+ csd_service_,
+ sb_service_,
+ this);
classification_request_->Start();
}
}
@@ -219,12 +279,12 @@ void ClientSideDetectionHost::OnDetectedPhishingSite(const GURL& phishing_url,
// There is something seriously wrong if there is no service class but
// this method is called. The renderer should not start phishing detection
// if there isn't any service class in the browser.
- DCHECK(service_);
- if (service_) {
+ DCHECK(csd_service_);
+ if (csd_service_) {
// There shouldn't be any pending requests because we revoke them everytime
// we navigate away.
DCHECK(!cb_factory_.HasPendingCallbacks());
- service_->SendClientReportPhishingRequest(
+ csd_service_->SendClientReportPhishingRequest(
phishing_url,
phishing_score,
cb_factory_.NewCallback(
@@ -269,7 +329,7 @@ void ClientSideDetectionHost::MaybeShowPhishingWarning(GURL phishing_url,
void ClientSideDetectionHost::set_client_side_detection_service(
ClientSideDetectionService* service) {
- service_ = service;
+ csd_service_ = service;
}
void ClientSideDetectionHost::set_safe_browsing_service(
diff --git a/chrome/browser/safe_browsing/client_side_detection_host.h b/chrome/browser/safe_browsing/client_side_detection_host.h
index 9ebdf15..3c000c3 100644
--- a/chrome/browser/safe_browsing/client_side_detection_host.h
+++ b/chrome/browser/safe_browsing/client_side_detection_host.h
@@ -63,12 +63,12 @@ class ClientSideDetectionHost : public TabContentsObserver {
void set_safe_browsing_service(SafeBrowsingService* service);
// This pointer may be NULL if client-side phishing detection is disabled.
- ClientSideDetectionService* service_;
+ ClientSideDetectionService* csd_service_;
// This pointer may be NULL if SafeBrowsing is disabled.
scoped_refptr<SafeBrowsingService> sb_service_;
// Keep a handle to the latest classification request so that we can cancel
// it if necessary.
- scoped_ptr<ShouldClassifyUrlRequest> classification_request_;
+ scoped_refptr<ShouldClassifyUrlRequest> classification_request_;
base::ScopedCallbackFactory<ClientSideDetectionHost> cb_factory_;
diff --git a/chrome/browser/safe_browsing/client_side_detection_host_unittest.cc b/chrome/browser/safe_browsing/client_side_detection_host_unittest.cc
index 8964f9e..b81874e 100644
--- a/chrome/browser/safe_browsing/client_side_detection_host_unittest.cc
+++ b/chrome/browser/safe_browsing/client_side_detection_host_unittest.cc
@@ -28,6 +28,7 @@
using ::testing::_;
using ::testing::DeleteArg;
using ::testing::DoAll;
+using ::testing::Eq;
using ::testing::Mock;
using ::testing::NotNull;
using ::testing::Return;
@@ -35,6 +36,11 @@ using ::testing::SaveArg;
using ::testing::SetArgumentPointee;
using ::testing::StrictMock;
+namespace {
+const bool kFalse = false;
+const bool kTrue = true;
+}
+
namespace safe_browsing {
class MockClientSideDetectionService : public ClientSideDetectionService {
@@ -62,6 +68,7 @@ class MockSafeBrowsingService : public SafeBrowsingService {
MOCK_METHOD8(DisplayBlockingPage,
void(const GURL&, const GURL&, const std::vector<GURL>&,
ResourceType::Type, UrlCheckResult, Client*, int, int));
+ MOCK_METHOD1(MatchCsdWhitelistUrl, bool(const GURL&));
// Helper function which calls OnBlockingPageComplete for this client
// object.
@@ -106,12 +113,18 @@ class ClientSideDetectionHostTest : public RenderViewHostTestHarness {
csd_host_ = contents()->safebrowsing_detection_host();
csd_host_->set_client_side_detection_service(csd_service_.get());
csd_host_->set_safe_browsing_service(sb_service_.get());
+
+ // Save command-line so that it can be restored for every test.
+ original_cmd_line_.reset(
+ new CommandLine(*CommandLine::ForCurrentProcess()));
}
virtual void TearDown() {
io_thread_.reset();
ui_thread_.reset();
RenderViewHostTestHarness::TearDown();
+ // Restore the command-line like it was before we ran the test.
+ *CommandLine::ForCurrentProcess() = *original_cmd_line_;
}
void OnDetectedPhishingSite(const GURL& phishing_url, double phishing_score) {
@@ -128,6 +141,43 @@ class ClientSideDetectionHostTest : public RenderViewHostTestHarness {
MessageLoop::current()->Run();
}
+ void ExpectPreClassificationChecks(const GURL& url,
+ const bool* is_private,
+ const bool* match_csd_whitelist,
+ const bool* get_valid_cached_result,
+ const bool* is_in_cache,
+ const bool* over_report_limit) {
+ if (is_private) {
+ EXPECT_CALL(*csd_service_, IsPrivateIPAddress(_))
+ .WillOnce(Return(*is_private));
+ }
+ if (match_csd_whitelist) {
+ EXPECT_CALL(*sb_service_, MatchCsdWhitelistUrl(url))
+ .WillOnce(Return(*match_csd_whitelist));
+ }
+ if (get_valid_cached_result) {
+ EXPECT_CALL(*csd_service_, GetValidCachedResult(url, NotNull()))
+ .WillOnce(DoAll(SetArgumentPointee<1>(true),
+ Return(*get_valid_cached_result)));
+ }
+ if (is_in_cache) {
+ EXPECT_CALL(*csd_service_, IsInCache(url)).WillOnce(Return(*is_in_cache));
+ }
+ if (over_report_limit) {
+ EXPECT_CALL(*csd_service_, OverReportLimit())
+ .WillOnce(Return(*over_report_limit));
+ }
+ }
+
+ void WaitAndCheckPreClassificationChecks() {
+ // Wait for CheckCsdWhitelist to be called if at all.
+ FlushIOMessageLoop();
+ // Checks for CheckCache() to be called if at all.
+ MessageLoop::current()->RunAllPending();
+ EXPECT_TRUE(Mock::VerifyAndClear(csd_service_.get()));
+ EXPECT_TRUE(Mock::VerifyAndClear(sb_service_.get()));
+ }
+
protected:
ClientSideDetectionHost* csd_host_;
scoped_ptr<StrictMock<MockClientSideDetectionService> > csd_service_;
@@ -136,6 +186,7 @@ class ClientSideDetectionHostTest : public RenderViewHostTestHarness {
private:
scoped_ptr<BrowserThread> ui_thread_;
scoped_ptr<BrowserThread> io_thread_;
+ scoped_ptr<CommandLine> original_cmd_line_;
};
TEST_F(ClientSideDetectionHostTest, OnDetectedPhishingSiteNotPhishing) {
@@ -149,7 +200,7 @@ TEST_F(ClientSideDetectionHostTest, OnDetectedPhishingSiteNotPhishing) {
.WillOnce(SaveArg<2>(&cb));
OnDetectedPhishingSite(phishing_url, 1.0);
EXPECT_TRUE(Mock::VerifyAndClear(csd_service_.get()));
- ASSERT_TRUE(cb != NULL);
+ ASSERT_TRUE(cb);
// Make sure DisplayBlockingPage is not going to be called.
EXPECT_CALL(*sb_service_,
@@ -177,7 +228,7 @@ TEST_F(ClientSideDetectionHostTest, OnDetectedPhishingSiteDisabled) {
.WillOnce(SaveArg<2>(&cb));
OnDetectedPhishingSite(phishing_url, 1.0);
EXPECT_TRUE(Mock::VerifyAndClear(csd_service_.get()));
- ASSERT_TRUE(cb != NULL);
+ ASSERT_TRUE(cb);
// Make sure DisplayBlockingPage is not going to be called.
EXPECT_CALL(*sb_service_,
@@ -203,7 +254,7 @@ TEST_F(ClientSideDetectionHostTest, OnDetectedPhishingSiteShowInterstitial) {
.WillOnce(SaveArg<2>(&cb));
OnDetectedPhishingSite(phishing_url, 1.0);
EXPECT_TRUE(Mock::VerifyAndClear(csd_service_.get()));
- ASSERT_TRUE(cb != NULL);
+ ASSERT_TRUE(cb);
SafeBrowsingService::Client* client;
EXPECT_CALL(*sb_service_,
@@ -255,18 +306,14 @@ TEST_F(ClientSideDetectionHostTest, OnDetectedPhishingSiteMultiplePings) {
.WillOnce(SaveArg<2>(&cb));
OnDetectedPhishingSite(phishing_url, 1.0);
EXPECT_TRUE(Mock::VerifyAndClear(csd_service_.get()));
- ASSERT_TRUE(cb != NULL);
+ ASSERT_TRUE(cb);
GURL other_phishing_url("http://other_phishing_url.com/bla");
- EXPECT_CALL(*csd_service_, IsPrivateIPAddress(_)).WillOnce(Return(false));
- EXPECT_CALL(*csd_service_, GetValidCachedResult(_, _))
- .WillOnce(Return(false));
- EXPECT_CALL(*csd_service_, IsInCache(_)).WillOnce(Return(false));
- EXPECT_CALL(*csd_service_, OverReportLimit()).WillOnce(Return(false));
-
+ ExpectPreClassificationChecks(other_phishing_url, &kFalse, &kFalse, &kFalse,
+ &kFalse, &kFalse);
// We navigate away. The callback cb should be revoked.
NavigateAndCommit(other_phishing_url);
// Wait for the pre-classification checks to finish for other_phishing_url.
- FlushIOMessageLoop();
+ WaitAndCheckPreClassificationChecks();
ClientSideDetectionService::ClientReportPhishingRequestCallback* cb_other;
EXPECT_CALL(*csd_service_,
@@ -317,68 +364,70 @@ TEST_F(ClientSideDetectionHostTest, OnDetectedPhishingSiteMultiplePings) {
}
TEST_F(ClientSideDetectionHostTest, NavigationCancelsShouldClassifyUrl) {
+ // Test that canceling pending should classify requests works as expected.
+
GURL first_url("http://first.phishy.url.com");
+ // The proxy checks is done synchronously so check that it has been done
+ // for the first URL.
+ ExpectPreClassificationChecks(first_url, &kFalse, &kFalse, NULL, NULL, NULL);
NavigateAndCommit(first_url);
+
// Don't flush the message loop, as we want to navigate to a different
- // url before Run() is called on ShouldClassifyUrl.
+ // url before the final pre-classification checks are run.
GURL second_url("http://second.url.com/");
- // We should only see one call to these functions.
- EXPECT_CALL(*csd_service_, IsPrivateIPAddress(_)).WillOnce(Return(false));
- EXPECT_CALL(*csd_service_, GetValidCachedResult(_, _))
- .WillOnce(Return(false));
- EXPECT_CALL(*csd_service_, IsInCache(_)).WillOnce(Return(false));
- EXPECT_CALL(*csd_service_, OverReportLimit()).WillOnce(Return(false));
+ ExpectPreClassificationChecks(second_url, &kFalse, &kFalse, &kFalse, &kFalse,
+ &kFalse);
NavigateAndCommit(second_url);
-
- FlushIOMessageLoop();
+ WaitAndCheckPreClassificationChecks();
}
TEST_F(ClientSideDetectionHostTest, ShouldClassifyUrl) {
// Navigate the tab to a page. We should see a StartPhishingDetection IPC.
- EXPECT_CALL(*csd_service_, IsPrivateIPAddress(_)).WillOnce(Return(false));
- EXPECT_CALL(*csd_service_, GetValidCachedResult(_, _))
- .WillOnce(Return(false));
- EXPECT_CALL(*csd_service_, IsInCache(_)).WillOnce(Return(false));
- EXPECT_CALL(*csd_service_, OverReportLimit()).WillOnce(Return(false));
- NavigateAndCommit(GURL("http://host.com/"));
- FlushIOMessageLoop();
+ GURL url("http://host.com/");
+ ExpectPreClassificationChecks(url, &kFalse, &kFalse, &kFalse, &kFalse,
+ &kFalse);
+ NavigateAndCommit(url);
+ WaitAndCheckPreClassificationChecks();
+
const IPC::Message* msg = process()->sink().GetFirstMessageMatching(
ViewMsg_StartPhishingDetection::ID);
ASSERT_TRUE(msg);
- Tuple1<GURL> url;
- ViewMsg_StartPhishingDetection::Read(msg, &url);
- EXPECT_EQ(GURL("http://host.com/"), url.a);
+ Tuple1<GURL> actual_url;
+ ViewMsg_StartPhishingDetection::Read(msg, &actual_url);
+ EXPECT_EQ(url, actual_url.a);
EXPECT_EQ(rvh()->routing_id(), msg->routing_id());
process()->sink().ClearMessages();
// Now try an in-page navigation. This should not trigger an IPC.
EXPECT_CALL(*csd_service_, IsPrivateIPAddress(_)).Times(0);
- NavigateAndCommit(GURL("http://host.com/#foo"));
- FlushIOMessageLoop();
+ url = GURL("http://host.com/#foo");
+ ExpectPreClassificationChecks(url, NULL, NULL, NULL, NULL, NULL);
+ NavigateAndCommit(url);
+ WaitAndCheckPreClassificationChecks();
+
msg = process()->sink().GetFirstMessageMatching(
ViewMsg_StartPhishingDetection::ID);
ASSERT_FALSE(msg);
// Navigate to a new host, which should cause another IPC.
- EXPECT_CALL(*csd_service_, IsPrivateIPAddress(_)).WillOnce(Return(false));
- EXPECT_CALL(*csd_service_, GetValidCachedResult(_, _))
- .WillOnce(Return(false));
- EXPECT_CALL(*csd_service_, IsInCache(_)).WillOnce(Return(false));
- EXPECT_CALL(*csd_service_, OverReportLimit()).WillOnce(Return(false));
- NavigateAndCommit(GURL("http://host2.com/"));
- FlushIOMessageLoop();
+ url = GURL("http://host2.com/");
+ ExpectPreClassificationChecks(url, &kFalse, &kFalse, &kFalse, &kFalse,
+ &kFalse);
+ NavigateAndCommit(url);
+ WaitAndCheckPreClassificationChecks();
msg = process()->sink().GetFirstMessageMatching(
ViewMsg_StartPhishingDetection::ID);
ASSERT_TRUE(msg);
- ViewMsg_StartPhishingDetection::Read(msg, &url);
- EXPECT_EQ(GURL("http://host2.com/"), url.a);
+ ViewMsg_StartPhishingDetection::Read(msg, &actual_url);
+ EXPECT_EQ(url, actual_url.a);
EXPECT_EQ(rvh()->routing_id(), msg->routing_id());
process()->sink().ClearMessages();
// If IsPrivateIPAddress returns true, no IPC should be triggered.
- EXPECT_CALL(*csd_service_, IsPrivateIPAddress(_)).WillOnce(Return(true));
- NavigateAndCommit(GURL("http://host3.com/"));
- FlushIOMessageLoop();
+ url = GURL("http://host3.com/");
+ ExpectPreClassificationChecks(url, &kTrue, NULL, NULL, NULL, NULL);
+ NavigateAndCommit(url);
+ WaitAndCheckPreClassificationChecks();
msg = process()->sink().GetFirstMessageMatching(
ViewMsg_StartPhishingDetection::ID);
ASSERT_FALSE(msg);
@@ -387,58 +436,71 @@ TEST_F(ClientSideDetectionHostTest, ShouldClassifyUrl) {
// Note: for this test to work correctly, the new URL must be on the
// same domain as the previous URL, otherwise it will create a new
// RenderViewHost that won't have simulate_fetch_via_proxy set.
+ url = GURL("http://host3.com/abc");
rvh()->set_simulate_fetch_via_proxy(true);
- EXPECT_CALL(*csd_service_, IsPrivateIPAddress(_)).Times(0);
- NavigateAndCommit(GURL("http://host3.com/abc"));
- FlushIOMessageLoop();
+ ExpectPreClassificationChecks(url, NULL, NULL, NULL, NULL, NULL);
+ NavigateAndCommit(url);
+ WaitAndCheckPreClassificationChecks();
msg = process()->sink().GetFirstMessageMatching(
ViewMsg_StartPhishingDetection::ID);
ASSERT_FALSE(msg);
- // If result is cached, we will try and display the blocking page directly
- // with no start classification message.
- rvh()->set_simulate_fetch_via_proxy(false);
- EXPECT_CALL(*csd_service_, IsPrivateIPAddress(_)).WillOnce(Return(false));
- EXPECT_CALL(*csd_service_,
- GetValidCachedResult(_, NotNull()))
- .WillOnce(
- DoAll(SetArgumentPointee<1>(true),
- Return(true)));
- EXPECT_CALL(*sb_service_,
- DisplayBlockingPage(_, _, _, _, _, _, _, _))
- .WillOnce(DeleteArg<5>());
-
- NavigateAndCommit(GURL("http://host4.com/"));
- FlushIOMessageLoop();
+ // If the URL is on the csd whitelist, no IPC should be triggered.
+ url = GURL("http://host4.com/");
+ ExpectPreClassificationChecks(url, &kFalse, &kTrue, NULL, NULL, NULL);
+ NavigateAndCommit(url);
+ WaitAndCheckPreClassificationChecks();
msg = process()->sink().GetFirstMessageMatching(
ViewMsg_StartPhishingDetection::ID);
ASSERT_FALSE(msg);
// If item is in the cache but it isn't valid, we will classify regardless
// of whether we are over the reporting limit.
- EXPECT_CALL(*csd_service_, IsPrivateIPAddress(_)).WillOnce(Return(false));
- EXPECT_CALL(*csd_service_, GetValidCachedResult(_, _))
- .WillOnce(Return(false));
- EXPECT_CALL(*csd_service_, IsInCache(_)).WillOnce(Return(true));
- NavigateAndCommit(GURL("http://host5.com/"));
- FlushIOMessageLoop();
+ url = GURL("http://host5.com/");
+ ExpectPreClassificationChecks(url, &kFalse, &kFalse, &kFalse, &kTrue,
+ NULL);
+ NavigateAndCommit(url);
+ WaitAndCheckPreClassificationChecks();
msg = process()->sink().GetFirstMessageMatching(
ViewMsg_StartPhishingDetection::ID);
ASSERT_TRUE(msg);
- ViewMsg_StartPhishingDetection::Read(msg, &url);
- EXPECT_EQ(GURL("http://host5.com/"), url.a);
+ ViewMsg_StartPhishingDetection::Read(msg, &actual_url);
+ EXPECT_EQ(url, actual_url.a);
EXPECT_EQ(rvh()->routing_id(), msg->routing_id());
process()->sink().ClearMessages();
// If the url isn't in the cache and we are over the reporting limit, we
// don't do classification.
- EXPECT_CALL(*csd_service_, IsPrivateIPAddress(_)).WillOnce(Return(false));
- EXPECT_CALL(*csd_service_, GetValidCachedResult(_, _))
- .WillOnce(Return(false));
- EXPECT_CALL(*csd_service_, IsInCache(_)).WillOnce(Return(false));
- EXPECT_CALL(*csd_service_, OverReportLimit()).WillOnce(Return(true));
- NavigateAndCommit(GURL("http://host6.com/"));
+ url = GURL("http://host6.com/");
+ ExpectPreClassificationChecks(url, &kFalse, &kFalse, &kFalse, &kFalse,
+ &kTrue);
+ NavigateAndCommit(url);
+ WaitAndCheckPreClassificationChecks();
+ msg = process()->sink().GetFirstMessageMatching(
+ ViewMsg_StartPhishingDetection::ID);
+ ASSERT_FALSE(msg);
+
+ // If result is cached, we will try and display the blocking page directly
+ // with no start classification message.
+ CommandLine::ForCurrentProcess()->AppendSwitch(
+ switches::kEnableClientSidePhishingInterstitial);
+ url = GURL("http://host7.com/");
+ ExpectPreClassificationChecks(url, &kFalse, &kFalse, &kTrue, NULL,
+ NULL);
+ EXPECT_CALL(*sb_service_,
+ DisplayBlockingPage(Eq(url), Eq(url), _, _, _, _, _, _))
+ .WillOnce(DeleteArg<5>());
+ NavigateAndCommit(url);
+ // Wait for CheckCsdWhitelist to be called on the IO thread.
+ FlushIOMessageLoop();
+ // Wait for CheckCache() to be called on the UI thread.
+ MessageLoop::current()->RunAllPending();
+ // Wait for DisplayBlockingPage to be called on the IO thread.
FlushIOMessageLoop();
+ // Now we check that all expected functions were indeed called on the two
+ // service objects.
+ EXPECT_TRUE(Mock::VerifyAndClear(csd_service_.get()));
+ EXPECT_TRUE(Mock::VerifyAndClear(sb_service_.get()));
msg = process()->sink().GetFirstMessageMatching(
ViewMsg_StartPhishingDetection::ID);
ASSERT_FALSE(msg);
diff --git a/chrome/browser/safe_browsing/safe_browsing_service.h b/chrome/browser/safe_browsing/safe_browsing_service.h
index a3703f3..530374c 100644
--- a/chrome/browser/safe_browsing/safe_browsing_service.h
+++ b/chrome/browser/safe_browsing/safe_browsing_service.h
@@ -165,7 +165,7 @@ class SafeBrowsingService
// match and false otherwise. To make sure we are conservative we will return
// true if an error occurs. This method is expected to be called on the IO
// thread.
- bool MatchCsdWhitelistUrl(const GURL& url);
+ virtual bool MatchCsdWhitelistUrl(const GURL& url);
// Called on the IO thread to cancel a pending check if the result is no
// longer needed.