Home | History | Annotate | Download | only in captive_portal
      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
   2207