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"
44 using base::ASCIIToUTF16
;
46 using ::testing::InSequence
;
47 using ::testing::Mock
;
48 using ::testing::Pointee
;
49 using ::testing::StrictMock
;
51 namespace safe_browsing
{
55 // The RenderFrame is routing ID 1, and the RenderView is 2.
56 const int kRenderViewRoutingId
= 2;
58 class MockPhishingClassifier
: public PhishingClassifier
{
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());
70 DISALLOW_COPY_AND_ASSIGN(MockPhishingClassifier
);
73 class MockScorer
: public Scorer
{
75 MockScorer() : Scorer() {}
76 virtual ~MockScorer() {}
78 MOCK_CONST_METHOD1(ComputeScore
, double(const FeatureMap
&));
81 DISALLOW_COPY_AND_ASSIGN(MockScorer
);
84 class InterceptingMessageFilter
: public content::BrowserMessageFilter
{
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
{
94 IPC_BEGIN_MESSAGE_MAP(InterceptingMessageFilter
, message
)
95 IPC_MESSAGE_HANDLER(SafeBrowsingHostMsg_PhishingDetectionDone
,
96 OnPhishingDetectionDone
)
97 IPC_MESSAGE_UNHANDLED(handled
= false);
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();
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_
);
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_
;
136 class PhishingClassifierDelegateTest
: public InProcessBrowserTest
{
138 void CancelCalled() {
140 content::BrowserThread::PostTask(
141 content::BrowserThread::UI
, FROM_HERE
, runner_
->QuitClosure());
146 void SetUpCommandLine(base::CommandLine
* command_line
) override
{
147 command_line
->AppendSwitch(switches::kSingleProcess
);
149 // Don't want to try to create a GPU process.
150 command_line
->AppendSwitch(switches::kDisableGpu
);
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_
),
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
>();
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
;
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
));
251 GetWebContents()->GetController().GoBack();
252 content::WaitForLoadStop(GetWebContents());
256 GetWebContents()->GetController().GoForward();
257 content::WaitForLoadStop(GetWebContents());
260 scoped_refptr
<InterceptingMessageFilter
> intercepting_filter_
;
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
) {
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:";
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");
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
);
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
+ "/"));
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");
350 Mock::VerifyAndClearExpectations(classifier_
);
351 page_text
= ASCIIToUTF16("dummy2");
352 OnStartPhishingDetection(url
);
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);
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());
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);
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
416 #define MAYBE_NoScorer NoScorer
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
), _
));
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
456 #define MAYBE_NoScorer_Ref NoScorer_Ref
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
), _
));
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.
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
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
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());
544 OnStartPhishingDetection(GURL(url_str
));
545 page_text
= ASCIIToUTF16("123");
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
562 #define MAYBE_IgnorePreliminaryCapture IgnorePreliminaryCapture
564 IN_PROC_BROWSER_TEST_F(PhishingClassifierDelegateTest
,
565 MAYBE_IgnorePreliminaryCapture
) {
566 // Tests that preliminary PageCaptured notifications are ignored.
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");
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
595 #define Maybe_DuplicatePageCapture DuplicatePageCapture
597 IN_PROC_BROWSER_TEST_F(PhishingClassifierDelegateTest
,
598 Maybe_DuplicatePageCapture
) {
599 // Tests that a second PageCaptured notification causes classification to
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");
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
631 #define MAYBE_PhishingDetectionDone PhishingDetectionDone
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.
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
);
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