Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / renderer / safe_browsing / phishing_classifier_delegate_browsertest.cc
bloba3c3b4b1ad78489a681fa305b29faafdeaddf6ef
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 <stdint.h>
8 #include "base/command_line.h"
9 #include "base/location.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/run_loop.h"
12 #include "base/single_thread_task_runner.h"
13 #include "base/strings/string_number_conversions.h"
14 #include "base/strings/utf_string_conversions.h"
15 #include "chrome/browser/ui/browser.h"
16 #include "chrome/browser/ui/browser_commands.h"
17 #include "chrome/browser/ui/tabs/tab_strip_model.h"
18 #include "chrome/common/chrome_switches.h"
19 #include "chrome/common/safe_browsing/csd.pb.h"
20 #include "chrome/common/safe_browsing/safebrowsing_messages.h"
21 #include "chrome/renderer/safe_browsing/features.h"
22 #include "chrome/renderer/safe_browsing/phishing_classifier.h"
23 #include "chrome/renderer/safe_browsing/scorer.h"
24 #include "chrome/test/base/in_process_browser_test.h"
25 #include "chrome/test/base/ui_test_utils.h"
26 #include "content/public/browser/browser_message_filter.h"
27 #include "content/public/browser/browser_thread.h"
28 #include "content/public/browser/render_process_host.h"
29 #include "content/public/browser/render_view_host.h"
30 #include "content/public/browser/web_contents.h"
31 #include "content/public/renderer/render_view.h"
32 #include "content/public/test/browser_test_utils.h"
33 #include "content/public/test/test_navigation_observer.h"
34 #include "content/public/test/test_utils.h"
35 #include "net/dns/mock_host_resolver.h"
36 #include "net/test/embedded_test_server/embedded_test_server.h"
37 #include "net/test/embedded_test_server/http_request.h"
38 #include "net/test/embedded_test_server/http_response.h"
39 #include "testing/gmock/include/gmock/gmock.h"
40 #include "third_party/WebKit/public/platform/WebURL.h"
41 #include "third_party/WebKit/public/platform/WebURLRequest.h"
42 #include "third_party/WebKit/public/web/WebFrame.h"
43 #include "third_party/WebKit/public/web/WebView.h"
44 #include "url/gurl.h"
46 using base::ASCIIToUTF16;
47 using ::testing::_;
48 using ::testing::InSequence;
49 using ::testing::Mock;
50 using ::testing::Pointee;
51 using ::testing::StrictMock;
53 namespace safe_browsing {
55 namespace {
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 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_->task_runner()->PostTask(FROM_HERE, quit_closure_);
125 private:
126 ~InterceptingMessageFilter() override {}
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 PhishingClassifierDelegateTest()
146 : render_view_routing_id_(MSG_ROUTING_NONE) {}
148 void SetUpCommandLine(base::CommandLine* command_line) override {
149 command_line->AppendSwitch(switches::kSingleProcess);
150 #if defined(OS_WIN)
151 // Don't want to try to create a GPU process.
152 command_line->AppendSwitch(switches::kDisableGpu);
153 #endif
156 void SetUpOnMainThread() override {
157 intercepting_filter_ = new InterceptingMessageFilter();
158 render_view_routing_id_ =
159 GetWebContents()->GetRenderViewHost()->GetRoutingID();
161 GetWebContents()->GetRenderProcessHost()->AddFilter(
162 intercepting_filter_.get());
163 classifier_ = new StrictMock<MockPhishingClassifier>(GetRenderView());
164 delegate_ =
165 PhishingClassifierDelegate::Create(GetRenderView(), classifier_);
167 ASSERT_TRUE(StartTestServer());
168 host_resolver()->AddRule("*", "127.0.0.1");
171 // Runs the ClassificationDone callback, then waits for the
172 // PhishingDetectionDone IPC to arrive.
173 void RunClassificationDone(const ClientPhishingRequest& verdict) {
174 // Clear out any previous state.
175 intercepting_filter_->Reset();
176 PostTaskToInProcessRendererAndWait(
177 base::Bind(&PhishingClassifierDelegate::ClassificationDone,
178 base::Unretained(delegate_),
179 verdict));
180 intercepting_filter_->RunUntilVerdictReceived();
183 void OnStartPhishingDetection(const GURL& url) {
184 PostTaskToInProcessRendererAndWait(
185 base::Bind(&PhishingClassifierDelegate::OnStartPhishingDetection,
186 base::Unretained(delegate_), url));
189 void PageCaptured(base::string16* page_text, bool preliminary_capture) {
190 PostTaskToInProcessRendererAndWait(
191 base::Bind(&PhishingClassifierDelegate::PageCaptured,
192 base::Unretained(delegate_), page_text,
193 preliminary_capture));
196 bool StartTestServer() {
197 CHECK(!embedded_test_server_);
198 embedded_test_server_.reset(new net::test_server::EmbeddedTestServer());
199 embedded_test_server_->RegisterRequestHandler(
200 base::Bind(&PhishingClassifierDelegateTest::HandleRequest,
201 base::Unretained(this)));
202 return embedded_test_server_->InitializeAndWaitUntilReady();
205 scoped_ptr<net::test_server::HttpResponse> HandleRequest(
206 const net::test_server::HttpRequest& request) {
207 std::map<std::string, std::string>::const_iterator host_it =
208 request.headers.find("Host");
209 if (host_it == request.headers.end())
210 return scoped_ptr<net::test_server::HttpResponse>();
212 std::string url =
213 std::string("http://") + host_it->second + request.relative_url;
214 if (response_url_.spec() != url)
215 return scoped_ptr<net::test_server::HttpResponse>();
217 scoped_ptr<net::test_server::BasicHttpResponse> http_response(
218 new net::test_server::BasicHttpResponse());
219 http_response->set_code(net::HTTP_OK);
220 http_response->set_content_type("text/html");
221 http_response->set_content(response_content_);
222 return http_response.Pass();
225 content::WebContents* GetWebContents() {
226 return browser()->tab_strip_model()->GetActiveWebContents();
229 content::RenderView* GetRenderView() {
230 return content::RenderView::FromRoutingID(render_view_routing_id_);
233 // Returns the URL that was loaded.
234 GURL LoadHtml(const std::string& host, const std::string& content) {
235 GURL::Replacements replace_host;
236 replace_host.SetHostStr(host);
237 response_content_ = content;
238 response_url_ =
239 embedded_test_server_->base_url().ReplaceComponents(replace_host);
240 ui_test_utils::NavigateToURL(browser(), response_url_);
241 return response_url_;
244 void NavigateMainFrame(const GURL& url) {
245 PostTaskToInProcessRendererAndWait(
246 base::Bind(&PhishingClassifierDelegateTest::NavigateMainFrameInternal,
247 base::Unretained(this), url));
250 void NavigateMainFrameInternal(const GURL& url) {
251 GetRenderView()->GetWebView()->mainFrame()->firstChild()->loadRequest(
252 blink::WebURLRequest(url));
255 void GoBack() {
256 GetWebContents()->GetController().GoBack();
257 content::WaitForLoadStop(GetWebContents());
260 void GoForward() {
261 GetWebContents()->GetController().GoForward();
262 content::WaitForLoadStop(GetWebContents());
265 scoped_refptr<InterceptingMessageFilter> intercepting_filter_;
266 GURL response_url_;
267 std::string response_content_;
268 scoped_ptr<net::test_server::EmbeddedTestServer> embedded_test_server_;
269 scoped_ptr<ClientPhishingRequest> verdict_;
270 StrictMock<MockPhishingClassifier>* classifier_; // Owned by |delegate_|.
271 int32_t render_view_routing_id_;
272 PhishingClassifierDelegate* delegate_; // Owned by the RenderView.
273 scoped_refptr<content::MessageLoopRunner> runner_;
276 IN_PROC_BROWSER_TEST_F(PhishingClassifierDelegateTest, Navigation) {
277 MockScorer scorer;
278 delegate_->SetPhishingScorer(&scorer);
279 ASSERT_TRUE(classifier_->is_ready());
281 // Test an initial load. We expect classification to happen normally.
282 EXPECT_CALL(*classifier_, CancelPendingClassification()).Times(2);
283 std::string port = base::UintToString(embedded_test_server_->port());
284 std::string html = "<html><body><iframe src=\"http://sub1.com:";
285 html += port;
286 html += "/\"></iframe></body></html>";
287 GURL url = LoadHtml("host.com", html);
288 Mock::VerifyAndClearExpectations(classifier_);
289 OnStartPhishingDetection(url);
290 base::string16 page_text = ASCIIToUTF16("dummy");
292 InSequence s;
293 EXPECT_CALL(*classifier_, CancelPendingClassification());
294 EXPECT_CALL(*classifier_, BeginClassification(Pointee(page_text), _));
295 PageCaptured(&page_text, false);
296 Mock::VerifyAndClearExpectations(classifier_);
299 // Reloading the same page should not trigger a reclassification.
300 // However, it will cancel any pending classification since the
301 // content is being replaced.
302 EXPECT_CALL(*classifier_, CancelPendingClassification()).Times(2);
304 content::TestNavigationObserver observer(GetWebContents());
305 chrome::Reload(browser(), CURRENT_TAB);
306 observer.Wait();
308 Mock::VerifyAndClearExpectations(classifier_);
309 OnStartPhishingDetection(url);
310 page_text = ASCIIToUTF16("dummy");
311 EXPECT_CALL(*classifier_, CancelPendingClassification());
312 PageCaptured(&page_text, false);
313 Mock::VerifyAndClearExpectations(classifier_);
315 // Navigating in a subframe will not change the toplevel URL. However, this
316 // should cancel pending classification since the page content is changing.
317 // Currently, we do not start a new classification after subframe loads.
318 EXPECT_CALL(*classifier_, CancelPendingClassification())
319 .WillOnce(Invoke(this, &PhishingClassifierDelegateTest::CancelCalled));
321 runner_ = new content::MessageLoopRunner;
322 NavigateMainFrame(GURL(std::string("http://sub2.com:") + port + "/"));
324 runner_->Run();
325 runner_ = NULL;
327 Mock::VerifyAndClearExpectations(classifier_);
329 OnStartPhishingDetection(url);
330 page_text = ASCIIToUTF16("dummy");
331 EXPECT_CALL(*classifier_, CancelPendingClassification());
332 PageCaptured(&page_text, false);
333 Mock::VerifyAndClearExpectations(classifier_);
335 // Scrolling to an anchor works similarly to a subframe navigation, but
336 // see the TODO in PhishingClassifierDelegate::DidCommitProvisionalLoad.
337 EXPECT_CALL(*classifier_, CancelPendingClassification());
338 GURL foo_url = GURL(url.spec() + "#foo");
339 ui_test_utils::NavigateToURL(browser(), foo_url);
340 Mock::VerifyAndClearExpectations(classifier_);
341 OnStartPhishingDetection(url);
342 page_text = ASCIIToUTF16("dummy");
343 EXPECT_CALL(*classifier_, CancelPendingClassification());
344 PageCaptured(&page_text, false);
345 Mock::VerifyAndClearExpectations(classifier_);
347 // Now load a new toplevel page, which should trigger another classification.
348 EXPECT_CALL(*classifier_, CancelPendingClassification())
349 .WillOnce(Invoke(this, &PhishingClassifierDelegateTest::CancelCalled));
351 runner_ = new content::MessageLoopRunner;
352 url = LoadHtml("host2.com", "dummy2");
353 runner_->Run();
354 runner_ = NULL;
356 Mock::VerifyAndClearExpectations(classifier_);
357 page_text = ASCIIToUTF16("dummy2");
358 OnStartPhishingDetection(url);
360 InSequence s;
361 EXPECT_CALL(*classifier_, CancelPendingClassification());
362 EXPECT_CALL(*classifier_, BeginClassification(Pointee(page_text), _));
363 PageCaptured(&page_text, false);
364 Mock::VerifyAndClearExpectations(classifier_);
367 // No classification should happen on back/forward navigation.
368 // Note: in practice, the browser will not send a StartPhishingDetection IPC
369 // in this case. However, we want to make sure that the delegate behaves
370 // correctly regardless.
371 EXPECT_CALL(*classifier_, CancelPendingClassification()).Times(2);
372 GoBack();
373 Mock::VerifyAndClearExpectations(classifier_);
375 page_text = ASCIIToUTF16("dummy");
376 OnStartPhishingDetection(url);
377 EXPECT_CALL(*classifier_, CancelPendingClassification());
378 PageCaptured(&page_text, false);
379 Mock::VerifyAndClearExpectations(classifier_);
381 EXPECT_CALL(*classifier_, CancelPendingClassification());
382 GoForward();
383 Mock::VerifyAndClearExpectations(classifier_);
385 page_text = ASCIIToUTF16("dummy2");
386 OnStartPhishingDetection(url);
387 EXPECT_CALL(*classifier_, CancelPendingClassification());
388 PageCaptured(&page_text, false);
389 Mock::VerifyAndClearExpectations(classifier_);
391 // Now go back again and scroll to a different anchor.
392 // No classification should happen.
393 EXPECT_CALL(*classifier_, CancelPendingClassification()).Times(2);
394 GoBack();
395 Mock::VerifyAndClearExpectations(classifier_);
396 page_text = ASCIIToUTF16("dummy");
398 OnStartPhishingDetection(url);
399 EXPECT_CALL(*classifier_, CancelPendingClassification());
400 PageCaptured(&page_text, false);
401 Mock::VerifyAndClearExpectations(classifier_);
403 EXPECT_CALL(*classifier_, CancelPendingClassification());
404 GURL foo2_url = GURL(foo_url.spec() + "2");
405 ui_test_utils::NavigateToURL(browser(), foo2_url);
406 Mock::VerifyAndClearExpectations(classifier_);
408 OnStartPhishingDetection(url);
409 page_text = ASCIIToUTF16("dummy");
410 EXPECT_CALL(*classifier_, CancelPendingClassification());
411 PageCaptured(&page_text, false);
412 Mock::VerifyAndClearExpectations(classifier_);
414 // The delegate will cancel pending classification on destruction.
415 EXPECT_CALL(*classifier_, CancelPendingClassification());
418 // Flaky: crbug.com/479757
419 #if defined(LEAK_SANITIZER)
420 #define MAYBE_NoScorer DISABLED_NoScorer
421 #else
422 #define MAYBE_NoScorer NoScorer
423 #endif
425 IN_PROC_BROWSER_TEST_F(PhishingClassifierDelegateTest, MAYBE_NoScorer) {
426 // For this test, we'll create the delegate with no scorer available yet.
427 ASSERT_FALSE(classifier_->is_ready());
429 // Queue up a pending classification, cancel it, then queue up another one.
430 GURL url = LoadHtml("host.com", "dummy");
431 base::string16 page_text = ASCIIToUTF16("dummy");
432 OnStartPhishingDetection(url);
433 PageCaptured(&page_text, false);
435 url = LoadHtml("host2.com", "dummy2");
436 page_text = ASCIIToUTF16("dummy2");
437 OnStartPhishingDetection(url);
438 PageCaptured(&page_text, false);
440 // Now set a scorer, which should cause a classifier to be created and
441 // the classification to proceed.
442 page_text = ASCIIToUTF16("dummy2");
443 EXPECT_CALL(*classifier_, BeginClassification(Pointee(page_text), _));
444 MockScorer scorer;
445 delegate_->SetPhishingScorer(&scorer);
446 Mock::VerifyAndClearExpectations(classifier_);
448 // If we set a new scorer while a classification is going on the
449 // classification should be cancelled.
450 EXPECT_CALL(*classifier_, CancelPendingClassification());
451 delegate_->SetPhishingScorer(&scorer);
452 Mock::VerifyAndClearExpectations(classifier_);
454 // The delegate will cancel pending classification on destruction.
455 EXPECT_CALL(*classifier_, CancelPendingClassification());
458 // Flaky: crbug.com/435719
459 #if defined(LEAK_SANITIZER)
460 #define MAYBE_NoScorer_Ref DISABLED_NoScorer_Ref
461 #else
462 #define MAYBE_NoScorer_Ref NoScorer_Ref
463 #endif
465 IN_PROC_BROWSER_TEST_F(PhishingClassifierDelegateTest, MAYBE_NoScorer_Ref) {
466 // Similar to the last test, but navigates within the page before
467 // setting the scorer.
468 ASSERT_FALSE(classifier_->is_ready());
470 // Queue up a pending classification, cancel it, then queue up another one.
471 GURL url = LoadHtml("host.com", "dummy");
472 base::string16 page_text = ASCIIToUTF16("dummy");
473 OnStartPhishingDetection(url);
474 PageCaptured(&page_text, false);
476 OnStartPhishingDetection(url);
477 page_text = ASCIIToUTF16("dummy");
478 PageCaptured(&page_text, false);
480 // Now set a scorer, which should cause a classifier to be created and
481 // the classification to proceed.
482 page_text = ASCIIToUTF16("dummy");
483 EXPECT_CALL(*classifier_, BeginClassification(Pointee(page_text), _));
484 MockScorer scorer;
485 delegate_->SetPhishingScorer(&scorer);
486 Mock::VerifyAndClearExpectations(classifier_);
488 // The delegate will cancel pending classification on destruction.
489 EXPECT_CALL(*classifier_, CancelPendingClassification());
492 IN_PROC_BROWSER_TEST_F(PhishingClassifierDelegateTest,
493 NoStartPhishingDetection) {
494 // Tests the behavior when OnStartPhishingDetection has not yet been called
495 // when the page load finishes.
496 MockScorer scorer;
497 delegate_->SetPhishingScorer(&scorer);
498 ASSERT_TRUE(classifier_->is_ready());
500 EXPECT_CALL(*classifier_, CancelPendingClassification());
501 GURL url = LoadHtml("host.com", "<html><body>phish</body></html>");
502 Mock::VerifyAndClearExpectations(classifier_);
503 base::string16 page_text = ASCIIToUTF16("phish");
504 EXPECT_CALL(*classifier_, CancelPendingClassification());
505 PageCaptured(&page_text, false);
506 Mock::VerifyAndClearExpectations(classifier_);
507 // Now simulate the StartPhishingDetection IPC. We expect classification
508 // to begin.
509 page_text = ASCIIToUTF16("phish");
510 EXPECT_CALL(*classifier_, BeginClassification(Pointee(page_text), _));
511 OnStartPhishingDetection(url);
512 Mock::VerifyAndClearExpectations(classifier_);
514 // Now try again, but this time we will navigate the page away before
515 // the IPC is sent.
516 EXPECT_CALL(*classifier_, CancelPendingClassification());
517 LoadHtml("host2.com", "<html><body>phish</body></html>");
518 Mock::VerifyAndClearExpectations(classifier_);
519 page_text = ASCIIToUTF16("phish");
520 EXPECT_CALL(*classifier_, CancelPendingClassification());
521 PageCaptured(&page_text, false);
522 Mock::VerifyAndClearExpectations(classifier_);
524 EXPECT_CALL(*classifier_, CancelPendingClassification());
525 LoadHtml("host3.com", "<html><body>phish</body></html>");
526 Mock::VerifyAndClearExpectations(classifier_);
527 OnStartPhishingDetection(url);
529 // In this test, the original page is a redirect, which we do not get a
530 // StartPhishingDetection IPC for. We use location.replace() to load a
531 // new page while reusing the original session history entry, and check that
532 // classification begins correctly for the landing page.
533 EXPECT_CALL(*classifier_, CancelPendingClassification());
534 LoadHtml("host4.com", "<html><body>abc</body></html>");
535 Mock::VerifyAndClearExpectations(classifier_);
536 page_text = ASCIIToUTF16("abc");
537 EXPECT_CALL(*classifier_, CancelPendingClassification());
538 PageCaptured(&page_text, false);
539 Mock::VerifyAndClearExpectations(classifier_);
540 EXPECT_CALL(*classifier_, CancelPendingClassification());
542 ui_test_utils::NavigateToURL(
543 browser(), GURL("javascript:location.replace(\'redir\');"));
545 Mock::VerifyAndClearExpectations(classifier_);
547 std::string url_str = "http://host4.com:";
548 url_str += base::UintToString(embedded_test_server_->port());
549 url_str += "/redir";
550 OnStartPhishingDetection(GURL(url_str));
551 page_text = ASCIIToUTF16("123");
553 InSequence s;
554 EXPECT_CALL(*classifier_, CancelPendingClassification());
555 EXPECT_CALL(*classifier_, BeginClassification(Pointee(page_text), _));
556 PageCaptured(&page_text, false);
557 Mock::VerifyAndClearExpectations(classifier_);
560 // The delegate will cancel pending classification on destruction.
561 EXPECT_CALL(*classifier_, CancelPendingClassification());
564 // Test flakes with LSAN enabled. See http://crbug.com/373155.
565 #if defined(LEAK_SANITIZER)
566 #define MAYBE_IgnorePreliminaryCapture DISABLED_IgnorePreliminaryCapture
567 #else
568 #define MAYBE_IgnorePreliminaryCapture IgnorePreliminaryCapture
569 #endif
570 IN_PROC_BROWSER_TEST_F(PhishingClassifierDelegateTest,
571 MAYBE_IgnorePreliminaryCapture) {
572 // Tests that preliminary PageCaptured notifications are ignored.
573 MockScorer scorer;
574 delegate_->SetPhishingScorer(&scorer);
575 ASSERT_TRUE(classifier_->is_ready());
577 EXPECT_CALL(*classifier_, CancelPendingClassification());
578 GURL url = LoadHtml("host.com", "<html><body>phish</body></html>");
579 Mock::VerifyAndClearExpectations(classifier_);
580 OnStartPhishingDetection(url);
581 base::string16 page_text = ASCIIToUTF16("phish");
582 PageCaptured(&page_text, true);
584 // Once the non-preliminary capture happens, classification should begin.
585 page_text = ASCIIToUTF16("phish");
587 InSequence s;
588 EXPECT_CALL(*classifier_, CancelPendingClassification());
589 EXPECT_CALL(*classifier_, BeginClassification(Pointee(page_text), _));
590 PageCaptured(&page_text, false);
591 Mock::VerifyAndClearExpectations(classifier_);
594 // The delegate will cancel pending classification on destruction.
595 EXPECT_CALL(*classifier_, CancelPendingClassification());
598 #if defined(ADDRESS_SANITIZER)
599 #define Maybe_DuplicatePageCapture DISABLED_DuplicatePageCapture
600 #else
601 #define Maybe_DuplicatePageCapture DuplicatePageCapture
602 #endif
603 IN_PROC_BROWSER_TEST_F(PhishingClassifierDelegateTest,
604 Maybe_DuplicatePageCapture) {
605 // Tests that a second PageCaptured notification causes classification to
606 // be cancelled.
607 MockScorer scorer;
608 delegate_->SetPhishingScorer(&scorer);
609 ASSERT_TRUE(classifier_->is_ready());
611 EXPECT_CALL(*classifier_, CancelPendingClassification());
612 GURL url = LoadHtml("host.com", "<html><body>phish</body></html>");
613 Mock::VerifyAndClearExpectations(classifier_);
614 OnStartPhishingDetection(url);
615 base::string16 page_text = ASCIIToUTF16("phish");
617 InSequence s;
618 EXPECT_CALL(*classifier_, CancelPendingClassification());
619 EXPECT_CALL(*classifier_, BeginClassification(Pointee(page_text), _));
620 PageCaptured(&page_text, false);
621 Mock::VerifyAndClearExpectations(classifier_);
624 page_text = ASCIIToUTF16("phish");
625 EXPECT_CALL(*classifier_, CancelPendingClassification());
626 PageCaptured(&page_text, false);
627 Mock::VerifyAndClearExpectations(classifier_);
629 // The delegate will cancel pending classification on destruction.
630 EXPECT_CALL(*classifier_, CancelPendingClassification());
633 // Test flakes with LSAN enabled. See http://crbug.com/373155.
634 #if defined(LEAK_SANITIZER)
635 #define MAYBE_PhishingDetectionDone DISABLED_PhishingDetectionDone
636 #else
637 #define MAYBE_PhishingDetectionDone PhishingDetectionDone
638 #endif
639 IN_PROC_BROWSER_TEST_F(PhishingClassifierDelegateTest,
640 MAYBE_PhishingDetectionDone) {
641 // Tests that a PhishingDetectionDone IPC is sent to the browser
642 // whenever we finish classification.
643 MockScorer scorer;
644 delegate_->SetPhishingScorer(&scorer);
645 ASSERT_TRUE(classifier_->is_ready());
647 // Start by loading a page to populate the delegate's state.
648 EXPECT_CALL(*classifier_, CancelPendingClassification());
649 GURL url = LoadHtml("host.com", "<html><body>phish</body></html>");
650 Mock::VerifyAndClearExpectations(classifier_);
651 base::string16 page_text = ASCIIToUTF16("phish");
652 OnStartPhishingDetection(url);
654 InSequence s;
655 EXPECT_CALL(*classifier_, CancelPendingClassification());
656 EXPECT_CALL(*classifier_, BeginClassification(Pointee(page_text), _));
657 PageCaptured(&page_text, false);
658 Mock::VerifyAndClearExpectations(classifier_);
661 // Now run the callback to simulate the classifier finishing.
662 ClientPhishingRequest verdict;
663 verdict.set_url(url.spec());
664 verdict.set_client_score(0.8f);
665 verdict.set_is_phishing(false); // Send IPC even if site is not phishing.
666 RunClassificationDone(verdict);
667 ASSERT_TRUE(intercepting_filter_->verdict());
668 EXPECT_EQ(verdict.SerializeAsString(),
669 intercepting_filter_->verdict()->SerializeAsString());
671 // The delegate will cancel pending classification on destruction.
672 EXPECT_CALL(*classifier_, CancelPendingClassification());
675 } // namespace safe_browsing