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