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