42d0d694d335cc9a087dd5bd18bd66daeaf780ae
[platform/framework/web/crosswalk.git] / src / chrome / browser / safe_browsing / safe_browsing_blocking_page_test.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 // This test creates a fake safebrowsing service, where we can inject
6 // malware and phishing urls.  It then uses a real browser to go to
7 // these urls, and sends "goback" or "proceed" commands and verifies
8 // they work.
9
10 #include "base/bind.h"
11 #include "base/command_line.h"
12 #include "base/prefs/pref_service.h"
13 #include "base/strings/utf_string_conversions.h"
14 #include "base/values.h"
15 #include "chrome/browser/browser_process.h"
16 #include "chrome/browser/profiles/profile.h"
17 #include "chrome/browser/safe_browsing/database_manager.h"
18 #include "chrome/browser/safe_browsing/malware_details.h"
19 #include "chrome/browser/safe_browsing/safe_browsing_blocking_page.h"
20 #include "chrome/browser/safe_browsing/safe_browsing_service.h"
21 #include "chrome/browser/safe_browsing/safe_browsing_util.h"
22 #include "chrome/browser/safe_browsing/ui_manager.h"
23 #include "chrome/browser/ui/browser.h"
24 #include "chrome/browser/ui/browser_tabstrip.h"
25 #include "chrome/browser/ui/tabs/tab_strip_model.h"
26 #include "chrome/common/pref_names.h"
27 #include "chrome/common/url_constants.h"
28 #include "chrome/test/base/in_process_browser_test.h"
29 #include "chrome/test/base/test_switches.h"
30 #include "chrome/test/base/ui_test_utils.h"
31 #include "content/public/browser/interstitial_page.h"
32 #include "content/public/browser/navigation_controller.h"
33 #include "content/public/browser/notification_types.h"
34 #include "content/public/browser/render_frame_host.h"
35 #include "content/public/browser/render_view_host.h"
36 #include "content/public/browser/web_contents.h"
37 #include "content/public/test/browser_test_utils.h"
38 #include "content/public/test/test_browser_thread.h"
39 #include "content/public/test/test_utils.h"
40
41 using content::BrowserThread;
42 using content::InterstitialPage;
43 using content::NavigationController;
44 using content::WebContents;
45
46 namespace {
47
48 const char kEmptyPage[] = "files/empty.html";
49 const char kMalwarePage[] = "files/safe_browsing/malware.html";
50 const char kMalwareIframe[] = "files/safe_browsing/malware_iframe.html";
51
52 // A SafeBrowsingDatabaseManager class that allows us to inject the malicious
53 // URLs.
54 class FakeSafeBrowsingDatabaseManager :  public SafeBrowsingDatabaseManager {
55  public:
56   explicit FakeSafeBrowsingDatabaseManager(SafeBrowsingService* service)
57       : SafeBrowsingDatabaseManager(service) { }
58
59   // Called on the IO thread to check if the given url is safe or not.  If we
60   // can synchronously determine that the url is safe, CheckUrl returns true.
61   // Otherwise it returns false, and "client" is called asynchronously with the
62   // result when it is ready.
63   // Overrides SafeBrowsingDatabaseManager::CheckBrowseUrl.
64   bool CheckBrowseUrl(const GURL& gurl, Client* client) override {
65     if (badurls[gurl.spec()] == SB_THREAT_TYPE_SAFE)
66       return true;
67
68     BrowserThread::PostTask(
69         BrowserThread::IO, FROM_HERE,
70         base::Bind(&FakeSafeBrowsingDatabaseManager::OnCheckBrowseURLDone,
71                    this, gurl, client));
72     return false;
73   }
74
75   void OnCheckBrowseURLDone(const GURL& gurl, Client* client) {
76     std::vector<SBThreatType> expected_threats;
77     expected_threats.push_back(SB_THREAT_TYPE_URL_MALWARE);
78     expected_threats.push_back(SB_THREAT_TYPE_URL_PHISHING);
79     SafeBrowsingDatabaseManager::SafeBrowsingCheck sb_check(
80         std::vector<GURL>(1, gurl),
81         std::vector<SBFullHash>(),
82         client,
83         safe_browsing_util::MALWARE,
84         expected_threats);
85     sb_check.url_results[0] = badurls[gurl.spec()];
86     client->OnSafeBrowsingResult(sb_check);
87   }
88
89   void SetURLThreatType(const GURL& url, SBThreatType threat_type) {
90     badurls[url.spec()] = threat_type;
91   }
92
93  private:
94   ~FakeSafeBrowsingDatabaseManager() override {}
95
96   base::hash_map<std::string, SBThreatType> badurls;
97   DISALLOW_COPY_AND_ASSIGN(FakeSafeBrowsingDatabaseManager);
98 };
99
100 // A SafeBrowingUIManager class that allows intercepting malware details.
101 class FakeSafeBrowsingUIManager :  public SafeBrowsingUIManager {
102  public:
103   explicit FakeSafeBrowsingUIManager(SafeBrowsingService* service) :
104       SafeBrowsingUIManager(service) { }
105
106   // Overrides SafeBrowsingUIManager
107   void SendSerializedMalwareDetails(const std::string& serialized) override {
108     // Notify the UI thread that we got a report.
109     BrowserThread::PostTask(
110         BrowserThread::UI,
111         FROM_HERE,
112         base::Bind(&FakeSafeBrowsingUIManager::OnMalwareDetailsDone,
113                    this,
114                    serialized));
115   }
116
117   void OnMalwareDetailsDone(const std::string& serialized) {
118     EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI));
119     report_ = serialized;
120
121     EXPECT_FALSE(malware_details_done_callback_.is_null());
122     if (!malware_details_done_callback_.is_null()) {
123       malware_details_done_callback_.Run();
124       malware_details_done_callback_ = base::Closure();
125     }
126   }
127
128   void set_malware_details_done_callback(const base::Closure& callback) {
129     EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI));
130     EXPECT_TRUE(malware_details_done_callback_.is_null());
131     malware_details_done_callback_ = callback;
132   }
133
134   std::string GetReport() {
135     EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI));
136     return report_;
137   }
138
139  protected:
140   ~FakeSafeBrowsingUIManager() override {}
141
142  private:
143   std::string report_;
144   base::Closure malware_details_done_callback_;
145
146   DISALLOW_COPY_AND_ASSIGN(FakeSafeBrowsingUIManager);
147 };
148
149 class FakeSafeBrowsingService : public SafeBrowsingService {
150  public:
151   FakeSafeBrowsingService()
152       : fake_database_manager_(),
153         fake_ui_manager_() { }
154
155   // Returned pointer has the same lifespan as the database_manager_ refcounted
156   // object.
157   FakeSafeBrowsingDatabaseManager* fake_database_manager() {
158     return fake_database_manager_;
159   }
160   // Returned pointer has the same lifespan as the ui_manager_ refcounted
161   // object.
162   FakeSafeBrowsingUIManager* fake_ui_manager() {
163     return fake_ui_manager_;
164   }
165
166  protected:
167   ~FakeSafeBrowsingService() override {}
168
169   SafeBrowsingDatabaseManager* CreateDatabaseManager() override {
170     fake_database_manager_ = new FakeSafeBrowsingDatabaseManager(this);
171     return fake_database_manager_;
172   }
173
174   SafeBrowsingUIManager* CreateUIManager() override {
175     fake_ui_manager_ = new FakeSafeBrowsingUIManager(this);
176     return fake_ui_manager_;
177   }
178
179  private:
180   FakeSafeBrowsingDatabaseManager* fake_database_manager_;
181   FakeSafeBrowsingUIManager* fake_ui_manager_;
182
183   DISALLOW_COPY_AND_ASSIGN(FakeSafeBrowsingService);
184 };
185
186 // Factory that creates FakeSafeBrowsingService instances.
187 class TestSafeBrowsingServiceFactory : public SafeBrowsingServiceFactory {
188  public:
189   TestSafeBrowsingServiceFactory() :
190       most_recent_service_(NULL) { }
191   ~TestSafeBrowsingServiceFactory() override {}
192
193   SafeBrowsingService* CreateSafeBrowsingService() override {
194     most_recent_service_ =  new FakeSafeBrowsingService();
195     return most_recent_service_;
196   }
197
198   FakeSafeBrowsingService* most_recent_service() const {
199     return most_recent_service_;
200   }
201
202  private:
203   FakeSafeBrowsingService* most_recent_service_;
204 };
205
206 // A MalwareDetails class lets us intercept calls from the renderer.
207 class FakeMalwareDetails : public MalwareDetails {
208  public:
209   FakeMalwareDetails(
210       SafeBrowsingUIManager* delegate,
211       WebContents* web_contents,
212       const SafeBrowsingUIManager::UnsafeResource& unsafe_resource)
213       : MalwareDetails(delegate, web_contents, unsafe_resource),
214         got_dom_(false),
215         waiting_(false) { }
216
217   void AddDOMDetails(
218       const std::vector<SafeBrowsingHostMsg_MalwareDOMDetails_Node>& params)
219       override {
220     EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
221     MalwareDetails::AddDOMDetails(params);
222
223     // Notify the UI thread that we got the dom details.
224     BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
225                             base::Bind(&FakeMalwareDetails::OnDOMDetailsDone,
226                                        this));
227   }
228
229   void WaitForDOM() {
230     if (got_dom_) {
231       return;
232     }
233     // This condition might not trigger normally, but if you add a
234     // sleep(1) in malware_dom_details it triggers :).
235     waiting_ = true;
236     content::RunMessageLoop();
237     EXPECT_TRUE(got_dom_);
238   }
239
240  private:
241   ~FakeMalwareDetails() override {}
242
243   void OnDOMDetailsDone() {
244     got_dom_ = true;
245     if (waiting_) {
246       base::MessageLoopForUI::current()->Quit();
247     }
248   }
249
250   // Some logic to figure out if we should wait for the dom details or not.
251   // These variables should only be accessed in the UI thread.
252   bool got_dom_;
253   bool waiting_;
254 };
255
256 class TestMalwareDetailsFactory : public MalwareDetailsFactory {
257  public:
258   TestMalwareDetailsFactory() : details_() { }
259   ~TestMalwareDetailsFactory() override {}
260
261   MalwareDetails* CreateMalwareDetails(
262       SafeBrowsingUIManager* delegate,
263       WebContents* web_contents,
264       const SafeBrowsingUIManager::UnsafeResource& unsafe_resource) override {
265     details_ = new FakeMalwareDetails(delegate, web_contents,
266                                       unsafe_resource);
267     return details_;
268   }
269
270   FakeMalwareDetails* get_details() {
271     return details_;
272   }
273
274  private:
275   FakeMalwareDetails* details_;
276 };
277
278 // A SafeBrowingBlockingPage class that lets us wait until it's hidden.
279 class TestSafeBrowsingBlockingPage : public SafeBrowsingBlockingPage {
280  public:
281   TestSafeBrowsingBlockingPage(SafeBrowsingUIManager* manager,
282                                  WebContents* web_contents,
283                                  const UnsafeResourceList& unsafe_resources)
284       : SafeBrowsingBlockingPage(manager, web_contents, unsafe_resources),
285         wait_for_delete_(false) {
286     // Don't wait the whole 3 seconds for the browser test.
287     malware_details_proceed_delay_ms_ = 100;
288   }
289
290   ~TestSafeBrowsingBlockingPage() override {
291     if (!wait_for_delete_)
292       return;
293
294     // Notify that we are gone
295     base::MessageLoopForUI::current()->Quit();
296     wait_for_delete_ = false;
297   }
298
299   void WaitForDelete() {
300     wait_for_delete_ = true;
301     content::RunMessageLoop();
302   }
303
304   // InterstitialPageDelegate methods:
305   void CommandReceived(const std::string& command) override {
306     SafeBrowsingBlockingPage::CommandReceived(command);
307   }
308   void OnProceed() override { SafeBrowsingBlockingPage::OnProceed(); }
309   void OnDontProceed() override { SafeBrowsingBlockingPage::OnDontProceed(); }
310
311  private:
312   bool wait_for_delete_;
313 };
314
315 class TestSafeBrowsingBlockingPageFactory
316     : public SafeBrowsingBlockingPageFactory {
317  public:
318   TestSafeBrowsingBlockingPageFactory() { }
319   ~TestSafeBrowsingBlockingPageFactory() override {}
320
321   SafeBrowsingBlockingPage* CreateSafeBrowsingPage(
322       SafeBrowsingUIManager* delegate,
323       WebContents* web_contents,
324       const SafeBrowsingBlockingPage::UnsafeResourceList& unsafe_resources)
325       override {
326     return new TestSafeBrowsingBlockingPage(delegate, web_contents,
327                                               unsafe_resources);
328   }
329 };
330
331 }  // namespace
332
333 // Tests the safe browsing blocking page in a browser.
334 class SafeBrowsingBlockingPageBrowserTest
335     : public InProcessBrowserTest,
336       public testing::WithParamInterface<int> {
337  public:
338   enum Visibility {
339     VISIBILITY_ERROR = -1,
340     HIDDEN = 0,
341     VISIBLE = 1
342   };
343
344   SafeBrowsingBlockingPageBrowserTest() {
345   }
346
347   void SetUp() override {
348     SafeBrowsingService::RegisterFactory(&factory_);
349     SafeBrowsingBlockingPage::RegisterFactory(&blocking_page_factory_);
350     MalwareDetails::RegisterFactory(&details_factory_);
351     InProcessBrowserTest::SetUp();
352   }
353
354   void TearDown() override {
355     InProcessBrowserTest::TearDown();
356     SafeBrowsingBlockingPage::RegisterFactory(NULL);
357     SafeBrowsingService::RegisterFactory(NULL);
358     MalwareDetails::RegisterFactory(NULL);
359   }
360
361   void SetUpInProcessBrowserTestFixture() override {
362     ASSERT_TRUE(test_server()->Start());
363   }
364
365   void SetURLThreatType(const GURL& url, SBThreatType threat_type) {
366     FakeSafeBrowsingService* service =
367         static_cast<FakeSafeBrowsingService*>(
368             g_browser_process->safe_browsing_service());
369
370     ASSERT_TRUE(service);
371     service->fake_database_manager()->SetURLThreatType(url, threat_type);
372   }
373
374   // Adds a safebrowsing result of type |threat_type| to the fake safebrowsing
375   // service, navigates to that page, and returns the url.
376   GURL SetupWarningAndNavigate(SBThreatType threat_type) {
377     GURL url = test_server()->GetURL(kEmptyPage);
378     SetURLThreatType(url, threat_type);
379
380     ui_test_utils::NavigateToURL(browser(), url);
381     EXPECT_TRUE(WaitForReady());
382     return url;
383   }
384
385   // Adds a safebrowsing malware result to the fake safebrowsing service,
386   // navigates to a page with an iframe containing the malware site, and
387   // returns the url of the parent page.
388   GURL SetupMalwareIframeWarningAndNavigate() {
389     GURL url = test_server()->GetURL(kMalwarePage);
390     GURL iframe_url = test_server()->GetURL(kMalwareIframe);
391     SetURLThreatType(iframe_url, SB_THREAT_TYPE_URL_MALWARE);
392
393     ui_test_utils::NavigateToURL(browser(), url);
394     EXPECT_TRUE(WaitForReady());
395     return url;
396   }
397
398   void SendCommand(const std::string& command) {
399     WebContents* contents =
400         browser()->tab_strip_model()->GetActiveWebContents();
401     // We use InterstitialPage::GetInterstitialPage(tab) instead of
402     // tab->GetInterstitialPage() because the tab doesn't have a pointer
403     // to its interstital page until it gets a command from the renderer
404     // that it has indeed displayed it -- and this sometimes happens after
405     // NavigateToURL returns.
406     SafeBrowsingBlockingPage* interstitial_page =
407         static_cast<SafeBrowsingBlockingPage*>(
408             InterstitialPage::GetInterstitialPage(contents)->
409                 GetDelegateForTesting());
410     ASSERT_TRUE(interstitial_page);
411     interstitial_page->CommandReceived(command);
412   }
413
414   void DontProceedThroughInterstitial() {
415     WebContents* contents =
416         browser()->tab_strip_model()->GetActiveWebContents();
417     InterstitialPage* interstitial_page = InterstitialPage::GetInterstitialPage(
418         contents);
419     ASSERT_TRUE(interstitial_page);
420     interstitial_page->DontProceed();
421   }
422
423   void ProceedThroughInterstitial() {
424     WebContents* contents =
425         browser()->tab_strip_model()->GetActiveWebContents();
426     InterstitialPage* interstitial_page = InterstitialPage::GetInterstitialPage(
427         contents);
428     ASSERT_TRUE(interstitial_page);
429     interstitial_page->Proceed();
430   }
431
432   void AssertNoInterstitial(bool wait_for_delete) {
433     WebContents* contents =
434         browser()->tab_strip_model()->GetActiveWebContents();
435
436     if (contents->ShowingInterstitialPage() && wait_for_delete) {
437       // We'll get notified when the interstitial is deleted.
438       TestSafeBrowsingBlockingPage* page =
439           static_cast<TestSafeBrowsingBlockingPage*>(
440               contents->GetInterstitialPage()->GetDelegateForTesting());
441       page->WaitForDelete();
442     }
443
444     // Can't use InterstitialPage::GetInterstitialPage() because that
445     // gets updated after the TestSafeBrowsingBlockingPage destructor
446     ASSERT_FALSE(contents->ShowingInterstitialPage());
447   }
448
449   bool YesInterstitial() {
450     WebContents* contents =
451         browser()->tab_strip_model()->GetActiveWebContents();
452     InterstitialPage* interstitial_page = InterstitialPage::GetInterstitialPage(
453         contents);
454     return interstitial_page != NULL;
455   }
456
457   void SetReportSentCallback(const base::Closure& callback) {
458     factory_.most_recent_service()
459         ->fake_ui_manager()
460         ->set_malware_details_done_callback(callback);
461   }
462
463   std::string GetReportSent() {
464     return factory_.most_recent_service()->fake_ui_manager()->GetReport();
465   }
466
467   void MalwareRedirectCancelAndProceed(const std::string& open_function) {
468     GURL load_url = test_server()->GetURL(
469         "files/safe_browsing/interstitial_cancel.html");
470     GURL malware_url("http://localhost/files/safe_browsing/malware.html");
471     SetURLThreatType(malware_url, SB_THREAT_TYPE_URL_MALWARE);
472
473     // Load the test page.
474     ui_test_utils::NavigateToURL(browser(), load_url);
475     // Trigger the safe browsing interstitial page via a redirect in
476     // "openWin()".
477     ui_test_utils::NavigateToURLWithDisposition(
478         browser(),
479         GURL("javascript:" + open_function + "()"),
480         CURRENT_TAB,
481         ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB);
482     WebContents* contents =
483         browser()->tab_strip_model()->GetActiveWebContents();
484     content::WaitForInterstitialAttach(contents);
485     // Cancel the redirect request while interstitial page is open.
486     browser()->tab_strip_model()->ActivateTabAt(0, true);
487     ui_test_utils::NavigateToURLWithDisposition(
488         browser(),
489         GURL("javascript:stopWin()"),
490         CURRENT_TAB,
491         ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
492     browser()->tab_strip_model()->ActivateTabAt(1, true);
493     // Simulate the user clicking "proceed", there should be no crash.  Since
494     // clicking proceed may do nothing (see comment in MalwareRedirectCanceled
495     // below, and crbug.com/76460), we use SendCommand to trigger the callback
496     // directly rather than using ClickAndWaitForDetach since there might not
497     // be a notification to wait for.
498     SendCommand("\"proceed\"");
499   }
500
501   content::RenderViewHost* GetRenderViewHost() {
502     InterstitialPage* interstitial = InterstitialPage::GetInterstitialPage(
503         browser()->tab_strip_model()->GetActiveWebContents());
504     if (!interstitial)
505       return NULL;
506     return interstitial->GetRenderViewHostForTesting();
507   }
508
509   bool WaitForReady() {
510     content::RenderViewHost* rvh = GetRenderViewHost();
511     if (!rvh)
512       return false;
513     // Wait until all <script> tags have executed, including jstemplate.
514     // TODO(joaodasilva): it would be nice to avoid the busy loop, though in
515     // practice it spins at most once or twice.
516     std::string ready_state;
517     do {
518       scoped_ptr<base::Value> value = content::ExecuteScriptAndGetValue(
519           rvh->GetMainFrame(), "document.readyState");
520       if (!value.get() || !value->GetAsString(&ready_state))
521         return false;
522     } while (ready_state != "complete");
523     return true;
524   }
525
526   Visibility GetVisibility(const std::string& node_id) {
527     content::RenderViewHost* rvh = GetRenderViewHost();
528     if (!rvh)
529       return VISIBILITY_ERROR;
530     scoped_ptr<base::Value> value = content::ExecuteScriptAndGetValue(
531         rvh->GetMainFrame(),
532         "var node = document.getElementById('" + node_id + "');\n"
533         "if (node)\n"
534         "   node.offsetWidth > 0 && node.offsetHeight > 0;"
535         "else\n"
536         "  'node not found';\n");
537     if (!value.get())
538       return VISIBILITY_ERROR;
539     bool result = false;
540     if (!value->GetAsBoolean(&result))
541       return VISIBILITY_ERROR;
542     return result ? VISIBLE : HIDDEN;
543   }
544
545   bool Click(const std::string& node_id) {
546     content::RenderViewHost* rvh = GetRenderViewHost();
547     if (!rvh)
548       return false;
549     // We don't use ExecuteScriptAndGetValue for this one, since clicking
550     // the button/link may navigate away before the injected javascript can
551     // reply, hanging the test.
552     rvh->GetMainFrame()->ExecuteJavaScript(
553         base::ASCIIToUTF16(
554             "document.getElementById('" + node_id + "').click();\n"));
555     return true;
556   }
557
558   bool ClickAndWaitForDetach(const std::string& node_id) {
559     // We wait for interstitial_detached rather than nav_entry_committed, as
560     // going back from a main-frame malware interstitial page will not cause a
561     // nav entry committed event.
562     if (!Click(node_id))
563       return false;
564     content::WaitForInterstitialDetach(
565         browser()->tab_strip_model()->GetActiveWebContents());
566     return true;
567   }
568
569  protected:
570   TestMalwareDetailsFactory details_factory_;
571
572  private:
573   TestSafeBrowsingServiceFactory factory_;
574   TestSafeBrowsingBlockingPageFactory blocking_page_factory_;
575
576   DISALLOW_COPY_AND_ASSIGN(SafeBrowsingBlockingPageBrowserTest);
577 };
578
579 // TODO(linux_aura) http://crbug.com/163931
580 // TODO(win_aura) http://crbug.com/154081
581 #if defined(USE_AURA) && !defined(OS_CHROMEOS)
582 #define MAYBE_MalwareRedirectInIFrameCanceled DISABLED_MalwareRedirectInIFrameCanceled
583 #else
584 #define MAYBE_MalwareRedirectInIFrameCanceled MalwareRedirectInIFrameCanceled
585 #endif
586 IN_PROC_BROWSER_TEST_F(SafeBrowsingBlockingPageBrowserTest,
587                        MAYBE_MalwareRedirectInIFrameCanceled) {
588   // 1. Test the case that redirect is a subresource.
589   MalwareRedirectCancelAndProceed("openWinIFrame");
590   // If the redirect was from subresource but canceled, "proceed" will continue
591   // with the rest of resources.
592   AssertNoInterstitial(true);
593 }
594
595 IN_PROC_BROWSER_TEST_F(SafeBrowsingBlockingPageBrowserTest,
596                        MalwareRedirectCanceled) {
597   // 2. Test the case that redirect is the only resource.
598   MalwareRedirectCancelAndProceed("openWin");
599   // Clicking proceed won't do anything if the main request is cancelled
600   // already.  See crbug.com/76460.
601   EXPECT_TRUE(YesInterstitial());
602 }
603
604 IN_PROC_BROWSER_TEST_F(SafeBrowsingBlockingPageBrowserTest,
605                        MalwareDontProceed) {
606 #if defined(OS_WIN) && defined(USE_ASH)
607   // Disable this test in Metro+Ash for now (http://crbug.com/262796).
608   if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests))
609     return;
610 #endif
611
612   SetupWarningAndNavigate(SB_THREAT_TYPE_URL_MALWARE);
613
614   EXPECT_EQ(VISIBLE, GetVisibility("primary-button"));
615   EXPECT_EQ(HIDDEN, GetVisibility("details"));
616   EXPECT_EQ(HIDDEN, GetVisibility("proceed-link"));
617   EXPECT_EQ(HIDDEN, GetVisibility("error-code"));
618   EXPECT_TRUE(Click("details-button"));
619   EXPECT_EQ(VISIBLE, GetVisibility("details"));
620   EXPECT_EQ(VISIBLE, GetVisibility("proceed-link"));
621   EXPECT_EQ(HIDDEN, GetVisibility("error-code"));
622   EXPECT_TRUE(ClickAndWaitForDetach("primary-button"));
623
624   AssertNoInterstitial(false);   // Assert the interstitial is gone
625   EXPECT_EQ(GURL(url::kAboutBlankURL),  // Back to "about:blank"
626             browser()->tab_strip_model()->GetActiveWebContents()->GetURL());
627 }
628
629 IN_PROC_BROWSER_TEST_F(SafeBrowsingBlockingPageBrowserTest,
630                        HarmfulDontProceed) {
631 #if defined(OS_WIN) && defined(USE_ASH)
632   // Disable this test in Metro+Ash for now (http://crbug.com/262796).
633   if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests))
634     return;
635 #endif
636
637   SetupWarningAndNavigate(SB_THREAT_TYPE_URL_UNWANTED);
638
639   EXPECT_EQ(VISIBLE, GetVisibility("primary-button"));
640   EXPECT_EQ(HIDDEN, GetVisibility("details"));
641   EXPECT_EQ(HIDDEN, GetVisibility("proceed-link"));
642   EXPECT_EQ(HIDDEN, GetVisibility("error-code"));
643   EXPECT_TRUE(Click("details-button"));
644   EXPECT_EQ(VISIBLE, GetVisibility("details"));
645   EXPECT_EQ(VISIBLE, GetVisibility("proceed-link"));
646   EXPECT_EQ(HIDDEN, GetVisibility("error-code"));
647   EXPECT_TRUE(ClickAndWaitForDetach("primary-button"));
648
649   AssertNoInterstitial(false);   // Assert the interstitial is gone
650   EXPECT_EQ(GURL(url::kAboutBlankURL),  // Back to "about:blank"
651             browser()->tab_strip_model()->GetActiveWebContents()->GetURL());
652 }
653
654 IN_PROC_BROWSER_TEST_F(SafeBrowsingBlockingPageBrowserTest, MalwareProceed) {
655   GURL url = SetupWarningAndNavigate(SB_THREAT_TYPE_URL_MALWARE);
656
657   EXPECT_TRUE(ClickAndWaitForDetach("proceed-link"));
658   AssertNoInterstitial(true);  // Assert the interstitial is gone.
659   EXPECT_EQ(url,
660             browser()->tab_strip_model()->GetActiveWebContents()->GetURL());
661 }
662
663 IN_PROC_BROWSER_TEST_F(SafeBrowsingBlockingPageBrowserTest, HarmfulProceed) {
664   GURL url = SetupWarningAndNavigate(SB_THREAT_TYPE_URL_UNWANTED);
665
666   EXPECT_TRUE(ClickAndWaitForDetach("proceed-link"));
667   AssertNoInterstitial(true);  // Assert the interstitial is gone.
668   EXPECT_EQ(url,
669             browser()->tab_strip_model()->GetActiveWebContents()->GetURL());
670 }
671
672 IN_PROC_BROWSER_TEST_F(SafeBrowsingBlockingPageBrowserTest,
673                        MalwareIframeDontProceed) {
674 #if defined(OS_WIN) && defined(USE_ASH)
675   // Disable this test in Metro+Ash for now (http://crbug.com/262796).
676   if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests))
677     return;
678 #endif
679
680   SetupMalwareIframeWarningAndNavigate();
681
682   EXPECT_EQ(VISIBLE, GetVisibility("primary-button"));
683   EXPECT_EQ(HIDDEN, GetVisibility("details"));
684   EXPECT_EQ(HIDDEN, GetVisibility("proceed-link"));
685   EXPECT_EQ(HIDDEN, GetVisibility("error-code"));
686   EXPECT_TRUE(Click("details-button"));
687   EXPECT_EQ(VISIBLE, GetVisibility("details"));
688   EXPECT_EQ(VISIBLE, GetVisibility("proceed-link"));
689   EXPECT_EQ(HIDDEN, GetVisibility("error-code"));
690   EXPECT_TRUE(ClickAndWaitForDetach("primary-button"));
691
692   AssertNoInterstitial(false);  // Assert the interstitial is gone
693
694   EXPECT_EQ(GURL(url::kAboutBlankURL),  // Back to "about:blank"
695             browser()->tab_strip_model()->GetActiveWebContents()->GetURL());
696 }
697
698 IN_PROC_BROWSER_TEST_F(SafeBrowsingBlockingPageBrowserTest,
699     MalwareIframeProceed) {
700   GURL url = SetupMalwareIframeWarningAndNavigate();
701
702   EXPECT_TRUE(ClickAndWaitForDetach("proceed-link"));
703   AssertNoInterstitial(true);  // Assert the interstitial is gone
704
705   EXPECT_EQ(url,
706             browser()->tab_strip_model()->GetActiveWebContents()->GetURL());
707 }
708
709 IN_PROC_BROWSER_TEST_F(SafeBrowsingBlockingPageBrowserTest,
710                        MalwareIframeReportDetails) {
711   scoped_refptr<content::MessageLoopRunner> malware_report_sent_runner(
712       new content::MessageLoopRunner);
713   SetReportSentCallback(malware_report_sent_runner->QuitClosure());
714
715   GURL url = SetupMalwareIframeWarningAndNavigate();
716
717   // If the DOM details from renderer did not already return, wait for them.
718   details_factory_.get_details()->WaitForDOM();
719
720   EXPECT_TRUE(Click("opt-in-checkbox"));
721   EXPECT_TRUE(ClickAndWaitForDetach("proceed-link"));
722   AssertNoInterstitial(true);  // Assert the interstitial is gone
723
724   ASSERT_TRUE(browser()->profile()->GetPrefs()->GetBoolean(
725       prefs::kSafeBrowsingExtendedReportingEnabled));
726   EXPECT_EQ(url,
727             browser()->tab_strip_model()->GetActiveWebContents()->GetURL());
728
729   malware_report_sent_runner->Run();
730   std::string serialized = GetReportSent();
731   safe_browsing::ClientMalwareReportRequest report;
732   ASSERT_TRUE(report.ParseFromString(serialized));
733   // Verify the report is complete.
734   EXPECT_TRUE(report.complete());
735 }
736
737 // Verifies that the "proceed anyway" link isn't available when it is disabled
738 // by the corresponding policy. Also verifies that sending the "proceed"
739 // command anyway doesn't advance to the malware site.
740 IN_PROC_BROWSER_TEST_F(SafeBrowsingBlockingPageBrowserTest, ProceedDisabled) {
741 #if defined(OS_WIN) && defined(USE_ASH)
742   // Disable this test in Metro+Ash for now (http://crbug.com/262796).
743   if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests))
744     return;
745 #endif
746
747   // Simulate a policy disabling the "proceed anyway" link.
748   browser()->profile()->GetPrefs()->SetBoolean(
749       prefs::kSafeBrowsingProceedAnywayDisabled, true);
750
751   SetupWarningAndNavigate(SB_THREAT_TYPE_URL_MALWARE);
752
753   EXPECT_EQ(VISIBLE, GetVisibility("primary-button"));
754   EXPECT_EQ(HIDDEN, GetVisibility("details"));
755   EXPECT_EQ(HIDDEN, GetVisibility("proceed-link"));
756   EXPECT_EQ(HIDDEN, GetVisibility("final-paragraph"));
757   EXPECT_TRUE(Click("details-button"));
758   EXPECT_EQ(HIDDEN, GetVisibility("proceed-link"));
759   EXPECT_EQ(HIDDEN, GetVisibility("final-paragraph"));
760   SendCommand("proceed");
761
762   // The "proceed" command should go back instead, if proceeding is disabled.
763   AssertNoInterstitial(true);
764   EXPECT_EQ(GURL(url::kAboutBlankURL),  // Back to "about:blank"
765             browser()->tab_strip_model()->GetActiveWebContents()->GetURL());
766 }
767
768 // Verifies that the reporting checkbox is hidden on non-HTTP pages.
769 // TODO(mattm): Should also verify that no report is sent, but there isn't a
770 // good way to do that in the current design.
771 IN_PROC_BROWSER_TEST_F(SafeBrowsingBlockingPageBrowserTest,
772                        ReportingDisabled) {
773 #if defined(OS_WIN) && defined(USE_ASH)
774   // Disable this test in Metro+Ash for now (http://crbug.com/262796).
775   if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests))
776     return;
777 #endif
778
779   browser()->profile()->GetPrefs()->SetBoolean(
780       prefs::kSafeBrowsingExtendedReportingEnabled, true);
781
782   net::SpawnedTestServer https_server(
783       net::SpawnedTestServer::TYPE_HTTPS, net::SpawnedTestServer::kLocalhost,
784       base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
785   ASSERT_TRUE(https_server.Start());
786   GURL url = https_server.GetURL(kEmptyPage);
787   SetURLThreatType(url, SB_THREAT_TYPE_URL_MALWARE);
788   ui_test_utils::NavigateToURL(browser(), url);
789   ASSERT_TRUE(WaitForReady());
790
791   EXPECT_EQ(HIDDEN, GetVisibility("malware-opt-in"));
792   EXPECT_EQ(HIDDEN, GetVisibility("opt-in-checkbox"));
793   EXPECT_EQ(HIDDEN, GetVisibility("proceed-link"));
794   EXPECT_TRUE(Click("details-button"));
795   EXPECT_EQ(VISIBLE, GetVisibility("help-link"));
796   EXPECT_EQ(VISIBLE, GetVisibility("proceed-link"));
797
798   EXPECT_TRUE(ClickAndWaitForDetach("primary-button"));
799   AssertNoInterstitial(false);   // Assert the interstitial is gone
800   EXPECT_EQ(GURL(url::kAboutBlankURL),  // Back to "about:blank"
801             browser()->tab_strip_model()->GetActiveWebContents()->GetURL());
802 }
803
804 IN_PROC_BROWSER_TEST_F(SafeBrowsingBlockingPageBrowserTest,
805     PhishingDontProceed) {
806 #if defined(OS_WIN) && defined(USE_ASH)
807   // Disable this test in Metro+Ash for now (http://crbug.com/262796).
808   if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests))
809     return;
810 #endif
811
812   SetupWarningAndNavigate(SB_THREAT_TYPE_URL_PHISHING);
813
814   EXPECT_EQ(VISIBLE, GetVisibility("primary-button"));
815   EXPECT_EQ(HIDDEN, GetVisibility("details"));
816   EXPECT_EQ(HIDDEN, GetVisibility("proceed-link"));
817   EXPECT_EQ(HIDDEN, GetVisibility("error-code"));
818   EXPECT_TRUE(Click("details-button"));
819   EXPECT_EQ(VISIBLE, GetVisibility("details"));
820   EXPECT_EQ(VISIBLE, GetVisibility("proceed-link"));
821   EXPECT_EQ(HIDDEN, GetVisibility("error-code"));
822   EXPECT_TRUE(ClickAndWaitForDetach("primary-button"));
823
824   AssertNoInterstitial(false);  // Assert the interstitial is gone
825   EXPECT_EQ(GURL(url::kAboutBlankURL),  // We are back to "about:blank".
826             browser()->tab_strip_model()->GetActiveWebContents()->GetURL());
827 }
828
829 IN_PROC_BROWSER_TEST_F(SafeBrowsingBlockingPageBrowserTest, PhishingProceed) {
830   GURL url = SetupWarningAndNavigate(SB_THREAT_TYPE_URL_PHISHING);
831   EXPECT_TRUE(ClickAndWaitForDetach("proceed-link"));
832   AssertNoInterstitial(true);  // Assert the interstitial is gone
833   EXPECT_EQ(url,
834             browser()->tab_strip_model()->GetActiveWebContents()->GetURL());
835 }
836
837 IN_PROC_BROWSER_TEST_F(SafeBrowsingBlockingPageBrowserTest, PhishingLearnMore) {
838   SetupWarningAndNavigate(SB_THREAT_TYPE_URL_PHISHING);
839   EXPECT_TRUE(ClickAndWaitForDetach("help-link"));
840   AssertNoInterstitial(false);  // Assert the interstitial is gone
841
842   // We are in the help page.
843   EXPECT_EQ(
844       "/transparencyreport/safebrowsing/",
845        browser()->tab_strip_model()->GetActiveWebContents()->GetURL().path());
846 }