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