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