Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / captive_portal / captive_portal_browsertest.cc
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <map>
6 #include <set>
7
8 #include "base/basictypes.h"
9 #include "base/bind.h"
10 #include "base/command_line.h"
11 #include "base/compiler_specific.h"
12 #include "base/files/file_path.h"
13 #include "base/message_loop/message_loop.h"
14 #include "base/path_service.h"
15 #include "base/prefs/pref_service.h"
16 #include "base/strings/utf_string_conversions.h"
17 #include "chrome/browser/captive_portal/captive_portal_service.h"
18 #include "chrome/browser/captive_portal/captive_portal_service_factory.h"
19 #include "chrome/browser/captive_portal/captive_portal_tab_helper.h"
20 #include "chrome/browser/captive_portal/captive_portal_tab_reloader.h"
21 #include "chrome/browser/chrome_notification_types.h"
22 #include "chrome/browser/net/url_request_mock_util.h"
23 #include "chrome/browser/profiles/profile.h"
24 #include "chrome/browser/ui/browser.h"
25 #include "chrome/browser/ui/browser_commands.h"
26 #include "chrome/browser/ui/browser_finder.h"
27 #include "chrome/browser/ui/browser_navigator.h"
28 #include "chrome/browser/ui/tab_contents/tab_contents_iterator.h"
29 #include "chrome/browser/ui/tabs/tab_strip_model.h"
30 #include "chrome/common/chrome_paths.h"
31 #include "chrome/common/chrome_switches.h"
32 #include "chrome/common/pref_names.h"
33 #include "chrome/test/base/in_process_browser_test.h"
34 #include "chrome/test/base/ui_test_utils.h"
35 #include "content/public/browser/browser_thread.h"
36 #include "content/public/browser/navigation_controller.h"
37 #include "content/public/browser/notification_observer.h"
38 #include "content/public/browser/notification_registrar.h"
39 #include "content/public/browser/notification_service.h"
40 #include "content/public/browser/notification_types.h"
41 #include "content/public/browser/render_frame_host.h"
42 #include "content/public/browser/web_contents.h"
43 #include "content/public/common/url_constants.h"
44 #include "net/base/net_errors.h"
45 #include "net/http/transport_security_state.h"
46 #include "net/test/url_request/url_request_failed_job.h"
47 #include "net/test/url_request/url_request_mock_http_job.h"
48 #include "net/url_request/url_request.h"
49 #include "net/url_request/url_request_context.h"
50 #include "net/url_request/url_request_context_getter.h"
51 #include "net/url_request/url_request_filter.h"
52 #include "net/url_request/url_request_job.h"
53 #include "net/url_request/url_request_status.h"
54 #include "testing/gtest/include/gtest/gtest.h"
55
56 using captive_portal::CaptivePortalResult;
57 using content::BrowserThread;
58 using content::WebContents;
59 using net::URLRequestFailedJob;
60 using net::URLRequestMockHTTPJob;
61
62 namespace {
63
64 // Path of the fake login page, when using the TestServer.
65 const char* const kTestServerLoginPath = "files/captive_portal/login.html";
66
67 // Path of a page with an iframe that has a mock SSL timeout, when using the
68 // TestServer.
69 const char* const kTestServerIframeTimeoutPath =
70     "files/captive_portal/iframe_timeout.html";
71
72 // The following URLs each have two different behaviors, depending on whether
73 // URLRequestMockCaptivePortalJobFactory is currently simulating the presence
74 // of a captive portal or not.  They use different domains so that HSTS can be
75 // applied to them independently.
76
77 // A mock URL for the CaptivePortalService's |test_url|.  When behind a captive
78 // portal, this URL returns a mock login page.  When connected to the Internet,
79 // it returns a 204 response.  Uses the name of the login file so that reloading
80 // it will not request a different URL.
81 const char* const kMockCaptivePortalTestUrl =
82     "http://mock.captive.portal.test/login.html";
83
84 // Another mock URL for the CaptivePortalService's |test_url|.  When behind a
85 // captive portal, this URL returns a 511 status code and an HTML page that
86 // redirect to the above URL.  When connected to the Internet, it returns a 204
87 // response.
88 const char* const kMockCaptivePortal511Url =
89     "http://mock.captive.portal.511/page511.html";
90
91 // When behind a captive portal, this URL hangs without committing until a call
92 // to URLRequestTimeoutOnDemandJob::FailJobs.  When that function is called,
93 // the request will time out.
94 //
95 // When connected to the Internet, this URL returns a non-error page.
96 const char* const kMockHttpsUrl =
97     "https://mock.captive.portal.long.timeout/title2.html";
98
99 // Same as above, but different domain, so can be used to trigger cross-site
100 // navigations.
101 const char* const kMockHttpsUrl2 =
102     "https://mock.captive.portal.long.timeout2/title2.html";
103
104 // Same as kMockHttpsUrl, except the timeout happens instantly.
105 const char* const kMockHttpsQuickTimeoutUrl =
106     "https://mock.captive.portal.quick.timeout/title2.html";
107
108 // Expected title of a tab once an HTTPS load completes, when not behind a
109 // captive portal.
110 const char* const kInternetConnectedTitle = "Title Of Awesomeness";
111
112 // A URL request job that hangs until FailJobs() is called.  Started jobs
113 // are stored in a static class variable containing a linked list so that
114 // FailJobs() can locate them.
115 class URLRequestTimeoutOnDemandJob : public net::URLRequestJob,
116                                      public base::NonThreadSafe {
117  public:
118   // net::URLRequestJob:
119   void Start() override;
120
121   // All the public static methods below can be called on any thread.
122
123   // Waits for exactly |num_jobs|.
124   static void WaitForJobs(int num_jobs);
125
126   // Fails all active URLRequestTimeoutOnDemandJobs with connection timeouts.
127   // There are expected to be exactly |expected_num_jobs| waiting for
128   // failure.  The only way to gaurantee this is with an earlier call to
129   // WaitForJobs, so makes sure there has been a matching WaitForJobs call.
130   static void FailJobs(int expected_num_jobs);
131
132   // Abandon all active URLRequestTimeoutOnDemandJobs.  |expected_num_jobs|
133   // behaves just as in FailJobs.
134   static void AbandonJobs(int expected_num_jobs);
135
136  private:
137   friend class URLRequestMockCaptivePortalJobFactory;
138
139   // Operation to perform on jobs when removing them from |job_list_|.
140   enum EndJobOperation {
141     FAIL_JOBS,
142     ABANDON_JOBS,
143   };
144
145   URLRequestTimeoutOnDemandJob(net::URLRequest* request,
146                                net::NetworkDelegate* network_delegate);
147   ~URLRequestTimeoutOnDemandJob() override;
148
149   // Attempts to removes |this| from |jobs_|.  Returns true if it was removed
150   // from the list.
151   bool RemoveFromList();
152
153   static void WaitForJobsOnIOThread(int num_jobs);
154   static void FailOrAbandonJobsOnIOThread(
155       int expected_num_jobs,
156       EndJobOperation end_job_operation);
157
158   // Checks if there are at least |num_jobs_to_wait_for_| jobs in
159   // |job_list_|.  If so, exits the message loop on the UI thread, which
160   // should be spinning in a call to WaitForJobs.  Does nothing when
161   // |num_jobs_to_wait_for_| is 0.
162   static void MaybeStopWaitingForJobsOnIOThread();
163
164   // All class variables are only accessed on the IO thread.
165
166   // Number of jobs currently being waited for, or 0 if not currently
167   // waiting for jobs.
168   static int num_jobs_to_wait_for_;
169
170   // The last number of jobs that were waited for.  When FailJobs or
171   // AbandonJobs is called, this should match |expected_num_jobs|.
172   static int last_num_jobs_to_wait_for_;
173
174   // Number of jobs that have been started, but not yet waited for.  If jobs
175   // are deleted unexpectedly, they're still included in this count, even though
176   // they've been removed from |job_list_|.  Intended to reduce chance of stalls
177   // on regressions.
178   static int num_jobs_started_;
179
180   // Head of linked list of jobs that have been started and are now waiting to
181   // be timed out.
182   static URLRequestTimeoutOnDemandJob* job_list_;
183
184   // The next job that had been started but not yet timed out.
185   URLRequestTimeoutOnDemandJob* next_job_;
186
187   DISALLOW_COPY_AND_ASSIGN(URLRequestTimeoutOnDemandJob);
188 };
189
190 int URLRequestTimeoutOnDemandJob::num_jobs_to_wait_for_ = 0;
191 int URLRequestTimeoutOnDemandJob::last_num_jobs_to_wait_for_ = 0;
192 int URLRequestTimeoutOnDemandJob::num_jobs_started_ = 0;
193 URLRequestTimeoutOnDemandJob* URLRequestTimeoutOnDemandJob::job_list_ = NULL;
194
195 void URLRequestTimeoutOnDemandJob::Start() {
196   EXPECT_TRUE(CalledOnValidThread());
197
198   // Insert at start of the list.
199   next_job_ = job_list_;
200   job_list_ = this;
201   ++num_jobs_started_;
202
203   // Checks if there are at least |num_jobs_to_wait_for_| jobs in
204   // |job_list_|.  If so, exits the message loop on the UI thread, which
205   // should be spinning in a call to WaitForJobs.  Does nothing if
206   // |num_jobs_to_wait_for_| is 0.
207   MaybeStopWaitingForJobsOnIOThread();
208 }
209
210 // static
211 void URLRequestTimeoutOnDemandJob::WaitForJobs(int num_jobs) {
212   content::BrowserThread::PostTask(
213       content::BrowserThread::IO, FROM_HERE,
214       base::Bind(&URLRequestTimeoutOnDemandJob::WaitForJobsOnIOThread,
215                  num_jobs));
216   content::RunMessageLoop();
217 }
218
219 // static
220 void URLRequestTimeoutOnDemandJob::FailJobs(int expected_num_jobs) {
221   content::BrowserThread::PostTask(
222       content::BrowserThread::IO, FROM_HERE,
223       base::Bind(&URLRequestTimeoutOnDemandJob::FailOrAbandonJobsOnIOThread,
224                  expected_num_jobs,
225                  FAIL_JOBS));
226 }
227
228 // static
229 void URLRequestTimeoutOnDemandJob::AbandonJobs(int expected_num_jobs) {
230   content::BrowserThread::PostTask(
231       content::BrowserThread::IO, FROM_HERE,
232       base::Bind(&URLRequestTimeoutOnDemandJob::FailOrAbandonJobsOnIOThread,
233                  expected_num_jobs,
234                  ABANDON_JOBS));
235 }
236
237 URLRequestTimeoutOnDemandJob::URLRequestTimeoutOnDemandJob(
238     net::URLRequest* request, net::NetworkDelegate* network_delegate)
239     : net::URLRequestJob(request, network_delegate),
240       next_job_(NULL) {
241 }
242
243 URLRequestTimeoutOnDemandJob::~URLRequestTimeoutOnDemandJob() {
244   // All hanging jobs should have failed or been abandoned before being
245   // destroyed.
246   EXPECT_FALSE(RemoveFromList());
247 }
248
249 bool URLRequestTimeoutOnDemandJob::RemoveFromList() {
250   URLRequestTimeoutOnDemandJob** job = &job_list_;
251   while (*job) {
252     if (*job == this) {
253       *job = next_job_;
254       next_job_ = NULL;
255       return true;
256     }
257     job = &next_job_;
258   }
259
260   // If the job wasn't in this list, |next_job_| should be NULL.
261   EXPECT_FALSE(next_job_);
262   return false;
263 }
264
265 // static
266 void URLRequestTimeoutOnDemandJob::WaitForJobsOnIOThread(int num_jobs) {
267   ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
268   ASSERT_EQ(0, num_jobs_to_wait_for_);
269   ASSERT_LT(0, num_jobs);
270   // Number of tabs being waited on should be strictly increasing.
271   ASSERT_LE(last_num_jobs_to_wait_for_, num_jobs);
272
273   num_jobs_to_wait_for_ = num_jobs;
274   MaybeStopWaitingForJobsOnIOThread();
275 }
276
277 // static
278 void URLRequestTimeoutOnDemandJob::MaybeStopWaitingForJobsOnIOThread() {
279   ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
280   if (num_jobs_to_wait_for_ == 0)
281     return;
282
283   // There shouldn't be any extra jobs.
284   EXPECT_LE(num_jobs_started_, num_jobs_to_wait_for_);
285
286   // Should never be greater, but if it is, go ahead and exit the message loop
287   // to try and avoid hanging.
288   if (num_jobs_started_ >= num_jobs_to_wait_for_) {
289     last_num_jobs_to_wait_for_ = num_jobs_to_wait_for_;
290     num_jobs_to_wait_for_ = 0;
291     BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
292                             base::MessageLoop::QuitClosure());
293   }
294 }
295
296 // static
297 void URLRequestTimeoutOnDemandJob::FailOrAbandonJobsOnIOThread(
298     int expected_num_jobs,
299     EndJobOperation end_job_operation) {
300   ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
301   ASSERT_LT(0, expected_num_jobs);
302   EXPECT_EQ(last_num_jobs_to_wait_for_, expected_num_jobs);
303   last_num_jobs_to_wait_for_ = 0;
304
305   int num_jobs = 0;
306   while (job_list_) {
307     ++num_jobs;
308     URLRequestTimeoutOnDemandJob* job = job_list_;
309     // Since the error notification may result in the job's destruction, remove
310     // it from the job list before the error.
311     EXPECT_TRUE(job->RemoveFromList());
312     if (end_job_operation == FAIL_JOBS) {
313       job->NotifyStartError(net::URLRequestStatus(
314                                 net::URLRequestStatus::FAILED,
315                                 net::ERR_CONNECTION_TIMED_OUT));
316     }
317   }
318
319   EXPECT_EQ(expected_num_jobs, num_jobs_started_);
320   EXPECT_EQ(expected_num_jobs, num_jobs);
321
322   num_jobs_started_ -= expected_num_jobs;
323 }
324
325 // URLRequestCaptivePortalJobFactory emulates captive portal behavior.
326 // Initially, it emulates being behind a captive portal.  When
327 // SetBehindCaptivePortal(false) is called, it emulates behavior when not behind
328 // a captive portal.  The class itself is never instantiated.
329 //
330 // It handles requests for kMockCaptivePortalTestUrl, kMockHttpsUrl, and
331 // kMockHttpsQuickTimeoutUrl.
332 class URLRequestMockCaptivePortalJobFactory {
333  public:
334   // The public static methods below can be called on any thread.
335
336   // Adds the testing URLs to the net::URLRequestFilter.  Should only be called
337   // once.
338   static void AddUrlHandlers();
339
340   // Sets whether or not there is a captive portal.  Outstanding requests are
341   // not affected.
342   static void SetBehindCaptivePortal(bool behind_captive_portal);
343
344  private:
345   // These do all the work of the corresponding public functions, with the only
346   // difference being that they must be called on the IO thread.
347   static void AddUrlHandlersOnIOThread();
348   static void SetBehindCaptivePortalOnIOThread(bool behind_captive_portal);
349
350   // Returns a URLRequestJob that reflects the current captive portal state
351   // for the URLs: kMockCaptivePortalTestUrl, kMockHttpsUrl, and
352   // kMockHttpsQuickTimeoutUrl.  See documentation of individual URLs for
353   // actual behavior.
354   static net::URLRequestJob* Factory(net::URLRequest* request,
355                                      net::NetworkDelegate* network_delegate,
356                                      const std::string& scheme);
357
358   static bool behind_captive_portal_;
359
360   DISALLOW_IMPLICIT_CONSTRUCTORS(URLRequestMockCaptivePortalJobFactory);
361 };
362
363 bool URLRequestMockCaptivePortalJobFactory::behind_captive_portal_ = true;
364
365 // static
366 void URLRequestMockCaptivePortalJobFactory::AddUrlHandlers() {
367   content::BrowserThread::PostTask(
368       content::BrowserThread::IO, FROM_HERE,
369       base::Bind(
370           &URLRequestMockCaptivePortalJobFactory::AddUrlHandlersOnIOThread));
371 }
372
373 // static
374 void URLRequestMockCaptivePortalJobFactory::SetBehindCaptivePortal(
375     bool behind_captive_portal) {
376   content::BrowserThread::PostTask(
377       content::BrowserThread::IO, FROM_HERE,
378       base::Bind(
379           &URLRequestMockCaptivePortalJobFactory::
380               SetBehindCaptivePortalOnIOThread,
381           behind_captive_portal));
382 }
383
384 // static
385 void URLRequestMockCaptivePortalJobFactory::AddUrlHandlersOnIOThread() {
386   EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
387
388   // Handle only exact matches, so any related requests, such as those for
389   // favicons, are not handled by the factory.
390   net::URLRequestFilter* filter = net::URLRequestFilter::GetInstance();
391   filter->AddUrlHandler(GURL(kMockCaptivePortalTestUrl),
392                         URLRequestMockCaptivePortalJobFactory::Factory);
393   filter->AddUrlHandler(GURL(kMockCaptivePortal511Url),
394                         URLRequestMockCaptivePortalJobFactory::Factory);
395   filter->AddUrlHandler(GURL(kMockHttpsUrl),
396                         URLRequestMockCaptivePortalJobFactory::Factory);
397   filter->AddUrlHandler(GURL(kMockHttpsUrl2),
398                         URLRequestMockCaptivePortalJobFactory::Factory);
399   filter->AddUrlHandler(GURL(kMockHttpsQuickTimeoutUrl),
400                         URLRequestMockCaptivePortalJobFactory::Factory);
401 }
402
403 // static
404 void URLRequestMockCaptivePortalJobFactory::SetBehindCaptivePortalOnIOThread(
405     bool behind_captive_portal) {
406   EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
407   behind_captive_portal_ = behind_captive_portal;
408 }
409
410 // static
411 net::URLRequestJob* URLRequestMockCaptivePortalJobFactory::Factory(
412     net::URLRequest* request,
413     net::NetworkDelegate* network_delegate,
414     const std::string& scheme) {
415   EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
416
417   // The PathService is threadsafe.
418   base::FilePath root_http;
419   PathService::Get(chrome::DIR_TEST_DATA, &root_http);
420
421   if (request->url() == GURL(kMockHttpsUrl) ||
422       request->url() == GURL(kMockHttpsUrl2)) {
423     if (behind_captive_portal_)
424       return new URLRequestTimeoutOnDemandJob(request, network_delegate);
425     // Once logged in to the portal, HTTPS requests return the page that was
426     // actually requested.
427     return new URLRequestMockHTTPJob(
428         request,
429         network_delegate,
430         root_http.Append(FILE_PATH_LITERAL("title2.html")),
431         BrowserThread::GetBlockingPool()->GetTaskRunnerWithShutdownBehavior(
432             base::SequencedWorkerPool::SKIP_ON_SHUTDOWN));
433   } else if (request->url() == GURL(kMockHttpsQuickTimeoutUrl)) {
434     if (behind_captive_portal_)
435       return new URLRequestFailedJob(
436           request, network_delegate, net::ERR_CONNECTION_TIMED_OUT);
437     // Once logged in to the portal, HTTPS requests return the page that was
438     // actually requested.
439     return new URLRequestMockHTTPJob(
440         request,
441         network_delegate,
442         root_http.Append(FILE_PATH_LITERAL("title2.html")),
443         BrowserThread::GetBlockingPool()->GetTaskRunnerWithShutdownBehavior(
444             base::SequencedWorkerPool::SKIP_ON_SHUTDOWN));
445   } else {
446     // The URL should be the captive portal test URL.
447     EXPECT_TRUE(GURL(kMockCaptivePortalTestUrl) == request->url() ||
448                 GURL(kMockCaptivePortal511Url) == request->url());
449
450     if (behind_captive_portal_) {
451       // Prior to logging in to the portal, the HTTP test URLs are intercepted
452       // by the captive portal.
453       if (GURL(kMockCaptivePortal511Url) == request->url()) {
454         return new URLRequestMockHTTPJob(
455             request,
456             network_delegate,
457             root_http.Append(FILE_PATH_LITERAL("captive_portal/page511.html")),
458             BrowserThread::GetBlockingPool()->GetTaskRunnerWithShutdownBehavior(
459                 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN));
460       }
461       return new URLRequestMockHTTPJob(
462           request,
463           network_delegate,
464           root_http.Append(FILE_PATH_LITERAL("captive_portal/login.html")),
465           BrowserThread::GetBlockingPool()->GetTaskRunnerWithShutdownBehavior(
466               base::SequencedWorkerPool::SKIP_ON_SHUTDOWN));
467     }
468
469     // After logging in to the portal, the test URLs return a 204 response.
470     return new URLRequestMockHTTPJob(
471         request,
472         network_delegate,
473         root_http.Append(FILE_PATH_LITERAL("captive_portal/page204.html")),
474         BrowserThread::GetBlockingPool()->GetTaskRunnerWithShutdownBehavior(
475             base::SequencedWorkerPool::SKIP_ON_SHUTDOWN));
476   }
477 }
478
479 // Creates a server-side redirect for use with the TestServer.
480 std::string CreateServerRedirect(const std::string& dest_url) {
481   const char* const kServerRedirectBase = "server-redirect?";
482   return kServerRedirectBase + dest_url;
483 }
484
485 // Returns the total number of loading tabs across all Browsers, for all
486 // Profiles.
487 int NumLoadingTabs() {
488   int num_loading_tabs = 0;
489   for (TabContentsIterator it; !it.done(); it.Next()) {
490     if (it->IsLoading())
491       ++num_loading_tabs;
492   }
493   return num_loading_tabs;
494 }
495
496 bool IsLoginTab(WebContents* web_contents) {
497   return CaptivePortalTabHelper::FromWebContents(web_contents)->IsLoginTab();
498 }
499
500 // Tracks how many times each tab has been navigated since the Observer was
501 // created.  The standard TestNavigationObserver can only watch specific
502 // pre-existing tabs or loads in serial for all tabs.
503 class MultiNavigationObserver : public content::NotificationObserver {
504  public:
505   MultiNavigationObserver();
506   ~MultiNavigationObserver() override;
507
508   // Waits for exactly |num_navigations_to_wait_for| LOAD_STOP
509   // notifications to have occurred since the construction of |this|.  More
510   // navigations than expected occuring will trigger a expect failure.
511   void WaitForNavigations(int num_navigations_to_wait_for);
512
513   // Returns the number of LOAD_STOP events that have occurred for
514   // |web_contents| since this was constructed.
515   int NumNavigationsForTab(WebContents* web_contents) const;
516
517   // The number of LOAD_STOP events since |this| was created.
518   int num_navigations() const { return num_navigations_; }
519
520  private:
521   typedef std::map<const WebContents*, int> TabNavigationMap;
522
523   // content::NotificationObserver:
524   void Observe(int type,
525                const content::NotificationSource& source,
526                const content::NotificationDetails& details) override;
527
528   int num_navigations_;
529
530   // Map of how many times each tab has navigated since |this| was created.
531   TabNavigationMap tab_navigation_map_;
532
533   // Total number of navigations to wait for.  Value only matters when
534   // |waiting_for_navigation_| is true.
535   int num_navigations_to_wait_for_;
536
537   // True if WaitForNavigations has been called, until
538   // |num_navigations_to_wait_for_| have been observed.
539   bool waiting_for_navigation_;
540
541   content::NotificationRegistrar registrar_;
542
543   DISALLOW_COPY_AND_ASSIGN(MultiNavigationObserver);
544 };
545
546 MultiNavigationObserver::MultiNavigationObserver()
547     : num_navigations_(0),
548       num_navigations_to_wait_for_(0),
549       waiting_for_navigation_(false) {
550   registrar_.Add(this, content::NOTIFICATION_LOAD_STOP,
551                  content::NotificationService::AllSources());
552 }
553
554 MultiNavigationObserver::~MultiNavigationObserver() {
555 }
556
557 void MultiNavigationObserver::WaitForNavigations(
558     int num_navigations_to_wait_for) {
559   // Shouldn't already be waiting for navigations.
560   EXPECT_FALSE(waiting_for_navigation_);
561   EXPECT_LT(0, num_navigations_to_wait_for);
562   if (num_navigations_ < num_navigations_to_wait_for) {
563     num_navigations_to_wait_for_ = num_navigations_to_wait_for;
564     waiting_for_navigation_ = true;
565     content::RunMessageLoop();
566     EXPECT_FALSE(waiting_for_navigation_);
567   }
568   EXPECT_EQ(num_navigations_, num_navigations_to_wait_for);
569 }
570
571 int MultiNavigationObserver::NumNavigationsForTab(
572     WebContents* web_contents) const {
573   TabNavigationMap::const_iterator tab_navigations =
574       tab_navigation_map_.find(web_contents);
575   if (tab_navigations == tab_navigation_map_.end())
576     return 0;
577   return tab_navigations->second;
578 }
579
580 void MultiNavigationObserver::Observe(
581     int type,
582     const content::NotificationSource& source,
583     const content::NotificationDetails& details) {
584   ASSERT_EQ(type, content::NOTIFICATION_LOAD_STOP);
585   content::NavigationController* controller =
586       content::Source<content::NavigationController>(source).ptr();
587   ++num_navigations_;
588   ++tab_navigation_map_[controller->GetWebContents()];
589   if (waiting_for_navigation_ &&
590       num_navigations_to_wait_for_ == num_navigations_) {
591     waiting_for_navigation_ = false;
592     base::MessageLoopForUI::current()->Quit();
593   }
594 }
595
596 // This observer creates a list of loading tabs, and then waits for them all
597 // to stop loading and have the kInternetConnectedTitle.
598 //
599 // This is for the specific purpose of observing tabs time out after logging in
600 // to a captive portal, which will then cause them to reload.
601 // MultiNavigationObserver is insufficient for this because there may or may not
602 // be a LOAD_STOP event between the timeout and the reload.
603 // See bug http://crbug.com/133227
604 class FailLoadsAfterLoginObserver : public content::NotificationObserver {
605  public:
606   FailLoadsAfterLoginObserver();
607   ~FailLoadsAfterLoginObserver() override;
608
609   void WaitForNavigations();
610
611  private:
612   typedef std::set<const WebContents*> TabSet;
613
614   // content::NotificationObserver:
615   void Observe(int type,
616                const content::NotificationSource& source,
617                const content::NotificationDetails& details) override;
618
619   // The set of tabs that need to be navigated.  This is the set of loading
620   // tabs when the observer is created.
621   TabSet tabs_needing_navigation_;
622
623   // Number of tabs that have stopped navigating with the expected title.  These
624   // are expected not to be navigated again.
625   TabSet tabs_navigated_to_final_destination_;
626
627   // True if WaitForNavigations has been called, until
628   // |tabs_navigated_to_final_destination_| equals |tabs_needing_navigation_|.
629   bool waiting_for_navigation_;
630
631   content::NotificationRegistrar registrar_;
632
633   DISALLOW_COPY_AND_ASSIGN(FailLoadsAfterLoginObserver);
634 };
635
636 FailLoadsAfterLoginObserver::FailLoadsAfterLoginObserver()
637     : waiting_for_navigation_(false) {
638   registrar_.Add(this, content::NOTIFICATION_LOAD_STOP,
639                  content::NotificationService::AllSources());
640   for (TabContentsIterator it; !it.done(); it.Next()) {
641     if (it->IsLoading())
642       tabs_needing_navigation_.insert(*it);
643   }
644 }
645
646 FailLoadsAfterLoginObserver::~FailLoadsAfterLoginObserver() {
647 }
648
649 void FailLoadsAfterLoginObserver::WaitForNavigations() {
650   // Shouldn't already be waiting for navigations.
651   EXPECT_FALSE(waiting_for_navigation_);
652   if (tabs_needing_navigation_.size() !=
653           tabs_navigated_to_final_destination_.size()) {
654     waiting_for_navigation_ = true;
655     content::RunMessageLoop();
656     EXPECT_FALSE(waiting_for_navigation_);
657   }
658   EXPECT_EQ(tabs_needing_navigation_.size(),
659             tabs_navigated_to_final_destination_.size());
660 }
661
662 void FailLoadsAfterLoginObserver::Observe(
663     int type,
664     const content::NotificationSource& source,
665     const content::NotificationDetails& details) {
666   ASSERT_EQ(type, content::NOTIFICATION_LOAD_STOP);
667   content::NavigationController* controller =
668       content::Source<content::NavigationController>(source).ptr();
669   WebContents* contents = controller->GetWebContents();
670
671   ASSERT_EQ(1u, tabs_needing_navigation_.count(contents));
672   ASSERT_EQ(0u, tabs_navigated_to_final_destination_.count(contents));
673
674   if (contents->GetTitle() != base::ASCIIToUTF16(kInternetConnectedTitle))
675     return;
676   tabs_navigated_to_final_destination_.insert(contents);
677
678   if (waiting_for_navigation_ &&
679       tabs_needing_navigation_.size() ==
680           tabs_navigated_to_final_destination_.size()) {
681     waiting_for_navigation_ = false;
682     base::MessageLoopForUI::current()->Quit();
683   }
684 }
685
686 // An observer for watching the CaptivePortalService.  It tracks the last
687 // received result and the total number of received results.
688 class CaptivePortalObserver : public content::NotificationObserver {
689  public:
690   explicit CaptivePortalObserver(Profile* profile);
691
692   // Runs the message loop until until at exactly |update_count| capitive portal
693   // results have been received, since this creation of |this|.  Expects no
694   // additional captive portal results.
695   void WaitForResults(int num_results_to_wait_for);
696
697   int num_results_received() const { return num_results_received_; }
698
699   CaptivePortalResult captive_portal_result() const {
700     return captive_portal_result_;
701   }
702
703  private:
704   // Records results and exits the message loop, if needed.
705   void Observe(int type,
706                const content::NotificationSource& source,
707                const content::NotificationDetails& details) override;
708
709   // Number of times OnPortalResult has been called since construction.
710   int num_results_received_;
711
712   // If WaitForResults was called, the total number of updates for which to
713   // wait.  Value doesn't matter when |waiting_for_result_| is false.
714   int num_results_to_wait_for_;
715
716   bool waiting_for_result_;
717
718   Profile* profile_;
719
720   CaptivePortalService* captive_portal_service_;
721
722   // Last result received.
723   CaptivePortalResult captive_portal_result_;
724
725   content::NotificationRegistrar registrar_;
726
727   DISALLOW_COPY_AND_ASSIGN(CaptivePortalObserver);
728 };
729
730 CaptivePortalObserver::CaptivePortalObserver(Profile* profile)
731     : num_results_received_(0),
732       num_results_to_wait_for_(0),
733       waiting_for_result_(false),
734       profile_(profile),
735       captive_portal_service_(
736           CaptivePortalServiceFactory::GetForProfile(profile)),
737       captive_portal_result_(
738           captive_portal_service_->last_detection_result()) {
739   registrar_.Add(this,
740                  chrome::NOTIFICATION_CAPTIVE_PORTAL_CHECK_RESULT,
741                  content::Source<Profile>(profile_));
742 }
743
744 void CaptivePortalObserver::WaitForResults(int num_results_to_wait_for) {
745   EXPECT_LT(0, num_results_to_wait_for);
746   EXPECT_FALSE(waiting_for_result_);
747   if (num_results_received_ < num_results_to_wait_for) {
748     num_results_to_wait_for_ = num_results_to_wait_for;
749     waiting_for_result_ = true;
750     content::RunMessageLoop();
751     EXPECT_FALSE(waiting_for_result_);
752   }
753   EXPECT_EQ(num_results_to_wait_for, num_results_received_);
754 }
755
756 void CaptivePortalObserver::Observe(
757     int type,
758     const content::NotificationSource& source,
759     const content::NotificationDetails& details) {
760   ASSERT_EQ(type, chrome::NOTIFICATION_CAPTIVE_PORTAL_CHECK_RESULT);
761   ASSERT_EQ(profile_, content::Source<Profile>(source).ptr());
762
763   CaptivePortalService::Results* results =
764       content::Details<CaptivePortalService::Results>(details).ptr();
765
766   EXPECT_EQ(captive_portal_result_, results->previous_result);
767   EXPECT_EQ(captive_portal_service_->last_detection_result(),
768             results->result);
769
770   captive_portal_result_ = results->result;
771   ++num_results_received_;
772
773   if (waiting_for_result_ &&
774       num_results_to_wait_for_ == num_results_received_) {
775     waiting_for_result_ = false;
776     base::MessageLoop::current()->Quit();
777   }
778 }
779
780 // Adds an HSTS rule for |host|, so that all HTTP requests sent to it will
781 // be switched to HTTPS requests.
782 void AddHstsHost(net::URLRequestContextGetter* context_getter,
783                  const std::string& host) {
784   ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
785   net::TransportSecurityState* transport_security_state =
786       context_getter->GetURLRequestContext()->transport_security_state();
787   if (!transport_security_state) {
788     FAIL();
789     return;
790   }
791
792   base::Time expiry = base::Time::Now() + base::TimeDelta::FromDays(1000);
793   bool include_subdomains = false;
794   transport_security_state->AddHSTS(host, expiry, include_subdomains);
795 }
796
797 }  // namespace
798
799 class CaptivePortalBrowserTest : public InProcessBrowserTest {
800  public:
801   CaptivePortalBrowserTest();
802
803   // InProcessBrowserTest:
804   void SetUpOnMainThread() override;
805   void TearDownOnMainThread() override;
806
807   // Sets the captive portal checking preference.  Does not affect the command
808   // line flag, which is set in SetUpCommandLine.
809   void EnableCaptivePortalDetection(Profile* profile, bool enabled);
810
811   // Sets up the captive portal service for the given profile so that
812   // all checks go to |test_url|.  Also disables all timers.
813   void SetUpCaptivePortalService(Profile* profile, const GURL& test_url);
814
815   // Returns true if |browser|'s profile is currently running a captive portal
816   // check.
817   bool CheckPending(Browser* browser);
818
819   // Returns the CaptivePortalTabReloader::State of |web_contents|.
820   CaptivePortalTabReloader::State GetStateOfTabReloader(
821       WebContents* web_contents) const;
822
823   // Returns the CaptivePortalTabReloader::State of the indicated tab.
824   CaptivePortalTabReloader::State GetStateOfTabReloaderAt(Browser* browser,
825                                                           int index) const;
826
827   // Returns the number of tabs with the given state, across all profiles.
828   int NumTabsWithState(CaptivePortalTabReloader::State state) const;
829
830   // Returns the number of tabs broken by captive portals, across all profiles.
831   int NumBrokenTabs() const;
832
833   // Returns the number of tabs that need to be reloaded due to having logged
834   // in to a captive portal, across all profiles.
835   int NumNeedReloadTabs() const;
836
837   // Navigates |browser|'s active tab to |url| and expects no captive portal
838   // test to be triggered.  |expected_navigations| is the number of times the
839   // active tab will end up being navigated.  It should be 1, except for the
840   // Link Doctor page, which acts like two navigations.
841   void NavigateToPageExpectNoTest(Browser* browser,
842                                   const GURL& url,
843                                   int expected_navigations);
844
845   // Navigates |browser|'s active tab to an SSL tab that takes a while to load,
846   // triggering a captive portal check, which is expected to give the result
847   // |expected_result|.  The page finishes loading, with a timeout, after the
848   // captive portal check.
849   void SlowLoadNoCaptivePortal(Browser* browser,
850                                CaptivePortalResult expected_result);
851
852   // Navigates |browser|'s active tab to an SSL timeout, expecting a captive
853   // portal check to be triggered and return a result which will indicates
854   // there's no detected captive portal.
855   void FastTimeoutNoCaptivePortal(Browser* browser,
856                                   CaptivePortalResult expected_result);
857
858   // Navigates the active tab to a slow loading SSL page, which will then
859   // trigger a captive portal test.  The test is expected to find a captive
860   // portal.  The slow loading page will continue to load after the function
861   // returns, until URLRequestTimeoutOnDemandJob::FailJobs() is called,
862   // at which point it will timeout.
863   //
864   // When |expect_login_tab| is false, no login tab is expected to be opened,
865   // because one already exists, and the function returns once the captive
866   // portal test is complete.
867   //
868   // If |expect_login_tab| is true, a login tab is then expected to be opened.
869   // It waits until both the login tab has finished loading, and two captive
870   // portal tests complete.  The second test is triggered by the load of the
871   // captive portal tab completing.
872   //
873   // This function must not be called when the active tab is currently loading.
874   // Waits for the hanging request to be issued, so other functions can rely
875   // on URLRequestTimeoutOnDemandJob::WaitForJobs having been called.
876   void SlowLoadBehindCaptivePortal(Browser* browser, bool expect_login_tab);
877
878   // Same as above, but takes extra parameters.
879   //
880   // |hanging_url| should either be kMockHttpsUrl or redirect to kMockHttpsUrl.
881   //
882   // |expected_portal_checks| and |expected_login_tab_navigations| allow
883   // client-side redirects to be tested.  |expected_login_tab_navigations| is
884   // ignored when |expect_open_login_tab| is false.
885   void SlowLoadBehindCaptivePortal(Browser* browser,
886                                    bool expect_open_login_tab,
887                                    const GURL& hanging_url,
888                                    int expected_portal_checks,
889                                    int expected_login_tab_navigations);
890
891   // Just like SlowLoadBehindCaptivePortal, except the navigated tab has
892   // a connection timeout rather having its time trigger, and the function
893   // waits until that timeout occurs.
894   void FastTimeoutBehindCaptivePortal(Browser* browser,
895                                       bool expect_open_login_tab);
896
897   // Much as above, but accepts a URL parameter and can be used for errors that
898   // trigger captive portal checks other than timeouts.  |error_url| should
899   // result in an error rather than hanging.
900   void FastErrorBehindCaptivePortal(Browser* browser,
901                                     bool expect_open_login_tab,
902                                     const GURL& error_url);
903
904   // Navigates the login tab without logging in.  The login tab must be the
905   // specified browser's active tab.  Expects no other tab to change state.
906   // |num_loading_tabs| and |num_timed_out_tabs| are used as extra checks
907   // that nothing has gone wrong prior to the function call.
908   void NavigateLoginTab(Browser* browser,
909                         int num_loading_tabs,
910                         int num_timed_out_tabs);
911
912   // Simulates a login by updating the URLRequestMockCaptivePortalJob's
913   // behind captive portal state, and navigating the login tab.  Waits for
914   // all broken but not loading tabs to be reloaded.
915   // |num_loading_tabs| and |num_timed_out_tabs| are used as extra checks
916   // that nothing has gone wrong prior to the function call.
917   void Login(Browser* browser, int num_loading_tabs, int num_timed_out_tabs);
918
919   // Makes the slow SSL loads of all active tabs time out at once, and waits for
920   // them to finish both that load and the automatic reload it should trigger.
921   // There should be no timed out tabs when this is called.
922   void FailLoadsAfterLogin(Browser* browser, int num_loading_tabs);
923
924   // Makes the slow SSL loads of all active tabs time out at once, and waits for
925   // them to finish displaying their error pages.  The login tab should be the
926   // active tab.  There should be no timed out tabs when this is called.
927   void FailLoadsWithoutLogin(Browser* browser, int num_loading_tabs);
928
929   // Navigates |browser|'s active tab to |starting_url| while not behind a
930   // captive portal.  Then navigates to |interrupted_url|, which should create
931   // a URLRequestTimeoutOnDemandJob, which is then abandoned.  The load should
932   // trigger a captive portal check, which finds a captive portal and opens a
933   // tab.
934   //
935   // Then the navigation is interrupted by a navigation to |timeout_url|, which
936   // should trigger a captive portal check, and finally the test simulates
937   // logging in.
938   //
939   // The purpose of this test is to make sure the TabHelper triggers a captive
940   // portal check when a load is interrupted by another load, particularly in
941   // the case of cross-process navigations.
942   void RunNavigateLoadingTabToTimeoutTest(Browser* browser,
943                                           const GURL& starting_url,
944                                           const GURL& interrupted_url,
945                                           const GURL& timeout_url);
946
947   // Sets the timeout used by a CaptivePortalTabReloader on slow SSL loads
948   // before a captive portal check.
949   void SetSlowSSLLoadTime(CaptivePortalTabReloader* tab_reloader,
950                           base::TimeDelta slow_ssl_load_time);
951
952   CaptivePortalTabReloader* GetTabReloader(WebContents* web_contents) const;
953
954  private:
955   DISALLOW_COPY_AND_ASSIGN(CaptivePortalBrowserTest);
956 };
957
958 CaptivePortalBrowserTest::CaptivePortalBrowserTest() {
959 }
960
961 void CaptivePortalBrowserTest::SetUpOnMainThread() {
962   // Enable mock requests.
963   content::BrowserThread::PostTask(
964       content::BrowserThread::IO, FROM_HERE,
965       base::Bind(&chrome_browser_net::SetUrlRequestMocksEnabled, true));
966   URLRequestMockCaptivePortalJobFactory::AddUrlHandlers();
967
968   // Double-check that the captive portal service isn't enabled by default for
969   // browser tests.
970   EXPECT_EQ(CaptivePortalService::DISABLED_FOR_TESTING,
971             CaptivePortalService::get_state_for_testing());
972
973   CaptivePortalService::set_state_for_testing(
974       CaptivePortalService::SKIP_OS_CHECK_FOR_TESTING);
975   EnableCaptivePortalDetection(browser()->profile(), true);
976
977   // Set the captive portal service to use URLRequestMockCaptivePortalJob's
978   // mock URL, by default.
979   SetUpCaptivePortalService(browser()->profile(),
980                             GURL(kMockCaptivePortalTestUrl));
981 }
982
983 void CaptivePortalBrowserTest::TearDownOnMainThread() {
984   // No test should have a captive portal check pending on quit.
985   EXPECT_FALSE(CheckPending(browser()));
986 }
987
988 void CaptivePortalBrowserTest::EnableCaptivePortalDetection(
989     Profile* profile, bool enabled) {
990   profile->GetPrefs()->SetBoolean(prefs::kAlternateErrorPagesEnabled, enabled);
991 }
992
993 void CaptivePortalBrowserTest::SetUpCaptivePortalService(Profile* profile,
994                                                          const GURL& test_url) {
995   CaptivePortalService* captive_portal_service =
996       CaptivePortalServiceFactory::GetForProfile(profile);
997   captive_portal_service->set_test_url(test_url);
998
999   // Don't use any non-zero timers.  Timers are checked in unit tests.
1000   CaptivePortalService::RecheckPolicy* recheck_policy =
1001       &captive_portal_service->recheck_policy();
1002   recheck_policy->initial_backoff_no_portal_ms = 0;
1003   recheck_policy->initial_backoff_portal_ms = 0;
1004   recheck_policy->backoff_policy.maximum_backoff_ms = 0;
1005 }
1006
1007 bool CaptivePortalBrowserTest::CheckPending(Browser* browser) {
1008   CaptivePortalService* captive_portal_service =
1009       CaptivePortalServiceFactory::GetForProfile(browser->profile());
1010
1011   return captive_portal_service->DetectionInProgress() ||
1012       captive_portal_service->TimerRunning();
1013 }
1014
1015 CaptivePortalTabReloader::State CaptivePortalBrowserTest::GetStateOfTabReloader(
1016     WebContents* web_contents) const {
1017   return GetTabReloader(web_contents)->state();
1018 }
1019
1020 CaptivePortalTabReloader::State
1021 CaptivePortalBrowserTest::GetStateOfTabReloaderAt(Browser* browser,
1022                                                   int index) const {
1023   return GetStateOfTabReloader(
1024       browser->tab_strip_model()->GetWebContentsAt(index));
1025 }
1026
1027 int CaptivePortalBrowserTest::NumTabsWithState(
1028     CaptivePortalTabReloader::State state) const {
1029   int num_tabs = 0;
1030   for (TabContentsIterator it; !it.done(); it.Next()) {
1031     if (GetStateOfTabReloader(*it) == state)
1032       ++num_tabs;
1033   }
1034   return num_tabs;
1035 }
1036
1037 int CaptivePortalBrowserTest::NumBrokenTabs() const {
1038   return NumTabsWithState(CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL);
1039 }
1040
1041 int CaptivePortalBrowserTest::NumNeedReloadTabs() const {
1042   return NumTabsWithState(CaptivePortalTabReloader::STATE_NEEDS_RELOAD);
1043 }
1044
1045 void CaptivePortalBrowserTest::NavigateToPageExpectNoTest(
1046     Browser* browser,
1047     const GURL& url,
1048     int expected_navigations) {
1049   MultiNavigationObserver navigation_observer;
1050   CaptivePortalObserver portal_observer(browser->profile());
1051
1052   ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
1053       browser, url, expected_navigations);
1054
1055   // No captive portal checks should have ocurred or be pending, and there
1056   // should be no new tabs.
1057   EXPECT_EQ(0, portal_observer.num_results_received());
1058   EXPECT_FALSE(CheckPending(browser));
1059   EXPECT_EQ(1, browser->tab_strip_model()->count());
1060   EXPECT_EQ(expected_navigations, navigation_observer.num_navigations());
1061   EXPECT_EQ(0, NumLoadingTabs());
1062   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE,
1063             GetStateOfTabReloaderAt(browser, 0));
1064 }
1065
1066 void CaptivePortalBrowserTest::SlowLoadNoCaptivePortal(
1067     Browser* browser,
1068     CaptivePortalResult expected_result) {
1069   CaptivePortalTabReloader* tab_reloader =
1070       GetTabReloader(browser->tab_strip_model()->GetActiveWebContents());
1071   ASSERT_TRUE(tab_reloader);
1072   SetSlowSSLLoadTime(tab_reloader, base::TimeDelta());
1073
1074   MultiNavigationObserver navigation_observer;
1075   CaptivePortalObserver portal_observer(browser->profile());
1076   ui_test_utils::NavigateToURLWithDisposition(browser,
1077                                               GURL(kMockHttpsUrl),
1078                                               CURRENT_TAB,
1079                                               ui_test_utils::BROWSER_TEST_NONE);
1080
1081   portal_observer.WaitForResults(1);
1082
1083   ASSERT_EQ(1, browser->tab_strip_model()->count());
1084   EXPECT_EQ(expected_result, portal_observer.captive_portal_result());
1085   EXPECT_EQ(1, portal_observer.num_results_received());
1086   EXPECT_EQ(0, navigation_observer.num_navigations());
1087   EXPECT_FALSE(CheckPending(browser));
1088
1089   // First tab should still be loading.
1090   EXPECT_EQ(1, NumLoadingTabs());
1091
1092   // Wait for the request to be issued, then time it out.
1093   URLRequestTimeoutOnDemandJob::WaitForJobs(1);
1094   URLRequestTimeoutOnDemandJob::FailJobs(1);
1095   navigation_observer.WaitForNavigations(1);
1096
1097   ASSERT_EQ(1, browser->tab_strip_model()->count());
1098   EXPECT_EQ(1, portal_observer.num_results_received());
1099   EXPECT_FALSE(CheckPending(browser));
1100   EXPECT_EQ(0, NumLoadingTabs());
1101
1102   // Set a slow SSL load time to prevent the timer from triggering.
1103   SetSlowSSLLoadTime(tab_reloader, base::TimeDelta::FromDays(1));
1104 }
1105
1106 void CaptivePortalBrowserTest::FastTimeoutNoCaptivePortal(
1107     Browser* browser,
1108     CaptivePortalResult expected_result) {
1109   ASSERT_NE(expected_result, captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL);
1110
1111   // Set the load time to be large, so the timer won't trigger.  The value is
1112   // not restored at the end of the function.
1113   CaptivePortalTabReloader* tab_reloader =
1114       GetTabReloader(browser->tab_strip_model()->GetActiveWebContents());
1115   ASSERT_TRUE(tab_reloader);
1116   SetSlowSSLLoadTime(tab_reloader, base::TimeDelta::FromHours(1));
1117
1118   MultiNavigationObserver navigation_observer;
1119   CaptivePortalObserver portal_observer(browser->profile());
1120
1121   // Neither of these should be changed by the navigation.
1122   int active_index = browser->tab_strip_model()->active_index();
1123   int expected_tab_count = browser->tab_strip_model()->count();
1124
1125   ui_test_utils::NavigateToURL(
1126       browser,
1127       URLRequestFailedJob::GetMockHttpsUrl(net::ERR_CONNECTION_TIMED_OUT));
1128
1129   // An attempt to detect a captive portal should have started by now.  If not,
1130   // abort early to prevent hanging.
1131   ASSERT_TRUE(portal_observer.num_results_received() > 0 ||
1132               CheckPending(browser));
1133
1134   portal_observer.WaitForResults(1);
1135   navigation_observer.WaitForNavigations(1);
1136
1137   // Check the result.
1138   EXPECT_EQ(1, portal_observer.num_results_received());
1139   EXPECT_EQ(expected_result, portal_observer.captive_portal_result());
1140
1141   // Check that the right tab was navigated, and there were no extra
1142   // navigations.
1143   EXPECT_EQ(1, navigation_observer.NumNavigationsForTab(
1144                    browser->tab_strip_model()->GetWebContentsAt(active_index)));
1145   EXPECT_EQ(0, NumLoadingTabs());
1146
1147   // Check the tab's state, and verify no captive portal check is pending.
1148   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE,
1149             GetStateOfTabReloaderAt(browser, 0));
1150   EXPECT_FALSE(CheckPending(browser));
1151
1152   // Make sure no login tab was opened.
1153   EXPECT_EQ(expected_tab_count, browser->tab_strip_model()->count());
1154 }
1155
1156 void CaptivePortalBrowserTest::SlowLoadBehindCaptivePortal(
1157     Browser* browser,
1158     bool expect_open_login_tab) {
1159   SlowLoadBehindCaptivePortal(browser,
1160                               expect_open_login_tab,
1161                               GURL(kMockHttpsUrl),
1162                               1,
1163                               1);
1164 }
1165
1166 void CaptivePortalBrowserTest::SlowLoadBehindCaptivePortal(
1167     Browser* browser,
1168     bool expect_open_login_tab,
1169     const GURL& hanging_url,
1170     int expected_portal_checks,
1171     int expected_login_tab_navigations) {
1172   ASSERT_GE(expected_portal_checks, 1);
1173   TabStripModel* tab_strip_model = browser->tab_strip_model();
1174   // Calling this on a tab that's waiting for a load to manually be timed out
1175   // will result in a hang.
1176   ASSERT_FALSE(tab_strip_model->GetActiveWebContents()->IsLoading());
1177
1178   // Trigger a captive portal check quickly.
1179   CaptivePortalTabReloader* tab_reloader =
1180       GetTabReloader(tab_strip_model->GetActiveWebContents());
1181   ASSERT_TRUE(tab_reloader);
1182   SetSlowSSLLoadTime(tab_reloader, base::TimeDelta());
1183
1184   // Number of tabs expected to be open after the captive portal checks
1185   // have completed.
1186   int initial_tab_count = tab_strip_model->count();
1187   int initial_active_index = tab_strip_model->active_index();
1188   int initial_loading_tabs = NumLoadingTabs();
1189   int expected_broken_tabs = NumBrokenTabs();
1190   if (CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL !=
1191           GetStateOfTabReloader(tab_strip_model->GetActiveWebContents())) {
1192     ++expected_broken_tabs;
1193   }
1194
1195   MultiNavigationObserver navigation_observer;
1196   CaptivePortalObserver portal_observer(browser->profile());
1197   ui_test_utils::NavigateToURLWithDisposition(browser,
1198                                               hanging_url,
1199                                               CURRENT_TAB,
1200                                               ui_test_utils::BROWSER_TEST_NONE);
1201   portal_observer.WaitForResults(expected_portal_checks);
1202
1203   if (expect_open_login_tab) {
1204     ASSERT_GE(expected_login_tab_navigations, 1);
1205
1206     navigation_observer.WaitForNavigations(expected_login_tab_navigations);
1207
1208     ASSERT_EQ(initial_tab_count + 1, tab_strip_model->count());
1209     EXPECT_EQ(initial_tab_count, tab_strip_model->active_index());
1210
1211     EXPECT_EQ(expected_login_tab_navigations,
1212               navigation_observer.NumNavigationsForTab(
1213                   tab_strip_model->GetWebContentsAt(initial_tab_count)));
1214     EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE,
1215               GetStateOfTabReloaderAt(browser, 1));
1216     EXPECT_TRUE(IsLoginTab(tab_strip_model->GetWebContentsAt(1)));
1217   } else {
1218     EXPECT_EQ(0, navigation_observer.num_navigations());
1219     EXPECT_EQ(initial_active_index, tab_strip_model->active_index());
1220     ASSERT_EQ(initial_tab_count, tab_strip_model->count());
1221     EXPECT_EQ(initial_active_index, tab_strip_model->active_index());
1222   }
1223
1224   // Wait for all the expect resource loads to actually start, so subsequent
1225   // functions can rely on them having started.
1226   URLRequestTimeoutOnDemandJob::WaitForJobs(initial_loading_tabs + 1);
1227
1228   EXPECT_EQ(initial_loading_tabs + 1, NumLoadingTabs());
1229   EXPECT_EQ(expected_broken_tabs, NumBrokenTabs());
1230   EXPECT_EQ(captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL,
1231             portal_observer.captive_portal_result());
1232   EXPECT_EQ(expected_portal_checks, portal_observer.num_results_received());
1233   EXPECT_FALSE(CheckPending(browser));
1234
1235   EXPECT_EQ(CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL,
1236             GetStateOfTabReloaderAt(browser, initial_active_index));
1237
1238   // Reset the load time to be large, so the timer won't trigger on a reload.
1239   SetSlowSSLLoadTime(tab_reloader, base::TimeDelta::FromHours(1));
1240 }
1241
1242 void CaptivePortalBrowserTest::FastTimeoutBehindCaptivePortal(
1243     Browser* browser,
1244     bool expect_open_login_tab) {
1245   FastErrorBehindCaptivePortal(browser,
1246                                expect_open_login_tab,
1247                                GURL(kMockHttpsQuickTimeoutUrl));
1248 }
1249
1250 void CaptivePortalBrowserTest::FastErrorBehindCaptivePortal(
1251     Browser* browser,
1252     bool expect_open_login_tab,
1253     const GURL& error_url) {
1254   TabStripModel* tab_strip_model = browser->tab_strip_model();
1255   // Calling this on a tab that's waiting for a load to manually be timed out
1256   // will result in a hang.
1257   ASSERT_FALSE(tab_strip_model->GetActiveWebContents()->IsLoading());
1258
1259   // Set the load time to be large, so the timer won't trigger.  The value is
1260   // not restored at the end of the function.
1261   CaptivePortalTabReloader* tab_reloader =
1262       GetTabReloader(tab_strip_model->GetActiveWebContents());
1263   ASSERT_TRUE(tab_reloader);
1264   SetSlowSSLLoadTime(tab_reloader, base::TimeDelta::FromHours(1));
1265
1266   // Number of tabs expected to be open after the captive portal checks
1267   // have completed.
1268   int initial_tab_count = tab_strip_model->count();
1269   int initial_active_index = tab_strip_model->active_index();
1270   int initial_loading_tabs = NumLoadingTabs();
1271   int expected_broken_tabs = NumBrokenTabs();
1272   if (CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL !=
1273           GetStateOfTabReloader(tab_strip_model->GetActiveWebContents())) {
1274     ++expected_broken_tabs;
1275   }
1276
1277   MultiNavigationObserver navigation_observer;
1278   CaptivePortalObserver portal_observer(browser->profile());
1279   ui_test_utils::NavigateToURLWithDisposition(browser,
1280                                               error_url,
1281                                               CURRENT_TAB,
1282                                               ui_test_utils::BROWSER_TEST_NONE);
1283   portal_observer.WaitForResults(1);
1284
1285   if (expect_open_login_tab) {
1286     navigation_observer.WaitForNavigations(2);
1287     ASSERT_EQ(initial_tab_count + 1, tab_strip_model->count());
1288     EXPECT_EQ(initial_tab_count, tab_strip_model->active_index());
1289     // Make sure that the originally active tab and the captive portal tab have
1290     // each loaded once.
1291     EXPECT_EQ(1, navigation_observer.NumNavigationsForTab(
1292                      tab_strip_model->GetWebContentsAt(initial_active_index)));
1293     EXPECT_EQ(1, navigation_observer.NumNavigationsForTab(
1294                      tab_strip_model->GetWebContentsAt(initial_tab_count)));
1295     EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE,
1296               GetStateOfTabReloaderAt(browser, 1));
1297     EXPECT_TRUE(IsLoginTab(tab_strip_model->GetWebContentsAt(1)));
1298   } else {
1299     navigation_observer.WaitForNavigations(1);
1300     EXPECT_EQ(initial_active_index, tab_strip_model->active_index());
1301     EXPECT_EQ(1, navigation_observer.NumNavigationsForTab(
1302                      tab_strip_model->GetWebContentsAt(initial_active_index)));
1303     ASSERT_EQ(initial_tab_count, tab_strip_model->count());
1304     EXPECT_EQ(initial_active_index, tab_strip_model->active_index());
1305   }
1306
1307   EXPECT_EQ(initial_loading_tabs, NumLoadingTabs());
1308   EXPECT_EQ(expected_broken_tabs, NumBrokenTabs());
1309   EXPECT_EQ(captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL,
1310             portal_observer.captive_portal_result());
1311   EXPECT_EQ(1, portal_observer.num_results_received());
1312   EXPECT_FALSE(CheckPending(browser));
1313
1314   EXPECT_EQ(CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL,
1315             GetStateOfTabReloaderAt(browser, initial_active_index));
1316 }
1317
1318 void CaptivePortalBrowserTest::NavigateLoginTab(Browser* browser,
1319                                                 int num_loading_tabs,
1320                                                 int num_timed_out_tabs) {
1321   MultiNavigationObserver navigation_observer;
1322   CaptivePortalObserver portal_observer(browser->profile());
1323
1324   TabStripModel* tab_strip_model = browser->tab_strip_model();
1325   int initial_tab_count = tab_strip_model->count();
1326   EXPECT_EQ(num_loading_tabs, NumLoadingTabs());
1327   EXPECT_EQ(num_timed_out_tabs, NumBrokenTabs() - NumLoadingTabs());
1328
1329   int login_tab_index = tab_strip_model->active_index();
1330   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE,
1331             GetStateOfTabReloader(tab_strip_model->GetActiveWebContents()));
1332   ASSERT_TRUE(IsLoginTab(browser->tab_strip_model()->GetActiveWebContents()));
1333
1334   // Do the navigation.
1335   content::RenderFrameHost* render_frame_host =
1336       tab_strip_model->GetActiveWebContents()->GetMainFrame();
1337   render_frame_host->ExecuteJavaScript(base::ASCIIToUTF16("submitForm()"));
1338
1339   portal_observer.WaitForResults(1);
1340   navigation_observer.WaitForNavigations(1);
1341
1342   // Check the captive portal result.
1343   EXPECT_EQ(captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL,
1344             portal_observer.captive_portal_result());
1345   EXPECT_EQ(1, portal_observer.num_results_received());
1346   EXPECT_FALSE(CheckPending(browser));
1347
1348   // Make sure not much has changed.
1349   EXPECT_EQ(initial_tab_count, tab_strip_model->count());
1350   EXPECT_EQ(num_loading_tabs, NumLoadingTabs());
1351   EXPECT_EQ(num_loading_tabs + num_timed_out_tabs, NumBrokenTabs());
1352   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE,
1353             GetStateOfTabReloaderAt(browser, login_tab_index));
1354   EXPECT_TRUE(IsLoginTab(tab_strip_model->GetWebContentsAt(login_tab_index)));
1355
1356   // Make sure there were no unexpected navigations.
1357   EXPECT_EQ(1, navigation_observer.NumNavigationsForTab(
1358                    tab_strip_model->GetWebContentsAt(login_tab_index)));
1359 }
1360
1361 void CaptivePortalBrowserTest::Login(Browser* browser,
1362                                      int num_loading_tabs,
1363                                      int num_timed_out_tabs) {
1364   // Simulate logging in.
1365   URLRequestMockCaptivePortalJobFactory::SetBehindCaptivePortal(false);
1366
1367   MultiNavigationObserver navigation_observer;
1368   CaptivePortalObserver portal_observer(browser->profile());
1369
1370   TabStripModel* tab_strip_model = browser->tab_strip_model();
1371   int initial_tab_count = tab_strip_model->count();
1372   ASSERT_EQ(num_loading_tabs, NumLoadingTabs());
1373   EXPECT_EQ(num_timed_out_tabs, NumBrokenTabs() - NumLoadingTabs());
1374
1375   // Verify that the login page is on top.
1376   int login_tab_index = tab_strip_model->active_index();
1377   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE,
1378             GetStateOfTabReloaderAt(browser, login_tab_index));
1379   ASSERT_TRUE(IsLoginTab(tab_strip_model->GetWebContentsAt(login_tab_index)));
1380
1381   // Trigger a navigation.
1382   content::RenderFrameHost* render_frame_host =
1383       tab_strip_model->GetActiveWebContents()->GetMainFrame();
1384   render_frame_host->ExecuteJavaScript(base::ASCIIToUTF16("submitForm()"));
1385
1386   portal_observer.WaitForResults(1);
1387
1388   // Wait for all the timed out tabs to reload.
1389   navigation_observer.WaitForNavigations(1 + num_timed_out_tabs);
1390   EXPECT_EQ(1, portal_observer.num_results_received());
1391
1392   // The tabs that were loading before should still be loading, and now be in
1393   // STATE_NEEDS_RELOAD.
1394   EXPECT_EQ(0, NumBrokenTabs());
1395   EXPECT_EQ(num_loading_tabs, NumLoadingTabs());
1396   EXPECT_EQ(num_loading_tabs, NumNeedReloadTabs());
1397
1398   // Make sure that the broken tabs have reloaded, and there's no more
1399   // captive portal tab.
1400   EXPECT_EQ(initial_tab_count, tab_strip_model->count());
1401   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE,
1402             GetStateOfTabReloaderAt(browser, login_tab_index));
1403   EXPECT_FALSE(IsLoginTab(tab_strip_model->GetWebContentsAt(login_tab_index)));
1404
1405   // Make sure there were no unexpected navigations of the login tab.
1406   EXPECT_EQ(1, navigation_observer.NumNavigationsForTab(
1407                    tab_strip_model->GetWebContentsAt(login_tab_index)));
1408 }
1409
1410 void CaptivePortalBrowserTest::FailLoadsAfterLogin(Browser* browser,
1411                                                    int num_loading_tabs) {
1412   ASSERT_EQ(num_loading_tabs, NumLoadingTabs());
1413   ASSERT_EQ(num_loading_tabs, NumNeedReloadTabs());
1414   EXPECT_EQ(0, NumBrokenTabs());
1415
1416   TabStripModel* tab_strip_model = browser->tab_strip_model();
1417   int initial_num_tabs = tab_strip_model->count();
1418   int initial_active_tab = tab_strip_model->active_index();
1419
1420   CaptivePortalObserver portal_observer(browser->profile());
1421   FailLoadsAfterLoginObserver fail_loads_observer;
1422   // Connection(s) finally time out.  There should have already been a call
1423   // to wait for the requests to be issued before logging on.
1424   URLRequestTimeoutOnDemandJob::WaitForJobs(num_loading_tabs);
1425   URLRequestTimeoutOnDemandJob::FailJobs(num_loading_tabs);
1426
1427   fail_loads_observer.WaitForNavigations();
1428
1429   // No captive portal checks should have ocurred or be pending, and there
1430   // should be no new tabs.
1431   EXPECT_EQ(0, portal_observer.num_results_received());
1432   EXPECT_FALSE(CheckPending(browser));
1433   EXPECT_EQ(initial_num_tabs, tab_strip_model->count());
1434
1435   EXPECT_EQ(initial_active_tab, tab_strip_model->active_index());
1436
1437   EXPECT_EQ(0, NumNeedReloadTabs());
1438   EXPECT_EQ(0, NumLoadingTabs());
1439 }
1440
1441 void CaptivePortalBrowserTest::FailLoadsWithoutLogin(Browser* browser,
1442                                                      int num_loading_tabs) {
1443   ASSERT_EQ(num_loading_tabs, NumLoadingTabs());
1444   ASSERT_EQ(0, NumNeedReloadTabs());
1445   EXPECT_EQ(num_loading_tabs, NumBrokenTabs());
1446
1447   TabStripModel* tab_strip_model = browser->tab_strip_model();
1448   int initial_num_tabs = tab_strip_model->count();
1449   int login_tab = tab_strip_model->active_index();
1450   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE,
1451             GetStateOfTabReloader(tab_strip_model->GetActiveWebContents()));
1452   ASSERT_TRUE(IsLoginTab(tab_strip_model->GetActiveWebContents()));
1453
1454   CaptivePortalObserver portal_observer(browser->profile());
1455   MultiNavigationObserver navigation_observer;
1456   // Connection(s) finally time out.  There should have already been a call
1457   // to wait for the requests to be issued.
1458   URLRequestTimeoutOnDemandJob::FailJobs(num_loading_tabs);
1459
1460   navigation_observer.WaitForNavigations(num_loading_tabs);
1461
1462   // No captive portal checks should have ocurred or be pending, and there
1463   // should be no new tabs.
1464   EXPECT_EQ(0, portal_observer.num_results_received());
1465   EXPECT_FALSE(CheckPending(browser));
1466   EXPECT_EQ(initial_num_tabs, tab_strip_model->count());
1467
1468   EXPECT_EQ(0, NumNeedReloadTabs());
1469   EXPECT_EQ(0, NumLoadingTabs());
1470   EXPECT_EQ(num_loading_tabs, NumBrokenTabs());
1471   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE,
1472             GetStateOfTabReloader(tab_strip_model->GetActiveWebContents()));
1473   EXPECT_TRUE(IsLoginTab(tab_strip_model->GetActiveWebContents()));
1474   EXPECT_EQ(login_tab, tab_strip_model->active_index());
1475
1476   EXPECT_EQ(0, navigation_observer.NumNavigationsForTab(
1477                    tab_strip_model->GetWebContentsAt(login_tab)));
1478 }
1479
1480 void CaptivePortalBrowserTest::RunNavigateLoadingTabToTimeoutTest(
1481     Browser* browser,
1482     const GURL& starting_url,
1483     const GURL& hanging_url,
1484     const GURL& timeout_url) {
1485   // Temporarily disable the captive portal and navigate to the starting
1486   // URL, which may be a URL that will hang when behind a captive portal.
1487   URLRequestMockCaptivePortalJobFactory::SetBehindCaptivePortal(false);
1488   NavigateToPageExpectNoTest(browser, starting_url, 1);
1489   URLRequestMockCaptivePortalJobFactory::SetBehindCaptivePortal(true);
1490
1491   // Go to the first hanging url.
1492   SlowLoadBehindCaptivePortal(browser, true, hanging_url, 1, 1);
1493
1494   // Abandon the request.
1495   URLRequestTimeoutOnDemandJob::WaitForJobs(1);
1496   URLRequestTimeoutOnDemandJob::AbandonJobs(1);
1497
1498   TabStripModel* tab_strip_model = browser->tab_strip_model();
1499   CaptivePortalTabReloader* tab_reloader =
1500       GetTabReloader(tab_strip_model->GetWebContentsAt(0));
1501   ASSERT_TRUE(tab_reloader);
1502
1503   // A non-zero delay makes it more likely that CaptivePortalTabHelper will
1504   // be confused by events relating to canceling the old navigation.
1505   SetSlowSSLLoadTime(tab_reloader, base::TimeDelta::FromSeconds(2));
1506   CaptivePortalObserver portal_observer(browser->profile());
1507
1508   // Navigate the error tab to another slow loading page.  Can't have
1509   // ui_test_utils do the navigation because it will wait for loading tabs to
1510   // stop loading before navigating.
1511   //
1512   // This may result in either 0 or 1 DidStopLoading events.  If there is one,
1513   // it must happen before the CaptivePortalService sends out its test request,
1514   // so waiting for PortalObserver to see that request prevents it from
1515   // confusing the MultiNavigationObservers used later.
1516   tab_strip_model->ActivateTabAt(0, true);
1517   browser->OpenURL(content::OpenURLParams(timeout_url,
1518                                           content::Referrer(),
1519                                           CURRENT_TAB,
1520                                           ui::PAGE_TRANSITION_TYPED,
1521                                           false));
1522   portal_observer.WaitForResults(1);
1523   EXPECT_FALSE(CheckPending(browser));
1524   EXPECT_EQ(1, NumLoadingTabs());
1525   EXPECT_EQ(CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL,
1526             GetStateOfTabReloaderAt(browser, 0));
1527   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE,
1528             GetStateOfTabReloaderAt(browser, 1));
1529   ASSERT_TRUE(IsLoginTab(tab_strip_model->GetWebContentsAt(1)));
1530
1531   // Need to make sure the request has been issued before logging in.
1532   URLRequestTimeoutOnDemandJob::WaitForJobs(1);
1533
1534   // Simulate logging in.
1535   tab_strip_model->ActivateTabAt(1, true);
1536   SetSlowSSLLoadTime(tab_reloader, base::TimeDelta::FromDays(1));
1537   Login(browser, 1, 0);
1538
1539   // Timeout occurs, and page is automatically reloaded.
1540   FailLoadsAfterLogin(browser, 1);
1541 }
1542
1543 void CaptivePortalBrowserTest::SetSlowSSLLoadTime(
1544     CaptivePortalTabReloader* tab_reloader,
1545     base::TimeDelta slow_ssl_load_time) {
1546   tab_reloader->set_slow_ssl_load_time(slow_ssl_load_time);
1547 }
1548
1549 CaptivePortalTabReloader* CaptivePortalBrowserTest::GetTabReloader(
1550     WebContents* web_contents) const {
1551   return CaptivePortalTabHelper::FromWebContents(web_contents)->
1552       GetTabReloaderForTest();
1553 }
1554
1555 // Make sure there's no test for a captive portal on HTTP timeouts.  This will
1556 // also trigger the link doctor page, which results in the load of a second
1557 // error page.
1558 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, HttpTimeout) {
1559   GURL url = URLRequestFailedJob::GetMockHttpUrl(net::ERR_CONNECTION_TIMED_OUT);
1560   NavigateToPageExpectNoTest(browser(), url, 2);
1561 }
1562
1563 // Make sure there's no check for a captive portal on HTTPS errors other than
1564 // timeouts, when they preempt the slow load timer.
1565 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, HttpsNonTimeoutError) {
1566   GURL url = URLRequestFailedJob::GetMockHttpsUrl(net::ERR_UNEXPECTED);
1567   NavigateToPageExpectNoTest(browser(), url, 1);
1568 }
1569
1570 // Make sure no captive portal test triggers on HTTPS timeouts of iframes.
1571 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, HttpsIframeTimeout) {
1572   // Use an HTTPS server for the top level page.
1573   net::SpawnedTestServer https_server(
1574       net::SpawnedTestServer::TYPE_HTTPS, net::SpawnedTestServer::kLocalhost,
1575       base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
1576   ASSERT_TRUE(https_server.Start());
1577
1578   GURL url = https_server.GetURL(kTestServerIframeTimeoutPath);
1579   NavigateToPageExpectNoTest(browser(), url, 1);
1580 }
1581
1582 // Check the captive portal result when the test request reports a network
1583 // error.  The check is triggered by a slow loading page, and the page
1584 // errors out only after getting a captive portal result.
1585 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, RequestFails) {
1586   SetUpCaptivePortalService(
1587       browser()->profile(),
1588       URLRequestFailedJob::GetMockHttpUrl(net::ERR_CONNECTION_CLOSED));
1589   SlowLoadNoCaptivePortal(browser(), captive_portal::RESULT_NO_RESPONSE);
1590 }
1591
1592 // Same as above, but for the rather unlikely case that the connection times out
1593 // before the timer triggers.
1594 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, RequestFailsFastTimout) {
1595   SetUpCaptivePortalService(
1596       browser()->profile(),
1597       URLRequestFailedJob::GetMockHttpUrl(net::ERR_CONNECTION_CLOSED));
1598   FastTimeoutNoCaptivePortal(browser(), captive_portal::RESULT_NO_RESPONSE);
1599 }
1600
1601 // Checks the case that captive portal detection is disabled.
1602 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, Disabled) {
1603   EnableCaptivePortalDetection(browser()->profile(), false);
1604   SlowLoadNoCaptivePortal(browser(), captive_portal::RESULT_INTERNET_CONNECTED);
1605 }
1606
1607 // Checks that we look for a captive portal on HTTPS timeouts and don't reload
1608 // the error tab when the captive portal probe gets a 204 response, indicating
1609 // there is no captive portal.
1610 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, InternetConnected) {
1611   // Can't just use SetBehindCaptivePortal(false), since then there wouldn't
1612   // be a timeout.
1613   ASSERT_TRUE(test_server()->Start());
1614   SetUpCaptivePortalService(browser()->profile(),
1615                             test_server()->GetURL("nocontent"));
1616   SlowLoadNoCaptivePortal(browser(), captive_portal::RESULT_INTERNET_CONNECTED);
1617 }
1618
1619 // Checks that no login page is opened when the HTTP test URL redirects to an
1620 // SSL certificate error.
1621 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, RedirectSSLCertError) {
1622   // Need an HTTP TestServer to handle a dynamically created server redirect.
1623   ASSERT_TRUE(test_server()->Start());
1624
1625   net::SpawnedTestServer::SSLOptions ssl_options;
1626   ssl_options.server_certificate =
1627       net::SpawnedTestServer::SSLOptions::CERT_MISMATCHED_NAME;
1628   net::SpawnedTestServer https_server(
1629       net::SpawnedTestServer::TYPE_HTTPS, ssl_options,
1630       base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
1631   ASSERT_TRUE(https_server.Start());
1632
1633   GURL ssl_login_url = https_server.GetURL(kTestServerLoginPath);
1634
1635   CaptivePortalService* captive_portal_service =
1636       CaptivePortalServiceFactory::GetForProfile(browser()->profile());
1637   ASSERT_TRUE(captive_portal_service);
1638   SetUpCaptivePortalService(
1639       browser()->profile(),
1640       test_server()->GetURL(CreateServerRedirect(ssl_login_url.spec())));
1641
1642   SlowLoadNoCaptivePortal(browser(), captive_portal::RESULT_NO_RESPONSE);
1643 }
1644
1645 // A slow SSL load triggers a captive portal check.  The user logs on before
1646 // the SSL page times out.  We wait for the timeout and subsequent reload.
1647 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, Login) {
1648   // Load starts, detect captive portal and open up a login tab.
1649   SlowLoadBehindCaptivePortal(browser(), true);
1650
1651   // Log in.  One loading tab, no timed out ones.
1652   Login(browser(), 1, 0);
1653
1654   // Timeout occurs, and page is automatically reloaded.
1655   FailLoadsAfterLogin(browser(), 1);
1656 }
1657
1658 // Same as above, except we make sure everything works with an incognito
1659 // profile.  Main issues it tests for are that the incognito has its own
1660 // non-NULL captive portal service, and we open the tab in the correct
1661 // window.
1662 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, LoginIncognito) {
1663   // This will watch tabs for both profiles, but only used to make sure no
1664   // navigations occur for the non-incognito profile.
1665   MultiNavigationObserver navigation_observer;
1666   CaptivePortalObserver non_incognito_portal_observer(browser()->profile());
1667
1668   Browser* incognito_browser = CreateIncognitoBrowser();
1669   EnableCaptivePortalDetection(incognito_browser->profile(), true);
1670   SetUpCaptivePortalService(incognito_browser->profile(),
1671                             GURL(kMockCaptivePortalTestUrl));
1672
1673   SlowLoadBehindCaptivePortal(incognito_browser, true);
1674
1675   TabStripModel* tab_strip_model = browser()->tab_strip_model();
1676   EXPECT_EQ(1, tab_strip_model->count());
1677   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE,
1678             GetStateOfTabReloaderAt(browser(), 0));
1679
1680   Login(incognito_browser, 1, 0);
1681   FailLoadsAfterLogin(incognito_browser, 1);
1682
1683   EXPECT_EQ(1, tab_strip_model->count());
1684   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE,
1685             GetStateOfTabReloaderAt(browser(), 0));
1686
1687   EXPECT_EQ(0, navigation_observer.NumNavigationsForTab(
1688                    tab_strip_model->GetWebContentsAt(0)));
1689   EXPECT_EQ(0, non_incognito_portal_observer.num_results_received());
1690 }
1691
1692 // The captive portal page is opened before the SSL page times out,
1693 // but the user logs in only after the page times out.
1694 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, LoginSlow) {
1695   SlowLoadBehindCaptivePortal(browser(), true);
1696   FailLoadsWithoutLogin(browser(), 1);
1697   Login(browser(), 0, 1);
1698 }
1699
1700 // Checks the unlikely case that the tab times out before the timer triggers.
1701 // This most likely won't happen, but should still work:
1702 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, LoginFastTimeout) {
1703   FastTimeoutBehindCaptivePortal(browser(), true);
1704   Login(browser(), 0, 1);
1705 }
1706
1707 // A cert error triggers a captive portal check and results in opening a login
1708 // tab.  The user then logs in and the page with the error is reloaded.
1709 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, SSLCertErrorLogin) {
1710   // Need an HTTP TestServer to handle a dynamically created server redirect.
1711   ASSERT_TRUE(test_server()->Start());
1712
1713   net::SpawnedTestServer::SSLOptions https_options;
1714   https_options.server_certificate =
1715       net::SpawnedTestServer::SSLOptions::CERT_MISMATCHED_NAME;
1716   net::SpawnedTestServer https_server(
1717       net::SpawnedTestServer::TYPE_HTTPS, https_options,
1718       base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
1719   ASSERT_TRUE(https_server.Start());
1720
1721   // The path does not matter.
1722   GURL cert_error_url = https_server.GetURL(kTestServerLoginPath);
1723   // The interstitial should trigger a captive portal check when it opens, just
1724   // like navigating to kMockHttpsQuickTimeoutUrl.
1725   FastErrorBehindCaptivePortal(browser(), true, cert_error_url);
1726
1727   // Simulate logging in.  Can't use Login() because the interstitial tab looks
1728   // like a cross between a hung tab (Load was never committed) and a tab at an
1729   // error page (The load was stopped).
1730   URLRequestMockCaptivePortalJobFactory::SetBehindCaptivePortal(false);
1731   MultiNavigationObserver navigation_observer;
1732   CaptivePortalObserver portal_observer(browser()->profile());
1733
1734   TabStripModel* tab_strip_model = browser()->tab_strip_model();
1735   content::RenderFrameHost* render_frame_host =
1736       tab_strip_model->GetActiveWebContents()->GetMainFrame();
1737   render_frame_host->ExecuteJavaScript(base::ASCIIToUTF16("submitForm()"));
1738
1739   // The captive portal tab navigation will trigger a captive portal check,
1740   // and reloading the original tab will bring up the interstitial page again,
1741   // triggering a second captive portal check.
1742   portal_observer.WaitForResults(2);
1743
1744   // Wait for both tabs to finish loading.
1745   navigation_observer.WaitForNavigations(2);
1746   EXPECT_EQ(2, portal_observer.num_results_received());
1747   EXPECT_FALSE(CheckPending(browser()));
1748   EXPECT_EQ(captive_portal::RESULT_INTERNET_CONNECTED,
1749             portal_observer.captive_portal_result());
1750
1751   // Check state of tabs.  While the first tab is still displaying an
1752   // interstitial page, since no portal was found, it should be in STATE_NONE,
1753   // as should the login tab.
1754   ASSERT_EQ(2, tab_strip_model->count());
1755   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE,
1756             GetStateOfTabReloaderAt(browser(), 0));
1757   EXPECT_FALSE(IsLoginTab(tab_strip_model->GetWebContentsAt(1)));
1758   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE,
1759             GetStateOfTabReloaderAt(browser(), 1));
1760
1761   // Make sure only one navigation was for the login tab.
1762   EXPECT_EQ(1, navigation_observer.NumNavigationsForTab(
1763                    tab_strip_model->GetWebContentsAt(1)));
1764 }
1765
1766 // Tries navigating both the tab that encounters an SSL timeout and the
1767 // login tab twice, only logging in the second time.
1768 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, LoginExtraNavigations) {
1769   FastTimeoutBehindCaptivePortal(browser(), true);
1770
1771   // Activate the timed out tab and navigate it to a timeout again.
1772   TabStripModel* tab_strip_model = browser()->tab_strip_model();
1773   tab_strip_model->ActivateTabAt(0, true);
1774   FastTimeoutBehindCaptivePortal(browser(), false);
1775
1776   // Activate and navigate the captive portal tab.  This should not trigger a
1777   // reload of the tab with the error.
1778   tab_strip_model->ActivateTabAt(1, true);
1779   NavigateLoginTab(browser(), 0, 1);
1780
1781   // Simulate logging in.
1782   Login(browser(), 0, 1);
1783 }
1784
1785 // After the first SSL timeout, closes the login tab and makes sure it's opened
1786 // it again on a second timeout.
1787 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, CloseLoginTab) {
1788   // First load starts, opens a login tab, and then times out.
1789   SlowLoadBehindCaptivePortal(browser(), true);
1790   FailLoadsWithoutLogin(browser(), 1);
1791
1792   // Close login tab.
1793   chrome::CloseTab(browser());
1794
1795   // Go through the standard slow load login, and make sure it still works.
1796   SlowLoadBehindCaptivePortal(browser(), true);
1797   Login(browser(), 1, 0);
1798   FailLoadsAfterLogin(browser(), 1);
1799 }
1800
1801 // Checks that two tabs with SSL timeouts in the same window work.  Both
1802 // tabs only timeout after logging in.
1803 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, TwoBrokenTabs) {
1804   SlowLoadBehindCaptivePortal(browser(), true);
1805
1806   // Can't set the TabReloader HTTPS timeout on a new tab without doing some
1807   // acrobatics, so open a new tab at a normal page, and then navigate it to a
1808   // timeout.
1809   MultiNavigationObserver navigation_observer;
1810   CaptivePortalObserver portal_observer(browser()->profile());
1811   ui_test_utils::NavigateToURLWithDisposition(
1812       browser(),
1813       URLRequestMockHTTPJob::GetMockUrl(
1814           base::FilePath(FILE_PATH_LITERAL("title2.html"))),
1815       NEW_FOREGROUND_TAB,
1816       ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
1817
1818   TabStripModel* tab_strip_model = browser()->tab_strip_model();
1819   ASSERT_EQ(3, tab_strip_model->count());
1820   EXPECT_FALSE(CheckPending(browser()));
1821   EXPECT_EQ(0, portal_observer.num_results_received());
1822   EXPECT_EQ(1, NumLoadingTabs());
1823   EXPECT_EQ(1, navigation_observer.num_navigations());
1824   EXPECT_EQ(1, navigation_observer.NumNavigationsForTab(
1825                    tab_strip_model->GetWebContentsAt(2)));
1826   ASSERT_EQ(CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL,
1827             GetStateOfTabReloaderAt(browser(), 0));
1828   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE,
1829             GetStateOfTabReloaderAt(browser(), 1));
1830   ASSERT_TRUE(IsLoginTab(tab_strip_model->GetWebContentsAt(1)));
1831   ASSERT_EQ(CaptivePortalTabReloader::STATE_NONE,
1832             GetStateOfTabReloaderAt(browser(), 2));
1833   ASSERT_EQ(2, tab_strip_model->active_index());
1834
1835   SlowLoadBehindCaptivePortal(browser(), false);
1836
1837   tab_strip_model->ActivateTabAt(1, true);
1838   Login(browser(), 2, 0);
1839   FailLoadsAfterLogin(browser(), 2);
1840 }
1841
1842 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, AbortLoad) {
1843   SlowLoadBehindCaptivePortal(browser(), true);
1844
1845   // Abandon the request.
1846   URLRequestTimeoutOnDemandJob::WaitForJobs(1);
1847   URLRequestTimeoutOnDemandJob::AbandonJobs(1);
1848
1849   CaptivePortalObserver portal_observer(browser()->profile());
1850   MultiNavigationObserver navigation_observer;
1851
1852   // Switch back to the hung tab from the login tab, and abort the navigation.
1853   TabStripModel* tab_strip_model = browser()->tab_strip_model();
1854   tab_strip_model->ActivateTabAt(0, true);
1855   chrome::Stop(browser());
1856   navigation_observer.WaitForNavigations(1);
1857
1858   EXPECT_EQ(0, NumBrokenTabs());
1859   EXPECT_EQ(0, portal_observer.num_results_received());
1860   EXPECT_FALSE(CheckPending(browser()));
1861   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE,
1862             GetStateOfTabReloaderAt(browser(), 0));
1863
1864   tab_strip_model->ActivateTabAt(1, true);
1865   Login(browser(), 0, 0);
1866 }
1867
1868 // Checks the case where the timed out tab is successfully navigated before
1869 // logging in.
1870 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, NavigateBrokenTab) {
1871   // Go to the error page.
1872   SlowLoadBehindCaptivePortal(browser(), true);
1873   FailLoadsWithoutLogin(browser(), 1);
1874
1875   // Navigate the error tab to a non-error page.
1876   TabStripModel* tab_strip_model = browser()->tab_strip_model();
1877   tab_strip_model->ActivateTabAt(0, true);
1878   ui_test_utils::NavigateToURL(
1879       browser(), URLRequestMockHTTPJob::GetMockUrl(
1880                      base::FilePath(FILE_PATH_LITERAL("title2.html"))));
1881   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE,
1882             GetStateOfTabReloaderAt(browser(), 0));
1883
1884   // Simulate logging in.
1885   tab_strip_model->ActivateTabAt(1, true);
1886   Login(browser(), 0, 0);
1887 }
1888
1889 // Checks that captive portal detection triggers correctly when a same-site
1890 // navigation is cancelled by a navigation to the same site.
1891 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest,
1892                        NavigateLoadingTabToTimeoutSingleSite) {
1893   RunNavigateLoadingTabToTimeoutTest(
1894       browser(),
1895       GURL(kMockHttpsUrl),
1896       GURL(kMockHttpsUrl),
1897       GURL(kMockHttpsUrl));
1898 }
1899
1900 // Fails on Windows only, mostly on Win7. http://crbug.com/170033
1901 #if defined(OS_WIN)
1902 #define MAYBE_NavigateLoadingTabToTimeoutTwoSites \
1903         DISABLED_NavigateLoadingTabToTimeoutTwoSites
1904 #else
1905 #define MAYBE_NavigateLoadingTabToTimeoutTwoSites \
1906         NavigateLoadingTabToTimeoutTwoSites
1907 #endif
1908
1909 // Checks that captive portal detection triggers correctly when a same-site
1910 // navigation is cancelled by a navigation to another site.
1911 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest,
1912                        MAYBE_NavigateLoadingTabToTimeoutTwoSites) {
1913   RunNavigateLoadingTabToTimeoutTest(
1914       browser(),
1915       GURL(kMockHttpsUrl),
1916       GURL(kMockHttpsUrl),
1917       GURL(kMockHttpsUrl2));
1918 }
1919
1920 // Checks that captive portal detection triggers correctly when a cross-site
1921 // navigation is cancelled by a navigation to yet another site.
1922 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest,
1923                        NavigateLoadingTabToTimeoutThreeSites) {
1924   RunNavigateLoadingTabToTimeoutTest(
1925       browser(),
1926       URLRequestMockHTTPJob::GetMockUrl(
1927           base::FilePath(FILE_PATH_LITERAL("title.html"))),
1928       GURL(kMockHttpsUrl),
1929       GURL(kMockHttpsUrl2));
1930 }
1931
1932 // Checks that navigating a timed out tab back clears its state.
1933 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, GoBack) {
1934   // Navigate to a working page.
1935   ui_test_utils::NavigateToURL(
1936       browser(),
1937       URLRequestMockHTTPJob::GetMockUrl(
1938           base::FilePath(FILE_PATH_LITERAL("title2.html"))));
1939
1940   // Go to the error page.
1941   SlowLoadBehindCaptivePortal(browser(), true);
1942   FailLoadsWithoutLogin(browser(), 1);
1943
1944   CaptivePortalObserver portal_observer(browser()->profile());
1945   MultiNavigationObserver navigation_observer;
1946
1947   // Activate the error page tab again and go back.
1948   TabStripModel* tab_strip_model = browser()->tab_strip_model();
1949   tab_strip_model->ActivateTabAt(0, true);
1950   chrome::GoBack(browser(), CURRENT_TAB);
1951   navigation_observer.WaitForNavigations(1);
1952
1953   EXPECT_EQ(1, navigation_observer.NumNavigationsForTab(
1954                    tab_strip_model->GetWebContentsAt(0)));
1955   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE,
1956             GetStateOfTabReloaderAt(browser(), 0));
1957   EXPECT_EQ(0, portal_observer.num_results_received());
1958 }
1959
1960 // Checks that navigating back to a timeout triggers captive portal detection.
1961 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, GoBackToTimeout) {
1962   // Disable captive portal detection so the first navigation doesn't open a
1963   // login tab.
1964   EnableCaptivePortalDetection(browser()->profile(), false);
1965
1966   SlowLoadNoCaptivePortal(browser(), captive_portal::RESULT_INTERNET_CONNECTED);
1967
1968   // Navigate to a working page.
1969   ui_test_utils::NavigateToURL(
1970       browser(), URLRequestMockHTTPJob::GetMockUrl(
1971                      base::FilePath(FILE_PATH_LITERAL("title2.html"))));
1972   ASSERT_EQ(CaptivePortalTabReloader::STATE_NONE,
1973             GetStateOfTabReloaderAt(browser(), 0));
1974
1975   EnableCaptivePortalDetection(browser()->profile(), true);
1976
1977   TabStripModel* tab_strip_model = browser()->tab_strip_model();
1978   CaptivePortalTabReloader* tab_reloader =
1979       GetTabReloader(tab_strip_model->GetActiveWebContents());
1980   ASSERT_TRUE(tab_reloader);
1981   SetSlowSSLLoadTime(tab_reloader, base::TimeDelta());
1982
1983   // Go to the error page.
1984   MultiNavigationObserver navigation_observer;
1985   CaptivePortalObserver portal_observer(browser()->profile());
1986   chrome::GoBack(browser(), CURRENT_TAB);
1987
1988   // Wait for the check triggered by the broken tab and for the login tab to
1989   // stop loading.
1990   portal_observer.WaitForResults(1);
1991   navigation_observer.WaitForNavigations(1);
1992   // Make sure the request has been issued.
1993   URLRequestTimeoutOnDemandJob::WaitForJobs(1);
1994
1995   EXPECT_EQ(1, portal_observer.num_results_received());
1996   ASSERT_FALSE(CheckPending(browser()));
1997   ASSERT_EQ(captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL,
1998             portal_observer.captive_portal_result());
1999
2000   ASSERT_EQ(CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL,
2001             GetStateOfTabReloaderAt(browser(), 0));
2002   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE,
2003             GetStateOfTabReloaderAt(browser(), 1));
2004   ASSERT_TRUE(IsLoginTab(browser()->tab_strip_model()->GetWebContentsAt(1)));
2005
2006   ASSERT_EQ(2, tab_strip_model->count());
2007   EXPECT_EQ(1, tab_strip_model->active_index());
2008   EXPECT_EQ(1, navigation_observer.NumNavigationsForTab(
2009                    tab_strip_model->GetWebContentsAt(1)));
2010   EXPECT_EQ(1, NumLoadingTabs());
2011
2012   SetSlowSSLLoadTime(tab_reloader, base::TimeDelta::FromDays(1));
2013   Login(browser(), 1, 0);
2014   FailLoadsAfterLogin(browser(), 1);
2015 }
2016
2017 // Checks that reloading a timeout triggers captive portal detection.
2018 // Much like the last test, though the captive portal is disabled before
2019 // the inital navigation, rather than captive portal detection.
2020 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, ReloadTimeout) {
2021   URLRequestMockCaptivePortalJobFactory::SetBehindCaptivePortal(false);
2022
2023   // Do the first navigation while not behind a captive portal.
2024   TabStripModel* tab_strip_model = browser()->tab_strip_model();
2025   CaptivePortalObserver portal_observer(browser()->profile());
2026   ui_test_utils::NavigateToURL(browser(), GURL(kMockHttpsUrl));
2027   ASSERT_EQ(0, portal_observer.num_results_received());
2028   ASSERT_EQ(1, tab_strip_model->count());
2029
2030   // A captive portal spontaneously appears.
2031   URLRequestMockCaptivePortalJobFactory::SetBehindCaptivePortal(true);
2032
2033   CaptivePortalTabReloader* tab_reloader =
2034       GetTabReloader(tab_strip_model->GetActiveWebContents());
2035   ASSERT_TRUE(tab_reloader);
2036   SetSlowSSLLoadTime(tab_reloader, base::TimeDelta());
2037
2038   MultiNavigationObserver navigation_observer;
2039   tab_strip_model->GetActiveWebContents()->GetController().Reload(true);
2040
2041   // Wait for the check triggered by the broken tab and for the login tab to
2042   // stop loading.
2043   portal_observer.WaitForResults(1);
2044   navigation_observer.WaitForNavigations(1);
2045   // Make sure the request has been issued.
2046   URLRequestTimeoutOnDemandJob::WaitForJobs(1);
2047
2048   ASSERT_EQ(1, portal_observer.num_results_received());
2049   ASSERT_FALSE(CheckPending(browser()));
2050   ASSERT_EQ(captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL,
2051             portal_observer.captive_portal_result());
2052
2053   ASSERT_EQ(CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL,
2054             GetStateOfTabReloaderAt(browser(), 0));
2055   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE,
2056             GetStateOfTabReloaderAt(browser(), 1));
2057   ASSERT_TRUE(IsLoginTab(tab_strip_model->GetWebContentsAt(1)));
2058
2059   ASSERT_EQ(2, tab_strip_model->count());
2060   EXPECT_EQ(1, tab_strip_model->active_index());
2061   EXPECT_EQ(1, navigation_observer.NumNavigationsForTab(
2062                    tab_strip_model->GetWebContentsAt(1)));
2063   EXPECT_EQ(1, NumLoadingTabs());
2064
2065   SetSlowSSLLoadTime(tab_reloader, base::TimeDelta::FromDays(1));
2066   Login(browser(), 1, 0);
2067   FailLoadsAfterLogin(browser(), 1);
2068 }
2069
2070 // Checks the case where there are two windows, and there's an SSL timeout in
2071 // the background one.
2072 // Disabled:  http://crbug.com/134357
2073 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, DISABLED_TwoWindows) {
2074   Browser* browser2 =
2075       new Browser(Browser::CreateParams(browser()->profile(),
2076                                         browser()->host_desktop_type()));
2077   // Navigate the new browser window so it'll be shown and we can pick the
2078   // active window.
2079   ui_test_utils::NavigateToURL(browser2, GURL(url::kAboutBlankURL));
2080
2081   // Generally, |browser2| will be the active window.  However, if the
2082   // original browser window lost focus before creating the new one, such as
2083   // when running multiple tests at once, the original browser window may
2084   // remain the profile's active window.
2085   Browser* active_browser =
2086       chrome::FindTabbedBrowser(browser()->profile(), true,
2087                                 browser()->host_desktop_type());
2088   Browser* inactive_browser;
2089   if (active_browser == browser2) {
2090     // When only one test is running at a time, the new browser will probably be
2091     // on top, but when multiple tests are running at once, this is not
2092     // guaranteed.
2093     inactive_browser = browser();
2094   } else {
2095     ASSERT_EQ(active_browser, browser());
2096     inactive_browser = browser2;
2097   }
2098
2099   CaptivePortalObserver portal_observer(browser()->profile());
2100   MultiNavigationObserver navigation_observer;
2101
2102   // Navigate the tab in the inactive browser to an SSL timeout.  Have to use
2103   // chrome::NavigateParams and NEW_BACKGROUND_TAB to avoid activating the
2104   // window.
2105   chrome::NavigateParams params(inactive_browser,
2106                                 GURL(kMockHttpsQuickTimeoutUrl),
2107                                 ui::PAGE_TRANSITION_TYPED);
2108   params.disposition = NEW_BACKGROUND_TAB;
2109   params.window_action = chrome::NavigateParams::NO_ACTION;
2110   ui_test_utils::NavigateToURL(&params);
2111   navigation_observer.WaitForNavigations(2);
2112
2113   // Make sure the active window hasn't changed, and its new tab is
2114   // active.
2115   ASSERT_EQ(active_browser,
2116             chrome::FindTabbedBrowser(browser()->profile(), true,
2117                                       browser()->host_desktop_type()));
2118   ASSERT_EQ(1, active_browser->tab_strip_model()->active_index());
2119
2120   // Check that the only two navigated tabs were the new error tab in the
2121   // backround windows, and the login tab in the active window.
2122   EXPECT_EQ(1, navigation_observer.NumNavigationsForTab(
2123                    inactive_browser->tab_strip_model()->GetWebContentsAt(1)));
2124   EXPECT_EQ(1, navigation_observer.NumNavigationsForTab(
2125                    active_browser->tab_strip_model()->GetWebContentsAt(1)));
2126   EXPECT_EQ(0, NumLoadingTabs());
2127
2128   // Check captive portal test results.
2129   portal_observer.WaitForResults(1);
2130   ASSERT_EQ(captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL,
2131             portal_observer.captive_portal_result());
2132   EXPECT_EQ(1, portal_observer.num_results_received());
2133
2134   // Check the inactive browser.
2135   EXPECT_EQ(2, inactive_browser->tab_strip_model()->count());
2136   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE,
2137             GetStateOfTabReloaderAt(inactive_browser, 0));
2138   EXPECT_EQ(CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL,
2139             GetStateOfTabReloaderAt(inactive_browser, 1));
2140
2141   // Check the active browser.
2142   ASSERT_EQ(2, active_browser->tab_strip_model()->count());
2143   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE,
2144             GetStateOfTabReloaderAt(active_browser, 0));
2145   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE,
2146             GetStateOfTabReloaderAt(active_browser, 1));
2147   EXPECT_TRUE(
2148       IsLoginTab(active_browser->tab_strip_model()->GetWebContentsAt(1)));
2149
2150   // Simulate logging in.
2151   Login(active_browser, 0, 1);
2152 }
2153
2154 // An HTTP page redirects to an HTTPS page loads slowly before timing out.  A
2155 // captive portal is found, and then the user logs in before the original page
2156 // times out.
2157 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, HttpToHttpsRedirectLogin) {
2158   ASSERT_TRUE(test_server()->Start());
2159   SlowLoadBehindCaptivePortal(
2160       browser(),
2161       true,
2162       test_server()->GetURL(CreateServerRedirect(kMockHttpsUrl)),
2163       1,
2164       1);
2165   Login(browser(), 1, 0);
2166   FailLoadsAfterLogin(browser(), 1);
2167 }
2168
2169 // An HTTPS page redirects to an HTTP page.
2170 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, HttpsToHttpRedirect) {
2171   // Use an HTTPS server for the top level page.
2172   net::SpawnedTestServer https_server(
2173       net::SpawnedTestServer::TYPE_HTTPS, net::SpawnedTestServer::kLocalhost,
2174       base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
2175   ASSERT_TRUE(https_server.Start());
2176
2177   GURL http_timeout_url =
2178       URLRequestFailedJob::GetMockHttpUrl(net::ERR_CONNECTION_TIMED_OUT);
2179
2180   // 2 navigations due to the Link Doctor.
2181   NavigateToPageExpectNoTest(
2182       browser(),
2183       https_server.GetURL(CreateServerRedirect(http_timeout_url.spec())),
2184       2);
2185 }
2186
2187 // Tests the 511 response code, along with an HTML redirect to a login page.
2188 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, Status511) {
2189   SetUpCaptivePortalService(browser()->profile(),
2190                             GURL(kMockCaptivePortal511Url));
2191   SlowLoadBehindCaptivePortal(browser(), true, GURL(kMockHttpsUrl), 2, 2);
2192   Login(browser(), 1, 0);
2193   FailLoadsAfterLogin(browser(), 1);
2194 }
2195
2196 // HSTS redirects an HTTP request to HTTPS, and the request then times out.
2197 // A captive portal is then detected, and a login tab opened, before logging
2198 // in.
2199 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, HstsLogin) {
2200   GURL::Replacements replacements;
2201   std::string scheme = "http";
2202   replacements.SetSchemeStr(scheme);
2203   GURL http_timeout_url = GURL(kMockHttpsUrl).ReplaceComponents(replacements);
2204
2205   URLRequestFailedJob::GetMockHttpUrl(net::ERR_CONNECTION_TIMED_OUT);
2206   content::BrowserThread::PostTask(
2207       content::BrowserThread::IO, FROM_HERE,
2208       base::Bind(&AddHstsHost,
2209                  make_scoped_refptr(browser()->profile()->GetRequestContext()),
2210                  http_timeout_url.host()));
2211
2212   SlowLoadBehindCaptivePortal(browser(), true, http_timeout_url, 1, 1);
2213   Login(browser(), 1, 0);
2214   FailLoadsAfterLogin(browser(), 1);
2215 }