Adding instrumentation to locate the source of jankiness
[chromium-blink-merge.git] / chrome / renderer / safe_browsing / phishing_classifier_delegate_browsertest.cc
blobc78172431b8c8d44472776a1a7638a830e8d1f62
1 // Copyright (c) 2012 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.
5 #include "chrome/renderer/safe_browsing/phishing_classifier_delegate.h"
7 #include "base/command_line.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/run_loop.h"
10 #include "base/strings/string_number_conversions.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "chrome/browser/ui/browser.h"
13 #include "chrome/browser/ui/browser_commands.h"
14 #include "chrome/browser/ui/tabs/tab_strip_model.h"
15 #include "chrome/common/chrome_switches.h"
16 #include "chrome/common/safe_browsing/csd.pb.h"
17 #include "chrome/common/safe_browsing/safebrowsing_messages.h"
18 #include "chrome/renderer/safe_browsing/features.h"
19 #include "chrome/renderer/safe_browsing/phishing_classifier.h"
20 #include "chrome/renderer/safe_browsing/scorer.h"
21 #include "chrome/test/base/in_process_browser_test.h"
22 #include "chrome/test/base/ui_test_utils.h"
23 #include "content/public/browser/browser_message_filter.h"
24 #include "content/public/browser/browser_thread.h"
25 #include "content/public/browser/render_process_host.h"
26 #include "content/public/browser/web_contents.h"
27 #include "content/public/renderer/render_view.h"
28 #include "content/public/test/browser_test_utils.h"
29 #include "content/public/test/routing_id_mangling_disabler.h"
30 #include "content/public/test/test_navigation_observer.h"
31 #include "content/public/test/test_utils.h"
32 #include "net/dns/mock_host_resolver.h"
33 #include "net/test/embedded_test_server/embedded_test_server.h"
34 #include "net/test/embedded_test_server/http_request.h"
35 #include "net/test/embedded_test_server/http_response.h"
36 #include "testing/gmock/include/gmock/gmock.h"
37 #include "third_party/WebKit/public/platform/WebURL.h"
38 #include "third_party/WebKit/public/platform/WebURLRequest.h"
39 #include "third_party/WebKit/public/web/WebFrame.h"
40 #include "third_party/WebKit/public/web/WebView.h"
41 #include "url/gurl.h"
43 using base::ASCIIToUTF16;
44 using ::testing::_;
45 using ::testing::InSequence;
46 using ::testing::Mock;
47 using ::testing::Pointee;
48 using ::testing::StrictMock;
50 namespace safe_browsing {
52 namespace {
54 // The RenderFrame is routing ID 1, and the RenderView is 2.
55 const int kRenderViewRoutingId = 2;
57 class MockPhishingClassifier : public PhishingClassifier {
58 public:
59 explicit MockPhishingClassifier(content::RenderView* render_view)
60 : PhishingClassifier(render_view, NULL /* clock */) {}
62 virtual ~MockPhishingClassifier() {}
64 MOCK_METHOD2(BeginClassification,
65 void(const base::string16*, const DoneCallback&));
66 MOCK_METHOD0(CancelPendingClassification, void());
68 private:
69 DISALLOW_COPY_AND_ASSIGN(MockPhishingClassifier);
72 class MockScorer : public Scorer {
73 public:
74 MockScorer() : Scorer() {}
75 virtual ~MockScorer() {}
77 MOCK_CONST_METHOD1(ComputeScore, double(const FeatureMap&));
79 private:
80 DISALLOW_COPY_AND_ASSIGN(MockScorer);
83 class InterceptingMessageFilter : public content::BrowserMessageFilter {
84 public:
85 InterceptingMessageFilter()
86 : BrowserMessageFilter(SafeBrowsingMsgStart),
87 waiting_message_loop_(NULL) {
90 const ClientPhishingRequest* verdict() const { return verdict_.get(); }
91 virtual bool OnMessageReceived(const IPC::Message& message) override {
92 bool handled = true;
93 IPC_BEGIN_MESSAGE_MAP(InterceptingMessageFilter, message)
94 IPC_MESSAGE_HANDLER(SafeBrowsingHostMsg_PhishingDetectionDone,
95 OnPhishingDetectionDone)
96 IPC_MESSAGE_UNHANDLED(handled = false);
97 IPC_END_MESSAGE_MAP()
98 return handled;
101 void Reset() {
102 run_loop_.reset(new base::RunLoop());
103 waiting_message_loop_ = base::MessageLoop::current();
104 quit_closure_ = run_loop_->QuitClosure();
107 void RunUntilVerdictReceived() {
108 content::RunThisRunLoop(run_loop_.get());
110 // Clear out the synchronization state just in case.
111 waiting_message_loop_ = NULL;
112 quit_closure_.Reset();
113 run_loop_.reset();
116 void OnPhishingDetectionDone(const std::string& verdict_str) {
117 scoped_ptr<ClientPhishingRequest> verdict(new ClientPhishingRequest);
118 if (verdict->ParseFromString(verdict_str) &&
119 verdict->IsInitialized()) {
120 verdict_.swap(verdict);
122 waiting_message_loop_->PostTask(FROM_HERE, quit_closure_);
125 private:
126 virtual ~InterceptingMessageFilter() {}
128 scoped_ptr<ClientPhishingRequest> verdict_;
129 base::MessageLoop* waiting_message_loop_;
130 base::Closure quit_closure_;
131 scoped_ptr<base::RunLoop> run_loop_;
133 } // namespace
135 class PhishingClassifierDelegateTest : public InProcessBrowserTest {
136 public:
137 void CancelCalled() {
138 if (runner_.get()) {
139 content::BrowserThread::PostTask(
140 content::BrowserThread::UI, FROM_HERE, runner_->QuitClosure());
144 protected:
145 virtual void SetUpCommandLine(CommandLine* command_line) override {
146 command_line->AppendSwitch(switches::kSingleProcess);
147 #if defined(OS_WIN)
148 // Don't want to try to create a GPU process.
149 command_line->AppendSwitch(switches::kDisableGpu);
150 #endif
153 virtual void SetUpOnMainThread() override {
154 intercepting_filter_ = new InterceptingMessageFilter();
155 content::RenderView* render_view =
156 content::RenderView::FromRoutingID(kRenderViewRoutingId);
158 GetWebContents()->GetRenderProcessHost()->AddFilter(
159 intercepting_filter_.get());
160 classifier_ = new StrictMock<MockPhishingClassifier>(render_view);
161 delegate_ = PhishingClassifierDelegate::Create(render_view, classifier_);
163 ASSERT_TRUE(StartTestServer());
164 host_resolver()->AddRule("*", "127.0.0.1");
167 // Runs the ClassificationDone callback, then waits for the
168 // PhishingDetectionDone IPC to arrive.
169 void RunClassificationDone(const ClientPhishingRequest& verdict) {
170 // Clear out any previous state.
171 intercepting_filter_->Reset();
172 PostTaskToInProcessRendererAndWait(
173 base::Bind(&PhishingClassifierDelegate::ClassificationDone,
174 base::Unretained(delegate_),
175 verdict));
176 intercepting_filter_->RunUntilVerdictReceived();
179 void OnStartPhishingDetection(const GURL& url) {
180 PostTaskToInProcessRendererAndWait(
181 base::Bind(&PhishingClassifierDelegate::OnStartPhishingDetection,
182 base::Unretained(delegate_), url));
185 void PageCaptured(base::string16* page_text, bool preliminary_capture) {
186 PostTaskToInProcessRendererAndWait(
187 base::Bind(&PhishingClassifierDelegate::PageCaptured,
188 base::Unretained(delegate_), page_text,
189 preliminary_capture));
192 bool StartTestServer() {
193 CHECK(!embedded_test_server_);
194 embedded_test_server_.reset(new net::test_server::EmbeddedTestServer());
195 embedded_test_server_->RegisterRequestHandler(
196 base::Bind(&PhishingClassifierDelegateTest::HandleRequest,
197 base::Unretained(this)));
198 return embedded_test_server_->InitializeAndWaitUntilReady();
201 scoped_ptr<net::test_server::HttpResponse> HandleRequest(
202 const net::test_server::HttpRequest& request) {
203 std::map<std::string, std::string>::const_iterator host_it =
204 request.headers.find("Host");
205 if (host_it == request.headers.end())
206 return scoped_ptr<net::test_server::HttpResponse>();
208 std::string url =
209 std::string("http://") + host_it->second + request.relative_url;
210 if (response_url_.spec() != url)
211 return scoped_ptr<net::test_server::HttpResponse>();
213 scoped_ptr<net::test_server::BasicHttpResponse> http_response(
214 new net::test_server::BasicHttpResponse());
215 http_response->set_code(net::HTTP_OK);
216 http_response->set_content_type("text/html");
217 http_response->set_content(response_content_);
218 return http_response.PassAs<net::test_server::HttpResponse>();
221 content::WebContents* GetWebContents() {
222 return browser()->tab_strip_model()->GetActiveWebContents();
225 // Returns the URL that was loaded.
226 GURL LoadHtml(const std::string& host, const std::string& content) {
227 GURL::Replacements replace_host;
228 replace_host.SetHostStr(host);
229 response_content_ = content;
230 response_url_ =
231 embedded_test_server_->base_url().ReplaceComponents(replace_host);
232 ui_test_utils::NavigateToURL(browser(), response_url_);
233 return response_url_;
236 void NavigateMainFrame(const GURL& url) {
237 PostTaskToInProcessRendererAndWait(
238 base::Bind(&PhishingClassifierDelegateTest::NavigateMainFrameInternal,
239 base::Unretained(this), url));
242 void NavigateMainFrameInternal(const GURL& url) {
243 content::RenderView* render_view =
244 content::RenderView::FromRoutingID(kRenderViewRoutingId);
245 render_view->GetWebView()->mainFrame()->firstChild()->loadRequest(
246 blink::WebURLRequest(url));
249 void GoBack() {
250 GetWebContents()->GetController().GoBack();
251 content::WaitForLoadStop(GetWebContents());
254 void GoForward() {
255 GetWebContents()->GetController().GoForward();
256 content::WaitForLoadStop(GetWebContents());
259 scoped_refptr<InterceptingMessageFilter> intercepting_filter_;
260 GURL response_url_;
261 std::string response_content_;
262 scoped_ptr<net::test_server::EmbeddedTestServer> embedded_test_server_;
263 scoped_ptr<ClientPhishingRequest> verdict_;
264 StrictMock<MockPhishingClassifier>* classifier_; // Owned by |delegate_|.
265 PhishingClassifierDelegate* delegate_; // Owned by the RenderView.
266 scoped_refptr<content::MessageLoopRunner> runner_;
267 content::RoutingIDManglingDisabler mangling_disabler_;
270 IN_PROC_BROWSER_TEST_F(PhishingClassifierDelegateTest, Navigation) {
271 MockScorer scorer;
272 delegate_->SetPhishingScorer(&scorer);
273 ASSERT_TRUE(classifier_->is_ready());
275 // Test an initial load. We expect classification to happen normally.
276 EXPECT_CALL(*classifier_, CancelPendingClassification()).Times(2);
277 std::string port = base::IntToString(embedded_test_server_->port());
278 std::string html = "<html><body><iframe src=\"http://sub1.com:";
279 html += port;
280 html += "/\"></iframe></body></html>";
281 GURL url = LoadHtml("host.com", html);
282 Mock::VerifyAndClearExpectations(classifier_);
283 OnStartPhishingDetection(url);
284 base::string16 page_text = ASCIIToUTF16("dummy");
286 InSequence s;
287 EXPECT_CALL(*classifier_, CancelPendingClassification());
288 EXPECT_CALL(*classifier_, BeginClassification(Pointee(page_text), _));
289 PageCaptured(&page_text, false);
290 Mock::VerifyAndClearExpectations(classifier_);
293 // Reloading the same page should not trigger a reclassification.
294 // However, it will cancel any pending classification since the
295 // content is being replaced.
296 EXPECT_CALL(*classifier_, CancelPendingClassification()).Times(2);
298 content::TestNavigationObserver observer(GetWebContents());
299 chrome::Reload(browser(), CURRENT_TAB);
300 observer.Wait();
302 Mock::VerifyAndClearExpectations(classifier_);
303 OnStartPhishingDetection(url);
304 page_text = ASCIIToUTF16("dummy");
305 EXPECT_CALL(*classifier_, CancelPendingClassification());
306 PageCaptured(&page_text, false);
307 Mock::VerifyAndClearExpectations(classifier_);
309 // Navigating in a subframe will not change the toplevel URL. However, this
310 // should cancel pending classification since the page content is changing.
311 // Currently, we do not start a new classification after subframe loads.
312 EXPECT_CALL(*classifier_, CancelPendingClassification())
313 .WillOnce(Invoke(this, &PhishingClassifierDelegateTest::CancelCalled));
315 runner_ = new content::MessageLoopRunner;
316 NavigateMainFrame(GURL(std::string("http://sub2.com:") + port + "/"));
318 runner_->Run();
319 runner_ = NULL;
321 Mock::VerifyAndClearExpectations(classifier_);
323 OnStartPhishingDetection(url);
324 page_text = ASCIIToUTF16("dummy");
325 EXPECT_CALL(*classifier_, CancelPendingClassification());
326 PageCaptured(&page_text, false);
327 Mock::VerifyAndClearExpectations(classifier_);
329 // Scrolling to an anchor works similarly to a subframe navigation, but
330 // see the TODO in PhishingClassifierDelegate::DidCommitProvisionalLoad.
331 EXPECT_CALL(*classifier_, CancelPendingClassification());
332 GURL foo_url = GURL(url.spec() + "#foo");
333 ui_test_utils::NavigateToURL(browser(), foo_url);
334 Mock::VerifyAndClearExpectations(classifier_);
335 OnStartPhishingDetection(url);
336 page_text = ASCIIToUTF16("dummy");
337 EXPECT_CALL(*classifier_, CancelPendingClassification());
338 PageCaptured(&page_text, false);
339 Mock::VerifyAndClearExpectations(classifier_);
341 // Now load a new toplevel page, which should trigger another classification.
342 EXPECT_CALL(*classifier_, CancelPendingClassification())
343 .WillOnce(Invoke(this, &PhishingClassifierDelegateTest::CancelCalled));
345 runner_ = new content::MessageLoopRunner;
346 url = LoadHtml("host2.com", "dummy2");
347 runner_->Run();
348 runner_ = NULL;
350 Mock::VerifyAndClearExpectations(classifier_);
351 page_text = ASCIIToUTF16("dummy2");
352 OnStartPhishingDetection(url);
354 InSequence s;
355 EXPECT_CALL(*classifier_, CancelPendingClassification());
356 EXPECT_CALL(*classifier_, BeginClassification(Pointee(page_text), _));
357 PageCaptured(&page_text, false);
358 Mock::VerifyAndClearExpectations(classifier_);
361 // No classification should happen on back/forward navigation.
362 // Note: in practice, the browser will not send a StartPhishingDetection IPC
363 // in this case. However, we want to make sure that the delegate behaves
364 // correctly regardless.
365 EXPECT_CALL(*classifier_, CancelPendingClassification()).Times(2);
366 GoBack();
367 Mock::VerifyAndClearExpectations(classifier_);
369 page_text = ASCIIToUTF16("dummy");
370 OnStartPhishingDetection(url);
371 EXPECT_CALL(*classifier_, CancelPendingClassification());
372 PageCaptured(&page_text, false);
373 Mock::VerifyAndClearExpectations(classifier_);
375 EXPECT_CALL(*classifier_, CancelPendingClassification());
376 GoForward();
377 Mock::VerifyAndClearExpectations(classifier_);
379 page_text = ASCIIToUTF16("dummy2");
380 OnStartPhishingDetection(url);
381 EXPECT_CALL(*classifier_, CancelPendingClassification());
382 PageCaptured(&page_text, false);
383 Mock::VerifyAndClearExpectations(classifier_);
385 // Now go back again and scroll to a different anchor.
386 // No classification should happen.
387 EXPECT_CALL(*classifier_, CancelPendingClassification()).Times(2);
388 GoBack();
389 Mock::VerifyAndClearExpectations(classifier_);
390 page_text = ASCIIToUTF16("dummy");
392 OnStartPhishingDetection(url);
393 EXPECT_CALL(*classifier_, CancelPendingClassification());
394 PageCaptured(&page_text, false);
395 Mock::VerifyAndClearExpectations(classifier_);
397 EXPECT_CALL(*classifier_, CancelPendingClassification());
398 GURL foo2_url = GURL(foo_url.spec() + "2");
399 ui_test_utils::NavigateToURL(browser(), foo2_url);
400 Mock::VerifyAndClearExpectations(classifier_);
402 OnStartPhishingDetection(url);
403 page_text = ASCIIToUTF16("dummy");
404 EXPECT_CALL(*classifier_, CancelPendingClassification());
405 PageCaptured(&page_text, false);
406 Mock::VerifyAndClearExpectations(classifier_);
408 // The delegate will cancel pending classification on destruction.
409 EXPECT_CALL(*classifier_, CancelPendingClassification());
412 IN_PROC_BROWSER_TEST_F(PhishingClassifierDelegateTest, NoScorer) {
413 // For this test, we'll create the delegate with no scorer available yet.
414 ASSERT_FALSE(classifier_->is_ready());
416 // Queue up a pending classification, cancel it, then queue up another one.
417 GURL url = LoadHtml("host.com", "dummy");
418 base::string16 page_text = ASCIIToUTF16("dummy");
419 OnStartPhishingDetection(url);
420 PageCaptured(&page_text, false);
422 url = LoadHtml("host2.com", "dummy2");
423 page_text = ASCIIToUTF16("dummy2");
424 OnStartPhishingDetection(url);
425 PageCaptured(&page_text, false);
427 // Now set a scorer, which should cause a classifier to be created and
428 // the classification to proceed.
429 page_text = ASCIIToUTF16("dummy2");
430 EXPECT_CALL(*classifier_, BeginClassification(Pointee(page_text), _));
431 MockScorer scorer;
432 delegate_->SetPhishingScorer(&scorer);
433 Mock::VerifyAndClearExpectations(classifier_);
435 // If we set a new scorer while a classification is going on the
436 // classification should be cancelled.
437 EXPECT_CALL(*classifier_, CancelPendingClassification());
438 delegate_->SetPhishingScorer(&scorer);
439 Mock::VerifyAndClearExpectations(classifier_);
441 // The delegate will cancel pending classification on destruction.
442 EXPECT_CALL(*classifier_, CancelPendingClassification());
445 IN_PROC_BROWSER_TEST_F(PhishingClassifierDelegateTest, NoScorer_Ref) {
446 // Similar to the last test, but navigates within the page before
447 // setting the scorer.
448 ASSERT_FALSE(classifier_->is_ready());
450 // Queue up a pending classification, cancel it, then queue up another one.
451 GURL url = LoadHtml("host.com", "dummy");
452 base::string16 page_text = ASCIIToUTF16("dummy");
453 OnStartPhishingDetection(url);
454 PageCaptured(&page_text, false);
456 OnStartPhishingDetection(url);
457 page_text = ASCIIToUTF16("dummy");
458 PageCaptured(&page_text, false);
460 // Now set a scorer, which should cause a classifier to be created and
461 // the classification to proceed.
462 page_text = ASCIIToUTF16("dummy");
463 EXPECT_CALL(*classifier_, BeginClassification(Pointee(page_text), _));
464 MockScorer scorer;
465 delegate_->SetPhishingScorer(&scorer);
466 Mock::VerifyAndClearExpectations(classifier_);
468 // The delegate will cancel pending classification on destruction.
469 EXPECT_CALL(*classifier_, CancelPendingClassification());
472 IN_PROC_BROWSER_TEST_F(PhishingClassifierDelegateTest,
473 NoStartPhishingDetection) {
474 // Tests the behavior when OnStartPhishingDetection has not yet been called
475 // when the page load finishes.
476 MockScorer scorer;
477 delegate_->SetPhishingScorer(&scorer);
478 ASSERT_TRUE(classifier_->is_ready());
480 EXPECT_CALL(*classifier_, CancelPendingClassification());
481 GURL url = LoadHtml("host.com", "<html><body>phish</body></html>");
482 Mock::VerifyAndClearExpectations(classifier_);
483 base::string16 page_text = ASCIIToUTF16("phish");
484 EXPECT_CALL(*classifier_, CancelPendingClassification());
485 PageCaptured(&page_text, false);
486 Mock::VerifyAndClearExpectations(classifier_);
487 // Now simulate the StartPhishingDetection IPC. We expect classification
488 // to begin.
489 page_text = ASCIIToUTF16("phish");
490 EXPECT_CALL(*classifier_, BeginClassification(Pointee(page_text), _));
491 OnStartPhishingDetection(url);
492 Mock::VerifyAndClearExpectations(classifier_);
494 // Now try again, but this time we will navigate the page away before
495 // the IPC is sent.
496 EXPECT_CALL(*classifier_, CancelPendingClassification());
497 LoadHtml("host2.com", "<html><body>phish</body></html>");
498 Mock::VerifyAndClearExpectations(classifier_);
499 page_text = ASCIIToUTF16("phish");
500 EXPECT_CALL(*classifier_, CancelPendingClassification());
501 PageCaptured(&page_text, false);
502 Mock::VerifyAndClearExpectations(classifier_);
504 EXPECT_CALL(*classifier_, CancelPendingClassification());
505 LoadHtml("host3.com", "<html><body>phish</body></html>");
506 Mock::VerifyAndClearExpectations(classifier_);
507 OnStartPhishingDetection(url);
509 // In this test, the original page is a redirect, which we do not get a
510 // StartPhishingDetection IPC for. We use location.replace() to load a
511 // new page while reusing the original session history entry, and check that
512 // classification begins correctly for the landing page.
513 EXPECT_CALL(*classifier_, CancelPendingClassification());
514 LoadHtml("host4.com", "<html><body>abc</body></html>");
515 Mock::VerifyAndClearExpectations(classifier_);
516 page_text = ASCIIToUTF16("abc");
517 EXPECT_CALL(*classifier_, CancelPendingClassification());
518 PageCaptured(&page_text, false);
519 Mock::VerifyAndClearExpectations(classifier_);
520 EXPECT_CALL(*classifier_, CancelPendingClassification());
522 ui_test_utils::NavigateToURL(
523 browser(), GURL("javascript:location.replace(\'redir\');"));
525 Mock::VerifyAndClearExpectations(classifier_);
527 std::string url_str = "http://host4.com:";
528 url_str += base::IntToString(embedded_test_server_->port());
529 url_str += "/redir";
530 OnStartPhishingDetection(GURL(url_str));
531 page_text = ASCIIToUTF16("123");
533 InSequence s;
534 EXPECT_CALL(*classifier_, CancelPendingClassification());
535 EXPECT_CALL(*classifier_, BeginClassification(Pointee(page_text), _));
536 PageCaptured(&page_text, false);
537 Mock::VerifyAndClearExpectations(classifier_);
540 // The delegate will cancel pending classification on destruction.
541 EXPECT_CALL(*classifier_, CancelPendingClassification());
544 IN_PROC_BROWSER_TEST_F(PhishingClassifierDelegateTest,
545 IgnorePreliminaryCapture) {
546 // Tests that preliminary PageCaptured notifications are ignored.
547 MockScorer scorer;
548 delegate_->SetPhishingScorer(&scorer);
549 ASSERT_TRUE(classifier_->is_ready());
551 EXPECT_CALL(*classifier_, CancelPendingClassification());
552 GURL url = LoadHtml("host.com", "<html><body>phish</body></html>");
553 Mock::VerifyAndClearExpectations(classifier_);
554 OnStartPhishingDetection(url);
555 base::string16 page_text = ASCIIToUTF16("phish");
556 PageCaptured(&page_text, true);
558 // Once the non-preliminary capture happens, classification should begin.
559 page_text = ASCIIToUTF16("phish");
561 InSequence s;
562 EXPECT_CALL(*classifier_, CancelPendingClassification());
563 EXPECT_CALL(*classifier_, BeginClassification(Pointee(page_text), _));
564 PageCaptured(&page_text, false);
565 Mock::VerifyAndClearExpectations(classifier_);
568 // The delegate will cancel pending classification on destruction.
569 EXPECT_CALL(*classifier_, CancelPendingClassification());
572 #if defined(ADDRESS_SANITIZER)
573 #define Maybe_DuplicatePageCapture DISABLED_DuplicatePageCapture
574 #else
575 #define Maybe_DuplicatePageCapture DuplicatePageCapture
576 #endif
577 IN_PROC_BROWSER_TEST_F(PhishingClassifierDelegateTest,
578 Maybe_DuplicatePageCapture) {
579 // Tests that a second PageCaptured notification causes classification to
580 // be cancelled.
581 MockScorer scorer;
582 delegate_->SetPhishingScorer(&scorer);
583 ASSERT_TRUE(classifier_->is_ready());
585 EXPECT_CALL(*classifier_, CancelPendingClassification());
586 GURL url = LoadHtml("host.com", "<html><body>phish</body></html>");
587 Mock::VerifyAndClearExpectations(classifier_);
588 OnStartPhishingDetection(url);
589 base::string16 page_text = ASCIIToUTF16("phish");
591 InSequence s;
592 EXPECT_CALL(*classifier_, CancelPendingClassification());
593 EXPECT_CALL(*classifier_, BeginClassification(Pointee(page_text), _));
594 PageCaptured(&page_text, false);
595 Mock::VerifyAndClearExpectations(classifier_);
598 page_text = ASCIIToUTF16("phish");
599 EXPECT_CALL(*classifier_, CancelPendingClassification());
600 PageCaptured(&page_text, false);
601 Mock::VerifyAndClearExpectations(classifier_);
603 // The delegate will cancel pending classification on destruction.
604 EXPECT_CALL(*classifier_, CancelPendingClassification());
607 IN_PROC_BROWSER_TEST_F(PhishingClassifierDelegateTest, PhishingDetectionDone) {
608 // Tests that a PhishingDetectionDone IPC is sent to the browser
609 // whenever we finish classification.
610 MockScorer scorer;
611 delegate_->SetPhishingScorer(&scorer);
612 ASSERT_TRUE(classifier_->is_ready());
614 // Start by loading a page to populate the delegate's state.
615 EXPECT_CALL(*classifier_, CancelPendingClassification());
616 GURL url = LoadHtml("host.com", "<html><body>phish</body></html>");
617 Mock::VerifyAndClearExpectations(classifier_);
618 base::string16 page_text = ASCIIToUTF16("phish");
619 OnStartPhishingDetection(url);
621 InSequence s;
622 EXPECT_CALL(*classifier_, CancelPendingClassification());
623 EXPECT_CALL(*classifier_, BeginClassification(Pointee(page_text), _));
624 PageCaptured(&page_text, false);
625 Mock::VerifyAndClearExpectations(classifier_);
628 // Now run the callback to simulate the classifier finishing.
629 ClientPhishingRequest verdict;
630 verdict.set_url(url.spec());
631 verdict.set_client_score(0.8f);
632 verdict.set_is_phishing(false); // Send IPC even if site is not phishing.
633 RunClassificationDone(verdict);
634 ASSERT_TRUE(intercepting_filter_->verdict());
635 EXPECT_EQ(verdict.SerializeAsString(),
636 intercepting_filter_->verdict()->SerializeAsString());
638 // The delegate will cancel pending classification on destruction.
639 EXPECT_CALL(*classifier_, CancelPendingClassification());
642 } // namespace safe_browsing