Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / net / dns_probe_browsertest.cc
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <set>
6
7 #include "base/bind.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/path_service.h"
11 #include "base/prefs/pref_service.h"
12 #include "base/run_loop.h"
13 #include "base/threading/thread_restrictions.h"
14 #include "chrome/browser/browser_process.h"
15 #include "chrome/browser/io_thread.h"
16 #include "chrome/browser/net/dns_probe_test_util.h"
17 #include "chrome/browser/net/net_error_tab_helper.h"
18 #include "chrome/browser/net/url_request_mock_util.h"
19 #include "chrome/browser/profiles/profile.h"
20 #include "chrome/browser/ui/browser.h"
21 #include "chrome/browser/ui/browser_commands.h"
22 #include "chrome/browser/ui/tabs/tab_strip_model.h"
23 #include "chrome/common/chrome_paths.h"
24 #include "chrome/common/pref_names.h"
25 #include "chrome/test/base/in_process_browser_test.h"
26 #include "chrome/test/base/ui_test_utils.h"
27 #include "components/error_page/common/net_error_info.h"
28 #include "components/google/core/browser/google_util.h"
29 #include "content/public/browser/browser_thread.h"
30 #include "content/public/browser/web_contents.h"
31 #include "content/public/test/browser_test_utils.h"
32 #include "content/public/test/test_navigation_observer.h"
33 #include "net/base/net_errors.h"
34 #include "net/dns/dns_test_util.h"
35 #include "net/test/url_request/url_request_failed_job.h"
36 #include "net/test/url_request/url_request_mock_http_job.h"
37 #include "net/url_request/url_request_filter.h"
38 #include "net/url_request/url_request_interceptor.h"
39 #include "net/url_request/url_request_job.h"
40
41 using base::Bind;
42 using base::Callback;
43 using base::Closure;
44 using base::ConstRef;
45 using base::FilePath;
46 using base::MessageLoop;
47 using base::Unretained;
48 using chrome_common_net::DnsProbeStatus;
49 using content::BrowserThread;
50 using net::URLRequestFailedJob;
51 using net::URLRequestMockHTTPJob;
52 using content::WebContents;
53 using google_util::LinkDoctorBaseURL;
54 using net::MockDnsClientRule;
55 using net::NetworkDelegate;
56 using net::URLRequest;
57 using net::URLRequestFilter;
58 using net::URLRequestInterceptor;
59 using net::URLRequestJob;
60 using ui_test_utils::NavigateToURL;
61 using ui_test_utils::NavigateToURLBlockUntilNavigationsComplete;
62
63 namespace chrome_browser_net {
64
65 namespace {
66
67 // Postable function to run a Closure on the UI thread.  Since
68 // BrowserThread::PostTask returns a bool, it can't directly be posted to
69 // another thread.
70 void RunClosureOnUIThread(const base::Closure& closure) {
71   BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, closure);
72 }
73
74 // Wraps DnsProbeService and delays callbacks until someone calls
75 // CallDelayedCallbacks.  This allows the DnsProbeBrowserTest to enforce a
76 // stricter ordering of events.
77 class DelayingDnsProbeService : public DnsProbeService {
78  public:
79   DelayingDnsProbeService() {}
80
81   ~DelayingDnsProbeService() override { EXPECT_TRUE(delayed_probes_.empty()); }
82
83   void ProbeDns(const ProbeCallback& callback) override {
84     delayed_probes_.push_back(callback);
85   }
86
87   void StartDelayedProbes() {
88     CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
89
90     std::vector<ProbeCallback> probes;
91     probes.swap(delayed_probes_);
92
93     for (std::vector<ProbeCallback>::const_iterator i = probes.begin();
94          i != probes.end(); ++i) {
95       DnsProbeService::ProbeDns(*i);
96     }
97   }
98
99   int delayed_probe_count() const {
100     CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
101     return delayed_probes_.size();
102   }
103
104  private:
105   std::vector<ProbeCallback> delayed_probes_;
106 };
107
108 FilePath GetMockLinkDoctorFilePath() {
109   FilePath root_http;
110   PathService::Get(chrome::DIR_TEST_DATA, &root_http);
111   return root_http.AppendASCII("mock-link-doctor.json");
112 }
113
114 // A request that can be delayed until Resume() is called.  Can also run a
115 // callback if destroyed without being resumed.  Resume can be called either
116 // before or after a the request is started.
117 class DelayableRequest {
118  public:
119   // Called by a DelayableRequest if it was set to be delayed, and has been
120   // destroyed without Undelay being called.
121   typedef base::Callback<void(DelayableRequest* request)> DestructionCallback;
122
123   virtual void Resume() = 0;
124
125  protected:
126   virtual ~DelayableRequest() {}
127 };
128
129 class DelayableURLRequestFailedJob : public URLRequestFailedJob,
130                                      public DelayableRequest {
131  public:
132   // |destruction_callback| is only called if a delayed request is destroyed
133   // without being resumed.
134   DelayableURLRequestFailedJob(net::URLRequest* request,
135                                net::NetworkDelegate* network_delegate,
136                                int net_error,
137                                bool should_delay,
138                                const DestructionCallback& destruction_callback)
139       : URLRequestFailedJob(request, network_delegate, net_error),
140         should_delay_(should_delay),
141         start_delayed_(false),
142         destruction_callback_(destruction_callback) {}
143
144   void Start() override {
145     if (should_delay_) {
146       DCHECK(!start_delayed_);
147       start_delayed_ = true;
148       return;
149     }
150     URLRequestFailedJob::Start();
151   }
152
153   void Resume() override {
154     DCHECK(should_delay_);
155     should_delay_ = false;
156     if (start_delayed_) {
157       start_delayed_ = false;
158       Start();
159     }
160   }
161
162  private:
163   ~DelayableURLRequestFailedJob() override {
164     if (should_delay_)
165       destruction_callback_.Run(this);
166   }
167
168   bool should_delay_;
169   bool start_delayed_;
170   const DestructionCallback destruction_callback_;
171 };
172
173 class DelayableURLRequestMockHTTPJob : public URLRequestMockHTTPJob,
174                                        public DelayableRequest {
175  public:
176   DelayableURLRequestMockHTTPJob(
177       net::URLRequest* request,
178       net::NetworkDelegate* network_delegate,
179       const base::FilePath& file_path,
180       bool should_delay,
181       const DestructionCallback& destruction_callback)
182       : URLRequestMockHTTPJob(
183             request,
184             network_delegate,
185             file_path,
186             BrowserThread::GetBlockingPool()->GetTaskRunnerWithShutdownBehavior(
187                 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN)),
188         should_delay_(should_delay),
189         start_delayed_(false),
190         destruction_callback_(destruction_callback) {}
191
192   void Start() override {
193     if (should_delay_) {
194       DCHECK(!start_delayed_);
195       start_delayed_ = true;
196       return;
197     }
198     URLRequestMockHTTPJob::Start();
199   }
200
201   void Resume() override {
202     DCHECK(should_delay_);
203     should_delay_ = false;
204     if (start_delayed_) {
205       start_delayed_ = false;
206       Start();
207     }
208   }
209
210  private:
211   ~DelayableURLRequestMockHTTPJob() override {
212     if (should_delay_)
213       destruction_callback_.Run(this);
214   }
215
216   bool should_delay_;
217   bool start_delayed_;
218   const DestructionCallback destruction_callback_;
219 };
220
221 // Interceptor for navigation correction requests.  Can cause requests to
222 // fail with an error, and/or delay a request until a test allows to continue.
223 // Also can run a callback when a delayed request is cancelled.
224 class BreakableCorrectionInterceptor : public URLRequestInterceptor {
225  public:
226   explicit BreakableCorrectionInterceptor(
227       const FilePath& mock_corrections_file_path)
228       : mock_corrections_file_path_(mock_corrections_file_path),
229         net_error_(net::OK),
230         delay_requests_(false),
231         on_request_destroyed_callback_(
232             base::Bind(&BreakableCorrectionInterceptor::OnRequestDestroyed,
233                        base::Unretained(this))) {
234   }
235
236   ~BreakableCorrectionInterceptor() override {
237     // All delayed requests should have been resumed or cancelled by this point.
238     EXPECT_TRUE(delayed_requests_.empty());
239   }
240
241   URLRequestJob* MaybeInterceptRequest(
242       URLRequest* request,
243       NetworkDelegate* network_delegate) const override {
244     if (net_error_ != net::OK) {
245       DelayableURLRequestFailedJob* job =
246           new DelayableURLRequestFailedJob(
247               request, network_delegate, net_error_, delay_requests_,
248               on_request_destroyed_callback_);
249       if (delay_requests_)
250         delayed_requests_.insert(job);
251       return job;
252     } else {
253       DelayableURLRequestMockHTTPJob* job =
254           new DelayableURLRequestMockHTTPJob(
255               request, network_delegate, mock_corrections_file_path_,
256               delay_requests_, on_request_destroyed_callback_);
257       if (delay_requests_)
258         delayed_requests_.insert(job);
259       return job;
260     }
261   }
262
263   void set_net_error(int net_error) { net_error_ = net_error; }
264
265   void SetDelayRequests(bool delay_requests) {
266     delay_requests_ = delay_requests;
267
268     // Resume all delayed requests if no longer delaying requests.
269     if (!delay_requests) {
270       while (!delayed_requests_.empty()) {
271         DelayableRequest* request = *delayed_requests_.begin();
272         delayed_requests_.erase(request);
273         request->Resume();
274       }
275     }
276   }
277
278   // Runs |callback| once all delayed requests have been destroyed.  Does not
279   // wait for delayed requests that have been resumed.
280   void SetRequestDestructionCallback(const base::Closure& callback) {
281     ASSERT_TRUE(delayed_request_destruction_callback_.is_null());
282     if (delayed_requests_.empty()) {
283       callback.Run();
284       return;
285     }
286     delayed_request_destruction_callback_ = callback;
287   }
288
289   void OnRequestDestroyed(DelayableRequest* request) {
290     ASSERT_EQ(1u, delayed_requests_.count(request));
291     delayed_requests_.erase(request);
292     if (delayed_requests_.empty() &&
293         !delayed_request_destruction_callback_.is_null()) {
294       delayed_request_destruction_callback_.Run();
295       delayed_request_destruction_callback_.Reset();
296     }
297   }
298
299  private:
300   const FilePath mock_corrections_file_path_;
301   int net_error_;
302   bool delay_requests_;
303
304   // Called when a request is destroyed.  Memeber variable because
305   // MaybeCreateJob is "const", so calling base::Bind in that function does
306   // not work well.
307   const DelayableRequest::DestructionCallback on_request_destroyed_callback_;
308
309   // Mutable is needed because MaybeCreateJob is const.
310   mutable std::set<DelayableRequest*> delayed_requests_;
311
312   base::Closure delayed_request_destruction_callback_;
313 };
314
315 class DnsProbeBrowserTestIOThreadHelper {
316  public:
317   DnsProbeBrowserTestIOThreadHelper();
318
319   void SetUpOnIOThread(IOThread* io_thread);
320   void CleanUpOnIOThreadAndDeleteHelper();
321
322   void SetMockDnsClientRules(MockDnsClientRule::Result system_good_result,
323                              MockDnsClientRule::Result public_good_result);
324   void SetCorrectionServiceNetError(int net_error);
325   void SetCorrectionServiceDelayRequests(bool delay_requests);
326   void SetRequestDestructionCallback(const base::Closure& callback);
327   void StartDelayedProbes(int expected_delayed_probe_count);
328
329  private:
330   IOThread* io_thread_;
331   DnsProbeService* original_dns_probe_service_;
332   DelayingDnsProbeService* delaying_dns_probe_service_;
333   BreakableCorrectionInterceptor* interceptor_;
334   FilePath mock_corrections_file_path_;
335 };
336
337 DnsProbeBrowserTestIOThreadHelper::DnsProbeBrowserTestIOThreadHelper()
338     : io_thread_(NULL),
339       original_dns_probe_service_(NULL),
340       delaying_dns_probe_service_(NULL),
341       interceptor_(NULL),
342       mock_corrections_file_path_(GetMockLinkDoctorFilePath()) {}
343
344 void DnsProbeBrowserTestIOThreadHelper::SetUpOnIOThread(IOThread* io_thread) {
345   CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
346   CHECK(io_thread);
347   CHECK(!io_thread_);
348   CHECK(!original_dns_probe_service_);
349   CHECK(!delaying_dns_probe_service_);
350   CHECK(!interceptor_);
351
352   io_thread_ = io_thread;
353
354   delaying_dns_probe_service_ = new DelayingDnsProbeService();
355
356   IOThread::Globals* globals = io_thread_->globals();
357   original_dns_probe_service_ = globals->dns_probe_service.release();
358   globals->dns_probe_service.reset(delaying_dns_probe_service_);
359
360   URLRequestFailedJob::AddUrlHandler();
361
362   interceptor_ =
363       new BreakableCorrectionInterceptor(mock_corrections_file_path_);
364   URLRequestFilter::GetInstance()->AddUrlInterceptor(
365       LinkDoctorBaseURL(), scoped_ptr<URLRequestInterceptor>(interceptor_));
366 }
367
368 void DnsProbeBrowserTestIOThreadHelper::CleanUpOnIOThreadAndDeleteHelper() {
369   CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
370
371   URLRequestFilter::GetInstance()->ClearHandlers();
372
373   IOThread::Globals* globals = io_thread_->globals();
374   scoped_ptr<DnsProbeService> delaying_dns_probe_service(
375       globals->dns_probe_service.release());
376   globals->dns_probe_service.reset(original_dns_probe_service_);
377
378   CHECK_EQ(delaying_dns_probe_service_, delaying_dns_probe_service.get());
379
380   delete this;
381 }
382
383 void DnsProbeBrowserTestIOThreadHelper::SetMockDnsClientRules(
384     MockDnsClientRule::Result system_result,
385     MockDnsClientRule::Result public_result) {
386   CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
387
388   DnsProbeService* service = io_thread_->globals()->dns_probe_service.get();
389   service->SetSystemClientForTesting(
390       CreateMockDnsClientForProbes(system_result));
391   service->SetPublicClientForTesting(
392       CreateMockDnsClientForProbes(public_result));
393 }
394
395 void DnsProbeBrowserTestIOThreadHelper::SetCorrectionServiceNetError(
396     int net_error) {
397   CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
398
399   interceptor_->set_net_error(net_error);
400 }
401
402 void DnsProbeBrowserTestIOThreadHelper::SetCorrectionServiceDelayRequests(
403     bool delay_requests) {
404   CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
405
406   interceptor_->SetDelayRequests(delay_requests);
407 }
408
409 void DnsProbeBrowserTestIOThreadHelper::SetRequestDestructionCallback(
410     const base::Closure& callback) {
411   CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
412
413   interceptor_->SetRequestDestructionCallback(callback);
414 }
415
416 void DnsProbeBrowserTestIOThreadHelper::StartDelayedProbes(
417     int expected_delayed_probe_count) {
418   CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
419
420   CHECK(delaying_dns_probe_service_);
421
422   int actual_delayed_probe_count =
423       delaying_dns_probe_service_->delayed_probe_count();
424   EXPECT_EQ(expected_delayed_probe_count, actual_delayed_probe_count);
425
426   delaying_dns_probe_service_->StartDelayedProbes();
427 }
428
429 class DnsProbeBrowserTest : public InProcessBrowserTest {
430  public:
431   DnsProbeBrowserTest();
432   ~DnsProbeBrowserTest() override;
433
434   void SetUpOnMainThread() override;
435   void TearDownOnMainThread() override;
436
437  protected:
438   // Sets the browser object that other methods apply to, and that has the
439   // DnsProbeStatus messages of its currently active tab monitored.
440   void SetActiveBrowser(Browser* browser);
441
442   void SetCorrectionServiceBroken(bool broken);
443   void SetCorrectionServiceDelayRequests(bool delay_requests);
444   void WaitForDelayedRequestDestruction();
445   void SetMockDnsClientRules(MockDnsClientRule::Result system_result,
446                              MockDnsClientRule::Result public_result);
447
448   // These functions are often used to wait for two navigations because two
449   // pages are loaded when navigation corrections are enabled: a blank page, so
450   // the user stops seeing the previous page, and then the error page, either
451   // with navigation corrections or without them (If the request failed).
452   void NavigateToDnsError(int num_navigations);
453   void NavigateToOtherError(int num_navigations);
454
455   void StartDelayedProbes(int expected_delayed_probe_count);
456   DnsProbeStatus WaitForSentStatus();
457   int pending_status_count() const { return dns_probe_status_queue_.size(); }
458
459   std::string Title();
460   bool PageContains(const std::string& expected);
461
462   // Checks that the local error page is being displayed, without navigation
463   // corrections, and with the specified status text.  The status text should be
464   // either a network error or DNS probe status.
465   void ExpectDisplayingLocalErrorPage(const std::string& status_text);
466
467   // Checks that an error page with mock navigation corrections is being
468   // displayed, with the specified status text. The status text should be either
469   // a network error or DNS probe status.
470   void ExpectDisplayingCorrections(const std::string& status_text);
471
472  private:
473   void OnDnsProbeStatusSent(DnsProbeStatus dns_probe_status);
474
475   DnsProbeBrowserTestIOThreadHelper* helper_;
476
477   // Browser that methods apply to.
478   Browser* active_browser_;
479   // Helper that current has its DnsProbeStatus messages monitored.
480   NetErrorTabHelper* monitored_tab_helper_;
481
482   bool awaiting_dns_probe_status_;
483   // Queue of statuses received but not yet consumed by WaitForSentStatus().
484   std::list<DnsProbeStatus> dns_probe_status_queue_;
485 };
486
487 DnsProbeBrowserTest::DnsProbeBrowserTest()
488     : helper_(new DnsProbeBrowserTestIOThreadHelper()),
489       active_browser_(NULL),
490       monitored_tab_helper_(NULL),
491       awaiting_dns_probe_status_(false) {
492 }
493
494 DnsProbeBrowserTest::~DnsProbeBrowserTest() {
495   // No tests should have any unconsumed probe statuses.
496   EXPECT_EQ(0, pending_status_count());
497 }
498
499 void DnsProbeBrowserTest::SetUpOnMainThread() {
500   NetErrorTabHelper::set_state_for_testing(
501       NetErrorTabHelper::TESTING_DEFAULT);
502
503   browser()->profile()->GetPrefs()->SetBoolean(
504       prefs::kAlternateErrorPagesEnabled, true);
505
506   BrowserThread::PostTask(
507       BrowserThread::IO, FROM_HERE,
508       Bind(&DnsProbeBrowserTestIOThreadHelper::SetUpOnIOThread,
509            Unretained(helper_),
510            g_browser_process->io_thread()));
511
512   SetActiveBrowser(browser());
513 }
514
515 void DnsProbeBrowserTest::TearDownOnMainThread() {
516   BrowserThread::PostTask(
517       BrowserThread::IO, FROM_HERE,
518       Bind(&DnsProbeBrowserTestIOThreadHelper::CleanUpOnIOThreadAndDeleteHelper,
519            Unretained(helper_)));
520
521   NetErrorTabHelper::set_state_for_testing(
522       NetErrorTabHelper::TESTING_DEFAULT);
523 }
524
525 void DnsProbeBrowserTest::SetActiveBrowser(Browser* browser) {
526   // If currently watching a NetErrorTabHelper, stop doing so before start
527   // watching another.
528   if (monitored_tab_helper_) {
529     monitored_tab_helper_->set_dns_probe_status_snoop_callback_for_testing(
530         NetErrorTabHelper::DnsProbeStatusSnoopCallback());
531   }
532   active_browser_ = browser;
533   monitored_tab_helper_ = NetErrorTabHelper::FromWebContents(
534       active_browser_->tab_strip_model()->GetActiveWebContents());
535   monitored_tab_helper_->set_dns_probe_status_snoop_callback_for_testing(
536       Bind(&DnsProbeBrowserTest::OnDnsProbeStatusSent, Unretained(this)));
537 }
538
539 void DnsProbeBrowserTest::SetCorrectionServiceBroken(bool broken) {
540   int net_error = broken ? net::ERR_NAME_NOT_RESOLVED : net::OK;
541
542   BrowserThread::PostTask(
543       BrowserThread::IO, FROM_HERE,
544       Bind(&DnsProbeBrowserTestIOThreadHelper::SetCorrectionServiceNetError,
545            Unretained(helper_),
546            net_error));
547 }
548
549 void DnsProbeBrowserTest::SetCorrectionServiceDelayRequests(
550     bool delay_requests) {
551   BrowserThread::PostTask(
552       BrowserThread::IO, FROM_HERE,
553       Bind(&DnsProbeBrowserTestIOThreadHelper::
554                SetCorrectionServiceDelayRequests,
555            Unretained(helper_),
556            delay_requests));
557 }
558
559 void DnsProbeBrowserTest::WaitForDelayedRequestDestruction() {
560   base::RunLoop run_loop;
561   BrowserThread::PostTask(
562       BrowserThread::IO, FROM_HERE,
563       Bind(&DnsProbeBrowserTestIOThreadHelper::SetRequestDestructionCallback,
564            Unretained(helper_),
565            base::Bind(&RunClosureOnUIThread,
566                       run_loop.QuitClosure())));
567   run_loop.Run();
568 }
569
570 void DnsProbeBrowserTest::NavigateToDnsError(int num_navigations) {
571   NavigateToURLBlockUntilNavigationsComplete(
572       active_browser_,
573       URLRequestFailedJob::GetMockHttpUrl(net::ERR_NAME_NOT_RESOLVED),
574       num_navigations);
575 }
576
577 void DnsProbeBrowserTest::NavigateToOtherError(int num_navigations) {
578   NavigateToURLBlockUntilNavigationsComplete(
579       active_browser_,
580       URLRequestFailedJob::GetMockHttpUrl(net::ERR_CONNECTION_REFUSED),
581       num_navigations);
582 }
583
584 void DnsProbeBrowserTest::SetMockDnsClientRules(
585     MockDnsClientRule::Result system_result,
586     MockDnsClientRule::Result public_result) {
587   BrowserThread::PostTask(
588       BrowserThread::IO, FROM_HERE,
589       Bind(&DnsProbeBrowserTestIOThreadHelper::SetMockDnsClientRules,
590            Unretained(helper_),
591            system_result,
592            public_result));
593 }
594
595 void DnsProbeBrowserTest::StartDelayedProbes(
596     int expected_delayed_probe_count) {
597   BrowserThread::PostTask(
598       BrowserThread::IO, FROM_HERE,
599       Bind(&DnsProbeBrowserTestIOThreadHelper::StartDelayedProbes,
600            Unretained(helper_),
601            expected_delayed_probe_count));
602 }
603
604 DnsProbeStatus DnsProbeBrowserTest::WaitForSentStatus() {
605   CHECK(!awaiting_dns_probe_status_);
606   while (dns_probe_status_queue_.empty()) {
607     awaiting_dns_probe_status_ = true;
608     MessageLoop::current()->Run();
609     awaiting_dns_probe_status_ = false;
610   }
611
612   CHECK(!dns_probe_status_queue_.empty());
613   DnsProbeStatus status = dns_probe_status_queue_.front();
614   dns_probe_status_queue_.pop_front();
615   return status;
616 }
617
618 // Check title by roundtripping to renderer, to make sure any probe results
619 // sent before this have been applied.
620 std::string DnsProbeBrowserTest::Title() {
621   std::string title;
622
623   WebContents* contents =
624       active_browser_->tab_strip_model()->GetActiveWebContents();
625
626   bool rv = content::ExecuteScriptAndExtractString(
627       contents,
628       "domAutomationController.send(document.title);",
629       &title);
630   if (!rv)
631     return "";
632
633   return title;
634 }
635
636 // Check text by roundtripping to renderer, to make sure any probe results
637 // sent before this have been applied.
638 bool DnsProbeBrowserTest::PageContains(const std::string& expected) {
639   std::string text_content;
640
641   bool rv = content::ExecuteScriptAndExtractString(
642       active_browser_->tab_strip_model()->GetActiveWebContents(),
643       "domAutomationController.send(document.body.textContent);",
644       &text_content);
645   if (!rv)
646     return false;
647
648   return text_content.find(expected) != std::string::npos;
649 }
650
651 void DnsProbeBrowserTest::ExpectDisplayingLocalErrorPage(
652     const std::string& status_text) {
653   EXPECT_FALSE(PageContains("http://correction1/"));
654   EXPECT_FALSE(PageContains("http://correction2/"));
655   EXPECT_TRUE(PageContains(status_text));
656 }
657
658 void DnsProbeBrowserTest::ExpectDisplayingCorrections(
659     const std::string& status_text) {
660   EXPECT_TRUE(PageContains("http://correction1/"));
661   EXPECT_TRUE(PageContains("http://correction2/"));
662   EXPECT_TRUE(PageContains(status_text));
663 }
664
665 void DnsProbeBrowserTest::OnDnsProbeStatusSent(
666     DnsProbeStatus dns_probe_status) {
667   dns_probe_status_queue_.push_back(dns_probe_status);
668   if (awaiting_dns_probe_status_)
669     MessageLoop::current()->Quit();
670 }
671
672 // Make sure probes don't break non-DNS error pages when corrections load.
673 IN_PROC_BROWSER_TEST_F(DnsProbeBrowserTest, OtherErrorWithCorrectionsSuccess) {
674   SetCorrectionServiceBroken(false);
675
676   NavigateToOtherError(2);
677   ExpectDisplayingCorrections("ERR_CONNECTION_REFUSED");
678 }
679
680 // Make sure probes don't break non-DNS error pages when corrections failed to
681 // load.
682 IN_PROC_BROWSER_TEST_F(DnsProbeBrowserTest, OtherErrorWithCorrectionsFailure) {
683   SetCorrectionServiceBroken(true);
684
685   NavigateToOtherError(2);
686   ExpectDisplayingLocalErrorPage("ERR_CONNECTION_REFUSED");
687 }
688
689 // Make sure probes don't break DNS error pages when corrections load.
690 IN_PROC_BROWSER_TEST_F(DnsProbeBrowserTest,
691                        NxdomainProbeResultWithWorkingCorrections) {
692   SetCorrectionServiceBroken(false);
693   SetMockDnsClientRules(MockDnsClientRule::OK, MockDnsClientRule::OK);
694
695   NavigateToDnsError(2);
696   ExpectDisplayingCorrections("ERR_NAME_NOT_RESOLVED");
697
698   // One status for committing a blank page before the corrections, and one for
699   // when the error page with corrections is committed.
700   EXPECT_EQ(chrome_common_net::DNS_PROBE_STARTED, WaitForSentStatus());
701   EXPECT_EQ(chrome_common_net::DNS_PROBE_STARTED, WaitForSentStatus());
702   EXPECT_EQ(0, pending_status_count());
703   ExpectDisplayingCorrections("ERR_NAME_NOT_RESOLVED");
704
705   StartDelayedProbes(1);
706
707   EXPECT_EQ(chrome_common_net::DNS_PROBE_FINISHED_NXDOMAIN,
708             WaitForSentStatus());
709   EXPECT_EQ(0, pending_status_count());
710   ExpectDisplayingCorrections("ERR_NAME_NOT_RESOLVED");
711 }
712
713 // Make sure probes don't break corrections when probes complete before the
714 // corrections load.
715 IN_PROC_BROWSER_TEST_F(DnsProbeBrowserTest,
716                        NxdomainProbeResultWithWorkingSlowCorrections) {
717   SetCorrectionServiceBroken(false);
718   SetCorrectionServiceDelayRequests(true);
719   SetMockDnsClientRules(MockDnsClientRule::OK, MockDnsClientRule::OK);
720
721   NavigateToDnsError(1);
722   // A blank page should be displayed while the corrections are loaded.
723   EXPECT_EQ("", Title());
724
725   // A single probe should be triggered by the error page load, and it should
726   // be ignored.
727   EXPECT_EQ(chrome_common_net::DNS_PROBE_STARTED, WaitForSentStatus());
728   EXPECT_EQ(0, pending_status_count());
729   EXPECT_EQ("", Title());
730
731   StartDelayedProbes(1);
732   EXPECT_EQ(chrome_common_net::DNS_PROBE_FINISHED_NXDOMAIN,
733             WaitForSentStatus());
734   EXPECT_EQ(0, pending_status_count());
735   EXPECT_EQ("", Title());
736
737   content::TestNavigationObserver observer(
738       browser()->tab_strip_model()->GetActiveWebContents(), 1);
739   // The corrections finish loading.
740   SetCorrectionServiceDelayRequests(false);
741   // Wait for it to commit.
742   observer.Wait();
743   ExpectDisplayingCorrections("ERR_NAME_NOT_RESOLVED");
744
745   // Committing the corections page should trigger sending the probe result
746   // again.
747   EXPECT_EQ(chrome_common_net::DNS_PROBE_FINISHED_NXDOMAIN,
748             WaitForSentStatus());
749   ExpectDisplayingCorrections("ERR_NAME_NOT_RESOLVED");
750 }
751
752 // Make sure probes update DNS error page properly when they're supposed to.
753 IN_PROC_BROWSER_TEST_F(DnsProbeBrowserTest,
754                        NoInternetProbeResultWithBrokenCorrections) {
755   SetCorrectionServiceBroken(true);
756   SetMockDnsClientRules(MockDnsClientRule::TIMEOUT,
757                         MockDnsClientRule::TIMEOUT);
758
759   NavigateToDnsError(2);
760
761   EXPECT_EQ(chrome_common_net::DNS_PROBE_STARTED, WaitForSentStatus());
762   EXPECT_EQ(chrome_common_net::DNS_PROBE_STARTED, WaitForSentStatus());
763
764   // Checking the page runs the RunLoop, so make sure nothing hairy happens.
765   EXPECT_EQ(0, pending_status_count());
766   ExpectDisplayingLocalErrorPage("DNS_PROBE_STARTED");
767   EXPECT_EQ(0, pending_status_count());
768
769   StartDelayedProbes(1);
770
771   EXPECT_EQ(chrome_common_net::DNS_PROBE_FINISHED_NO_INTERNET,
772             WaitForSentStatus());
773
774   // Checking the page runs the RunLoop, so make sure nothing hairy happens.
775   EXPECT_EQ(0, pending_status_count());
776   ExpectDisplayingLocalErrorPage("DNS_PROBE_FINISHED_NO_INTERNET");
777 }
778
779 // Make sure probes don't break corrections when probes complete before the
780 // corrections request returns an error.
781 IN_PROC_BROWSER_TEST_F(DnsProbeBrowserTest,
782                        NoInternetProbeResultWithSlowBrokenCorrections) {
783   SetCorrectionServiceBroken(true);
784   SetCorrectionServiceDelayRequests(true);
785   SetMockDnsClientRules(MockDnsClientRule::TIMEOUT,
786                         MockDnsClientRule::TIMEOUT);
787
788   NavigateToDnsError(1);
789   // A blank page should be displayed while the corrections load.
790   EXPECT_EQ("", Title());
791
792   // A single probe should be triggered by the error page load, and it should
793   // be ignored.
794   EXPECT_EQ(chrome_common_net::DNS_PROBE_STARTED, WaitForSentStatus());
795   EXPECT_EQ(0, pending_status_count());
796   EXPECT_EQ("", Title());
797
798   StartDelayedProbes(1);
799   EXPECT_EQ(chrome_common_net::DNS_PROBE_FINISHED_NO_INTERNET,
800             WaitForSentStatus());
801   EXPECT_EQ("", Title());
802   EXPECT_EQ(0, pending_status_count());
803
804   content::TestNavigationObserver observer(
805       browser()->tab_strip_model()->GetActiveWebContents(), 1);
806   // The corrections request fails.
807   SetCorrectionServiceDelayRequests(false);
808   // Wait for the DNS error page to load instead.
809   observer.Wait();
810   // The page committing should result in sending the probe results again.
811   EXPECT_EQ(chrome_common_net::DNS_PROBE_FINISHED_NO_INTERNET,
812             WaitForSentStatus());
813
814   EXPECT_EQ(0, pending_status_count());
815   ExpectDisplayingLocalErrorPage("DNS_PROBE_FINISHED_NO_INTERNET");
816 }
817
818 // Double-check to make sure sync failures don't explode.
819 IN_PROC_BROWSER_TEST_F(DnsProbeBrowserTest, SyncFailureWithBrokenCorrections) {
820   SetCorrectionServiceBroken(true);
821   SetMockDnsClientRules(MockDnsClientRule::FAIL, MockDnsClientRule::FAIL);
822
823   NavigateToDnsError(2);
824
825   EXPECT_EQ(chrome_common_net::DNS_PROBE_STARTED, WaitForSentStatus());
826   EXPECT_EQ(chrome_common_net::DNS_PROBE_STARTED, WaitForSentStatus());
827
828   // Checking the page runs the RunLoop, so make sure nothing hairy happens.
829   EXPECT_EQ(0, pending_status_count());
830   ExpectDisplayingLocalErrorPage("DNS_PROBE_STARTED");
831   EXPECT_EQ(0, pending_status_count());
832
833   StartDelayedProbes(1);
834
835   EXPECT_EQ(chrome_common_net::DNS_PROBE_FINISHED_INCONCLUSIVE,
836             WaitForSentStatus());
837
838   // Checking the page runs the RunLoop, so make sure nothing hairy happens.
839   EXPECT_EQ(0, pending_status_count());
840   ExpectDisplayingLocalErrorPage("ERR_NAME_NOT_RESOLVED");
841   EXPECT_EQ(0, pending_status_count());
842 }
843
844 // Test that pressing the stop button cancels loading corrections.
845 // TODO(mmenke):  Add a test for the cross process navigation case.
846 // TODO(mmenke):  This test could flakily pass due to the timeout on downloading
847 //                the corrections.  Disable that timeout for browser tests.
848 IN_PROC_BROWSER_TEST_F(DnsProbeBrowserTest, CorrectionsLoadStopped) {
849   SetCorrectionServiceDelayRequests(true);
850   SetCorrectionServiceBroken(true);
851   SetMockDnsClientRules(MockDnsClientRule::TIMEOUT, MockDnsClientRule::TIMEOUT);
852
853   NavigateToDnsError(1);
854
855   EXPECT_EQ(chrome_common_net::DNS_PROBE_STARTED, WaitForSentStatus());
856   StartDelayedProbes(1);
857   EXPECT_EQ(chrome_common_net::DNS_PROBE_FINISHED_NO_INTERNET,
858             WaitForSentStatus());
859
860   EXPECT_EQ("", Title());
861   EXPECT_EQ(0, pending_status_count());
862
863   chrome::Stop(browser());
864   WaitForDelayedRequestDestruction();
865
866   // End up displaying a blank page.
867   EXPECT_EQ("", Title());
868 }
869
870 // Test that pressing the stop button cancels the load of corrections, and
871 // receiving a probe result afterwards does not swap in a DNS error page.
872 IN_PROC_BROWSER_TEST_F(DnsProbeBrowserTest, CorrectionsLoadStoppedSlowProbe) {
873   SetCorrectionServiceDelayRequests(true);
874   SetCorrectionServiceBroken(true);
875   SetMockDnsClientRules(MockDnsClientRule::TIMEOUT, MockDnsClientRule::TIMEOUT);
876
877   NavigateToDnsError(1);
878
879   EXPECT_EQ(chrome_common_net::DNS_PROBE_STARTED, WaitForSentStatus());
880
881   EXPECT_EQ("", Title());
882   EXPECT_EQ(0, pending_status_count());
883
884   chrome::Stop(browser());
885   WaitForDelayedRequestDestruction();
886
887   EXPECT_EQ("", Title());
888   EXPECT_EQ(0, pending_status_count());
889
890   StartDelayedProbes(1);
891   EXPECT_EQ(chrome_common_net::DNS_PROBE_FINISHED_NO_INTERNET,
892             WaitForSentStatus());
893
894   EXPECT_EQ("", Title());
895 }
896
897 // Make sure probes don't run for subframe DNS errors.
898 IN_PROC_BROWSER_TEST_F(DnsProbeBrowserTest, NoProbeInSubframe) {
899   SetCorrectionServiceBroken(false);
900
901   const FilePath::CharType kIframeDnsErrorHtmlName[] =
902       FILE_PATH_LITERAL("iframe_dns_error.html");
903
904   NavigateToURL(
905       browser(),
906       URLRequestMockHTTPJob::GetMockUrl(FilePath(kIframeDnsErrorHtmlName)));
907
908   // By the time NavigateToURL returns, the browser will have seen the failed
909   // provisional load.  If a probe was started (or considered but not run),
910   // then the NetErrorTabHelper would have sent a NetErrorInfo message.  Thus,
911   // if one hasn't been sent by now, the NetErrorTabHelper has not (and won't)
912   // start a probe for this DNS error.
913   EXPECT_EQ(0, pending_status_count());
914 }
915
916 // Make sure browser sends NOT_RUN properly when probes are disabled.
917 IN_PROC_BROWSER_TEST_F(DnsProbeBrowserTest, ProbesDisabled) {
918   // Disable probes (And corrections).
919   browser()->profile()->GetPrefs()->SetBoolean(
920       prefs::kAlternateErrorPagesEnabled, false);
921
922   SetCorrectionServiceBroken(true);
923   SetMockDnsClientRules(MockDnsClientRule::TIMEOUT, MockDnsClientRule::TIMEOUT);
924
925   NavigateToDnsError(1);
926
927   EXPECT_EQ(chrome_common_net::DNS_PROBE_NOT_RUN, WaitForSentStatus());
928
929   // Checking the page runs the RunLoop, so make sure nothing hairy happens.
930   EXPECT_EQ(0, pending_status_count());
931   ExpectDisplayingLocalErrorPage("ERR_NAME_NOT_RESOLVED");
932 }
933
934 // Test the case that corrections are disabled, but DNS probes are enabled.
935 // This is the case with Chromium builds.
936 IN_PROC_BROWSER_TEST_F(DnsProbeBrowserTest, CorrectionsDisabled) {
937   // Disable corrections.
938   browser()->profile()->GetPrefs()->SetBoolean(
939       prefs::kAlternateErrorPagesEnabled, false);
940   // Requests to the correction service should work if any are made, so the test
941   // fails if that happens unexpectedly.
942   SetCorrectionServiceBroken(false);
943   // Normally disabling corrections disables DNS probes, so force DNS probes
944   // to be enabled.
945   NetErrorTabHelper::set_state_for_testing(
946       NetErrorTabHelper::TESTING_FORCE_ENABLED);
947
948   SetMockDnsClientRules(MockDnsClientRule::FAIL, MockDnsClientRule::FAIL);
949
950   // Just one commit and one sent status, since corrections are disabled.
951   NavigateToDnsError(1);
952   EXPECT_EQ(chrome_common_net::DNS_PROBE_STARTED, WaitForSentStatus());
953
954   // Checking the page runs the RunLoop, so make sure nothing hairy happens.
955   EXPECT_EQ(0, pending_status_count());
956   ExpectDisplayingLocalErrorPage("DNS_PROBE_STARTED");
957   EXPECT_EQ(0, pending_status_count());
958
959   StartDelayedProbes(1);
960
961   EXPECT_EQ(chrome_common_net::DNS_PROBE_FINISHED_INCONCLUSIVE,
962             WaitForSentStatus());
963   EXPECT_EQ(0, pending_status_count());
964   ExpectDisplayingLocalErrorPage("ERR_NAME_NOT_RESOLVED");
965 }
966
967 // Test incognito mode.  Corrections should be disabled, but DNS probes are
968 // still enabled.
969 IN_PROC_BROWSER_TEST_F(DnsProbeBrowserTest, Incognito) {
970   // Requests to the correction service should work if any are made, so the test
971   // will fail if one is requested unexpectedly.
972   SetCorrectionServiceBroken(false);
973
974   Browser* incognito = CreateIncognitoBrowser();
975   SetActiveBrowser(incognito);
976
977   SetMockDnsClientRules(MockDnsClientRule::FAIL, MockDnsClientRule::FAIL);
978
979   // Just one commit and one sent status, since the corrections are disabled.
980   NavigateToDnsError(1);
981   EXPECT_EQ(chrome_common_net::DNS_PROBE_STARTED, WaitForSentStatus());
982
983   // Checking the page runs the RunLoop, so make sure nothing hairy happens.
984   EXPECT_EQ(0, pending_status_count());
985   ExpectDisplayingLocalErrorPage("DNS_PROBE_STARTED");
986   EXPECT_EQ(0, pending_status_count());
987
988   StartDelayedProbes(1);
989
990   EXPECT_EQ(chrome_common_net::DNS_PROBE_FINISHED_INCONCLUSIVE,
991             WaitForSentStatus());
992   EXPECT_EQ(0, pending_status_count());
993   ExpectDisplayingLocalErrorPage("ERR_NAME_NOT_RESOLVED");
994 }
995
996 }  // namespace
997
998 }  // namespace chrome_browser_net