1dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Use of this source code is governed by a BSD-style license that can be
3dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// found in the LICENSE file.
4dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
5dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "base/command_line.h"
6dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "base/file_path.h"
7ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/ref_counted.h"
8ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/scoped_ptr.h"
9ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/scoped_temp_dir.h"
10dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "base/task.h"
11dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "chrome/browser/safe_browsing/client_side_detection_host.h"
12dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "chrome/browser/safe_browsing/client_side_detection_service.h"
13dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "chrome/browser/safe_browsing/safe_browsing_service.h"
14dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "chrome/common/chrome_switches.h"
15ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/common/safe_browsing/csd.pb.h"
16ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/common/safe_browsing/safebrowsing_messages.h"
17ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/test/testing_profile.h"
18dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "chrome/test/ui_test_utils.h"
19dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/browser_thread.h"
20dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/renderer_host/test_render_view_host.h"
21dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/tab_contents/test_tab_contents.h"
22dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "googleurl/src/gurl.h"
23dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "ipc/ipc_test_sink.h"
24dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "testing/gmock/include/gmock/gmock.h"
25ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "testing/gtest/include/gtest/gtest.h"
26dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
27dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenusing ::testing::_;
28ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenusing ::testing::DeleteArg;
29dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenusing ::testing::DoAll;
30ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenusing ::testing::Eq;
31dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenusing ::testing::Mock;
32ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenusing ::testing::NiceMock;
33ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenusing ::testing::NotNull;
34ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenusing ::testing::Pointee;
35dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenusing ::testing::Return;
36dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenusing ::testing::SaveArg;
37ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenusing ::testing::SetArgumentPointee;
38ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenusing ::testing::StrictMock;
39ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
40ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsennamespace {
41ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenconst bool kFalse = false;
42ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenconst bool kTrue = true;
43ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
44dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
45dc0f95d653279beabeb9817299e2902918ba123eKristian Monsennamespace safe_browsing {
46dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
47ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenMATCHER_P(EqualsProto, other, "") {
48ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return other.SerializeAsString() == arg.SerializeAsString();
49ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
50ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
51dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenclass MockClientSideDetectionService : public ClientSideDetectionService {
52dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen public:
53dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  explicit MockClientSideDetectionService(const FilePath& model_path)
54dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      : ClientSideDetectionService(model_path, NULL) {}
55dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  virtual ~MockClientSideDetectionService() {};
56dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
57ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  MOCK_METHOD2(SendClientReportPhishingRequest,
58ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen               void(ClientPhishingRequest*,
59ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                    ClientReportPhishingRequestCallback*));
60dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  MOCK_CONST_METHOD1(IsPrivateIPAddress, bool(const std::string&));
61ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  MOCK_METHOD2(GetValidCachedResult, bool(const GURL&, bool*));
62ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  MOCK_METHOD1(IsInCache, bool(const GURL&));
63ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  MOCK_METHOD0(OverReportLimit, bool());
64dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
65dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen private:
66dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DISALLOW_COPY_AND_ASSIGN(MockClientSideDetectionService);
67dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen};
68dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
69dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenclass MockSafeBrowsingService : public SafeBrowsingService {
70dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen public:
71dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  MockSafeBrowsingService() {}
72dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  virtual ~MockSafeBrowsingService() {}
73dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
74dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  MOCK_METHOD8(DisplayBlockingPage,
75dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen               void(const GURL&, const GURL&, const std::vector<GURL>&,
76dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                    ResourceType::Type, UrlCheckResult, Client*, int, int));
77ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  MOCK_METHOD1(MatchCsdWhitelistUrl, bool(const GURL&));
78dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
79dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Helper function which calls OnBlockingPageComplete for this client
80dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // object.
81dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  void InvokeOnBlockingPageComplete(SafeBrowsingService::Client* client) {
82dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
83dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    DCHECK(client);
84dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // Note: this will delete the client object in the case of the CsdClient
85dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // implementation.
86dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    client->OnBlockingPageComplete(false);
87dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
88dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
89dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen private:
90dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DISALLOW_COPY_AND_ASSIGN(MockSafeBrowsingService);
91dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen};
92dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
93ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenclass MockTestingProfile : public TestingProfile {
94ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen public:
95ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  MockTestingProfile() {}
96ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  virtual ~MockTestingProfile() {}
97ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
98ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  MOCK_METHOD0(IsOffTheRecord, bool());
99ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen};
100ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
101dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Helper function which quits the UI message loop from the IO message loop.
102dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid QuitUIMessageLoop() {
103dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
104dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  BrowserThread::PostTask(BrowserThread::UI,
105dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                          FROM_HERE,
106dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                          new MessageLoop::QuitTask());
107dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
108dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
109dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenclass ClientSideDetectionHostTest : public RenderViewHostTestHarness {
110dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen public:
111dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  virtual void SetUp() {
112ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // Set custom profile object so that we can mock calls to IsOffTheRecord.
113ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // This needs to happen before we call the parent SetUp() function.  We use
114ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // a nice mock because other parts of the code are calling IsOffTheRecord.
115ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    mock_profile_ = new NiceMock<MockTestingProfile>();
116ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    profile_.reset(mock_profile_);
117ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
118dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    RenderViewHostTestHarness::SetUp();
119dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    ui_thread_.reset(new BrowserThread(BrowserThread::UI, &message_loop_));
120dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // Note: we're starting a real IO thread to make sure our DCHECKs that
121dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // verify which thread is running are actually tested.
122dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    io_thread_.reset(new BrowserThread(BrowserThread::IO));
123dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    ASSERT_TRUE(io_thread_->Start());
124dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
125dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // Inject service classes.
126dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    ScopedTempDir tmp_dir;
127dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    ASSERT_TRUE(tmp_dir.CreateUniqueTempDir());
128dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    FilePath model_path = tmp_dir.path().AppendASCII("model");
129dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
130ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    csd_service_.reset(new StrictMock<MockClientSideDetectionService>(
131ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        model_path));
132ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    sb_service_ = new StrictMock<MockSafeBrowsingService>();
133dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    csd_host_ = contents()->safebrowsing_detection_host();
134dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    csd_host_->set_client_side_detection_service(csd_service_.get());
135dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    csd_host_->set_safe_browsing_service(sb_service_.get());
136ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
137ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // Save command-line so that it can be restored for every test.
138ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    original_cmd_line_.reset(
139ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        new CommandLine(*CommandLine::ForCurrentProcess()));
140dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
141dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
142dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  virtual void TearDown() {
143dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    io_thread_.reset();
144dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    ui_thread_.reset();
145dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    RenderViewHostTestHarness::TearDown();
146ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // Restore the command-line like it was before we ran the test.
147ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    *CommandLine::ForCurrentProcess() = *original_cmd_line_;
148dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
149dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
150ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  void OnDetectedPhishingSite(const std::string& verdict_str) {
151ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    csd_host_->OnDetectedPhishingSite(verdict_str);
152dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
153dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
154dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  void FlushIOMessageLoop() {
155dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // If there was a message posted on the IO thread to display the
156dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // interstitial page we know that it would have been posted before
157dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // we put the quit message there.
158dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    BrowserThread::PostTask(BrowserThread::IO,
159dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                            FROM_HERE,
160dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                            NewRunnableFunction(&QuitUIMessageLoop));
161dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    MessageLoop::current()->Run();
162dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
163dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
164ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  void ExpectPreClassificationChecks(const GURL& url,
165ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                     const bool* is_private,
166ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                     const bool* is_incognito,
167ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                     const bool* match_csd_whitelist,
168ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                     const bool* get_valid_cached_result,
169ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                     const bool* is_in_cache,
170ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                     const bool* over_report_limit) {
171ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (is_private) {
172ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      EXPECT_CALL(*csd_service_, IsPrivateIPAddress(_))
173ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          .WillOnce(Return(*is_private));
174ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
175ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (is_incognito) {
176ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      EXPECT_CALL(*mock_profile_, IsOffTheRecord())
177ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          .WillRepeatedly(Return(*is_incognito));
178ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
179ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (match_csd_whitelist) {
180ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      EXPECT_CALL(*sb_service_, MatchCsdWhitelistUrl(url))
181ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          .WillOnce(Return(*match_csd_whitelist));
182ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
183ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (get_valid_cached_result) {
184ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      EXPECT_CALL(*csd_service_, GetValidCachedResult(url, NotNull()))
185ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          .WillOnce(DoAll(SetArgumentPointee<1>(true),
186ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                          Return(*get_valid_cached_result)));
187ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
188ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (is_in_cache) {
189ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      EXPECT_CALL(*csd_service_, IsInCache(url)).WillOnce(Return(*is_in_cache));
190ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
191ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (over_report_limit) {
192ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      EXPECT_CALL(*csd_service_, OverReportLimit())
193ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          .WillOnce(Return(*over_report_limit));
194ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
195ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
196ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
197ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  void WaitAndCheckPreClassificationChecks() {
198ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // Wait for CheckCsdWhitelist to be called if at all.
199ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    FlushIOMessageLoop();
200ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // Checks for CheckCache() to be called if at all.
201ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    MessageLoop::current()->RunAllPending();
202ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    EXPECT_TRUE(Mock::VerifyAndClear(csd_service_.get()));
203ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    EXPECT_TRUE(Mock::VerifyAndClear(sb_service_.get()));
204ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    EXPECT_TRUE(Mock::VerifyAndClear(mock_profile_));
205ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
206ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
207dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen protected:
208dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  ClientSideDetectionHost* csd_host_;
209ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  scoped_ptr<StrictMock<MockClientSideDetectionService> > csd_service_;
210ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  scoped_refptr<StrictMock<MockSafeBrowsingService> > sb_service_;
211ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  MockTestingProfile* mock_profile_;  // We don't own this object
212dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
213dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen private:
214dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  scoped_ptr<BrowserThread> ui_thread_;
215dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  scoped_ptr<BrowserThread> io_thread_;
216ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  scoped_ptr<CommandLine> original_cmd_line_;
217dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen};
218dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
219ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenTEST_F(ClientSideDetectionHostTest, OnDetectedPhishingSiteInvalidVerdict) {
220ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Case 0: renderer sends an invalid verdict string that we're unable to
221ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // parse.
222ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  EXPECT_CALL(*csd_service_, SendClientReportPhishingRequest(_, _)).Times(0);
223ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  OnDetectedPhishingSite("Invalid Protocol Buffer");
224ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  EXPECT_TRUE(Mock::VerifyAndClear(csd_service_.get()));
225ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
226ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
227dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenTEST_F(ClientSideDetectionHostTest, OnDetectedPhishingSiteNotPhishing) {
228dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Case 1: client thinks the page is phishing.  The server does not agree.
229dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // No interstitial is shown.
230dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  ClientSideDetectionService::ClientReportPhishingRequestCallback* cb;
231ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ClientPhishingRequest verdict;
232ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  verdict.set_url("http://phishingurl.com/");
233ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  verdict.set_client_score(1.0f);
234ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  verdict.set_is_phishing(true);
235dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
236dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_CALL(*csd_service_,
237ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen              SendClientReportPhishingRequest(Pointee(EqualsProto(verdict)), _))
238ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      .WillOnce(DoAll(DeleteArg<0>(), SaveArg<1>(&cb)));
239ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  OnDetectedPhishingSite(verdict.SerializeAsString());
240dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_TRUE(Mock::VerifyAndClear(csd_service_.get()));
241ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ASSERT_TRUE(cb);
242dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
243dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Make sure DisplayBlockingPage is not going to be called.
244dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_CALL(*sb_service_,
245dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen              DisplayBlockingPage(_, _, _, _, _, _, _, _)).Times(0);
246ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  cb->Run(GURL(verdict.url()), false);
247dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  delete cb;
248dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // If there was a message posted on the IO thread to display the
249dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // interstitial page we know that it would have been posted before
250dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // we put the quit message there.
251dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  BrowserThread::PostTask(BrowserThread::IO,
252dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                          FROM_HERE,
253dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                          NewRunnableFunction(&QuitUIMessageLoop));
254dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  MessageLoop::current()->Run();
255dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_TRUE(Mock::VerifyAndClear(sb_service_.get()));
256dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
257dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
258dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenTEST_F(ClientSideDetectionHostTest, OnDetectedPhishingSiteDisabled) {
259dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Case 2: client thinks the page is phishing and so does the server but
260dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // showing the interstitial is disabled => no interstitial is shown.
261dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  ClientSideDetectionService::ClientReportPhishingRequestCallback* cb;
262ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ClientPhishingRequest verdict;
263ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  verdict.set_url("http://phishingurl.com/");
264ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  verdict.set_client_score(1.0f);
265ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  verdict.set_is_phishing(true);
266dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
267dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_CALL(*csd_service_,
268ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen              SendClientReportPhishingRequest(Pointee(EqualsProto(verdict)), _))
269ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      .WillOnce(DoAll(DeleteArg<0>(), SaveArg<1>(&cb)));
270ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  OnDetectedPhishingSite(verdict.SerializeAsString());
271dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_TRUE(Mock::VerifyAndClear(csd_service_.get()));
272ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ASSERT_TRUE(cb);
273dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
274dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Make sure DisplayBlockingPage is not going to be called.
275dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_CALL(*sb_service_,
276dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen              DisplayBlockingPage(_, _, _, _, _, _, _, _)).Times(0);
277ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  cb->Run(GURL(verdict.url()), false);
278dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  delete cb;
279dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
280dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  FlushIOMessageLoop();
281dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_TRUE(Mock::VerifyAndClear(sb_service_.get()));
282dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
283dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
284dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenTEST_F(ClientSideDetectionHostTest, OnDetectedPhishingSiteShowInterstitial) {
285dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Case 3: client thinks the page is phishing and so does the server.
286dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // We show an interstitial.
287dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  ClientSideDetectionService::ClientReportPhishingRequestCallback* cb;
288dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  GURL phishing_url("http://phishingurl.com/");
289ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ClientPhishingRequest verdict;
290ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  verdict.set_url(phishing_url.spec());
291ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  verdict.set_client_score(1.0f);
292ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  verdict.set_is_phishing(true);
293dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
294dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  CommandLine::ForCurrentProcess()->AppendSwitch(
295dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      switches::kEnableClientSidePhishingInterstitial);
296dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
297dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_CALL(*csd_service_,
298ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen              SendClientReportPhishingRequest(Pointee(EqualsProto(verdict)), _))
299ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      .WillOnce(DoAll(DeleteArg<0>(), SaveArg<1>(&cb)));
300ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  OnDetectedPhishingSite(verdict.SerializeAsString());
301dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_TRUE(Mock::VerifyAndClear(csd_service_.get()));
302ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ASSERT_TRUE(cb);
303dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
304dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  SafeBrowsingService::Client* client;
305dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_CALL(*sb_service_,
306dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen              DisplayBlockingPage(
307dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                  phishing_url,
308dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                  phishing_url,
309dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                  _,
310dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                  ResourceType::MAIN_FRAME,
311dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                  SafeBrowsingService::URL_PHISHING,
312dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                  _ /* a CsdClient object */,
313dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                  contents()->GetRenderProcessHost()->id(),
314dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                  contents()->render_view_host()->routing_id()))
315dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      .WillOnce(SaveArg<5>(&client));
316dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
317dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  cb->Run(phishing_url, true);
318dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  delete cb;
319dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
320dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  FlushIOMessageLoop();
321dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_TRUE(Mock::VerifyAndClear(sb_service_.get()));
322dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
323dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Make sure the client object will be deleted.
324dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  BrowserThread::PostTask(
325dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      BrowserThread::IO,
326dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      FROM_HERE,
327dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      NewRunnableMethod(
328dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          sb_service_.get(),
329dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          &MockSafeBrowsingService::InvokeOnBlockingPageComplete,
330dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          client));
331dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Since the CsdClient object will be deleted on the UI thread I need
332dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // to run the UI message loop.  Post a task to stop the UI message loop
333dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // after the client object destructor is called.
334dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  FlushIOMessageLoop();
335dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
336dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
337dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenTEST_F(ClientSideDetectionHostTest, OnDetectedPhishingSiteMultiplePings) {
338dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Case 4 & 5: client thinks a page is phishing then navigates to
339dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // another page which is also considered phishing by the client
340dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // before the server responds with a verdict.  After a while the
341dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // server responds for both requests with a phishing verdict.  Only
342dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // a single interstitial is shown for the second URL.
343dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  ClientSideDetectionService::ClientReportPhishingRequestCallback* cb;
344dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  GURL phishing_url("http://phishingurl.com/");
345ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ClientPhishingRequest verdict;
346ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  verdict.set_url(phishing_url.spec());
347ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  verdict.set_client_score(1.0f);
348ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  verdict.set_is_phishing(true);
349dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
350dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  CommandLine::ForCurrentProcess()->AppendSwitch(
351dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      switches::kEnableClientSidePhishingInterstitial);
352dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
353dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_CALL(*csd_service_,
354ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen              SendClientReportPhishingRequest(Pointee(EqualsProto(verdict)), _))
355ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      .WillOnce(DoAll(DeleteArg<0>(), SaveArg<1>(&cb)));
356ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  OnDetectedPhishingSite(verdict.SerializeAsString());
357dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_TRUE(Mock::VerifyAndClear(csd_service_.get()));
358ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ASSERT_TRUE(cb);
359dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  GURL other_phishing_url("http://other_phishing_url.com/bla");
360ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ExpectPreClassificationChecks(other_phishing_url, &kFalse, &kFalse, &kFalse,
361ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                &kFalse, &kFalse, &kFalse);
362dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // We navigate away.  The callback cb should be revoked.
363dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  NavigateAndCommit(other_phishing_url);
364dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Wait for the pre-classification checks to finish for other_phishing_url.
365ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  WaitAndCheckPreClassificationChecks();
366dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
367dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  ClientSideDetectionService::ClientReportPhishingRequestCallback* cb_other;
368ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  verdict.set_url(other_phishing_url.spec());
369ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  verdict.set_client_score(0.8f);
370dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_CALL(*csd_service_,
371ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen              SendClientReportPhishingRequest(Pointee(EqualsProto(verdict)), _))
372ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      .WillOnce(DoAll(DeleteArg<0>(), SaveArg<1>(&cb_other)));
373ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  OnDetectedPhishingSite(verdict.SerializeAsString());
374dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_TRUE(Mock::VerifyAndClear(csd_service_.get()));
375dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  ASSERT_TRUE(cb_other);
376dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
377dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // We expect that the interstitial is shown for the second phishing URL and
378dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // not for the first phishing URL.
379dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_CALL(*sb_service_,
380dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen              DisplayBlockingPage(phishing_url, phishing_url,_, _, _, _, _, _))
381dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      .Times(0);
382dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  SafeBrowsingService::Client* client;
383dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_CALL(*sb_service_,
384dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen              DisplayBlockingPage(
385dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                  other_phishing_url,
386dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                  other_phishing_url,
387dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                  _,
388dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                  ResourceType::MAIN_FRAME,
389dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                  SafeBrowsingService::URL_PHISHING,
390dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                  _ /* a CsdClient object */,
391dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                  contents()->GetRenderProcessHost()->id(),
392dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                  contents()->render_view_host()->routing_id()))
393dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      .WillOnce(SaveArg<5>(&client));
394dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
395dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  cb->Run(phishing_url, true);  // Should have no effect.
396dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  delete cb;
397dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  cb_other->Run(other_phishing_url, true);  // Should show interstitial.
398dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  delete cb_other;
399dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
400dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  FlushIOMessageLoop();
401dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_TRUE(Mock::VerifyAndClear(sb_service_.get()));
402dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
403dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Make sure the client object will be deleted.
404dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  BrowserThread::PostTask(
405dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      BrowserThread::IO,
406dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      FROM_HERE,
407dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      NewRunnableMethod(
408dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          sb_service_.get(),
409dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          &MockSafeBrowsingService::InvokeOnBlockingPageComplete,
410dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          client));
411dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Since the CsdClient object will be deleted on the UI thread I need
412dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // to run the UI message loop.  Post a task to stop the UI message loop
413dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // after the client object destructor is called.
414dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  FlushIOMessageLoop();
415dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
416dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
417ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenTEST_F(ClientSideDetectionHostTest, NavigationCancelsShouldClassifyUrl) {
418ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Test that canceling pending should classify requests works as expected.
419ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
420ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  GURL first_url("http://first.phishy.url.com");
421ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // The proxy checks is done synchronously so check that it has been done
422ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // for the first URL.
423ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ExpectPreClassificationChecks(first_url, &kFalse, &kFalse, &kFalse, NULL,
424ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                NULL, NULL);
425ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  NavigateAndCommit(first_url);
426ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
427ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Don't flush the message loop, as we want to navigate to a different
428ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // url before the final pre-classification checks are run.
429ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  GURL second_url("http://second.url.com/");
430ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ExpectPreClassificationChecks(second_url, &kFalse, &kFalse, &kFalse, &kFalse,
431ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                &kFalse, &kFalse);
432ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  NavigateAndCommit(second_url);
433ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  WaitAndCheckPreClassificationChecks();
434ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
435ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
436dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenTEST_F(ClientSideDetectionHostTest, ShouldClassifyUrl) {
437dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Navigate the tab to a page.  We should see a StartPhishingDetection IPC.
438ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  GURL url("http://host.com/");
439ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ExpectPreClassificationChecks(url, &kFalse, &kFalse, &kFalse, &kFalse,
440ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                &kFalse, &kFalse);
441ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  NavigateAndCommit(url);
442ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  WaitAndCheckPreClassificationChecks();
443ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
444dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  const IPC::Message* msg = process()->sink().GetFirstMessageMatching(
445ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      SafeBrowsingMsg_StartPhishingDetection::ID);
446dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  ASSERT_TRUE(msg);
447ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  Tuple1<GURL> actual_url;
448ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  SafeBrowsingMsg_StartPhishingDetection::Read(msg, &actual_url);
449ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  EXPECT_EQ(url, actual_url.a);
450dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_EQ(rvh()->routing_id(), msg->routing_id());
451dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  process()->sink().ClearMessages();
452dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
453dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Now try an in-page navigation.  This should not trigger an IPC.
454dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_CALL(*csd_service_, IsPrivateIPAddress(_)).Times(0);
455ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  url = GURL("http://host.com/#foo");
456ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ExpectPreClassificationChecks(url, NULL, NULL, NULL, NULL, NULL, NULL);
457ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  NavigateAndCommit(url);
458ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  WaitAndCheckPreClassificationChecks();
459ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
460dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  msg = process()->sink().GetFirstMessageMatching(
461ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      SafeBrowsingMsg_StartPhishingDetection::ID);
462dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  ASSERT_FALSE(msg);
463dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
464ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Check that XHTML is supported, in addition to the default HTML type.
465ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Note: for this test to work correctly, the new URL must be on the
466ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // same domain as the previous URL, otherwise it will create a new
467ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // RenderViewHost that won't have the mime type set.
468ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  url = GURL("http://host.com/xhtml");
469ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  rvh()->set_contents_mime_type("application/xhtml+xml");
470ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ExpectPreClassificationChecks(url, &kFalse, &kFalse, &kFalse, &kFalse,
471ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                &kFalse, &kFalse);
472ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  NavigateAndCommit(url);
473ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  WaitAndCheckPreClassificationChecks();
474ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  msg = process()->sink().GetFirstMessageMatching(
475ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      SafeBrowsingMsg_StartPhishingDetection::ID);
476ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ASSERT_TRUE(msg);
477ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  SafeBrowsingMsg_StartPhishingDetection::Read(msg, &actual_url);
478ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  EXPECT_EQ(url, actual_url.a);
479ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  EXPECT_EQ(rvh()->routing_id(), msg->routing_id());
480ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  process()->sink().ClearMessages();
481ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
482dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Navigate to a new host, which should cause another IPC.
483ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  url = GURL("http://host2.com/");
484ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ExpectPreClassificationChecks(url, &kFalse, &kFalse, &kFalse, &kFalse,
485ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                &kFalse, &kFalse);
486ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  NavigateAndCommit(url);
487ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  WaitAndCheckPreClassificationChecks();
488dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  msg = process()->sink().GetFirstMessageMatching(
489ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      SafeBrowsingMsg_StartPhishingDetection::ID);
490dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  ASSERT_TRUE(msg);
491ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  SafeBrowsingMsg_StartPhishingDetection::Read(msg, &actual_url);
492ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  EXPECT_EQ(url, actual_url.a);
493dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_EQ(rvh()->routing_id(), msg->routing_id());
494dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  process()->sink().ClearMessages();
495dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
496ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // If the mime type is not one that we support, no IPC should be triggered.
497ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Note: for this test to work correctly, the new URL must be on the
498ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // same domain as the previous URL, otherwise it will create a new
499ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // RenderViewHost that won't have the mime type set.
500ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  url = GURL("http://host2.com/image.jpg");
501ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  rvh()->set_contents_mime_type("image/jpeg");
502ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ExpectPreClassificationChecks(url, NULL, NULL, NULL, NULL, NULL, NULL);
503ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  NavigateAndCommit(url);
504ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  WaitAndCheckPreClassificationChecks();
505ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  msg = process()->sink().GetFirstMessageMatching(
506ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      SafeBrowsingMsg_StartPhishingDetection::ID);
507ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ASSERT_FALSE(msg);
508ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
509dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // If IsPrivateIPAddress returns true, no IPC should be triggered.
510ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  url = GURL("http://host3.com/");
511ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ExpectPreClassificationChecks(url, &kTrue, NULL, NULL, NULL, NULL, NULL);
512ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  NavigateAndCommit(url);
513ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  WaitAndCheckPreClassificationChecks();
514dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  msg = process()->sink().GetFirstMessageMatching(
515ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      SafeBrowsingMsg_StartPhishingDetection::ID);
516dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  ASSERT_FALSE(msg);
517dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
518dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // If the connection is proxied, no IPC should be triggered.
519dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Note: for this test to work correctly, the new URL must be on the
520dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // same domain as the previous URL, otherwise it will create a new
521dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // RenderViewHost that won't have simulate_fetch_via_proxy set.
522ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  url = GURL("http://host3.com/abc");
523dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  rvh()->set_simulate_fetch_via_proxy(true);
524ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ExpectPreClassificationChecks(url, NULL, NULL, NULL, NULL, NULL, NULL);
525ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  NavigateAndCommit(url);
526ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  WaitAndCheckPreClassificationChecks();
527ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  msg = process()->sink().GetFirstMessageMatching(
528ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      SafeBrowsingMsg_StartPhishingDetection::ID);
529ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ASSERT_FALSE(msg);
530ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
531ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // If the tab is incognito there should be no IPC.  Also, we shouldn't
532ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // even check the csd-whitelist.
533ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  url = GURL("http://host4.com/");
534ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ExpectPreClassificationChecks(url, &kFalse, &kTrue, NULL, NULL, NULL, NULL);
535ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  NavigateAndCommit(url);
536ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  WaitAndCheckPreClassificationChecks();
537ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  msg = process()->sink().GetFirstMessageMatching(
538ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      SafeBrowsingMsg_StartPhishingDetection::ID);
539ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ASSERT_FALSE(msg);
540ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
541ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // If the URL is on the csd whitelist, no IPC should be triggered.
542ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  url = GURL("http://host5.com/");
543ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ExpectPreClassificationChecks(url, &kFalse, &kFalse, &kTrue, NULL, NULL,
544ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                NULL);
545ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  NavigateAndCommit(url);
546ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  WaitAndCheckPreClassificationChecks();
547ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  msg = process()->sink().GetFirstMessageMatching(
548ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      SafeBrowsingMsg_StartPhishingDetection::ID);
549ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ASSERT_FALSE(msg);
550ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
551ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // If item is in the cache but it isn't valid, we will classify regardless
552ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // of whether we are over the reporting limit.
553ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  url = GURL("http://host6.com/");
554ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ExpectPreClassificationChecks(url, &kFalse, &kFalse, &kFalse, &kFalse, &kTrue,
555ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                NULL);
556ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  NavigateAndCommit(url);
557ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  WaitAndCheckPreClassificationChecks();
558ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  msg = process()->sink().GetFirstMessageMatching(
559ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      SafeBrowsingMsg_StartPhishingDetection::ID);
560ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ASSERT_TRUE(msg);
561ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  SafeBrowsingMsg_StartPhishingDetection::Read(msg, &actual_url);
562ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  EXPECT_EQ(url, actual_url.a);
563ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  EXPECT_EQ(rvh()->routing_id(), msg->routing_id());
564ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  process()->sink().ClearMessages();
565ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
566ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // If the url isn't in the cache and we are over the reporting limit, we
567ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // don't do classification.
568ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  url = GURL("http://host7.com/");
569ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ExpectPreClassificationChecks(url, &kFalse, &kFalse, &kFalse, &kFalse,
570ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                &kFalse, &kTrue);
571ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  NavigateAndCommit(url);
572ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  WaitAndCheckPreClassificationChecks();
573ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  msg = process()->sink().GetFirstMessageMatching(
574ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      SafeBrowsingMsg_StartPhishingDetection::ID);
575ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ASSERT_FALSE(msg);
576ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
577ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // If result is cached, we will try and display the blocking page directly
578ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // with no start classification message.
579ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  CommandLine::ForCurrentProcess()->AppendSwitch(
580ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      switches::kEnableClientSidePhishingInterstitial);
581ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  url = GURL("http://host8.com/");
582ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ExpectPreClassificationChecks(url, &kFalse, &kFalse, &kFalse, &kTrue, NULL,
583ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                NULL);
584ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  EXPECT_CALL(*sb_service_,
585ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen              DisplayBlockingPage(Eq(url), Eq(url), _, _, _, _, _, _))
586ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      .WillOnce(DeleteArg<5>());
587ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  NavigateAndCommit(url);
588ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Wait for CheckCsdWhitelist to be called on the IO thread.
589ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  FlushIOMessageLoop();
590ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Wait for CheckCache() to be called on the UI thread.
591ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  MessageLoop::current()->RunAllPending();
592ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Wait for DisplayBlockingPage to be called on the IO thread.
593dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  FlushIOMessageLoop();
594ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Now we check that all expected functions were indeed called on the two
595ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // service objects.
596ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  EXPECT_TRUE(Mock::VerifyAndClear(csd_service_.get()));
597ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  EXPECT_TRUE(Mock::VerifyAndClear(sb_service_.get()));
598dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  msg = process()->sink().GetFirstMessageMatching(
599ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      SafeBrowsingMsg_StartPhishingDetection::ID);
600dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  ASSERT_FALSE(msg);
601dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
602dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
603dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}  // namespace safe_browsing
604