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