• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2011 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 "chrome/browser/browser_process.h"
11 #include "chrome/browser/prefs/pref_service.h"
12 #include "chrome/browser/profiles/profile.h"
13 #include "chrome/browser/safe_browsing/malware_details.h"
14 #include "chrome/browser/safe_browsing/safe_browsing_service.h"
15 #include "chrome/browser/safe_browsing/safe_browsing_blocking_page.h"
16 #include "chrome/browser/ui/browser.h"
17 #include "chrome/common/pref_names.h"
18 #include "chrome/common/url_constants.h"
19 #include "chrome/test/in_process_browser_test.h"
20 #include "chrome/test/ui_test_utils.h"
21 #include "content/browser/browser_thread.h"
22 #include "content/browser/renderer_host/render_process_host.h"
23 #include "content/browser/renderer_host/resource_dispatcher_host.h"
24 #include "content/browser/tab_contents/tab_contents.h"
25 #include "content/browser/tab_contents/tab_contents_view.h"
26 
27 // A SafeBrowingService class that allows us to inject the malicious URLs.
28 class FakeSafeBrowsingService :  public SafeBrowsingService {
29  public:
FakeSafeBrowsingService()30   FakeSafeBrowsingService() {}
31 
~FakeSafeBrowsingService()32   virtual ~FakeSafeBrowsingService() {}
33 
34   // Called on the IO thread to check if the given url is safe or not.  If we
35   // can synchronously determine that the url is safe, CheckUrl returns true.
36   // Otherwise it returns false, and "client" is called asynchronously with the
37   // result when it is ready.
38   // Overrides SafeBrowsingService::CheckBrowseUrl.
CheckBrowseUrl(const GURL & gurl,Client * client)39   virtual bool CheckBrowseUrl(const GURL& gurl, Client* client) {
40     if (badurls[gurl.spec()] == SAFE)
41       return true;
42 
43     BrowserThread::PostTask(
44         BrowserThread::IO, FROM_HERE,
45         NewRunnableMethod(this, &FakeSafeBrowsingService::OnCheckBrowseURLDone,
46                           gurl, client));
47     return false;
48   }
49 
OnCheckBrowseURLDone(const GURL & gurl,Client * client)50   void OnCheckBrowseURLDone(const GURL& gurl, Client* client) {
51     SafeBrowsingService::SafeBrowsingCheck check;
52     check.urls.push_back(gurl);
53     check.client = client;
54     check.result = badurls[gurl.spec()];
55     client->OnSafeBrowsingResult(check);
56   }
57 
AddURLResult(const GURL & url,UrlCheckResult checkresult)58   void AddURLResult(const GURL& url, UrlCheckResult checkresult) {
59     badurls[url.spec()] = checkresult;
60   }
61 
62   // Overrides SafeBrowsingService.
SendSerializedMalwareDetails(const std::string & serialized)63   virtual void SendSerializedMalwareDetails(const std::string& serialized) {
64     reports_.push_back(serialized);
65     // Notify the UI thread that we got a report.
66     BrowserThread::PostTask(
67         BrowserThread::UI, FROM_HERE,
68         NewRunnableMethod(this,
69                           &FakeSafeBrowsingService::OnMalwareDetailsDone));
70   }
71 
OnMalwareDetailsDone()72   void OnMalwareDetailsDone() {
73     EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI));
74     MessageLoopForUI::current()->Quit();
75   }
76 
GetReport()77   std::string GetReport() {
78     EXPECT_TRUE(reports_.size() == 1);
79     return reports_[0];
80   }
81 
82   std::vector<std::string> reports_;
83 
84  private:
85   base::hash_map<std::string, UrlCheckResult> badurls;
86 };
87 
88 // Factory that creates FakeSafeBrowsingService instances.
89 class TestSafeBrowsingServiceFactory : public SafeBrowsingServiceFactory {
90  public:
TestSafeBrowsingServiceFactory()91   TestSafeBrowsingServiceFactory() { }
~TestSafeBrowsingServiceFactory()92   virtual ~TestSafeBrowsingServiceFactory() { }
93 
CreateSafeBrowsingService()94   virtual SafeBrowsingService* CreateSafeBrowsingService() {
95     return new FakeSafeBrowsingService();
96   }
97 };
98 
99 // A MalwareDetails class lets us intercept calls from the renderer.
100 class FakeMalwareDetails : public MalwareDetails {
101  public:
FakeMalwareDetails(SafeBrowsingService * sb_service,TabContents * tab_contents,const SafeBrowsingService::UnsafeResource & unsafe_resource)102   FakeMalwareDetails(SafeBrowsingService* sb_service,
103                      TabContents* tab_contents,
104                      const SafeBrowsingService::UnsafeResource& unsafe_resource)
105       : MalwareDetails(sb_service, tab_contents, unsafe_resource) { }
106 
~FakeMalwareDetails()107   virtual ~FakeMalwareDetails() {}
108 
AddDOMDetails(const std::vector<SafeBrowsingHostMsg_MalwareDOMDetails_Node> & params)109   virtual void AddDOMDetails(
110       const std::vector<SafeBrowsingHostMsg_MalwareDOMDetails_Node>& params) {
111     EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
112     MalwareDetails::AddDOMDetails(params);
113 
114     // Notify the UI thread that we got the dom details.
115     BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
116                             NewRunnableMethod(this,
117                             &FakeMalwareDetails::OnDOMDetailsDone));
118   }
119 
OnDOMDetailsDone()120   void OnDOMDetailsDone() {
121     got_dom_ = true;
122     if (waiting_) {
123       MessageLoopForUI::current()->Quit();
124     }
125   }
126 
got_dom() const127   bool got_dom() const {
128     return got_dom_;
129   }
130 
waiting() const131   bool waiting() const {
132     return waiting_;
133   }
134 
set_got_dom(bool got_dom)135   void set_got_dom(bool got_dom) {
136     got_dom_ = got_dom;
137   }
138 
set_waiting(bool waiting)139   void set_waiting(bool waiting) {
140     waiting_ = waiting;
141   }
142 
get_report()143   safe_browsing::ClientMalwareReportRequest* get_report() {
144     return report_.get();
145   }
146 
147  private:
148   // Some logic to figure out if we should wait for the dom details or not.
149   // These variables should only be accessed in the UI thread.
150   bool got_dom_;
151   bool waiting_;
152 
153 };
154 
155 class TestMalwareDetailsFactory : public MalwareDetailsFactory {
156  public:
TestMalwareDetailsFactory()157   TestMalwareDetailsFactory() { }
~TestMalwareDetailsFactory()158   virtual ~TestMalwareDetailsFactory() { }
159 
CreateMalwareDetails(SafeBrowsingService * sb_service,TabContents * tab_contents,const SafeBrowsingService::UnsafeResource & unsafe_resource)160   virtual MalwareDetails* CreateMalwareDetails(
161       SafeBrowsingService* sb_service,
162       TabContents* tab_contents,
163       const SafeBrowsingService::UnsafeResource& unsafe_resource) {
164     details_ = new FakeMalwareDetails(sb_service, tab_contents,
165                                       unsafe_resource);
166     return details_;
167   }
168 
get_details()169   FakeMalwareDetails* get_details() {
170     return details_;
171   }
172 
173  private:
174   FakeMalwareDetails* details_;
175 };
176 
177 // A SafeBrowingBlockingPage class that lets us wait until it's hidden.
178 class TestSafeBrowsingBlockingPage :  public SafeBrowsingBlockingPage {
179  public:
TestSafeBrowsingBlockingPage(SafeBrowsingService * service,TabContents * tab_contents,const UnsafeResourceList & unsafe_resources)180   TestSafeBrowsingBlockingPage(SafeBrowsingService* service,
181                                TabContents* tab_contents,
182                                const UnsafeResourceList& unsafe_resources)
183       : SafeBrowsingBlockingPage(service, tab_contents, unsafe_resources) {
184     wait_for_delete_ = false;
185   }
186 
~TestSafeBrowsingBlockingPage()187   ~TestSafeBrowsingBlockingPage() {
188     if (wait_for_delete_) {
189       // Notify that we are gone
190       MessageLoopForUI::current()->Quit();
191     }
192   }
193 
set_wait_for_delete()194   void set_wait_for_delete() {
195     wait_for_delete_ = true;
196   }
197 
198  private:
199   bool wait_for_delete_;
200 };
201 
202 class TestSafeBrowsingBlockingPageFactory
203     : public SafeBrowsingBlockingPageFactory {
204  public:
TestSafeBrowsingBlockingPageFactory()205   TestSafeBrowsingBlockingPageFactory() { }
~TestSafeBrowsingBlockingPageFactory()206   ~TestSafeBrowsingBlockingPageFactory() { }
207 
CreateSafeBrowsingPage(SafeBrowsingService * service,TabContents * tab_contents,const SafeBrowsingBlockingPage::UnsafeResourceList & unsafe_resources)208   virtual SafeBrowsingBlockingPage* CreateSafeBrowsingPage(
209       SafeBrowsingService* service,
210       TabContents* tab_contents,
211       const SafeBrowsingBlockingPage::UnsafeResourceList& unsafe_resources) {
212     return new TestSafeBrowsingBlockingPage(service, tab_contents,
213                                             unsafe_resources);
214   }
215 };
216 
217 // Tests the safe browsing blocking page in a browser.
218 class SafeBrowsingBlockingPageTest : public InProcessBrowserTest,
219                                      public SafeBrowsingService::Client {
220  public:
SafeBrowsingBlockingPageTest()221   SafeBrowsingBlockingPageTest() {
222   }
223 
SetUp()224   virtual void SetUp() {
225     SafeBrowsingService::RegisterFactory(&factory_);
226     SafeBrowsingBlockingPage::RegisterFactory(&blocking_page_factory_);
227     MalwareDetails::RegisterFactory(&details_factory_);
228     InProcessBrowserTest::SetUp();
229   }
230 
TearDown()231   virtual void TearDown() {
232     InProcessBrowserTest::TearDown();
233     SafeBrowsingBlockingPage::RegisterFactory(NULL);
234     SafeBrowsingService::RegisterFactory(NULL);
235     MalwareDetails::RegisterFactory(NULL);
236   }
237 
SetUpInProcessBrowserTestFixture()238   virtual void SetUpInProcessBrowserTestFixture() {
239     ASSERT_TRUE(test_server()->Start());
240   }
241 
242   // SafeBrowsingService::Client implementation.
OnSafeBrowsingResult(const SafeBrowsingService::SafeBrowsingCheck & check)243   virtual void OnSafeBrowsingResult(
244       const SafeBrowsingService::SafeBrowsingCheck& check) {
245   }
246 
OnBlockingPageComplete(bool proceed)247   virtual void OnBlockingPageComplete(bool proceed) {
248   }
249 
AddURLResult(const GURL & url,SafeBrowsingService::UrlCheckResult checkresult)250   void AddURLResult(const GURL& url,
251                     SafeBrowsingService::UrlCheckResult checkresult) {
252     FakeSafeBrowsingService* service =
253         static_cast<FakeSafeBrowsingService*>(
254             g_browser_process->resource_dispatcher_host()->
255             safe_browsing_service());
256 
257     ASSERT_TRUE(service);
258     service->AddURLResult(url, checkresult);
259   }
260 
SendCommand(const std::string & command)261   void SendCommand(const std::string& command) {
262     TabContents* contents = browser()->GetSelectedTabContents();
263     // We use InterstitialPage::GetInterstitialPage(tab) instead of
264     // tab->interstitial_page() because the tab doesn't have a pointer
265     // to its interstital page until it gets a command from the renderer
266     // that it has indeed displayed it -- and this sometimes happens after
267     // NavigateToURL returns.
268     SafeBrowsingBlockingPage* interstitial_page =
269         static_cast<SafeBrowsingBlockingPage*>(
270             InterstitialPage::GetInterstitialPage(contents));
271     ASSERT_TRUE(interstitial_page);
272     interstitial_page->CommandReceived(command);
273   }
274 
DontProceedThroughInterstitial()275   void DontProceedThroughInterstitial() {
276     TabContents* contents = browser()->GetSelectedTabContents();
277     InterstitialPage* interstitial_page = InterstitialPage::GetInterstitialPage(
278         contents);
279     ASSERT_TRUE(interstitial_page);
280     interstitial_page->DontProceed();
281   }
282 
ProceedThroughInterstitial()283   void ProceedThroughInterstitial() {
284     TabContents* contents = browser()->GetSelectedTabContents();
285     InterstitialPage* interstitial_page = InterstitialPage::GetInterstitialPage(
286         contents);
287     ASSERT_TRUE(interstitial_page);
288     interstitial_page->Proceed();
289   }
290 
AssertNoInterstitial(bool wait_for_delete)291   void AssertNoInterstitial(bool wait_for_delete) {
292     TabContents* contents = browser()->GetSelectedTabContents();
293 
294     if (contents->showing_interstitial_page() && wait_for_delete) {
295       // We'll get notified when the interstitial is deleted.
296       static_cast<TestSafeBrowsingBlockingPage*>(
297           contents->interstitial_page())->set_wait_for_delete();
298       ui_test_utils::RunMessageLoop();
299     }
300 
301     // Can't use InterstitialPage::GetInterstitialPage() because that
302     // gets updated after the TestSafeBrowsingBlockingPage destructor
303     ASSERT_FALSE(contents->showing_interstitial_page());
304   }
305 
YesInterstitial()306   bool YesInterstitial() {
307     TabContents* contents = browser()->GetSelectedTabContents();
308     InterstitialPage* interstitial_page = InterstitialPage::GetInterstitialPage(
309         contents);
310     return interstitial_page != NULL;
311   }
312 
WaitForInterstitial()313   void WaitForInterstitial() {
314     TabContents* contents = browser()->GetSelectedTabContents();
315     if (!InterstitialPage::GetInterstitialPage(contents))
316       ui_test_utils::WaitForNotificationFrom(
317           NotificationType::INTERSTITIAL_ATTACHED,
318           Source<TabContents>(contents));
319   }
320 
WaitForNavigation()321   void WaitForNavigation() {
322     NavigationController* controller =
323         &browser()->GetSelectedTabContents()->controller();
324     ui_test_utils::WaitForNavigation(controller);
325   }
326 
AssertReportSent()327   void AssertReportSent() {
328     // When a report is scheduled in the IO thread we should get notified.
329     ui_test_utils::RunMessageLoop();
330 
331     FakeSafeBrowsingService* service =
332         static_cast<FakeSafeBrowsingService*>(
333             g_browser_process->resource_dispatcher_host()->
334             safe_browsing_service());
335 
336     std::string serialized = service->GetReport();
337 
338     safe_browsing::ClientMalwareReportRequest report;
339     ASSERT_TRUE(report.ParseFromString(serialized));
340 
341     // Verify the report is complete.
342     EXPECT_TRUE(report.complete());
343   }
344 
345   void MalwareRedirectCancelAndProceed(const std::string open_function);
346 
347  protected:
348   TestMalwareDetailsFactory details_factory_;
349 
350  private:
351   TestSafeBrowsingServiceFactory factory_;
352   TestSafeBrowsingBlockingPageFactory blocking_page_factory_;
353 
354   DISALLOW_COPY_AND_ASSIGN(SafeBrowsingBlockingPageTest);
355 };
356 
MalwareRedirectCancelAndProceed(const std::string open_function)357 void SafeBrowsingBlockingPageTest::MalwareRedirectCancelAndProceed(
358     const std::string open_function) {
359   GURL load_url = test_server()->GetURL(
360       "files/safe_browsing/interstitial_cancel.html");
361   GURL malware_url("http://localhost/files/safe_browsing/malware.html");
362   AddURLResult(malware_url, SafeBrowsingService::URL_MALWARE);
363 
364   // Load the test page.
365   ui_test_utils::NavigateToURL(browser(), load_url);
366   // Trigger the safe browsing interstitial page via a redirect in "openWin()".
367   ui_test_utils::NavigateToURLWithDisposition(
368       browser(),
369       GURL("javascript:" + open_function + "()"),
370       CURRENT_TAB,
371       ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB);
372   WaitForInterstitial();
373   // Cancel the redirect request while interstitial page is open.
374   browser()->ActivateTabAt(0, true);
375   ui_test_utils::NavigateToURLWithDisposition(
376       browser(),
377       GURL("javascript:stopWin()"),
378       CURRENT_TAB,
379       ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
380   browser()->ActivateTabAt(1, true);
381   // Simulate the user clicking "proceed",  there should be no crash.
382   SendCommand("\"proceed\"");
383 }
384 
385 namespace {
386 
387 const char kEmptyPage[] = "files/empty.html";
388 const char kMalwarePage[] = "files/safe_browsing/malware.html";
389 const char kMalwareIframe[] = "files/safe_browsing/malware_iframe.html";
390 
IN_PROC_BROWSER_TEST_F(SafeBrowsingBlockingPageTest,MalwareRedirectInIFrameCanceled)391 IN_PROC_BROWSER_TEST_F(SafeBrowsingBlockingPageTest,
392                        MalwareRedirectInIFrameCanceled) {
393   // 1. Test the case that redirect is a subresource.
394   MalwareRedirectCancelAndProceed("openWinIFrame");
395   // If the redirect was from subresource but canceled, "proceed" will continue
396   // with the rest of resources.
397   AssertNoInterstitial(true);
398 }
399 
IN_PROC_BROWSER_TEST_F(SafeBrowsingBlockingPageTest,MalwareRedirectCanceled)400 IN_PROC_BROWSER_TEST_F(SafeBrowsingBlockingPageTest, MalwareRedirectCanceled) {
401   // 2. Test the case that redirect is the only resource.
402   MalwareRedirectCancelAndProceed("openWin");
403   // Clicking proceed won't do anything if the main request is cancelled
404   // already.  See crbug.com/76460.
405   EXPECT_TRUE(YesInterstitial());
406 }
407 
IN_PROC_BROWSER_TEST_F(SafeBrowsingBlockingPageTest,MalwareDontProceed)408 IN_PROC_BROWSER_TEST_F(SafeBrowsingBlockingPageTest, MalwareDontProceed) {
409   GURL url = test_server()->GetURL(kEmptyPage);
410   AddURLResult(url, SafeBrowsingService::URL_MALWARE);
411 
412   ui_test_utils::NavigateToURL(browser(), url);
413 
414   SendCommand("\"takeMeBack\"");   // Simulate the user clicking "back"
415   AssertNoInterstitial(false);   // Assert the interstitial is gone
416   EXPECT_EQ(GURL(chrome::kAboutBlankURL),   // Back to "about:blank"
417             browser()->GetSelectedTabContents()->GetURL());
418 }
419 
IN_PROC_BROWSER_TEST_F(SafeBrowsingBlockingPageTest,MalwareProceed)420 IN_PROC_BROWSER_TEST_F(SafeBrowsingBlockingPageTest, MalwareProceed) {
421   GURL url = test_server()->GetURL(kEmptyPage);
422   AddURLResult(url, SafeBrowsingService::URL_MALWARE);
423 
424   ui_test_utils::NavigateToURL(browser(), url);
425   SendCommand("\"proceed\"");    // Simulate the user clicking "proceed"
426   WaitForNavigation();    // Wait until we finish the navigation.
427   AssertNoInterstitial(true);    // Assert the interstitial is gone.
428   EXPECT_EQ(url, browser()->GetSelectedTabContents()->GetURL());
429 }
430 
IN_PROC_BROWSER_TEST_F(SafeBrowsingBlockingPageTest,PhishingDontProceed)431 IN_PROC_BROWSER_TEST_F(SafeBrowsingBlockingPageTest, PhishingDontProceed) {
432   GURL url = test_server()->GetURL(kEmptyPage);
433   AddURLResult(url, SafeBrowsingService::URL_PHISHING);
434 
435   ui_test_utils::NavigateToURL(browser(), url);
436 
437   SendCommand("\"takeMeBack\"");   // Simulate the user clicking "proceed"
438   AssertNoInterstitial(false);    // Assert the interstitial is gone
439   EXPECT_EQ(GURL(chrome::kAboutBlankURL),  // We are back to "about:blank".
440             browser()->GetSelectedTabContents()->GetURL());
441 }
442 
IN_PROC_BROWSER_TEST_F(SafeBrowsingBlockingPageTest,PhishingProceed)443 IN_PROC_BROWSER_TEST_F(SafeBrowsingBlockingPageTest, PhishingProceed) {
444   GURL url = test_server()->GetURL(kEmptyPage);
445   AddURLResult(url, SafeBrowsingService::URL_PHISHING);
446 
447   ui_test_utils::NavigateToURL(browser(), url);
448 
449   SendCommand("\"proceed\"");   // Simulate the user clicking "proceed".
450   WaitForNavigation();    // Wait until we finish the navigation.
451   AssertNoInterstitial(true);    // Assert the interstitial is gone
452   EXPECT_EQ(url, browser()->GetSelectedTabContents()->GetURL());
453 }
454 
IN_PROC_BROWSER_TEST_F(SafeBrowsingBlockingPageTest,PhishingReportError)455 IN_PROC_BROWSER_TEST_F(SafeBrowsingBlockingPageTest, PhishingReportError) {
456   GURL url = test_server()->GetURL(kEmptyPage);
457   AddURLResult(url, SafeBrowsingService::URL_PHISHING);
458 
459   ui_test_utils::NavigateToURL(browser(), url);
460 
461   SendCommand("\"reportError\"");   // Simulate the user clicking "report error"
462   WaitForNavigation();    // Wait until we finish the navigation.
463   AssertNoInterstitial(false);    // Assert the interstitial is gone
464 
465   // We are in the error reporting page.
466   EXPECT_EQ("/safebrowsing/report_error/",
467             browser()->GetSelectedTabContents()->GetURL().path());
468 }
469 
IN_PROC_BROWSER_TEST_F(SafeBrowsingBlockingPageTest,PhishingLearnMore)470 IN_PROC_BROWSER_TEST_F(SafeBrowsingBlockingPageTest, PhishingLearnMore) {
471   GURL url = test_server()->GetURL(kEmptyPage);
472   AddURLResult(url, SafeBrowsingService::URL_PHISHING);
473 
474   ui_test_utils::NavigateToURL(browser(), url);
475 
476   SendCommand("\"learnMore\"");   // Simulate the user clicking "learn more"
477   WaitForNavigation();    // Wait until we finish the navigation.
478   AssertNoInterstitial(false);    // Assert the interstitial is gone
479 
480   // We are in the help page.
481   EXPECT_EQ("/support/bin/answer.py",
482             browser()->GetSelectedTabContents()->GetURL().path());
483 }
484 
IN_PROC_BROWSER_TEST_F(SafeBrowsingBlockingPageTest,MalwareIframeDontProceed)485 IN_PROC_BROWSER_TEST_F(SafeBrowsingBlockingPageTest, MalwareIframeDontProceed) {
486   GURL url = test_server()->GetURL(kMalwarePage);
487   GURL iframe_url = test_server()->GetURL(kMalwareIframe);
488   AddURLResult(iframe_url, SafeBrowsingService::URL_MALWARE);
489 
490   ui_test_utils::NavigateToURL(browser(), url);
491 
492   SendCommand("\"takeMeBack\"");    // Simulate the user clicking "back"
493   AssertNoInterstitial(false);  // Assert the interstitial is gone
494 
495   EXPECT_EQ(GURL(chrome::kAboutBlankURL),    // Back to "about:blank"
496             browser()->GetSelectedTabContents()->GetURL());
497 }
498 
499 // Crashy, http://crbug.com/68834.
IN_PROC_BROWSER_TEST_F(SafeBrowsingBlockingPageTest,DISABLED_MalwareIframeProceed)500 IN_PROC_BROWSER_TEST_F(SafeBrowsingBlockingPageTest,
501                        DISABLED_MalwareIframeProceed) {
502   GURL url = test_server()->GetURL(kMalwarePage);
503   GURL iframe_url = test_server()->GetURL(kMalwareIframe);
504   AddURLResult(iframe_url, SafeBrowsingService::URL_MALWARE);
505 
506   ui_test_utils::NavigateToURL(browser(), url);
507 
508   SendCommand("\"proceed\"");   // Simulate the user clicking "proceed"
509   AssertNoInterstitial(true);    // Assert the interstitial is gone
510 
511   EXPECT_EQ(url, browser()->GetSelectedTabContents()->GetURL());
512 }
513 
IN_PROC_BROWSER_TEST_F(SafeBrowsingBlockingPageTest,MalwareIframeReportDetails)514 IN_PROC_BROWSER_TEST_F(SafeBrowsingBlockingPageTest,
515                        MalwareIframeReportDetails) {
516   GURL url = test_server()->GetURL(kMalwarePage);
517   GURL iframe_url = test_server()->GetURL(kMalwareIframe);
518   AddURLResult(iframe_url, SafeBrowsingService::URL_MALWARE);
519 
520   ui_test_utils::NavigateToURL(browser(), url);
521 
522   // If the DOM details from renderer did not already return, wait for them.
523   if (!details_factory_.get_details()->got_dom()) {
524     // This condition might not trigger normally, but if you add a
525     // sleep(1) in malware_dom_details it triggers :).
526     details_factory_.get_details()->set_waiting(true);
527     LOG(INFO) << "Waiting for dom details.";
528     ui_test_utils::RunMessageLoop();
529   } else {
530     LOG(INFO) << "Already got the dom details.";
531   }
532 
533   SendCommand("\"doReport\"");  // Simulate the user checking the checkbox.
534   EXPECT_TRUE(browser()->GetProfile()->GetPrefs()->GetBoolean(
535       prefs::kSafeBrowsingReportingEnabled));
536 
537   SendCommand("\"proceed\"");  // Simulate the user clicking "back"
538   AssertNoInterstitial(true);  // Assert the interstitial is gone
539 
540   EXPECT_EQ(url, browser()->GetSelectedTabContents()->GetURL());
541   AssertReportSent();
542 }
543 
544 }  // namespace
545