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