Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(194)

Side by Side Diff: chrome/browser/safe_browsing/client_side_detection_host_unittest.cc

Issue 6014003: Intergration of the client-side phishing detection. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Remove comment Created 9 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/command_line.h"
6 #include "base/file_path.h"
7 #include "base/ref_counted.h"
8 #include "base/scoped_ptr.h"
9 #include "base/scoped_temp_dir.h"
10 #include "base/task.h"
11 #include "chrome/browser/browser_thread.h"
12 #include "chrome/browser/renderer_host/test/test_render_view_host.h"
13 #include "chrome/browser/safe_browsing/client_side_detection_host.h"
14 #include "chrome/browser/safe_browsing/client_side_detection_service.h"
15 #include "chrome/browser/safe_browsing/safe_browsing_service.h"
16 #include "chrome/browser/tab_contents/test_tab_contents.h"
17 #include "chrome/common/chrome_switches.h"
18 #include "chrome/test/ui_test_utils.h"
19 #include "googleurl/src/gurl.h"
20 #include "testing/gmock/include/gmock/gmock.h"
21 #include "testing/gmock/include/gmock/gmock-spec-builders.h"
22
23 using ::testing::_;
24 using ::testing::DoAll;
25 using ::testing::Mock;
26 using ::testing::SaveArg;
27
28 namespace safe_browsing {
29
30 class MockClientSideDetectionService : public ClientSideDetectionService {
31 public:
32 MockClientSideDetectionService(const FilePath& model_path)
33 : ClientSideDetectionService(model_path, NULL) {}
34 virtual ~MockClientSideDetectionService() {};
35
36 MOCK_METHOD3(SendClientReportPhishingRequest,
37 void(const GURL&, double, ClientReportPhishingRequestCallback*));
38
39 private:
40 DISALLOW_COPY_AND_ASSIGN(MockClientSideDetectionService);
41 };
42
43 class MockSafeBrowsingService : public SafeBrowsingService {
44 public:
45 MockSafeBrowsingService() {}
46 virtual ~MockSafeBrowsingService() {}
47
48 MOCK_METHOD8(DisplayBlockingPage,
49 void(const GURL&, const GURL&, const std::vector<GURL>&,
50 ResourceType::Type, UrlCheckResult, Client*, int, int));
51
52 // Helper function which calls OnBlockingPageComplete for this client
53 // object.
54 void InvokeOnBlockingPageComplete(SafeBrowsingService::Client* client) {
55 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
56 DCHECK(client);
57 // Note: this will delete the client object in the case of the CsdClient
58 // implementation.
59 client->OnBlockingPageComplete(false);
60 }
61
62 private:
63 DISALLOW_COPY_AND_ASSIGN(MockSafeBrowsingService);
64 };
65
66 // Helper function which quits the UI message loop from the IO message loop.
67 void QuitUIMessageLoop() {
68 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
69 BrowserThread::PostTask(BrowserThread::UI,
70 FROM_HERE,
71 new MessageLoop::QuitTask());
72 }
73
74 class ClientSideDetectionHostTest : public RenderViewHostTestHarness {
75 public:
76 virtual void SetUp() {
77 RenderViewHostTestHarness::SetUp();
78 ui_thread_.reset(new BrowserThread(BrowserThread::UI, &message_loop_));
79 // Note: we're starting a real IO thread to make sure our DCHECKs that
80 // verify which thread is running are actually tested.
81 io_thread_.reset(new BrowserThread(BrowserThread::IO));
82 CHECK(io_thread_->Start());
Brian Ryner 2011/02/16 22:37:10 I've been told in the past to prefer ASSERT_TRUE o
noelutz 2011/02/16 23:22:36 Done.
83
84 // Inject service classes.
85 ScopedTempDir tmp_dir;
86 ASSERT_TRUE(tmp_dir.CreateUniqueTempDir());
87 FilePath model_path = tmp_dir.path().AppendASCII("model");
88
89 csd_service_.reset(new MockClientSideDetectionService(model_path));
90 sb_service_ = new MockSafeBrowsingService();
91 csd_host_ = contents()->safebrowsing_detection_host();
92 csd_host_->set_client_side_detection_service(csd_service_.get());
93 csd_host_->set_safe_browsing_service(sb_service_.get());
94 }
95
96 virtual void TearDown() {
97 io_thread_->Stop();
Brian Ryner 2011/02/16 22:37:10 I think the thread stops automatically when it is
noelutz 2011/02/16 23:22:36 Done.
98 io_thread_.reset();
99 ui_thread_.reset();
100 RenderViewHostTestHarness::TearDown();
101 }
102
103 void OnDetectedPhishingSite(const GURL& phishing_url, double phishing_score) {
104 csd_host_->OnDetectedPhishingSite(phishing_url, phishing_score);
105 }
106
107 protected:
108 ClientSideDetectionHost* csd_host_;
109 scoped_ptr<MockClientSideDetectionService> csd_service_;
110 scoped_refptr<MockSafeBrowsingService> sb_service_;
111
112 private:
113 scoped_ptr<BrowserThread> ui_thread_;
114 scoped_ptr<BrowserThread> io_thread_;
115 };
116
117 TEST_F(ClientSideDetectionHostTest, OnDetectedPhishingSiteNotPhishing) {
118 // Case 1: client thinks the page is phishing. The server does not agree.
119 // No interstitial is shown.
120 ClientSideDetectionService::ClientReportPhishingRequestCallback* cb;
121 GURL phishing_url("http://phishingurl.com/");
122
123 EXPECT_CALL(*csd_service_,
124 SendClientReportPhishingRequest(phishing_url, 1.0, _))
125 .WillOnce(SaveArg<2>(&cb));
126 OnDetectedPhishingSite(phishing_url, 1.0);
127 EXPECT_TRUE(Mock::VerifyAndClear(csd_service_.get()));
128 ASSERT_TRUE(cb != NULL);
129
130 // Make sure DisplayBlockingPage is not going to be called.
131 EXPECT_CALL(*sb_service_,
132 DisplayBlockingPage(_, _, _, _, _, _, _, _)).Times(0);
133 cb->Run(phishing_url, false);
134 delete cb;
135 // If there was a message posted on the IO thread to display the
136 // interstitial page we know that it would have been posted before
137 // we put the quit message there.
138 BrowserThread::PostTask(BrowserThread::IO,
139 FROM_HERE,
140 NewRunnableFunction(&QuitUIMessageLoop));
141 MessageLoop::current()->Run();
142 EXPECT_TRUE(Mock::VerifyAndClear(sb_service_.get()));
143 }
144
145 TEST_F(ClientSideDetectionHostTest, OnDetectedPhishingSiteDisabled) {
146 // Case 2: client thinks the page is phishing and so does the server but
147 // showing the interstitial is disabled => no interstitial is shown.
148 ClientSideDetectionService::ClientReportPhishingRequestCallback* cb;
149 GURL phishing_url("http://phishingurl.com/");
150
151 EXPECT_CALL(*csd_service_,
152 SendClientReportPhishingRequest(phishing_url, 1.0, _))
153 .WillOnce(SaveArg<2>(&cb));
154 OnDetectedPhishingSite(phishing_url, 1.0);
155 EXPECT_TRUE(Mock::VerifyAndClear(csd_service_.get()));
156 ASSERT_TRUE(cb != NULL);
157
158 // Make sure DisplayBlockingPage is not going to be called.
159 EXPECT_CALL(*sb_service_,
160 DisplayBlockingPage(_, _, _, _, _, _, _, _)).Times(0);
161 cb->Run(phishing_url, false);
162 delete cb;
163
164 // If there was a message posted on the IO thread to display the
Brian Ryner 2011/02/16 22:37:10 You could factor this out into a helper method, th
noelutz 2011/02/16 23:22:36 Done.
noelutz 2011/02/16 23:22:36 Done.
165 // interstitial page we know that it would have been posted before
166 // we put the quit message there.
167 BrowserThread::PostTask(BrowserThread::IO,
168 FROM_HERE,
169 NewRunnableFunction(&QuitUIMessageLoop));
170 MessageLoop::current()->Run();
171 EXPECT_TRUE(Mock::VerifyAndClear(sb_service_.get()));
172 }
173
174 TEST_F(ClientSideDetectionHostTest, OnDetectedPhishingSiteShowInterstitial) {
175 // Case 3: client thinks the page is phishing and so does the server.
176 // We show an interstitial.
177 ClientSideDetectionService::ClientReportPhishingRequestCallback* cb;
178 GURL phishing_url("http://phishingurl.com/");
179
180 CommandLine::ForCurrentProcess()->AppendSwitch(
181 switches::kEnableClientSidePhishingInterstitial);
182
183 EXPECT_CALL(*csd_service_,
184 SendClientReportPhishingRequest(phishing_url, 1.0, _))
185 .WillOnce(SaveArg<2>(&cb));
186 OnDetectedPhishingSite(phishing_url, 1.0);
187 EXPECT_TRUE(Mock::VerifyAndClear(csd_service_.get()));
188 ASSERT_TRUE(cb != NULL);
189
190 SafeBrowsingService::Client* client;
191 EXPECT_CALL(*sb_service_,
192 DisplayBlockingPage(
193 phishing_url,
194 phishing_url,
195 _,
196 ResourceType::MAIN_FRAME,
197 SafeBrowsingService::URL_PHISHING,
198 _ /* a CsdClient object */,
199 contents()->GetRenderProcessHost()->id(),
200 contents()->render_view_host()->routing_id()))
201 .WillOnce(SaveArg<5>(&client));
202
203 cb->Run(phishing_url, true);
204 delete cb;
205
206 BrowserThread::PostTask(BrowserThread::IO,
207 FROM_HERE,
208 NewRunnableFunction(&QuitUIMessageLoop));
209 MessageLoop::current()->Run();
210 EXPECT_TRUE(Mock::VerifyAndClear(sb_service_.get()));
211
212 // Make sure the client object will be deleted.
213 BrowserThread::PostTask(
214 BrowserThread::IO,
215 FROM_HERE,
216 NewRunnableMethod(
217 sb_service_.get(),
218 &MockSafeBrowsingService::InvokeOnBlockingPageComplete,
219 client));
220 // Since the CsdClient object will be deleted on the UI thread I need
221 // to run the UI message loop. Post a task to stop the UI message loop
222 // after the client object destructor is called.
223 BrowserThread::PostTask(BrowserThread::IO,
224 FROM_HERE,
225 NewRunnableFunction(&QuitUIMessageLoop));
226 MessageLoop::current()->Run();
227 }
228
229 TEST_F(ClientSideDetectionHostTest, OnDetectedPhishingSiteMultiplePings) {
230 // Case 4 & 5: client thinks a page is phishing then navigates to
231 // another page which is also considered phishing by the client
232 // before the server responds with a verdict. After a while the
233 // server responds for both requests with a phishing verdict. Only
234 // a single interstitial is shown for the second URL.
235 ClientSideDetectionService::ClientReportPhishingRequestCallback* cb;
236 GURL phishing_url("http://phishingurl.com/");
237
238 CommandLine::ForCurrentProcess()->AppendSwitch(
239 switches::kEnableClientSidePhishingInterstitial);
240
241 EXPECT_CALL(*csd_service_,
242 SendClientReportPhishingRequest(phishing_url, 1.0, _))
243 .WillOnce(SaveArg<2>(&cb));
244 OnDetectedPhishingSite(phishing_url, 1.0);
245 EXPECT_TRUE(Mock::VerifyAndClear(csd_service_.get()));
246 ASSERT_TRUE(cb != NULL);
247 GURL other_phishing_url("http://other_phishing_url.com/bla");
248 // We navigate away. The callback cb should be revoked.
249 NavigateAndCommit(other_phishing_url);
250
251 ClientSideDetectionService::ClientReportPhishingRequestCallback* cb_other;
252 EXPECT_CALL(*csd_service_,
253 SendClientReportPhishingRequest(other_phishing_url, 0.8, _))
254 .WillOnce(SaveArg<2>(&cb_other));
255 OnDetectedPhishingSite(other_phishing_url, 0.8);
256 EXPECT_TRUE(Mock::VerifyAndClear(csd_service_.get()));
257 ASSERT_TRUE(cb_other);
258
259 // We expect that the interstitial is shown for the second phishing URL.
Brian Ryner 2011/02/16 22:37:10 Do you want to add an EXPECT_CALL for the first ur
260 SafeBrowsingService::Client* client;
261 EXPECT_CALL(*sb_service_,
262 DisplayBlockingPage(
263 other_phishing_url,
264 other_phishing_url,
265 _,
266 ResourceType::MAIN_FRAME,
267 SafeBrowsingService::URL_PHISHING,
268 _ /* a CsdClient object */,
269 contents()->GetRenderProcessHost()->id(),
270 contents()->render_view_host()->routing_id()))
271 .WillOnce(SaveArg<5>(&client));
272
273 cb->Run(phishing_url, true); // Should have no effect.
274 delete cb;
275 cb_other->Run(other_phishing_url, true); // Should show interstitial.
276 delete cb_other;
277
278 BrowserThread::PostTask(BrowserThread::IO,
279 FROM_HERE,
280 NewRunnableFunction(&QuitUIMessageLoop));
281 MessageLoop::current()->Run();
282 EXPECT_TRUE(Mock::VerifyAndClear(sb_service_.get()));
283
284 // Make sure the client object will be deleted.
285 BrowserThread::PostTask(
286 BrowserThread::IO,
287 FROM_HERE,
288 NewRunnableMethod(
289 sb_service_.get(),
290 &MockSafeBrowsingService::InvokeOnBlockingPageComplete,
291 client));
292 // Since the CsdClient object will be deleted on the UI thread I need
293 // to run the UI message loop. Post a task to stop the UI message loop
294 // after the client object destructor is called.
295 BrowserThread::PostTask(BrowserThread::IO,
296 FROM_HERE,
297 NewRunnableFunction(&QuitUIMessageLoop));
298 MessageLoop::current()->Run();
299 }
300
301 } // namespace safe_browsing
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698