Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / chrome / renderer / safe_browsing / phishing_classifier_delegate_browsertest.cc
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.
4
5 #include "chrome/renderer/safe_browsing/phishing_classifier_delegate.h"
6
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"
40 #include "url/gurl.h"
41
42 using base::ASCIIToUTF16;
43 using ::testing::_;
44 using ::testing::InSequence;
45 using ::testing::Mock;
46 using ::testing::Pointee;
47 using ::testing::StrictMock;
48
49 namespace safe_browsing {
50
51 namespace {
52
53 // The RenderFrame is routing ID 1, and the RenderView is 2.
54 const int kRenderViewRoutingId = 2;
55
56 class MockPhishingClassifier : public PhishingClassifier {
57  public:
58   explicit MockPhishingClassifier(content::RenderView* render_view)
59       : PhishingClassifier(render_view, NULL /* clock */) {}
60
61   virtual ~MockPhishingClassifier() {}
62
63   MOCK_METHOD2(BeginClassification,
64                void(const base::string16*, const DoneCallback&));
65   MOCK_METHOD0(CancelPendingClassification, void());
66
67  private:
68   DISALLOW_COPY_AND_ASSIGN(MockPhishingClassifier);
69 };
70
71 class MockScorer : public Scorer {
72  public:
73   MockScorer() : Scorer() {}
74   virtual ~MockScorer() {}
75
76   MOCK_CONST_METHOD1(ComputeScore, double(const FeatureMap&));
77
78  private:
79   DISALLOW_COPY_AND_ASSIGN(MockScorer);
80 };
81
82 class InterceptingMessageFilter : public content::BrowserMessageFilter {
83  public:
84   InterceptingMessageFilter()
85       : BrowserMessageFilter(SafeBrowsingMsgStart),
86         waiting_message_loop_(NULL) {
87   }
88
89   const ClientPhishingRequest* verdict() const { return verdict_.get(); }
90   bool OnMessageReceived(const IPC::Message& message) override {
91     bool handled = true;
92     IPC_BEGIN_MESSAGE_MAP(InterceptingMessageFilter, message)
93         IPC_MESSAGE_HANDLER(SafeBrowsingHostMsg_PhishingDetectionDone,
94                             OnPhishingDetectionDone)
95         IPC_MESSAGE_UNHANDLED(handled = false);
96     IPC_END_MESSAGE_MAP()
97     return handled;
98   }
99
100   void Reset() {
101     run_loop_.reset(new base::RunLoop());
102     waiting_message_loop_ = base::MessageLoop::current();
103     quit_closure_ = run_loop_->QuitClosure();
104   }
105
106   void RunUntilVerdictReceived() {
107     content::RunThisRunLoop(run_loop_.get());
108
109     // Clear out the synchronization state just in case.
110     waiting_message_loop_ = NULL;
111     quit_closure_.Reset();
112     run_loop_.reset();
113   }
114
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);
120     }
121     waiting_message_loop_->PostTask(FROM_HERE, quit_closure_);
122   }
123
124  private:
125   ~InterceptingMessageFilter() override {}
126
127   scoped_ptr<ClientPhishingRequest> verdict_;
128   base::MessageLoop* waiting_message_loop_;
129   base::Closure quit_closure_;
130   scoped_ptr<base::RunLoop> run_loop_;
131 };
132 }  // namespace
133
134 class PhishingClassifierDelegateTest : public InProcessBrowserTest {
135  public:
136   void CancelCalled() {
137     if (runner_.get()) {
138       content::BrowserThread::PostTask(
139           content::BrowserThread::UI, FROM_HERE, runner_->QuitClosure());
140     }
141   }
142
143  protected:
144   void SetUpCommandLine(CommandLine* command_line) override {
145     command_line->AppendSwitch(switches::kSingleProcess);
146 #if defined(OS_WIN)
147     // Don't want to try to create a GPU process.
148     command_line->AppendSwitch(switches::kDisableGpu);
149 #endif
150   }
151
152   void SetUpOnMainThread() override {
153     intercepting_filter_ = new InterceptingMessageFilter();
154     content::RenderView* render_view =
155         content::RenderView::FromRoutingID(kRenderViewRoutingId);
156
157     GetWebContents()->GetRenderProcessHost()->AddFilter(
158         intercepting_filter_.get());
159     classifier_ = new StrictMock<MockPhishingClassifier>(render_view);
160     delegate_ = PhishingClassifierDelegate::Create(render_view, classifier_);
161
162     ASSERT_TRUE(StartTestServer());
163     host_resolver()->AddRule("*", "127.0.0.1");
164   }
165
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_),
174         verdict));
175     intercepting_filter_->RunUntilVerdictReceived();
176   }
177
178   void OnStartPhishingDetection(const GURL& url) {
179     PostTaskToInProcessRendererAndWait(
180         base::Bind(&PhishingClassifierDelegate::OnStartPhishingDetection,
181                    base::Unretained(delegate_), url));
182   }
183
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));
189   }
190
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();
198   }
199
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>();
206
207     std::string url =
208         std::string("http://") + host_it->second + request.relative_url;
209     if (response_url_.spec() != url)
210       return scoped_ptr<net::test_server::HttpResponse>();
211
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();
218   }
219
220   content::WebContents* GetWebContents() {
221     return browser()->tab_strip_model()->GetActiveWebContents();
222   }
223
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;
229     response_url_ =
230         embedded_test_server_->base_url().ReplaceComponents(replace_host);
231     ui_test_utils::NavigateToURL(browser(), response_url_);
232     return response_url_;
233   }
234
235   void NavigateMainFrame(const GURL& url) {
236     PostTaskToInProcessRendererAndWait(
237         base::Bind(&PhishingClassifierDelegateTest::NavigateMainFrameInternal,
238                    base::Unretained(this), url));
239   }
240
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));
246   }
247
248   void GoBack() {
249     GetWebContents()->GetController().GoBack();
250     content::WaitForLoadStop(GetWebContents());
251   }
252
253   void GoForward() {
254     GetWebContents()->GetController().GoForward();
255     content::WaitForLoadStop(GetWebContents());
256   }
257
258   scoped_refptr<InterceptingMessageFilter> intercepting_filter_;
259   GURL response_url_;
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_;
266 };
267
268 IN_PROC_BROWSER_TEST_F(PhishingClassifierDelegateTest, Navigation) {
269   MockScorer scorer;
270   delegate_->SetPhishingScorer(&scorer);
271   ASSERT_TRUE(classifier_->is_ready());
272
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:";
277   html += port;
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");
283   {
284     InSequence s;
285     EXPECT_CALL(*classifier_, CancelPendingClassification());
286     EXPECT_CALL(*classifier_, BeginClassification(Pointee(page_text), _));
287     PageCaptured(&page_text, false);
288     Mock::VerifyAndClearExpectations(classifier_);
289   }
290
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);
295
296   content::TestNavigationObserver observer(GetWebContents());
297   chrome::Reload(browser(), CURRENT_TAB);
298   observer.Wait();
299
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_);
306
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));
312
313   runner_ = new content::MessageLoopRunner;
314   NavigateMainFrame(GURL(std::string("http://sub2.com:") + port + "/"));
315
316   runner_->Run();
317   runner_ = NULL;
318
319   Mock::VerifyAndClearExpectations(classifier_);
320
321   OnStartPhishingDetection(url);
322   page_text = ASCIIToUTF16("dummy");
323   EXPECT_CALL(*classifier_, CancelPendingClassification());
324   PageCaptured(&page_text, false);
325   Mock::VerifyAndClearExpectations(classifier_);
326
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_);
338
339   // Now load a new toplevel page, which should trigger another classification.
340   EXPECT_CALL(*classifier_, CancelPendingClassification())
341       .WillOnce(Invoke(this, &PhishingClassifierDelegateTest::CancelCalled));
342
343   runner_ = new content::MessageLoopRunner;
344   url = LoadHtml("host2.com", "dummy2");
345   runner_->Run();
346   runner_ = NULL;
347
348   Mock::VerifyAndClearExpectations(classifier_);
349   page_text = ASCIIToUTF16("dummy2");
350   OnStartPhishingDetection(url);
351   {
352     InSequence s;
353     EXPECT_CALL(*classifier_, CancelPendingClassification());
354     EXPECT_CALL(*classifier_, BeginClassification(Pointee(page_text), _));
355     PageCaptured(&page_text, false);
356     Mock::VerifyAndClearExpectations(classifier_);
357   }
358
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);
364   GoBack();
365   Mock::VerifyAndClearExpectations(classifier_);
366
367   page_text = ASCIIToUTF16("dummy");
368   OnStartPhishingDetection(url);
369   EXPECT_CALL(*classifier_, CancelPendingClassification());
370   PageCaptured(&page_text, false);
371   Mock::VerifyAndClearExpectations(classifier_);
372
373   EXPECT_CALL(*classifier_, CancelPendingClassification());
374   GoForward();
375   Mock::VerifyAndClearExpectations(classifier_);
376
377   page_text = ASCIIToUTF16("dummy2");
378   OnStartPhishingDetection(url);
379   EXPECT_CALL(*classifier_, CancelPendingClassification());
380   PageCaptured(&page_text, false);
381   Mock::VerifyAndClearExpectations(classifier_);
382
383   // Now go back again and scroll to a different anchor.
384   // No classification should happen.
385   EXPECT_CALL(*classifier_, CancelPendingClassification()).Times(2);
386   GoBack();
387   Mock::VerifyAndClearExpectations(classifier_);
388   page_text = ASCIIToUTF16("dummy");
389
390   OnStartPhishingDetection(url);
391   EXPECT_CALL(*classifier_, CancelPendingClassification());
392   PageCaptured(&page_text, false);
393   Mock::VerifyAndClearExpectations(classifier_);
394
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_);
399
400   OnStartPhishingDetection(url);
401   page_text = ASCIIToUTF16("dummy");
402   EXPECT_CALL(*classifier_, CancelPendingClassification());
403   PageCaptured(&page_text, false);
404   Mock::VerifyAndClearExpectations(classifier_);
405
406   // The delegate will cancel pending classification on destruction.
407   EXPECT_CALL(*classifier_, CancelPendingClassification());
408 }
409
410 IN_PROC_BROWSER_TEST_F(PhishingClassifierDelegateTest, NoScorer) {
411   // For this test, we'll create the delegate with no scorer available yet.
412   ASSERT_FALSE(classifier_->is_ready());
413
414   // Queue up a pending classification, cancel it, then queue up another one.
415   GURL url = LoadHtml("host.com", "dummy");
416   base::string16 page_text = ASCIIToUTF16("dummy");
417   OnStartPhishingDetection(url);
418   PageCaptured(&page_text, false);
419
420   url = LoadHtml("host2.com", "dummy2");
421   page_text = ASCIIToUTF16("dummy2");
422   OnStartPhishingDetection(url);
423   PageCaptured(&page_text, false);
424
425   // Now set a scorer, which should cause a classifier to be created and
426   // the classification to proceed.
427   page_text = ASCIIToUTF16("dummy2");
428   EXPECT_CALL(*classifier_, BeginClassification(Pointee(page_text), _));
429   MockScorer scorer;
430   delegate_->SetPhishingScorer(&scorer);
431   Mock::VerifyAndClearExpectations(classifier_);
432
433   // If we set a new scorer while a classification is going on the
434   // classification should be cancelled.
435   EXPECT_CALL(*classifier_, CancelPendingClassification());
436   delegate_->SetPhishingScorer(&scorer);
437   Mock::VerifyAndClearExpectations(classifier_);
438
439   // The delegate will cancel pending classification on destruction.
440   EXPECT_CALL(*classifier_, CancelPendingClassification());
441 }
442
443 IN_PROC_BROWSER_TEST_F(PhishingClassifierDelegateTest, NoScorer_Ref) {
444   // Similar to the last test, but navigates within the page before
445   // setting the scorer.
446   ASSERT_FALSE(classifier_->is_ready());
447
448   // Queue up a pending classification, cancel it, then queue up another one.
449   GURL url = LoadHtml("host.com", "dummy");
450   base::string16 page_text = ASCIIToUTF16("dummy");
451   OnStartPhishingDetection(url);
452   PageCaptured(&page_text, false);
453
454   OnStartPhishingDetection(url);
455   page_text = ASCIIToUTF16("dummy");
456   PageCaptured(&page_text, false);
457
458   // Now set a scorer, which should cause a classifier to be created and
459   // the classification to proceed.
460   page_text = ASCIIToUTF16("dummy");
461   EXPECT_CALL(*classifier_, BeginClassification(Pointee(page_text), _));
462   MockScorer scorer;
463   delegate_->SetPhishingScorer(&scorer);
464   Mock::VerifyAndClearExpectations(classifier_);
465
466   // The delegate will cancel pending classification on destruction.
467   EXPECT_CALL(*classifier_, CancelPendingClassification());
468 }
469
470 IN_PROC_BROWSER_TEST_F(PhishingClassifierDelegateTest,
471                        NoStartPhishingDetection) {
472   // Tests the behavior when OnStartPhishingDetection has not yet been called
473   // when the page load finishes.
474   MockScorer scorer;
475   delegate_->SetPhishingScorer(&scorer);
476   ASSERT_TRUE(classifier_->is_ready());
477
478   EXPECT_CALL(*classifier_, CancelPendingClassification());
479   GURL url = LoadHtml("host.com", "<html><body>phish</body></html>");
480   Mock::VerifyAndClearExpectations(classifier_);
481   base::string16 page_text = ASCIIToUTF16("phish");
482   EXPECT_CALL(*classifier_, CancelPendingClassification());
483   PageCaptured(&page_text, false);
484   Mock::VerifyAndClearExpectations(classifier_);
485   // Now simulate the StartPhishingDetection IPC.  We expect classification
486   // to begin.
487   page_text = ASCIIToUTF16("phish");
488   EXPECT_CALL(*classifier_, BeginClassification(Pointee(page_text), _));
489   OnStartPhishingDetection(url);
490   Mock::VerifyAndClearExpectations(classifier_);
491
492   // Now try again, but this time we will navigate the page away before
493   // the IPC is sent.
494   EXPECT_CALL(*classifier_, CancelPendingClassification());
495   LoadHtml("host2.com", "<html><body>phish</body></html>");
496   Mock::VerifyAndClearExpectations(classifier_);
497   page_text = ASCIIToUTF16("phish");
498   EXPECT_CALL(*classifier_, CancelPendingClassification());
499   PageCaptured(&page_text, false);
500   Mock::VerifyAndClearExpectations(classifier_);
501
502   EXPECT_CALL(*classifier_, CancelPendingClassification());
503   LoadHtml("host3.com", "<html><body>phish</body></html>");
504   Mock::VerifyAndClearExpectations(classifier_);
505   OnStartPhishingDetection(url);
506
507   // In this test, the original page is a redirect, which we do not get a
508   // StartPhishingDetection IPC for.  We use location.replace() to load a
509   // new page while reusing the original session history entry, and check that
510   // classification begins correctly for the landing page.
511   EXPECT_CALL(*classifier_, CancelPendingClassification());
512   LoadHtml("host4.com", "<html><body>abc</body></html>");
513   Mock::VerifyAndClearExpectations(classifier_);
514   page_text = ASCIIToUTF16("abc");
515   EXPECT_CALL(*classifier_, CancelPendingClassification());
516   PageCaptured(&page_text, false);
517   Mock::VerifyAndClearExpectations(classifier_);
518   EXPECT_CALL(*classifier_, CancelPendingClassification());
519
520   ui_test_utils::NavigateToURL(
521       browser(), GURL("javascript:location.replace(\'redir\');"));
522
523   Mock::VerifyAndClearExpectations(classifier_);
524
525   std::string url_str = "http://host4.com:";
526   url_str += base::IntToString(embedded_test_server_->port());
527   url_str += "/redir";
528   OnStartPhishingDetection(GURL(url_str));
529   page_text = ASCIIToUTF16("123");
530   {
531     InSequence s;
532     EXPECT_CALL(*classifier_, CancelPendingClassification());
533     EXPECT_CALL(*classifier_, BeginClassification(Pointee(page_text), _));
534     PageCaptured(&page_text, false);
535     Mock::VerifyAndClearExpectations(classifier_);
536   }
537
538   // The delegate will cancel pending classification on destruction.
539   EXPECT_CALL(*classifier_, CancelPendingClassification());
540 }
541
542 IN_PROC_BROWSER_TEST_F(PhishingClassifierDelegateTest,
543                        IgnorePreliminaryCapture) {
544   // Tests that preliminary PageCaptured notifications are ignored.
545   MockScorer scorer;
546   delegate_->SetPhishingScorer(&scorer);
547   ASSERT_TRUE(classifier_->is_ready());
548
549   EXPECT_CALL(*classifier_, CancelPendingClassification());
550   GURL url = LoadHtml("host.com", "<html><body>phish</body></html>");
551   Mock::VerifyAndClearExpectations(classifier_);
552   OnStartPhishingDetection(url);
553   base::string16 page_text = ASCIIToUTF16("phish");
554   PageCaptured(&page_text, true);
555
556   // Once the non-preliminary capture happens, classification should begin.
557   page_text = ASCIIToUTF16("phish");
558   {
559     InSequence s;
560     EXPECT_CALL(*classifier_, CancelPendingClassification());
561     EXPECT_CALL(*classifier_, BeginClassification(Pointee(page_text), _));
562     PageCaptured(&page_text, false);
563     Mock::VerifyAndClearExpectations(classifier_);
564   }
565
566   // The delegate will cancel pending classification on destruction.
567   EXPECT_CALL(*classifier_, CancelPendingClassification());
568 }
569
570 #if defined(ADDRESS_SANITIZER)
571 #define Maybe_DuplicatePageCapture DISABLED_DuplicatePageCapture
572 #else
573 #define Maybe_DuplicatePageCapture DuplicatePageCapture
574 #endif
575 IN_PROC_BROWSER_TEST_F(PhishingClassifierDelegateTest,
576                        Maybe_DuplicatePageCapture) {
577   // Tests that a second PageCaptured notification causes classification to
578   // be cancelled.
579   MockScorer scorer;
580   delegate_->SetPhishingScorer(&scorer);
581   ASSERT_TRUE(classifier_->is_ready());
582
583   EXPECT_CALL(*classifier_, CancelPendingClassification());
584   GURL url = LoadHtml("host.com", "<html><body>phish</body></html>");
585   Mock::VerifyAndClearExpectations(classifier_);
586   OnStartPhishingDetection(url);
587   base::string16 page_text = ASCIIToUTF16("phish");
588   {
589     InSequence s;
590     EXPECT_CALL(*classifier_, CancelPendingClassification());
591     EXPECT_CALL(*classifier_, BeginClassification(Pointee(page_text), _));
592     PageCaptured(&page_text, false);
593     Mock::VerifyAndClearExpectations(classifier_);
594   }
595
596   page_text = ASCIIToUTF16("phish");
597   EXPECT_CALL(*classifier_, CancelPendingClassification());
598   PageCaptured(&page_text, false);
599   Mock::VerifyAndClearExpectations(classifier_);
600
601   // The delegate will cancel pending classification on destruction.
602   EXPECT_CALL(*classifier_, CancelPendingClassification());
603 }
604
605 IN_PROC_BROWSER_TEST_F(PhishingClassifierDelegateTest, PhishingDetectionDone) {
606   // Tests that a PhishingDetectionDone IPC is sent to the browser
607   // whenever we finish classification.
608   MockScorer scorer;
609   delegate_->SetPhishingScorer(&scorer);
610   ASSERT_TRUE(classifier_->is_ready());
611
612   // Start by loading a page to populate the delegate's state.
613   EXPECT_CALL(*classifier_, CancelPendingClassification());
614   GURL url = LoadHtml("host.com", "<html><body>phish</body></html>");
615   Mock::VerifyAndClearExpectations(classifier_);
616   base::string16 page_text = ASCIIToUTF16("phish");
617   OnStartPhishingDetection(url);
618   {
619     InSequence s;
620     EXPECT_CALL(*classifier_, CancelPendingClassification());
621     EXPECT_CALL(*classifier_, BeginClassification(Pointee(page_text), _));
622     PageCaptured(&page_text, false);
623     Mock::VerifyAndClearExpectations(classifier_);
624   }
625
626   // Now run the callback to simulate the classifier finishing.
627   ClientPhishingRequest verdict;
628   verdict.set_url(url.spec());
629   verdict.set_client_score(0.8f);
630   verdict.set_is_phishing(false);  // Send IPC even if site is not phishing.
631   RunClassificationDone(verdict);
632   ASSERT_TRUE(intercepting_filter_->verdict());
633   EXPECT_EQ(verdict.SerializeAsString(),
634             intercepting_filter_->verdict()->SerializeAsString());
635
636   // The delegate will cancel pending classification on destruction.
637   EXPECT_CALL(*classifier_, CancelPendingClassification());
638 }
639
640 }  // namespace safe_browsing