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