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/test_navigation_observer.h"
30 #include "content/public/test/test_utils.h"
31 #include "net/dns/mock_host_resolver.h"
32 #include "net/test/embedded_test_server/embedded_test_server.h"
33 #include "net/test/embedded_test_server/http_request.h"
34 #include "net/test/embedded_test_server/http_response.h"
35 #include "testing/gmock/include/gmock/gmock.h"
36 #include "third_party/WebKit/public/platform/WebURL.h"
37 #include "third_party/WebKit/public/platform/WebURLRequest.h"
38 #include "third_party/WebKit/public/web/WebFrame.h"
39 #include "third_party/WebKit/public/web/WebView.h"
42 using base::ASCIIToUTF16
;
44 using ::testing::InSequence
;
45 using ::testing::Mock
;
46 using ::testing::Pointee
;
47 using ::testing::StrictMock
;
49 namespace safe_browsing
{
53 // The RenderFrame is routing ID 1, and the RenderView is 2.
54 const int kRenderViewRoutingId
= 2;
56 class MockPhishingClassifier
: public PhishingClassifier
{
58 explicit MockPhishingClassifier(content::RenderView
* render_view
)
59 : PhishingClassifier(render_view
, NULL
/* clock */) {}
61 virtual ~MockPhishingClassifier() {}
63 MOCK_METHOD2(BeginClassification
,
64 void(const base::string16
*, const DoneCallback
&));
65 MOCK_METHOD0(CancelPendingClassification
, void());
68 DISALLOW_COPY_AND_ASSIGN(MockPhishingClassifier
);
71 class MockScorer
: public Scorer
{
73 MockScorer() : Scorer() {}
74 virtual ~MockScorer() {}
76 MOCK_CONST_METHOD1(ComputeScore
, double(const FeatureMap
&));
79 DISALLOW_COPY_AND_ASSIGN(MockScorer
);
82 class InterceptingMessageFilter
: public content::BrowserMessageFilter
{
84 InterceptingMessageFilter()
85 : BrowserMessageFilter(SafeBrowsingMsgStart
),
86 waiting_message_loop_(NULL
) {
89 const ClientPhishingRequest
* verdict() const { return verdict_
.get(); }
90 bool OnMessageReceived(const IPC::Message
& message
) override
{
92 IPC_BEGIN_MESSAGE_MAP(InterceptingMessageFilter
, message
)
93 IPC_MESSAGE_HANDLER(SafeBrowsingHostMsg_PhishingDetectionDone
,
94 OnPhishingDetectionDone
)
95 IPC_MESSAGE_UNHANDLED(handled
= false);
101 run_loop_
.reset(new base::RunLoop());
102 waiting_message_loop_
= base::MessageLoop::current();
103 quit_closure_
= run_loop_
->QuitClosure();
106 void RunUntilVerdictReceived() {
107 content::RunThisRunLoop(run_loop_
.get());
109 // Clear out the synchronization state just in case.
110 waiting_message_loop_
= NULL
;
111 quit_closure_
.Reset();
115 void OnPhishingDetectionDone(const std::string
& verdict_str
) {
116 scoped_ptr
<ClientPhishingRequest
> verdict(new ClientPhishingRequest
);
117 if (verdict
->ParseFromString(verdict_str
) &&
118 verdict
->IsInitialized()) {
119 verdict_
.swap(verdict
);
121 waiting_message_loop_
->PostTask(FROM_HERE
, quit_closure_
);
125 ~InterceptingMessageFilter() override
{}
127 scoped_ptr
<ClientPhishingRequest
> verdict_
;
128 base::MessageLoop
* waiting_message_loop_
;
129 base::Closure quit_closure_
;
130 scoped_ptr
<base::RunLoop
> run_loop_
;
134 class PhishingClassifierDelegateTest
: public InProcessBrowserTest
{
136 void CancelCalled() {
138 content::BrowserThread::PostTask(
139 content::BrowserThread::UI
, FROM_HERE
, runner_
->QuitClosure());
144 void SetUpCommandLine(base::CommandLine
* command_line
) override
{
145 command_line
->AppendSwitch(switches::kSingleProcess
);
147 // Don't want to try to create a GPU process.
148 command_line
->AppendSwitch(switches::kDisableGpu
);
152 void SetUpOnMainThread() override
{
153 intercepting_filter_
= new InterceptingMessageFilter();
154 content::RenderView
* render_view
=
155 content::RenderView::FromRoutingID(kRenderViewRoutingId
);
157 GetWebContents()->GetRenderProcessHost()->AddFilter(
158 intercepting_filter_
.get());
159 classifier_
= new StrictMock
<MockPhishingClassifier
>(render_view
);
160 delegate_
= PhishingClassifierDelegate::Create(render_view
, classifier_
);
162 ASSERT_TRUE(StartTestServer());
163 host_resolver()->AddRule("*", "127.0.0.1");
166 // Runs the ClassificationDone callback, then waits for the
167 // PhishingDetectionDone IPC to arrive.
168 void RunClassificationDone(const ClientPhishingRequest
& verdict
) {
169 // Clear out any previous state.
170 intercepting_filter_
->Reset();
171 PostTaskToInProcessRendererAndWait(
172 base::Bind(&PhishingClassifierDelegate::ClassificationDone
,
173 base::Unretained(delegate_
),
175 intercepting_filter_
->RunUntilVerdictReceived();
178 void OnStartPhishingDetection(const GURL
& url
) {
179 PostTaskToInProcessRendererAndWait(
180 base::Bind(&PhishingClassifierDelegate::OnStartPhishingDetection
,
181 base::Unretained(delegate_
), url
));
184 void PageCaptured(base::string16
* page_text
, bool preliminary_capture
) {
185 PostTaskToInProcessRendererAndWait(
186 base::Bind(&PhishingClassifierDelegate::PageCaptured
,
187 base::Unretained(delegate_
), page_text
,
188 preliminary_capture
));
191 bool StartTestServer() {
192 CHECK(!embedded_test_server_
);
193 embedded_test_server_
.reset(new net::test_server::EmbeddedTestServer());
194 embedded_test_server_
->RegisterRequestHandler(
195 base::Bind(&PhishingClassifierDelegateTest::HandleRequest
,
196 base::Unretained(this)));
197 return embedded_test_server_
->InitializeAndWaitUntilReady();
200 scoped_ptr
<net::test_server::HttpResponse
> HandleRequest(
201 const net::test_server::HttpRequest
& request
) {
202 std::map
<std::string
, std::string
>::const_iterator host_it
=
203 request
.headers
.find("Host");
204 if (host_it
== request
.headers
.end())
205 return scoped_ptr
<net::test_server::HttpResponse
>();
208 std::string("http://") + host_it
->second
+ request
.relative_url
;
209 if (response_url_
.spec() != url
)
210 return scoped_ptr
<net::test_server::HttpResponse
>();
212 scoped_ptr
<net::test_server::BasicHttpResponse
> http_response(
213 new net::test_server::BasicHttpResponse());
214 http_response
->set_code(net::HTTP_OK
);
215 http_response
->set_content_type("text/html");
216 http_response
->set_content(response_content_
);
217 return http_response
.Pass();
220 content::WebContents
* GetWebContents() {
221 return browser()->tab_strip_model()->GetActiveWebContents();
224 // Returns the URL that was loaded.
225 GURL
LoadHtml(const std::string
& host
, const std::string
& content
) {
226 GURL::Replacements replace_host
;
227 replace_host
.SetHostStr(host
);
228 response_content_
= content
;
230 embedded_test_server_
->base_url().ReplaceComponents(replace_host
);
231 ui_test_utils::NavigateToURL(browser(), response_url_
);
232 return response_url_
;
235 void NavigateMainFrame(const GURL
& url
) {
236 PostTaskToInProcessRendererAndWait(
237 base::Bind(&PhishingClassifierDelegateTest::NavigateMainFrameInternal
,
238 base::Unretained(this), url
));
241 void NavigateMainFrameInternal(const GURL
& url
) {
242 content::RenderView
* render_view
=
243 content::RenderView::FromRoutingID(kRenderViewRoutingId
);
244 render_view
->GetWebView()->mainFrame()->firstChild()->loadRequest(
245 blink::WebURLRequest(url
));
249 GetWebContents()->GetController().GoBack();
250 content::WaitForLoadStop(GetWebContents());
254 GetWebContents()->GetController().GoForward();
255 content::WaitForLoadStop(GetWebContents());
258 scoped_refptr
<InterceptingMessageFilter
> intercepting_filter_
;
260 std::string response_content_
;
261 scoped_ptr
<net::test_server::EmbeddedTestServer
> embedded_test_server_
;
262 scoped_ptr
<ClientPhishingRequest
> verdict_
;
263 StrictMock
<MockPhishingClassifier
>* classifier_
; // Owned by |delegate_|.
264 PhishingClassifierDelegate
* delegate_
; // Owned by the RenderView.
265 scoped_refptr
<content::MessageLoopRunner
> runner_
;
268 IN_PROC_BROWSER_TEST_F(PhishingClassifierDelegateTest
, Navigation
) {
270 delegate_
->SetPhishingScorer(&scorer
);
271 ASSERT_TRUE(classifier_
->is_ready());
273 // Test an initial load. We expect classification to happen normally.
274 EXPECT_CALL(*classifier_
, CancelPendingClassification()).Times(2);
275 std::string port
= base::IntToString(embedded_test_server_
->port());
276 std::string html
= "<html><body><iframe src=\"http://sub1.com:";
278 html
+= "/\"></iframe></body></html>";
279 GURL url
= LoadHtml("host.com", html
);
280 Mock::VerifyAndClearExpectations(classifier_
);
281 OnStartPhishingDetection(url
);
282 base::string16 page_text
= ASCIIToUTF16("dummy");
285 EXPECT_CALL(*classifier_
, CancelPendingClassification());
286 EXPECT_CALL(*classifier_
, BeginClassification(Pointee(page_text
), _
));
287 PageCaptured(&page_text
, false);
288 Mock::VerifyAndClearExpectations(classifier_
);
291 // Reloading the same page should not trigger a reclassification.
292 // However, it will cancel any pending classification since the
293 // content is being replaced.
294 EXPECT_CALL(*classifier_
, CancelPendingClassification()).Times(2);
296 content::TestNavigationObserver
observer(GetWebContents());
297 chrome::Reload(browser(), CURRENT_TAB
);
300 Mock::VerifyAndClearExpectations(classifier_
);
301 OnStartPhishingDetection(url
);
302 page_text
= ASCIIToUTF16("dummy");
303 EXPECT_CALL(*classifier_
, CancelPendingClassification());
304 PageCaptured(&page_text
, false);
305 Mock::VerifyAndClearExpectations(classifier_
);
307 // Navigating in a subframe will not change the toplevel URL. However, this
308 // should cancel pending classification since the page content is changing.
309 // Currently, we do not start a new classification after subframe loads.
310 EXPECT_CALL(*classifier_
, CancelPendingClassification())
311 .WillOnce(Invoke(this, &PhishingClassifierDelegateTest::CancelCalled
));
313 runner_
= new content::MessageLoopRunner
;
314 NavigateMainFrame(GURL(std::string("http://sub2.com:") + port
+ "/"));
319 Mock::VerifyAndClearExpectations(classifier_
);
321 OnStartPhishingDetection(url
);
322 page_text
= ASCIIToUTF16("dummy");
323 EXPECT_CALL(*classifier_
, CancelPendingClassification());
324 PageCaptured(&page_text
, false);
325 Mock::VerifyAndClearExpectations(classifier_
);
327 // Scrolling to an anchor works similarly to a subframe navigation, but
328 // see the TODO in PhishingClassifierDelegate::DidCommitProvisionalLoad.
329 EXPECT_CALL(*classifier_
, CancelPendingClassification());
330 GURL foo_url
= GURL(url
.spec() + "#foo");
331 ui_test_utils::NavigateToURL(browser(), foo_url
);
332 Mock::VerifyAndClearExpectations(classifier_
);
333 OnStartPhishingDetection(url
);
334 page_text
= ASCIIToUTF16("dummy");
335 EXPECT_CALL(*classifier_
, CancelPendingClassification());
336 PageCaptured(&page_text
, false);
337 Mock::VerifyAndClearExpectations(classifier_
);
339 // Now load a new toplevel page, which should trigger another classification.
340 EXPECT_CALL(*classifier_
, CancelPendingClassification())
341 .WillOnce(Invoke(this, &PhishingClassifierDelegateTest::CancelCalled
));
343 runner_
= new content::MessageLoopRunner
;
344 url
= LoadHtml("host2.com", "dummy2");
348 Mock::VerifyAndClearExpectations(classifier_
);
349 page_text
= ASCIIToUTF16("dummy2");
350 OnStartPhishingDetection(url
);
353 EXPECT_CALL(*classifier_
, CancelPendingClassification());
354 EXPECT_CALL(*classifier_
, BeginClassification(Pointee(page_text
), _
));
355 PageCaptured(&page_text
, false);
356 Mock::VerifyAndClearExpectations(classifier_
);
359 // No classification should happen on back/forward navigation.
360 // Note: in practice, the browser will not send a StartPhishingDetection IPC
361 // in this case. However, we want to make sure that the delegate behaves
362 // correctly regardless.
363 EXPECT_CALL(*classifier_
, CancelPendingClassification()).Times(2);
365 Mock::VerifyAndClearExpectations(classifier_
);
367 page_text
= ASCIIToUTF16("dummy");
368 OnStartPhishingDetection(url
);
369 EXPECT_CALL(*classifier_
, CancelPendingClassification());
370 PageCaptured(&page_text
, false);
371 Mock::VerifyAndClearExpectations(classifier_
);
373 EXPECT_CALL(*classifier_
, CancelPendingClassification());
375 Mock::VerifyAndClearExpectations(classifier_
);
377 page_text
= ASCIIToUTF16("dummy2");
378 OnStartPhishingDetection(url
);
379 EXPECT_CALL(*classifier_
, CancelPendingClassification());
380 PageCaptured(&page_text
, false);
381 Mock::VerifyAndClearExpectations(classifier_
);
383 // Now go back again and scroll to a different anchor.
384 // No classification should happen.
385 EXPECT_CALL(*classifier_
, CancelPendingClassification()).Times(2);
387 Mock::VerifyAndClearExpectations(classifier_
);
388 page_text
= ASCIIToUTF16("dummy");
390 OnStartPhishingDetection(url
);
391 EXPECT_CALL(*classifier_
, CancelPendingClassification());
392 PageCaptured(&page_text
, false);
393 Mock::VerifyAndClearExpectations(classifier_
);
395 EXPECT_CALL(*classifier_
, CancelPendingClassification());
396 GURL foo2_url
= GURL(foo_url
.spec() + "2");
397 ui_test_utils::NavigateToURL(browser(), foo2_url
);
398 Mock::VerifyAndClearExpectations(classifier_
);
400 OnStartPhishingDetection(url
);
401 page_text
= ASCIIToUTF16("dummy");
402 EXPECT_CALL(*classifier_
, CancelPendingClassification());
403 PageCaptured(&page_text
, false);
404 Mock::VerifyAndClearExpectations(classifier_
);
406 // The delegate will cancel pending classification on destruction.
407 EXPECT_CALL(*classifier_
, CancelPendingClassification());
410 // Flaky: crbug.com/479757
411 #if defined(LEAK_SANITIZER)
412 #define MAYBE_NoScorer DISABLED_NoScorer
414 #define MAYBE_NoScorer NoScorer
417 IN_PROC_BROWSER_TEST_F(PhishingClassifierDelegateTest
, MAYBE_NoScorer
) {
418 // For this test, we'll create the delegate with no scorer available yet.
419 ASSERT_FALSE(classifier_
->is_ready());
421 // Queue up a pending classification, cancel it, then queue up another one.
422 GURL url
= LoadHtml("host.com", "dummy");
423 base::string16 page_text
= ASCIIToUTF16("dummy");
424 OnStartPhishingDetection(url
);
425 PageCaptured(&page_text
, false);
427 url
= LoadHtml("host2.com", "dummy2");
428 page_text
= ASCIIToUTF16("dummy2");
429 OnStartPhishingDetection(url
);
430 PageCaptured(&page_text
, false);
432 // Now set a scorer, which should cause a classifier to be created and
433 // the classification to proceed.
434 page_text
= ASCIIToUTF16("dummy2");
435 EXPECT_CALL(*classifier_
, BeginClassification(Pointee(page_text
), _
));
437 delegate_
->SetPhishingScorer(&scorer
);
438 Mock::VerifyAndClearExpectations(classifier_
);
440 // If we set a new scorer while a classification is going on the
441 // classification should be cancelled.
442 EXPECT_CALL(*classifier_
, CancelPendingClassification());
443 delegate_
->SetPhishingScorer(&scorer
);
444 Mock::VerifyAndClearExpectations(classifier_
);
446 // The delegate will cancel pending classification on destruction.
447 EXPECT_CALL(*classifier_
, CancelPendingClassification());
450 // Flaky: crbug.com/435719
451 #if defined(LEAK_SANITIZER)
452 #define MAYBE_NoScorer_Ref DISABLED_NoScorer_Ref
454 #define MAYBE_NoScorer_Ref NoScorer_Ref
457 IN_PROC_BROWSER_TEST_F(PhishingClassifierDelegateTest
, MAYBE_NoScorer_Ref
) {
458 // Similar to the last test, but navigates within the page before
459 // setting the scorer.
460 ASSERT_FALSE(classifier_
->is_ready());
462 // Queue up a pending classification, cancel it, then queue up another one.
463 GURL url
= LoadHtml("host.com", "dummy");
464 base::string16 page_text
= ASCIIToUTF16("dummy");
465 OnStartPhishingDetection(url
);
466 PageCaptured(&page_text
, false);
468 OnStartPhishingDetection(url
);
469 page_text
= ASCIIToUTF16("dummy");
470 PageCaptured(&page_text
, false);
472 // Now set a scorer, which should cause a classifier to be created and
473 // the classification to proceed.
474 page_text
= ASCIIToUTF16("dummy");
475 EXPECT_CALL(*classifier_
, BeginClassification(Pointee(page_text
), _
));
477 delegate_
->SetPhishingScorer(&scorer
);
478 Mock::VerifyAndClearExpectations(classifier_
);
480 // The delegate will cancel pending classification on destruction.
481 EXPECT_CALL(*classifier_
, CancelPendingClassification());
484 IN_PROC_BROWSER_TEST_F(PhishingClassifierDelegateTest
,
485 NoStartPhishingDetection
) {
486 // Tests the behavior when OnStartPhishingDetection has not yet been called
487 // when the page load finishes.
489 delegate_
->SetPhishingScorer(&scorer
);
490 ASSERT_TRUE(classifier_
->is_ready());
492 EXPECT_CALL(*classifier_
, CancelPendingClassification());
493 GURL url
= LoadHtml("host.com", "<html><body>phish</body></html>");
494 Mock::VerifyAndClearExpectations(classifier_
);
495 base::string16 page_text
= ASCIIToUTF16("phish");
496 EXPECT_CALL(*classifier_
, CancelPendingClassification());
497 PageCaptured(&page_text
, false);
498 Mock::VerifyAndClearExpectations(classifier_
);
499 // Now simulate the StartPhishingDetection IPC. We expect classification
501 page_text
= ASCIIToUTF16("phish");
502 EXPECT_CALL(*classifier_
, BeginClassification(Pointee(page_text
), _
));
503 OnStartPhishingDetection(url
);
504 Mock::VerifyAndClearExpectations(classifier_
);
506 // Now try again, but this time we will navigate the page away before
508 EXPECT_CALL(*classifier_
, CancelPendingClassification());
509 LoadHtml("host2.com", "<html><body>phish</body></html>");
510 Mock::VerifyAndClearExpectations(classifier_
);
511 page_text
= ASCIIToUTF16("phish");
512 EXPECT_CALL(*classifier_
, CancelPendingClassification());
513 PageCaptured(&page_text
, false);
514 Mock::VerifyAndClearExpectations(classifier_
);
516 EXPECT_CALL(*classifier_
, CancelPendingClassification());
517 LoadHtml("host3.com", "<html><body>phish</body></html>");
518 Mock::VerifyAndClearExpectations(classifier_
);
519 OnStartPhishingDetection(url
);
521 // In this test, the original page is a redirect, which we do not get a
522 // StartPhishingDetection IPC for. We use location.replace() to load a
523 // new page while reusing the original session history entry, and check that
524 // classification begins correctly for the landing page.
525 EXPECT_CALL(*classifier_
, CancelPendingClassification());
526 LoadHtml("host4.com", "<html><body>abc</body></html>");
527 Mock::VerifyAndClearExpectations(classifier_
);
528 page_text
= ASCIIToUTF16("abc");
529 EXPECT_CALL(*classifier_
, CancelPendingClassification());
530 PageCaptured(&page_text
, false);
531 Mock::VerifyAndClearExpectations(classifier_
);
532 EXPECT_CALL(*classifier_
, CancelPendingClassification());
534 ui_test_utils::NavigateToURL(
535 browser(), GURL("javascript:location.replace(\'redir\');"));
537 Mock::VerifyAndClearExpectations(classifier_
);
539 std::string url_str
= "http://host4.com:";
540 url_str
+= base::IntToString(embedded_test_server_
->port());
542 OnStartPhishingDetection(GURL(url_str
));
543 page_text
= ASCIIToUTF16("123");
546 EXPECT_CALL(*classifier_
, CancelPendingClassification());
547 EXPECT_CALL(*classifier_
, BeginClassification(Pointee(page_text
), _
));
548 PageCaptured(&page_text
, false);
549 Mock::VerifyAndClearExpectations(classifier_
);
552 // The delegate will cancel pending classification on destruction.
553 EXPECT_CALL(*classifier_
, CancelPendingClassification());
556 // Test flakes with LSAN enabled. See http://crbug.com/373155.
557 #if defined(LEAK_SANITIZER)
558 #define MAYBE_IgnorePreliminaryCapture DISABLED_IgnorePreliminaryCapture
560 #define MAYBE_IgnorePreliminaryCapture IgnorePreliminaryCapture
562 IN_PROC_BROWSER_TEST_F(PhishingClassifierDelegateTest
,
563 MAYBE_IgnorePreliminaryCapture
) {
564 // Tests that preliminary PageCaptured notifications are ignored.
566 delegate_
->SetPhishingScorer(&scorer
);
567 ASSERT_TRUE(classifier_
->is_ready());
569 EXPECT_CALL(*classifier_
, CancelPendingClassification());
570 GURL url
= LoadHtml("host.com", "<html><body>phish</body></html>");
571 Mock::VerifyAndClearExpectations(classifier_
);
572 OnStartPhishingDetection(url
);
573 base::string16 page_text
= ASCIIToUTF16("phish");
574 PageCaptured(&page_text
, true);
576 // Once the non-preliminary capture happens, classification should begin.
577 page_text
= ASCIIToUTF16("phish");
580 EXPECT_CALL(*classifier_
, CancelPendingClassification());
581 EXPECT_CALL(*classifier_
, BeginClassification(Pointee(page_text
), _
));
582 PageCaptured(&page_text
, false);
583 Mock::VerifyAndClearExpectations(classifier_
);
586 // The delegate will cancel pending classification on destruction.
587 EXPECT_CALL(*classifier_
, CancelPendingClassification());
590 #if defined(ADDRESS_SANITIZER)
591 #define Maybe_DuplicatePageCapture DISABLED_DuplicatePageCapture
593 #define Maybe_DuplicatePageCapture DuplicatePageCapture
595 IN_PROC_BROWSER_TEST_F(PhishingClassifierDelegateTest
,
596 Maybe_DuplicatePageCapture
) {
597 // Tests that a second PageCaptured notification causes classification to
600 delegate_
->SetPhishingScorer(&scorer
);
601 ASSERT_TRUE(classifier_
->is_ready());
603 EXPECT_CALL(*classifier_
, CancelPendingClassification());
604 GURL url
= LoadHtml("host.com", "<html><body>phish</body></html>");
605 Mock::VerifyAndClearExpectations(classifier_
);
606 OnStartPhishingDetection(url
);
607 base::string16 page_text
= ASCIIToUTF16("phish");
610 EXPECT_CALL(*classifier_
, CancelPendingClassification());
611 EXPECT_CALL(*classifier_
, BeginClassification(Pointee(page_text
), _
));
612 PageCaptured(&page_text
, false);
613 Mock::VerifyAndClearExpectations(classifier_
);
616 page_text
= ASCIIToUTF16("phish");
617 EXPECT_CALL(*classifier_
, CancelPendingClassification());
618 PageCaptured(&page_text
, false);
619 Mock::VerifyAndClearExpectations(classifier_
);
621 // The delegate will cancel pending classification on destruction.
622 EXPECT_CALL(*classifier_
, CancelPendingClassification());
625 // Test flakes with LSAN enabled. See http://crbug.com/373155.
626 #if defined(LEAK_SANITIZER)
627 #define MAYBE_PhishingDetectionDone DISABLED_PhishingDetectionDone
629 #define MAYBE_PhishingDetectionDone PhishingDetectionDone
631 IN_PROC_BROWSER_TEST_F(PhishingClassifierDelegateTest
,
632 MAYBE_PhishingDetectionDone
) {
633 // Tests that a PhishingDetectionDone IPC is sent to the browser
634 // whenever we finish classification.
636 delegate_
->SetPhishingScorer(&scorer
);
637 ASSERT_TRUE(classifier_
->is_ready());
639 // Start by loading a page to populate the delegate's state.
640 EXPECT_CALL(*classifier_
, CancelPendingClassification());
641 GURL url
= LoadHtml("host.com", "<html><body>phish</body></html>");
642 Mock::VerifyAndClearExpectations(classifier_
);
643 base::string16 page_text
= ASCIIToUTF16("phish");
644 OnStartPhishingDetection(url
);
647 EXPECT_CALL(*classifier_
, CancelPendingClassification());
648 EXPECT_CALL(*classifier_
, BeginClassification(Pointee(page_text
), _
));
649 PageCaptured(&page_text
, false);
650 Mock::VerifyAndClearExpectations(classifier_
);
653 // Now run the callback to simulate the classifier finishing.
654 ClientPhishingRequest verdict
;
655 verdict
.set_url(url
.spec());
656 verdict
.set_client_score(0.8f
);
657 verdict
.set_is_phishing(false); // Send IPC even if site is not phishing.
658 RunClassificationDone(verdict
);
659 ASSERT_TRUE(intercepting_filter_
->verdict());
660 EXPECT_EQ(verdict
.SerializeAsString(),
661 intercepting_filter_
->verdict()->SerializeAsString());
663 // The delegate will cancel pending classification on destruction.
664 EXPECT_CALL(*classifier_
, CancelPendingClassification());
667 } // namespace safe_browsing