- add sources.
[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/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