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 "chrome/browser/captive_portal/captive_portal_tab_reloader.h"
      6 
      7 #include "base/callback.h"
      8 #include "base/message_loop/message_loop.h"
      9 #include "chrome/browser/captive_portal/captive_portal_service.h"
     10 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
     11 #include "content/public/browser/browser_thread.h"
     12 #include "content/public/browser/interstitial_page.h"
     13 #include "content/public/browser/interstitial_page_delegate.h"
     14 #include "content/public/browser/web_contents.h"
     15 #include "net/base/net_errors.h"
     16 #include "net/cert/cert_status_flags.h"
     17 #include "net/ssl/ssl_info.h"
     18 #include "testing/gmock/include/gmock/gmock.h"
     19 #include "testing/gtest/include/gtest/gtest.h"
     20 #include "url/gurl.h"
     21 
     22 namespace captive_portal {
     23 
     24 // Used for testing CaptivePortalTabReloader in isolation from the observer.
     25 // Exposes a number of private functions and mocks out others.
     26 class TestCaptivePortalTabReloader : public CaptivePortalTabReloader {
     27  public:
     28   explicit TestCaptivePortalTabReloader(content::WebContents* web_contents)
     29       : CaptivePortalTabReloader(NULL,
     30                                  web_contents,
     31                                  base::Callback<void(void)>()) {
     32   }
     33 
     34   virtual ~TestCaptivePortalTabReloader() {
     35   }
     36 
     37   bool TimerRunning() {
     38     return slow_ssl_load_timer_.IsRunning();
     39   }
     40 
     41   // The following methods are aliased so they can be publicly accessed by the
     42   // unit tests.
     43 
     44   State state() const {
     45     return CaptivePortalTabReloader::state();
     46   }
     47 
     48   void set_slow_ssl_load_time(base::TimeDelta slow_ssl_load_time) {
     49     EXPECT_FALSE(TimerRunning());
     50     CaptivePortalTabReloader::set_slow_ssl_load_time(slow_ssl_load_time);
     51   }
     52 
     53   // CaptivePortalTabReloader:
     54   MOCK_METHOD0(ReloadTab, void());
     55   MOCK_METHOD0(MaybeOpenCaptivePortalLoginTab, void());
     56   MOCK_METHOD0(CheckForCaptivePortal, void());
     57 
     58  private:
     59   DISALLOW_COPY_AND_ASSIGN(TestCaptivePortalTabReloader);
     60 };
     61 
     62 // Used to test behavior when a WebContents is showing an interstitial page.
     63 class MockInterstitialPageDelegate : public content::InterstitialPageDelegate {
     64  public:
     65   // The newly created MockInterstitialPageDelegate will be owned by the
     66   // WebContents' InterstitialPage, and cleaned up when the WebContents
     67   // destroys it.
     68   explicit MockInterstitialPageDelegate(
     69       content::WebContents* web_contents) {
     70     content::InterstitialPage* interstitial_page =
     71         content::InterstitialPage::Create(
     72             web_contents, true, GURL("http://blah"), this);
     73     interstitial_page->DontCreateViewForTesting();
     74     interstitial_page->Show();
     75   }
     76 
     77   virtual ~MockInterstitialPageDelegate() {
     78   }
     79 
     80  private:
     81   // InterstitialPageDelegate implementation:
     82   virtual std::string GetHTMLContents() OVERRIDE {
     83     return "HTML Contents";
     84   }
     85 
     86   DISALLOW_COPY_AND_ASSIGN(MockInterstitialPageDelegate);
     87 };
     88 
     89 class CaptivePortalTabReloaderTest : public ChromeRenderViewHostTestHarness {
     90  public:
     91   // testing::Test:
     92   virtual void SetUp() OVERRIDE {
     93     ChromeRenderViewHostTestHarness::SetUp();
     94     tab_reloader_.reset(new testing::StrictMock<TestCaptivePortalTabReloader>(
     95         web_contents()));
     96 
     97     // Most tests don't run the message loop, so don't use a timer for them.
     98     tab_reloader_->set_slow_ssl_load_time(base::TimeDelta());
     99   }
    100 
    101   virtual void TearDown() OVERRIDE {
    102     EXPECT_FALSE(tab_reloader().TimerRunning());
    103     tab_reloader_.reset(NULL);
    104     ChromeRenderViewHostTestHarness::TearDown();
    105   }
    106 
    107   TestCaptivePortalTabReloader& tab_reloader() { return *tab_reloader_.get(); }
    108 
    109  private:
    110   scoped_ptr<TestCaptivePortalTabReloader> tab_reloader_;
    111 };
    112 
    113 // Simulates a slow SSL load when the Internet is connected.
    114 TEST_F(CaptivePortalTabReloaderTest, InternetConnected) {
    115   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, tab_reloader().state());
    116 
    117   tab_reloader().OnLoadStart(true);
    118   EXPECT_EQ(CaptivePortalTabReloader::STATE_TIMER_RUNNING,
    119             tab_reloader().state());
    120   EXPECT_TRUE(tab_reloader().TimerRunning());
    121 
    122   EXPECT_CALL(tab_reloader(), CheckForCaptivePortal()).Times(1);
    123   base::MessageLoop::current()->RunUntilIdle();
    124   EXPECT_FALSE(tab_reloader().TimerRunning());
    125   EXPECT_EQ(CaptivePortalTabReloader::STATE_MAYBE_BROKEN_BY_PORTAL,
    126             tab_reloader().state());
    127 
    128   tab_reloader().OnCaptivePortalResults(RESULT_INTERNET_CONNECTED,
    129                                         RESULT_INTERNET_CONNECTED);
    130 
    131   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, tab_reloader().state());
    132   EXPECT_FALSE(tab_reloader().TimerRunning());
    133 
    134   tab_reloader().OnLoadCommitted(net::OK);
    135   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, tab_reloader().state());
    136 }
    137 
    138 // Simulates a slow SSL load when the Internet is connected.  In this case,
    139 // the timeout error occurs before the timer triggers.  Unlikely to happen
    140 // in practice, but best if it still works.
    141 TEST_F(CaptivePortalTabReloaderTest, InternetConnectedTimeout) {
    142   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, tab_reloader().state());
    143 
    144   tab_reloader().OnLoadStart(true);
    145   EXPECT_EQ(CaptivePortalTabReloader::STATE_TIMER_RUNNING,
    146             tab_reloader().state());
    147   EXPECT_TRUE(tab_reloader().TimerRunning());
    148 
    149   EXPECT_CALL(tab_reloader(), CheckForCaptivePortal()).Times(1);
    150   tab_reloader().OnLoadCommitted(net::ERR_CONNECTION_TIMED_OUT);
    151   EXPECT_FALSE(tab_reloader().TimerRunning());
    152   EXPECT_EQ(CaptivePortalTabReloader::STATE_MAYBE_BROKEN_BY_PORTAL,
    153             tab_reloader().state());
    154 
    155   tab_reloader().OnCaptivePortalResults(RESULT_INTERNET_CONNECTED,
    156                                         RESULT_INTERNET_CONNECTED);
    157 
    158   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, tab_reloader().state());
    159 }
    160 
    161 // Simulates a slow SSL load when captive portal checks return no response.
    162 TEST_F(CaptivePortalTabReloaderTest, NoResponse) {
    163   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, tab_reloader().state());
    164 
    165   tab_reloader().OnLoadStart(true);
    166   EXPECT_EQ(CaptivePortalTabReloader::STATE_TIMER_RUNNING,
    167             tab_reloader().state());
    168   EXPECT_TRUE(tab_reloader().TimerRunning());
    169 
    170   EXPECT_CALL(tab_reloader(), CheckForCaptivePortal()).Times(1);
    171   base::MessageLoop::current()->RunUntilIdle();
    172   EXPECT_FALSE(tab_reloader().TimerRunning());
    173   EXPECT_EQ(CaptivePortalTabReloader::STATE_MAYBE_BROKEN_BY_PORTAL,
    174             tab_reloader().state());
    175 
    176   tab_reloader().OnCaptivePortalResults(RESULT_NO_RESPONSE, RESULT_NO_RESPONSE);
    177 
    178   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, tab_reloader().state());
    179   EXPECT_FALSE(tab_reloader().TimerRunning());
    180 
    181   tab_reloader().OnLoadCommitted(net::OK);
    182   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, tab_reloader().state());
    183 }
    184 
    185 // Simulates a slow HTTP load when behind a captive portal, that eventually.
    186 // tiems out.  Since it's HTTP, the TabReloader should do nothing.
    187 TEST_F(CaptivePortalTabReloaderTest, DoesNothingOnHttp) {
    188   tab_reloader().OnLoadStart(false);
    189   EXPECT_FALSE(tab_reloader().TimerRunning());
    190   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, tab_reloader().state());
    191 
    192   tab_reloader().OnCaptivePortalResults(RESULT_INTERNET_CONNECTED,
    193                                         RESULT_BEHIND_CAPTIVE_PORTAL);
    194   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, tab_reloader().state());
    195 
    196   // The user logs in.
    197   tab_reloader().OnCaptivePortalResults(RESULT_BEHIND_CAPTIVE_PORTAL,
    198                                         RESULT_INTERNET_CONNECTED);
    199   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, tab_reloader().state());
    200 
    201   // The page times out.
    202   tab_reloader().OnLoadCommitted(net::ERR_CONNECTION_TIMED_OUT);
    203   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, tab_reloader().state());
    204 }
    205 
    206 // Simulate the normal login process.  The user logs in before the error page
    207 // in the original tab commits.
    208 TEST_F(CaptivePortalTabReloaderTest, Login) {
    209   tab_reloader().OnLoadStart(true);
    210 
    211   EXPECT_CALL(tab_reloader(), CheckForCaptivePortal()).Times(1);
    212   base::MessageLoop::current()->RunUntilIdle();
    213   EXPECT_FALSE(tab_reloader().TimerRunning());
    214   EXPECT_EQ(CaptivePortalTabReloader::STATE_MAYBE_BROKEN_BY_PORTAL,
    215             tab_reloader().state());
    216 
    217   // The captive portal service detects a captive portal.  The TabReloader
    218   // should try and create a new login tab in response.
    219   EXPECT_CALL(tab_reloader(), MaybeOpenCaptivePortalLoginTab()).Times(1);
    220   tab_reloader().OnCaptivePortalResults(RESULT_INTERNET_CONNECTED,
    221                                         RESULT_BEHIND_CAPTIVE_PORTAL);
    222   EXPECT_EQ(CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL,
    223             tab_reloader().state());
    224   EXPECT_FALSE(tab_reloader().TimerRunning());
    225 
    226   // The user logs on from another tab, and a captive portal check is triggered.
    227   tab_reloader().OnCaptivePortalResults(RESULT_BEHIND_CAPTIVE_PORTAL,
    228                                         RESULT_INTERNET_CONNECTED);
    229   EXPECT_EQ(CaptivePortalTabReloader::STATE_NEEDS_RELOAD,
    230             tab_reloader().state());
    231 
    232   // The error page commits, which should start an asynchronous reload.
    233   tab_reloader().OnLoadCommitted(net::ERR_CONNECTION_TIMED_OUT);
    234   EXPECT_EQ(CaptivePortalTabReloader::STATE_NEEDS_RELOAD,
    235             tab_reloader().state());
    236 
    237   EXPECT_CALL(tab_reloader(), ReloadTab()).Times(1);
    238   base::MessageLoop::current()->RunUntilIdle();
    239   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, tab_reloader().state());
    240 }
    241 
    242 // Simulate the normal login process.  The user logs in after the tab finishes
    243 // loading the error page.
    244 TEST_F(CaptivePortalTabReloaderTest, LoginLate) {
    245   tab_reloader().OnLoadStart(true);
    246 
    247   EXPECT_CALL(tab_reloader(), CheckForCaptivePortal()).Times(1);
    248   base::MessageLoop::current()->RunUntilIdle();
    249   EXPECT_FALSE(tab_reloader().TimerRunning());
    250   EXPECT_EQ(CaptivePortalTabReloader::STATE_MAYBE_BROKEN_BY_PORTAL,
    251             tab_reloader().state());
    252 
    253   // The captive portal service detects a captive portal.  The TabReloader
    254   // should try and create a new login tab in response.
    255   EXPECT_CALL(tab_reloader(), MaybeOpenCaptivePortalLoginTab()).Times(1);
    256   tab_reloader().OnCaptivePortalResults(RESULT_INTERNET_CONNECTED,
    257                                         RESULT_BEHIND_CAPTIVE_PORTAL);
    258   EXPECT_EQ(CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL,
    259             tab_reloader().state());
    260   EXPECT_FALSE(tab_reloader().TimerRunning());
    261 
    262   // The error page commits.
    263   tab_reloader().OnLoadCommitted(net::ERR_CONNECTION_TIMED_OUT);
    264   EXPECT_EQ(CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL,
    265             tab_reloader().state());
    266 
    267   // The user logs on from another tab, and a captive portal check is triggered.
    268   EXPECT_CALL(tab_reloader(), ReloadTab()).Times(1);
    269   tab_reloader().OnCaptivePortalResults(RESULT_BEHIND_CAPTIVE_PORTAL,
    270                                         RESULT_INTERNET_CONNECTED);
    271   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, tab_reloader().state());
    272 }
    273 
    274 // Simulate a login after the tab times out unexpectedly quickly.
    275 TEST_F(CaptivePortalTabReloaderTest, TimeoutFast) {
    276   tab_reloader().OnLoadStart(true);
    277 
    278   // The error page commits, which should trigger a captive portal check,
    279   // since the timer's still running.
    280   EXPECT_CALL(tab_reloader(), CheckForCaptivePortal()).Times(1);
    281   tab_reloader().OnLoadCommitted(net::ERR_CONNECTION_TIMED_OUT);
    282   EXPECT_EQ(CaptivePortalTabReloader::STATE_MAYBE_BROKEN_BY_PORTAL,
    283             tab_reloader().state());
    284 
    285   // The captive portal service detects a captive portal.  The TabReloader
    286   // should try and create a new login tab in response.
    287   EXPECT_CALL(tab_reloader(), MaybeOpenCaptivePortalLoginTab()).Times(1);
    288   tab_reloader().OnCaptivePortalResults(RESULT_INTERNET_CONNECTED,
    289                                         RESULT_BEHIND_CAPTIVE_PORTAL);
    290   EXPECT_EQ(CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL,
    291             tab_reloader().state());
    292   EXPECT_FALSE(tab_reloader().TimerRunning());
    293 
    294   // The user logs on from another tab, and a captive portal check is triggered.
    295   EXPECT_CALL(tab_reloader(), ReloadTab()).Times(1);
    296   tab_reloader().OnCaptivePortalResults(RESULT_BEHIND_CAPTIVE_PORTAL,
    297                                         RESULT_INTERNET_CONNECTED);
    298   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, tab_reloader().state());
    299 }
    300 
    301 // An SSL protocol error triggers a captive portal check behind a captive
    302 // portal.  The user then logs in.
    303 TEST_F(CaptivePortalTabReloaderTest, SSLProtocolError) {
    304   tab_reloader().OnLoadStart(true);
    305 
    306   // The error page commits, which should trigger a captive portal check,
    307   // since the timer's still running.
    308   EXPECT_CALL(tab_reloader(), CheckForCaptivePortal()).Times(1);
    309   tab_reloader().OnLoadCommitted(net::ERR_SSL_PROTOCOL_ERROR);
    310   EXPECT_EQ(CaptivePortalTabReloader::STATE_MAYBE_BROKEN_BY_PORTAL,
    311             tab_reloader().state());
    312 
    313   // The captive portal service detects a captive portal.  The TabReloader
    314   // should try and create a new login tab in response.
    315   EXPECT_CALL(tab_reloader(), MaybeOpenCaptivePortalLoginTab()).Times(1);
    316   tab_reloader().OnCaptivePortalResults(RESULT_INTERNET_CONNECTED,
    317                                         RESULT_BEHIND_CAPTIVE_PORTAL);
    318   EXPECT_EQ(CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL,
    319             tab_reloader().state());
    320   EXPECT_FALSE(tab_reloader().TimerRunning());
    321 
    322   // The user logs on from another tab, and a captive portal check is triggered.
    323   EXPECT_CALL(tab_reloader(), ReloadTab()).Times(1);
    324   tab_reloader().OnCaptivePortalResults(RESULT_BEHIND_CAPTIVE_PORTAL,
    325                                         RESULT_INTERNET_CONNECTED);
    326   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, tab_reloader().state());
    327 }
    328 
    329 // An SSL protocol error triggers a captive portal check behind a captive
    330 // portal.  The user logs in before the results from the captive portal check
    331 // completes.
    332 TEST_F(CaptivePortalTabReloaderTest, SSLProtocolErrorFastLogin) {
    333   tab_reloader().OnLoadStart(true);
    334 
    335   // The error page commits, which should trigger a captive portal check,
    336   // since the timer's still running.
    337   EXPECT_CALL(tab_reloader(), CheckForCaptivePortal()).Times(1);
    338   tab_reloader().OnLoadCommitted(net::ERR_SSL_PROTOCOL_ERROR);
    339   EXPECT_EQ(CaptivePortalTabReloader::STATE_MAYBE_BROKEN_BY_PORTAL,
    340             tab_reloader().state());
    341 
    342   // The user has logged in from another tab.  The tab automatically reloads.
    343   EXPECT_CALL(tab_reloader(), ReloadTab()).Times(1);
    344   tab_reloader().OnCaptivePortalResults(RESULT_BEHIND_CAPTIVE_PORTAL,
    345                                         RESULT_INTERNET_CONNECTED);
    346   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, tab_reloader().state());
    347 }
    348 
    349 // An SSL protocol error triggers a captive portal check behind a captive
    350 // portal.  The user logs in before the results from the captive portal check
    351 // completes.  This case is probably not too likely, but should be handled.
    352 TEST_F(CaptivePortalTabReloaderTest, SSLProtocolErrorAlreadyLoggedIn) {
    353   tab_reloader().OnLoadStart(true);
    354 
    355   // The user logs in from another tab before the tab errors out.
    356   tab_reloader().OnCaptivePortalResults(RESULT_BEHIND_CAPTIVE_PORTAL,
    357                                         RESULT_INTERNET_CONNECTED);
    358   EXPECT_EQ(CaptivePortalTabReloader::STATE_NEEDS_RELOAD,
    359             tab_reloader().state());
    360 
    361   // The error page commits, which should trigger a reload.
    362   EXPECT_CALL(tab_reloader(), ReloadTab()).Times(1);
    363   tab_reloader().OnLoadCommitted(net::ERR_SSL_PROTOCOL_ERROR);
    364   base::MessageLoop::current()->RunUntilIdle();
    365   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, tab_reloader().state());
    366 }
    367 
    368 // Simulate the case that a user has already logged in before the tab receives a
    369 // captive portal result, but a RESULT_BEHIND_CAPTIVE_PORTAL was received
    370 // before the tab started loading.
    371 TEST_F(CaptivePortalTabReloaderTest, AlreadyLoggedIn) {
    372   tab_reloader().OnLoadStart(true);
    373 
    374   EXPECT_CALL(tab_reloader(), CheckForCaptivePortal()).Times(1);
    375   base::MessageLoop::current()->RunUntilIdle();
    376   EXPECT_FALSE(tab_reloader().TimerRunning());
    377   EXPECT_EQ(CaptivePortalTabReloader::STATE_MAYBE_BROKEN_BY_PORTAL,
    378             tab_reloader().state());
    379 
    380   // The user has already logged in.  Since the last result found a captive
    381   // portal, the tab will be reloaded if a timeout is committed.
    382   tab_reloader().OnCaptivePortalResults(RESULT_BEHIND_CAPTIVE_PORTAL,
    383                                         RESULT_INTERNET_CONNECTED);
    384   EXPECT_EQ(CaptivePortalTabReloader::STATE_NEEDS_RELOAD,
    385             tab_reloader().state());
    386 
    387   // The error page commits, which should start an asynchronous reload.
    388   tab_reloader().OnLoadCommitted(net::ERR_CONNECTION_TIMED_OUT);
    389   EXPECT_EQ(CaptivePortalTabReloader::STATE_NEEDS_RELOAD,
    390             tab_reloader().state());
    391 
    392   EXPECT_CALL(tab_reloader(), ReloadTab()).Times(1);
    393   base::MessageLoop::current()->RunUntilIdle();
    394   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, tab_reloader().state());
    395 }
    396 
    397 // Same as above, except the result is received even before the timer triggers,
    398 // due to a captive portal test request from some external source, like a login
    399 // tab.
    400 TEST_F(CaptivePortalTabReloaderTest, AlreadyLoggedInBeforeTimerTriggers) {
    401   tab_reloader().OnLoadStart(true);
    402 
    403   // The user has already logged in.  Since the last result indicated there is
    404   // a captive portal, the tab will be reloaded if it times out.
    405   tab_reloader().OnCaptivePortalResults(RESULT_BEHIND_CAPTIVE_PORTAL,
    406                                         RESULT_INTERNET_CONNECTED);
    407   EXPECT_EQ(CaptivePortalTabReloader::STATE_NEEDS_RELOAD,
    408             tab_reloader().state());
    409   EXPECT_FALSE(tab_reloader().TimerRunning());
    410 
    411   // The error page commits, which should start an asynchronous reload.
    412   tab_reloader().OnLoadCommitted(net::ERR_CONNECTION_TIMED_OUT);
    413   EXPECT_EQ(CaptivePortalTabReloader::STATE_NEEDS_RELOAD,
    414             tab_reloader().state());
    415 
    416   EXPECT_CALL(tab_reloader(), ReloadTab()).Times(1);
    417   base::MessageLoop::current()->RunUntilIdle();
    418   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, tab_reloader().state());
    419 }
    420 
    421 // Simulate the user logging in while the timer is still running.  May happen
    422 // if the tab is reloaded just before logging in on another tab.
    423 TEST_F(CaptivePortalTabReloaderTest, LoginWhileTimerRunning) {
    424   tab_reloader().OnLoadStart(true);
    425   EXPECT_EQ(CaptivePortalTabReloader::STATE_TIMER_RUNNING,
    426             tab_reloader().state());
    427   EXPECT_TRUE(tab_reloader().TimerRunning());
    428 
    429   // The user has already logged in.
    430   tab_reloader().OnCaptivePortalResults(RESULT_BEHIND_CAPTIVE_PORTAL,
    431                                         RESULT_INTERNET_CONNECTED);
    432   EXPECT_EQ(CaptivePortalTabReloader::STATE_NEEDS_RELOAD,
    433             tab_reloader().state());
    434 
    435   // The error page commits, which should start an asynchronous reload.
    436   tab_reloader().OnLoadCommitted(net::ERR_CONNECTION_TIMED_OUT);
    437   EXPECT_EQ(CaptivePortalTabReloader::STATE_NEEDS_RELOAD,
    438             tab_reloader().state());
    439 
    440   EXPECT_CALL(tab_reloader(), ReloadTab()).Times(1);
    441   base::MessageLoop::current()->RunUntilIdle();
    442   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, tab_reloader().state());
    443 }
    444 
    445 // Simulate a captive portal being detected while the time is still running.
    446 // The captive portal check triggered by the timer detects the captive portal
    447 // again, and then the user logs in.
    448 TEST_F(CaptivePortalTabReloaderTest, BehindPortalResultWhileTimerRunning) {
    449   tab_reloader().OnLoadStart(true);
    450   EXPECT_EQ(CaptivePortalTabReloader::STATE_TIMER_RUNNING,
    451             tab_reloader().state());
    452   EXPECT_TRUE(tab_reloader().TimerRunning());
    453 
    454   // The user is behind a captive portal, but since the tab hasn't timed out,
    455   // the message is ignored.
    456   tab_reloader().OnCaptivePortalResults(RESULT_INTERNET_CONNECTED,
    457                                         RESULT_BEHIND_CAPTIVE_PORTAL);
    458   EXPECT_EQ(CaptivePortalTabReloader::STATE_TIMER_RUNNING,
    459             tab_reloader().state());
    460 
    461   // The rest proceeds as normal.
    462   EXPECT_CALL(tab_reloader(), CheckForCaptivePortal()).Times(1);
    463   base::MessageLoop::current()->RunUntilIdle();
    464   EXPECT_EQ(CaptivePortalTabReloader::STATE_MAYBE_BROKEN_BY_PORTAL,
    465             tab_reloader().state());
    466 
    467   // The captive portal service detects a captive portal, and this time the
    468   // tab tries to create a login tab.
    469   EXPECT_CALL(tab_reloader(), MaybeOpenCaptivePortalLoginTab()).Times(1);
    470   tab_reloader().OnCaptivePortalResults(RESULT_BEHIND_CAPTIVE_PORTAL,
    471                                         RESULT_BEHIND_CAPTIVE_PORTAL);
    472   EXPECT_EQ(CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL,
    473             tab_reloader().state());
    474   EXPECT_FALSE(tab_reloader().TimerRunning());
    475 
    476   // The user logs on from another tab, and a captive portal check is triggered.
    477   tab_reloader().OnCaptivePortalResults(RESULT_BEHIND_CAPTIVE_PORTAL,
    478                                         RESULT_INTERNET_CONNECTED);
    479   EXPECT_EQ(CaptivePortalTabReloader::STATE_NEEDS_RELOAD,
    480             tab_reloader().state());
    481 
    482   // The error page commits, which should start an asynchronous reload.
    483   tab_reloader().OnLoadCommitted(net::ERR_CONNECTION_TIMED_OUT);
    484   EXPECT_EQ(CaptivePortalTabReloader::STATE_NEEDS_RELOAD,
    485             tab_reloader().state());
    486 
    487   EXPECT_CALL(tab_reloader(), ReloadTab()).Times(1);
    488   base::MessageLoop::current()->RunUntilIdle();
    489   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, tab_reloader().state());
    490 }
    491 
    492 // The CaptivePortalService detects the user has logged in to a captive portal
    493 // while the timer is still running, but the original load succeeds, so no
    494 // reload is done.
    495 TEST_F(CaptivePortalTabReloaderTest, LogInWhileTimerRunningNoError) {
    496   tab_reloader().OnLoadStart(true);
    497   EXPECT_EQ(CaptivePortalTabReloader::STATE_TIMER_RUNNING,
    498             tab_reloader().state());
    499   EXPECT_TRUE(tab_reloader().TimerRunning());
    500 
    501   // The user has already logged in.
    502   tab_reloader().OnCaptivePortalResults(RESULT_BEHIND_CAPTIVE_PORTAL,
    503                                         RESULT_INTERNET_CONNECTED);
    504   EXPECT_FALSE(tab_reloader().TimerRunning());
    505   EXPECT_EQ(CaptivePortalTabReloader::STATE_NEEDS_RELOAD,
    506             tab_reloader().state());
    507 
    508   // The page successfully commits, so no reload is triggered.
    509   tab_reloader().OnLoadCommitted(net::OK);
    510   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, tab_reloader().state());
    511 }
    512 
    513 // Simulate the login process when there's an SSL certificate error.
    514 TEST_F(CaptivePortalTabReloaderTest, SSLCertErrorLogin) {
    515   tab_reloader().OnLoadStart(true);
    516   EXPECT_EQ(CaptivePortalTabReloader::STATE_TIMER_RUNNING,
    517             tab_reloader().state());
    518 
    519   // The load is interrupted by an interstitial page.  The interstitial page
    520   // is created after the TabReloader is notified.
    521   EXPECT_CALL(tab_reloader(), CheckForCaptivePortal());
    522   net::SSLInfo ssl_info;
    523   ssl_info.SetCertError(net::CERT_STATUS_COMMON_NAME_INVALID);
    524   tab_reloader().OnSSLCertError(ssl_info);
    525   EXPECT_EQ(CaptivePortalTabReloader::STATE_MAYBE_BROKEN_BY_PORTAL,
    526             tab_reloader().state());
    527   EXPECT_FALSE(tab_reloader().TimerRunning());
    528   // The MockInterstitialPageDelegate will cleaned up by the WebContents.
    529   new MockInterstitialPageDelegate(web_contents());
    530 
    531   // Captive portal probe finds a captive portal.
    532   EXPECT_CALL(tab_reloader(), MaybeOpenCaptivePortalLoginTab()).Times(1);
    533   tab_reloader().OnCaptivePortalResults(RESULT_INTERNET_CONNECTED,
    534                                         RESULT_BEHIND_CAPTIVE_PORTAL);
    535 
    536   // The user logs in.  Since the interstitial is showing, the page should
    537   // be reloaded, despite still having a provisional load.
    538   EXPECT_CALL(tab_reloader(), ReloadTab()).Times(1);
    539   tab_reloader().OnCaptivePortalResults(RESULT_BEHIND_CAPTIVE_PORTAL,
    540                                         RESULT_INTERNET_CONNECTED);
    541 }
    542 
    543 // Simulate an HTTP redirect to HTTPS, when the Internet is connected.
    544 TEST_F(CaptivePortalTabReloaderTest, HttpToHttpsRedirectInternetConnected) {
    545   tab_reloader().OnLoadStart(false);
    546   // There should be no captive portal check pending.
    547   base::MessageLoop::current()->RunUntilIdle();
    548 
    549   // HTTP to HTTPS redirect.
    550   tab_reloader().OnRedirect(true);
    551   EXPECT_EQ(CaptivePortalTabReloader::STATE_TIMER_RUNNING,
    552             tab_reloader().state());
    553   EXPECT_TRUE(tab_reloader().TimerRunning());
    554 
    555   EXPECT_CALL(tab_reloader(), CheckForCaptivePortal()).Times(1);
    556   base::MessageLoop::current()->RunUntilIdle();
    557   EXPECT_FALSE(tab_reloader().TimerRunning());
    558   EXPECT_EQ(CaptivePortalTabReloader::STATE_MAYBE_BROKEN_BY_PORTAL,
    559             tab_reloader().state());
    560 
    561   tab_reloader().OnCaptivePortalResults(RESULT_INTERNET_CONNECTED,
    562                                         RESULT_INTERNET_CONNECTED);
    563 
    564   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, tab_reloader().state());
    565   EXPECT_FALSE(tab_reloader().TimerRunning());
    566 
    567   tab_reloader().OnLoadCommitted(net::OK);
    568   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, tab_reloader().state());
    569 }
    570 
    571 // Simulate an HTTP redirect to HTTPS and subsequent Login, when the user logs
    572 // in before the original page commits.
    573 TEST_F(CaptivePortalTabReloaderTest, HttpToHttpsRedirectLogin) {
    574   tab_reloader().OnLoadStart(false);
    575   // There should be no captive portal check pending.
    576   base::MessageLoop::current()->RunUntilIdle();
    577 
    578   // HTTP to HTTPS redirect.
    579   tab_reloader().OnRedirect(true);
    580   EXPECT_EQ(CaptivePortalTabReloader::STATE_TIMER_RUNNING,
    581             tab_reloader().state());
    582 
    583   EXPECT_CALL(tab_reloader(), CheckForCaptivePortal()).Times(1);
    584   base::MessageLoop::current()->RunUntilIdle();
    585   EXPECT_FALSE(tab_reloader().TimerRunning());
    586   EXPECT_EQ(CaptivePortalTabReloader::STATE_MAYBE_BROKEN_BY_PORTAL,
    587             tab_reloader().state());
    588 
    589   // The captive portal service detects a captive portal.  The TabReloader
    590   // should try and create a new login tab in response.
    591   EXPECT_CALL(tab_reloader(), MaybeOpenCaptivePortalLoginTab()).Times(1);
    592   tab_reloader().OnCaptivePortalResults(RESULT_INTERNET_CONNECTED,
    593                                         RESULT_BEHIND_CAPTIVE_PORTAL);
    594   EXPECT_EQ(CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL,
    595             tab_reloader().state());
    596   EXPECT_FALSE(tab_reloader().TimerRunning());
    597 
    598   // The user logs on from another tab, and a captive portal check is triggered.
    599   tab_reloader().OnCaptivePortalResults(RESULT_BEHIND_CAPTIVE_PORTAL,
    600                                         RESULT_INTERNET_CONNECTED);
    601   EXPECT_EQ(CaptivePortalTabReloader::STATE_NEEDS_RELOAD,
    602             tab_reloader().state());
    603 
    604   // The error page commits, which should start an asynchronous reload.
    605   tab_reloader().OnLoadCommitted(net::ERR_CONNECTION_TIMED_OUT);
    606   EXPECT_EQ(CaptivePortalTabReloader::STATE_NEEDS_RELOAD,
    607             tab_reloader().state());
    608 
    609   EXPECT_CALL(tab_reloader(), ReloadTab()).Times(1);
    610   base::MessageLoop::current()->RunUntilIdle();
    611   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, tab_reloader().state());
    612 }
    613 
    614 // Simulate the case where an HTTPs page redirects to an HTTPS page, before
    615 // the timer triggers.
    616 TEST_F(CaptivePortalTabReloaderTest, HttpsToHttpRedirect) {
    617   tab_reloader().OnLoadStart(true);
    618   EXPECT_EQ(CaptivePortalTabReloader::STATE_TIMER_RUNNING,
    619             tab_reloader().state());
    620 
    621   tab_reloader().OnRedirect(false);
    622   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, tab_reloader().state());
    623   EXPECT_FALSE(tab_reloader().TimerRunning());
    624 
    625   // There should be no captive portal check pending after the redirect.
    626   base::MessageLoop::current()->RunUntilIdle();
    627 
    628   // Logging in shouldn't do anything.
    629   tab_reloader().OnCaptivePortalResults(RESULT_BEHIND_CAPTIVE_PORTAL,
    630                                         RESULT_INTERNET_CONNECTED);
    631   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, tab_reloader().state());
    632 }
    633 
    634 // Check that an HTTPS to HTTPS redirect results in no timer running.
    635 TEST_F(CaptivePortalTabReloaderTest, HttpsToHttpsRedirect) {
    636   tab_reloader().OnLoadStart(true);
    637   EXPECT_EQ(CaptivePortalTabReloader::STATE_TIMER_RUNNING,
    638             tab_reloader().state());
    639 
    640   tab_reloader().OnRedirect(true);
    641   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE,
    642             tab_reloader().state());
    643   EXPECT_FALSE(tab_reloader().TimerRunning());
    644   // Nothing should happen.
    645   base::MessageLoop::current()->RunUntilIdle();
    646 }
    647 
    648 // Check that an HTTPS to HTTP to HTTPS redirect results in no timer running.
    649 TEST_F(CaptivePortalTabReloaderTest, HttpsToHttpToHttpsRedirect) {
    650   tab_reloader().OnLoadStart(true);
    651   EXPECT_EQ(CaptivePortalTabReloader::STATE_TIMER_RUNNING,
    652             tab_reloader().state());
    653 
    654   tab_reloader().OnRedirect(false);
    655   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, tab_reloader().state());
    656   EXPECT_FALSE(tab_reloader().TimerRunning());
    657 
    658   tab_reloader().OnRedirect(true);
    659   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE,
    660             tab_reloader().state());
    661   EXPECT_FALSE(tab_reloader().TimerRunning());
    662   // Nothing should happen.
    663   base::MessageLoop::current()->RunUntilIdle();
    664 }
    665 
    666 // Check that an HTTP to HTTP redirect results in the timer not running.
    667 TEST_F(CaptivePortalTabReloaderTest, HttpToHttpRedirect) {
    668   tab_reloader().OnLoadStart(false);
    669   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, tab_reloader().state());
    670 
    671   tab_reloader().OnRedirect(false);
    672   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, tab_reloader().state());
    673   EXPECT_FALSE(tab_reloader().TimerRunning());
    674 
    675   // There should be no captive portal check pending after the redirect.
    676   base::MessageLoop::current()->RunUntilIdle();
    677 
    678   // Logging in shouldn't do anything.
    679   tab_reloader().OnCaptivePortalResults(RESULT_BEHIND_CAPTIVE_PORTAL,
    680                                         RESULT_INTERNET_CONNECTED);
    681   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, tab_reloader().state());
    682 }
    683 
    684 }  // namespace captive_portal
    685