Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / chrome / renderer / safe_browsing / phishing_classifier_delegate_browsertest.cc
blobfc973cd59e9fe191e20be56861f37932b7f76265
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/location.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "base/run_loop.h"
11 #include "base/single_thread_task_runner.h"
12 #include "base/strings/string_number_conversions.h"
13 #include "base/strings/utf_string_conversions.h"
14 #include "chrome/browser/ui/browser.h"
15 #include "chrome/browser/ui/browser_commands.h"
16 #include "chrome/browser/ui/tabs/tab_strip_model.h"
17 #include "chrome/common/chrome_switches.h"
18 #include "chrome/common/safe_browsing/csd.pb.h"
19 #include "chrome/common/safe_browsing/safebrowsing_messages.h"
20 #include "chrome/renderer/safe_browsing/features.h"
21 #include "chrome/renderer/safe_browsing/phishing_classifier.h"
22 #include "chrome/renderer/safe_browsing/scorer.h"
23 #include "chrome/test/base/in_process_browser_test.h"
24 #include "chrome/test/base/ui_test_utils.h"
25 #include "content/public/browser/browser_message_filter.h"
26 #include "content/public/browser/browser_thread.h"
27 #include "content/public/browser/render_process_host.h"
28 #include "content/public/browser/web_contents.h"
29 #include "content/public/renderer/render_view.h"
30 #include "content/public/test/browser_test_utils.h"
31 #include "content/public/test/test_navigation_observer.h"
32 #include "content/public/test/test_utils.h"
33 #include "net/dns/mock_host_resolver.h"
34 #include "net/test/embedded_test_server/embedded_test_server.h"
35 #include "net/test/embedded_test_server/http_request.h"
36 #include "net/test/embedded_test_server/http_response.h"
37 #include "testing/gmock/include/gmock/gmock.h"
38 #include "third_party/WebKit/public/platform/WebURL.h"
39 #include "third_party/WebKit/public/platform/WebURLRequest.h"
40 #include "third_party/WebKit/public/web/WebFrame.h"
41 #include "third_party/WebKit/public/web/WebView.h"
42 #include "url/gurl.h"
44 using base::ASCIIToUTF16;
45 using ::testing::_;
46 using ::testing::InSequence;
47 using ::testing::Mock;
48 using ::testing::Pointee;
49 using ::testing::StrictMock;
51 namespace safe_browsing {
53 namespace {
55 // The RenderFrame is routing ID 1, and the RenderView is 2.
56 const int kRenderViewRoutingId = 2;
58 class MockPhishingClassifier : public PhishingClassifier {
59 public:
60 explicit MockPhishingClassifier(content::RenderView* render_view)
61 : PhishingClassifier(render_view, NULL /* clock */) {}
63 virtual ~MockPhishingClassifier() {}
65 MOCK_METHOD2(BeginClassification,
66 void(const base::string16*, const DoneCallback&));
67 MOCK_METHOD0(CancelPendingClassification, void());
69 private:
70 DISALLOW_COPY_AND_ASSIGN(MockPhishingClassifier);
73 class MockScorer : public Scorer {
74 public:
75 MockScorer() : Scorer() {}
76 virtual ~MockScorer() {}
78 MOCK_CONST_METHOD1(ComputeScore, double(const FeatureMap&));
80 private:
81 DISALLOW_COPY_AND_ASSIGN(MockScorer);
84 class InterceptingMessageFilter : public content::BrowserMessageFilter {
85 public:
86 InterceptingMessageFilter()
87 : BrowserMessageFilter(SafeBrowsingMsgStart),
88 waiting_message_loop_(NULL) {
91 const ClientPhishingRequest* verdict() const { return verdict_.get(); }
92 bool OnMessageReceived(const IPC::Message& message) override {
93 bool handled = true;
94 IPC_BEGIN_MESSAGE_MAP(InterceptingMessageFilter, message)
95 IPC_MESSAGE_HANDLER(SafeBrowsingHostMsg_PhishingDetectionDone,
96 OnPhishingDetectionDone)
97 IPC_MESSAGE_UNHANDLED(handled = false);
98 IPC_END_MESSAGE_MAP()
99 return handled;
102 void Reset() {
103 run_loop_.reset(new base::RunLoop());
104 waiting_message_loop_ = base::MessageLoop::current();
105 quit_closure_ = run_loop_->QuitClosure();
108 void RunUntilVerdictReceived() {
109 content::RunThisRunLoop(run_loop_.get());
111 // Clear out the synchronization state just in case.
112 waiting_message_loop_ = NULL;
113 quit_closure_.Reset();
114 run_loop_.reset();
117 void OnPhishingDetectionDone(const std::string& verdict_str) {
118 scoped_ptr<ClientPhishingRequest> verdict(new ClientPhishingRequest);
119 if (verdict->ParseFromString(verdict_str) &&
120 verdict->IsInitialized()) {
121 verdict_.swap(verdict);
123 waiting_message_loop_->task_runner()->PostTask(FROM_HERE, quit_closure_);
126 private:
127 ~InterceptingMessageFilter() override {}
129 scoped_ptr<ClientPhishingRequest> verdict_;
130 base::MessageLoop* waiting_message_loop_;
131 base::Closure quit_closure_;
132 scoped_ptr<base::RunLoop> run_loop_;
134 } // namespace
136 class PhishingClassifierDelegateTest : public InProcessBrowserTest {
137 public:
138 void CancelCalled() {
139 if (runner_.get()) {
140 content::BrowserThread::PostTask(
141 content::BrowserThread::UI, FROM_HERE, runner_->QuitClosure());
145 protected:
146 void SetUpCommandLine(base::CommandLine* command_line) override {
147 command_line->AppendSwitch(switches::kSingleProcess);
148 #if defined(OS_WIN)
149 // Don't want to try to create a GPU process.
150 command_line->AppendSwitch(switches::kDisableGpu);
151 #endif
154 void SetUpOnMainThread() override {
155 intercepting_filter_ = new InterceptingMessageFilter();
156 content::RenderView* render_view =
157 content::RenderView::FromRoutingID(kRenderViewRoutingId);
159 GetWebContents()->GetRenderProcessHost()->AddFilter(
160 intercepting_filter_.get());
161 classifier_ = new StrictMock<MockPhishingClassifier>(render_view);
162 delegate_ = PhishingClassifierDelegate::Create(render_view, classifier_);
164 ASSERT_TRUE(StartTestServer());
165 host_resolver()->AddRule("*", "127.0.0.1");
168 // Runs the ClassificationDone callback, then waits for the
169 // PhishingDetectionDone IPC to arrive.
170 void RunClassificationDone(const ClientPhishingRequest& verdict) {
171 // Clear out any previous state.
172 intercepting_filter_->Reset();
173 PostTaskToInProcessRendererAndWait(
174 base::Bind(&PhishingClassifierDelegate::ClassificationDone,
175 base::Unretained(delegate_),
176 verdict));
177 intercepting_filter_->RunUntilVerdictReceived();
180 void OnStartPhishingDetection(const GURL& url) {
181 PostTaskToInProcessRendererAndWait(
182 base::Bind(&PhishingClassifierDelegate::OnStartPhishingDetection,
183 base::Unretained(delegate_), url));
186 void PageCaptured(base::string16* page_text, bool preliminary_capture) {
187 PostTaskToInProcessRendererAndWait(
188 base::Bind(&PhishingClassifierDelegate::PageCaptured,
189 base::Unretained(delegate_), page_text,
190 preliminary_capture));
193 bool StartTestServer() {
194 CHECK(!embedded_test_server_);
195 embedded_test_server_.reset(new net::test_server::EmbeddedTestServer());
196 embedded_test_server_->RegisterRequestHandler(
197 base::Bind(&PhishingClassifierDelegateTest::HandleRequest,
198 base::Unretained(this)));
199 return embedded_test_server_->InitializeAndWaitUntilReady();
202 scoped_ptr<net::test_server::HttpResponse> HandleRequest(
203 const net::test_server::HttpRequest& request) {
204 std::map<std::string, std::string>::const_iterator host_it =
205 request.headers.find("Host");
206 if (host_it == request.headers.end())
207 return scoped_ptr<net::test_server::HttpResponse>();
209 std::string url =
210 std::string("http://") + host_it->second + request.relative_url;
211 if (response_url_.spec() != url)
212 return scoped_ptr<net::test_server::HttpResponse>();
214 scoped_ptr<net::test_server::BasicHttpResponse> http_response(
215 new net::test_server::BasicHttpResponse());
216 http_response->set_code(net::HTTP_OK);
217 http_response->set_content_type("text/html");
218 http_response->set_content(response_content_);
219 return http_response.Pass();
222 content::WebContents* GetWebContents() {
223 return browser()->tab_strip_model()->GetActiveWebContents();
226 // Returns the URL that was loaded.
227 GURL LoadHtml(const std::string& host, const std::string& content) {
228 GURL::Replacements replace_host;
229 replace_host.SetHostStr(host);
230 response_content_ = content;
231 response_url_ =
232 embedded_test_server_->base_url().ReplaceComponents(replace_host);
233 ui_test_utils::NavigateToURL(browser(), response_url_);
234 return response_url_;
237 void NavigateMainFrame(const GURL& url) {
238 PostTaskToInProcessRendererAndWait(
239 base::Bind(&PhishingClassifierDelegateTest::NavigateMainFrameInternal,
240 base::Unretained(this), url));
243 void NavigateMainFrameInternal(const GURL& url) {
244 content::RenderView* render_view =
245 content::RenderView::FromRoutingID(kRenderViewRoutingId);
246 render_view->GetWebView()->mainFrame()->firstChild()->loadRequest(
247 blink::WebURLRequest(url));
250 void GoBack() {
251 GetWebContents()->GetController().GoBack();
252 content::WaitForLoadStop(GetWebContents());
255 void GoForward() {
256 GetWebContents()->GetController().GoForward();
257 content::WaitForLoadStop(GetWebContents());
260 scoped_refptr<InterceptingMessageFilter> intercepting_filter_;
261 GURL response_url_;
262 std::string response_content_;
263 scoped_ptr<net::test_server::EmbeddedTestServer> embedded_test_server_;
264 scoped_ptr<ClientPhishingRequest> verdict_;
265 StrictMock<MockPhishingClassifier>* classifier_; // Owned by |delegate_|.
266 PhishingClassifierDelegate* delegate_; // Owned by the RenderView.
267 scoped_refptr<content::MessageLoopRunner> runner_;
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 // Flaky: crbug.com/479757
413 #if defined(LEAK_SANITIZER)
414 #define MAYBE_NoScorer DISABLED_NoScorer
415 #else
416 #define MAYBE_NoScorer NoScorer
417 #endif
419 IN_PROC_BROWSER_TEST_F(PhishingClassifierDelegateTest, MAYBE_NoScorer) {
420 // For this test, we'll create the delegate with no scorer available yet.
421 ASSERT_FALSE(classifier_->is_ready());
423 // Queue up a pending classification, cancel it, then queue up another one.
424 GURL url = LoadHtml("host.com", "dummy");
425 base::string16 page_text = ASCIIToUTF16("dummy");
426 OnStartPhishingDetection(url);
427 PageCaptured(&page_text, false);
429 url = LoadHtml("host2.com", "dummy2");
430 page_text = ASCIIToUTF16("dummy2");
431 OnStartPhishingDetection(url);
432 PageCaptured(&page_text, false);
434 // Now set a scorer, which should cause a classifier to be created and
435 // the classification to proceed.
436 page_text = ASCIIToUTF16("dummy2");
437 EXPECT_CALL(*classifier_, BeginClassification(Pointee(page_text), _));
438 MockScorer scorer;
439 delegate_->SetPhishingScorer(&scorer);
440 Mock::VerifyAndClearExpectations(classifier_);
442 // If we set a new scorer while a classification is going on the
443 // classification should be cancelled.
444 EXPECT_CALL(*classifier_, CancelPendingClassification());
445 delegate_->SetPhishingScorer(&scorer);
446 Mock::VerifyAndClearExpectations(classifier_);
448 // The delegate will cancel pending classification on destruction.
449 EXPECT_CALL(*classifier_, CancelPendingClassification());
452 // Flaky: crbug.com/435719
453 #if defined(LEAK_SANITIZER)
454 #define MAYBE_NoScorer_Ref DISABLED_NoScorer_Ref
455 #else
456 #define MAYBE_NoScorer_Ref NoScorer_Ref
457 #endif
459 IN_PROC_BROWSER_TEST_F(PhishingClassifierDelegateTest, MAYBE_NoScorer_Ref) {
460 // Similar to the last test, but navigates within the page before
461 // setting the scorer.
462 ASSERT_FALSE(classifier_->is_ready());
464 // Queue up a pending classification, cancel it, then queue up another one.
465 GURL url = LoadHtml("host.com", "dummy");
466 base::string16 page_text = ASCIIToUTF16("dummy");
467 OnStartPhishingDetection(url);
468 PageCaptured(&page_text, false);
470 OnStartPhishingDetection(url);
471 page_text = ASCIIToUTF16("dummy");
472 PageCaptured(&page_text, false);
474 // Now set a scorer, which should cause a classifier to be created and
475 // the classification to proceed.
476 page_text = ASCIIToUTF16("dummy");
477 EXPECT_CALL(*classifier_, BeginClassification(Pointee(page_text), _));
478 MockScorer scorer;
479 delegate_->SetPhishingScorer(&scorer);
480 Mock::VerifyAndClearExpectations(classifier_);
482 // The delegate will cancel pending classification on destruction.
483 EXPECT_CALL(*classifier_, CancelPendingClassification());
486 IN_PROC_BROWSER_TEST_F(PhishingClassifierDelegateTest,
487 NoStartPhishingDetection) {
488 // Tests the behavior when OnStartPhishingDetection has not yet been called
489 // when the page load finishes.
490 MockScorer scorer;
491 delegate_->SetPhishingScorer(&scorer);
492 ASSERT_TRUE(classifier_->is_ready());
494 EXPECT_CALL(*classifier_, CancelPendingClassification());
495 GURL url = LoadHtml("host.com", "<html><body>phish</body></html>");
496 Mock::VerifyAndClearExpectations(classifier_);
497 base::string16 page_text = ASCIIToUTF16("phish");
498 EXPECT_CALL(*classifier_, CancelPendingClassification());
499 PageCaptured(&page_text, false);
500 Mock::VerifyAndClearExpectations(classifier_);
501 // Now simulate the StartPhishingDetection IPC. We expect classification
502 // to begin.
503 page_text = ASCIIToUTF16("phish");
504 EXPECT_CALL(*classifier_, BeginClassification(Pointee(page_text), _));
505 OnStartPhishingDetection(url);
506 Mock::VerifyAndClearExpectations(classifier_);
508 // Now try again, but this time we will navigate the page away before
509 // the IPC is sent.
510 EXPECT_CALL(*classifier_, CancelPendingClassification());
511 LoadHtml("host2.com", "<html><body>phish</body></html>");
512 Mock::VerifyAndClearExpectations(classifier_);
513 page_text = ASCIIToUTF16("phish");
514 EXPECT_CALL(*classifier_, CancelPendingClassification());
515 PageCaptured(&page_text, false);
516 Mock::VerifyAndClearExpectations(classifier_);
518 EXPECT_CALL(*classifier_, CancelPendingClassification());
519 LoadHtml("host3.com", "<html><body>phish</body></html>");
520 Mock::VerifyAndClearExpectations(classifier_);
521 OnStartPhishingDetection(url);
523 // In this test, the original page is a redirect, which we do not get a
524 // StartPhishingDetection IPC for. We use location.replace() to load a
525 // new page while reusing the original session history entry, and check that
526 // classification begins correctly for the landing page.
527 EXPECT_CALL(*classifier_, CancelPendingClassification());
528 LoadHtml("host4.com", "<html><body>abc</body></html>");
529 Mock::VerifyAndClearExpectations(classifier_);
530 page_text = ASCIIToUTF16("abc");
531 EXPECT_CALL(*classifier_, CancelPendingClassification());
532 PageCaptured(&page_text, false);
533 Mock::VerifyAndClearExpectations(classifier_);
534 EXPECT_CALL(*classifier_, CancelPendingClassification());
536 ui_test_utils::NavigateToURL(
537 browser(), GURL("javascript:location.replace(\'redir\');"));
539 Mock::VerifyAndClearExpectations(classifier_);
541 std::string url_str = "http://host4.com:";
542 url_str += base::IntToString(embedded_test_server_->port());
543 url_str += "/redir";
544 OnStartPhishingDetection(GURL(url_str));
545 page_text = ASCIIToUTF16("123");
547 InSequence s;
548 EXPECT_CALL(*classifier_, CancelPendingClassification());
549 EXPECT_CALL(*classifier_, BeginClassification(Pointee(page_text), _));
550 PageCaptured(&page_text, false);
551 Mock::VerifyAndClearExpectations(classifier_);
554 // The delegate will cancel pending classification on destruction.
555 EXPECT_CALL(*classifier_, CancelPendingClassification());
558 // Test flakes with LSAN enabled. See http://crbug.com/373155.
559 #if defined(LEAK_SANITIZER)
560 #define MAYBE_IgnorePreliminaryCapture DISABLED_IgnorePreliminaryCapture
561 #else
562 #define MAYBE_IgnorePreliminaryCapture IgnorePreliminaryCapture
563 #endif
564 IN_PROC_BROWSER_TEST_F(PhishingClassifierDelegateTest,
565 MAYBE_IgnorePreliminaryCapture) {
566 // Tests that preliminary PageCaptured notifications are ignored.
567 MockScorer scorer;
568 delegate_->SetPhishingScorer(&scorer);
569 ASSERT_TRUE(classifier_->is_ready());
571 EXPECT_CALL(*classifier_, CancelPendingClassification());
572 GURL url = LoadHtml("host.com", "<html><body>phish</body></html>");
573 Mock::VerifyAndClearExpectations(classifier_);
574 OnStartPhishingDetection(url);
575 base::string16 page_text = ASCIIToUTF16("phish");
576 PageCaptured(&page_text, true);
578 // Once the non-preliminary capture happens, classification should begin.
579 page_text = ASCIIToUTF16("phish");
581 InSequence s;
582 EXPECT_CALL(*classifier_, CancelPendingClassification());
583 EXPECT_CALL(*classifier_, BeginClassification(Pointee(page_text), _));
584 PageCaptured(&page_text, false);
585 Mock::VerifyAndClearExpectations(classifier_);
588 // The delegate will cancel pending classification on destruction.
589 EXPECT_CALL(*classifier_, CancelPendingClassification());
592 #if defined(ADDRESS_SANITIZER)
593 #define Maybe_DuplicatePageCapture DISABLED_DuplicatePageCapture
594 #else
595 #define Maybe_DuplicatePageCapture DuplicatePageCapture
596 #endif
597 IN_PROC_BROWSER_TEST_F(PhishingClassifierDelegateTest,
598 Maybe_DuplicatePageCapture) {
599 // Tests that a second PageCaptured notification causes classification to
600 // be cancelled.
601 MockScorer scorer;
602 delegate_->SetPhishingScorer(&scorer);
603 ASSERT_TRUE(classifier_->is_ready());
605 EXPECT_CALL(*classifier_, CancelPendingClassification());
606 GURL url = LoadHtml("host.com", "<html><body>phish</body></html>");
607 Mock::VerifyAndClearExpectations(classifier_);
608 OnStartPhishingDetection(url);
609 base::string16 page_text = ASCIIToUTF16("phish");
611 InSequence s;
612 EXPECT_CALL(*classifier_, CancelPendingClassification());
613 EXPECT_CALL(*classifier_, BeginClassification(Pointee(page_text), _));
614 PageCaptured(&page_text, false);
615 Mock::VerifyAndClearExpectations(classifier_);
618 page_text = ASCIIToUTF16("phish");
619 EXPECT_CALL(*classifier_, CancelPendingClassification());
620 PageCaptured(&page_text, false);
621 Mock::VerifyAndClearExpectations(classifier_);
623 // The delegate will cancel pending classification on destruction.
624 EXPECT_CALL(*classifier_, CancelPendingClassification());
627 // Test flakes with LSAN enabled. See http://crbug.com/373155.
628 #if defined(LEAK_SANITIZER)
629 #define MAYBE_PhishingDetectionDone DISABLED_PhishingDetectionDone
630 #else
631 #define MAYBE_PhishingDetectionDone PhishingDetectionDone
632 #endif
633 IN_PROC_BROWSER_TEST_F(PhishingClassifierDelegateTest,
634 MAYBE_PhishingDetectionDone) {
635 // Tests that a PhishingDetectionDone IPC is sent to the browser
636 // whenever we finish classification.
637 MockScorer scorer;
638 delegate_->SetPhishingScorer(&scorer);
639 ASSERT_TRUE(classifier_->is_ready());
641 // Start by loading a page to populate the delegate's state.
642 EXPECT_CALL(*classifier_, CancelPendingClassification());
643 GURL url = LoadHtml("host.com", "<html><body>phish</body></html>");
644 Mock::VerifyAndClearExpectations(classifier_);
645 base::string16 page_text = ASCIIToUTF16("phish");
646 OnStartPhishingDetection(url);
648 InSequence s;
649 EXPECT_CALL(*classifier_, CancelPendingClassification());
650 EXPECT_CALL(*classifier_, BeginClassification(Pointee(page_text), _));
651 PageCaptured(&page_text, false);
652 Mock::VerifyAndClearExpectations(classifier_);
655 // Now run the callback to simulate the classifier finishing.
656 ClientPhishingRequest verdict;
657 verdict.set_url(url.spec());
658 verdict.set_client_score(0.8f);
659 verdict.set_is_phishing(false); // Send IPC even if site is not phishing.
660 RunClassificationDone(verdict);
661 ASSERT_TRUE(intercepting_filter_->verdict());
662 EXPECT_EQ(verdict.SerializeAsString(),
663 intercepting_filter_->verdict()->SerializeAsString());
665 // The delegate will cancel pending classification on destruction.
666 EXPECT_CALL(*classifier_, CancelPendingClassification());
669 } // namespace safe_browsing