Upstream version 5.34.104.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 namespace captive_portal {
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(RESULT_INTERNET_CONNECTED,
128                                         RESULT_INTERNET_CONNECTED);
129
130   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, tab_reloader().state());
131   EXPECT_FALSE(tab_reloader().TimerRunning());
132
133   tab_reloader().OnLoadCommitted(net::OK);
134   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, tab_reloader().state());
135 }
136
137 // Simulates a slow SSL load when the Internet is connected.  In this case,
138 // the timeout error occurs before the timer triggers.  Unlikely to happen
139 // in practice, but best if it still works.
140 TEST_F(CaptivePortalTabReloaderTest, InternetConnectedTimeout) {
141   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, tab_reloader().state());
142
143   tab_reloader().OnLoadStart(true);
144   EXPECT_EQ(CaptivePortalTabReloader::STATE_TIMER_RUNNING,
145             tab_reloader().state());
146   EXPECT_TRUE(tab_reloader().TimerRunning());
147
148   EXPECT_CALL(tab_reloader(), CheckForCaptivePortal()).Times(1);
149   tab_reloader().OnLoadCommitted(net::ERR_CONNECTION_TIMED_OUT);
150   EXPECT_FALSE(tab_reloader().TimerRunning());
151   EXPECT_EQ(CaptivePortalTabReloader::STATE_MAYBE_BROKEN_BY_PORTAL,
152             tab_reloader().state());
153
154   tab_reloader().OnCaptivePortalResults(RESULT_INTERNET_CONNECTED,
155                                         RESULT_INTERNET_CONNECTED);
156
157   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, tab_reloader().state());
158 }
159
160 // Simulates a slow SSL load when captive portal checks return no response.
161 TEST_F(CaptivePortalTabReloaderTest, NoResponse) {
162   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, tab_reloader().state());
163
164   tab_reloader().OnLoadStart(true);
165   EXPECT_EQ(CaptivePortalTabReloader::STATE_TIMER_RUNNING,
166             tab_reloader().state());
167   EXPECT_TRUE(tab_reloader().TimerRunning());
168
169   EXPECT_CALL(tab_reloader(), CheckForCaptivePortal()).Times(1);
170   base::MessageLoop::current()->RunUntilIdle();
171   EXPECT_FALSE(tab_reloader().TimerRunning());
172   EXPECT_EQ(CaptivePortalTabReloader::STATE_MAYBE_BROKEN_BY_PORTAL,
173             tab_reloader().state());
174
175   tab_reloader().OnCaptivePortalResults(RESULT_NO_RESPONSE, RESULT_NO_RESPONSE);
176
177   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, tab_reloader().state());
178   EXPECT_FALSE(tab_reloader().TimerRunning());
179
180   tab_reloader().OnLoadCommitted(net::OK);
181   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, tab_reloader().state());
182 }
183
184 // Simulates a slow HTTP load when behind a captive portal, that eventually.
185 // tiems out.  Since it's HTTP, the TabReloader should do nothing.
186 TEST_F(CaptivePortalTabReloaderTest, DoesNothingOnHttp) {
187   tab_reloader().OnLoadStart(false);
188   EXPECT_FALSE(tab_reloader().TimerRunning());
189   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, tab_reloader().state());
190
191   tab_reloader().OnCaptivePortalResults(RESULT_INTERNET_CONNECTED,
192                                         RESULT_BEHIND_CAPTIVE_PORTAL);
193   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, tab_reloader().state());
194
195   // The user logs in.
196   tab_reloader().OnCaptivePortalResults(RESULT_BEHIND_CAPTIVE_PORTAL,
197                                         RESULT_INTERNET_CONNECTED);
198   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, tab_reloader().state());
199
200   // The page times out.
201   tab_reloader().OnLoadCommitted(net::ERR_CONNECTION_TIMED_OUT);
202   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, tab_reloader().state());
203 }
204
205 // Simulate the normal login process.  The user logs in before the error page
206 // in the original tab commits.
207 TEST_F(CaptivePortalTabReloaderTest, Login) {
208   tab_reloader().OnLoadStart(true);
209
210   EXPECT_CALL(tab_reloader(), CheckForCaptivePortal()).Times(1);
211   base::MessageLoop::current()->RunUntilIdle();
212   EXPECT_FALSE(tab_reloader().TimerRunning());
213   EXPECT_EQ(CaptivePortalTabReloader::STATE_MAYBE_BROKEN_BY_PORTAL,
214             tab_reloader().state());
215
216   // The captive portal service detects a captive portal.  The TabReloader
217   // should try and create a new login tab in response.
218   EXPECT_CALL(tab_reloader(), MaybeOpenCaptivePortalLoginTab()).Times(1);
219   tab_reloader().OnCaptivePortalResults(RESULT_INTERNET_CONNECTED,
220                                         RESULT_BEHIND_CAPTIVE_PORTAL);
221   EXPECT_EQ(CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL,
222             tab_reloader().state());
223   EXPECT_FALSE(tab_reloader().TimerRunning());
224
225   // The user logs on from another tab, and a captive portal check is triggered.
226   tab_reloader().OnCaptivePortalResults(RESULT_BEHIND_CAPTIVE_PORTAL,
227                                         RESULT_INTERNET_CONNECTED);
228   EXPECT_EQ(CaptivePortalTabReloader::STATE_NEEDS_RELOAD,
229             tab_reloader().state());
230
231   // The error page commits, which should start an asynchronous reload.
232   tab_reloader().OnLoadCommitted(net::ERR_CONNECTION_TIMED_OUT);
233   EXPECT_EQ(CaptivePortalTabReloader::STATE_NEEDS_RELOAD,
234             tab_reloader().state());
235
236   EXPECT_CALL(tab_reloader(), ReloadTab()).Times(1);
237   base::MessageLoop::current()->RunUntilIdle();
238   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, tab_reloader().state());
239 }
240
241 // Simulate the normal login process.  The user logs in after the tab finishes
242 // loading the error page.
243 TEST_F(CaptivePortalTabReloaderTest, LoginLate) {
244   tab_reloader().OnLoadStart(true);
245
246   EXPECT_CALL(tab_reloader(), CheckForCaptivePortal()).Times(1);
247   base::MessageLoop::current()->RunUntilIdle();
248   EXPECT_FALSE(tab_reloader().TimerRunning());
249   EXPECT_EQ(CaptivePortalTabReloader::STATE_MAYBE_BROKEN_BY_PORTAL,
250             tab_reloader().state());
251
252   // The captive portal service detects a captive portal.  The TabReloader
253   // should try and create a new login tab in response.
254   EXPECT_CALL(tab_reloader(), MaybeOpenCaptivePortalLoginTab()).Times(1);
255   tab_reloader().OnCaptivePortalResults(RESULT_INTERNET_CONNECTED,
256                                         RESULT_BEHIND_CAPTIVE_PORTAL);
257   EXPECT_EQ(CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL,
258             tab_reloader().state());
259   EXPECT_FALSE(tab_reloader().TimerRunning());
260
261   // The error page commits.
262   tab_reloader().OnLoadCommitted(net::ERR_CONNECTION_TIMED_OUT);
263   EXPECT_EQ(CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL,
264             tab_reloader().state());
265
266   // The user logs on from another tab, and a captive portal check is triggered.
267   EXPECT_CALL(tab_reloader(), ReloadTab()).Times(1);
268   tab_reloader().OnCaptivePortalResults(RESULT_BEHIND_CAPTIVE_PORTAL,
269                                         RESULT_INTERNET_CONNECTED);
270   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, tab_reloader().state());
271 }
272
273 // Simulate a login after the tab times out unexpectedly quickly.
274 TEST_F(CaptivePortalTabReloaderTest, TimeoutFast) {
275   tab_reloader().OnLoadStart(true);
276
277   // The error page commits, which should trigger a captive portal check,
278   // since the timer's still running.
279   EXPECT_CALL(tab_reloader(), CheckForCaptivePortal()).Times(1);
280   tab_reloader().OnLoadCommitted(net::ERR_CONNECTION_TIMED_OUT);
281   EXPECT_EQ(CaptivePortalTabReloader::STATE_MAYBE_BROKEN_BY_PORTAL,
282             tab_reloader().state());
283
284   // The captive portal service detects a captive portal.  The TabReloader
285   // should try and create a new login tab in response.
286   EXPECT_CALL(tab_reloader(), MaybeOpenCaptivePortalLoginTab()).Times(1);
287   tab_reloader().OnCaptivePortalResults(RESULT_INTERNET_CONNECTED,
288                                         RESULT_BEHIND_CAPTIVE_PORTAL);
289   EXPECT_EQ(CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL,
290             tab_reloader().state());
291   EXPECT_FALSE(tab_reloader().TimerRunning());
292
293   // The user logs on from another tab, and a captive portal check is triggered.
294   EXPECT_CALL(tab_reloader(), ReloadTab()).Times(1);
295   tab_reloader().OnCaptivePortalResults(RESULT_BEHIND_CAPTIVE_PORTAL,
296                                         RESULT_INTERNET_CONNECTED);
297   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, tab_reloader().state());
298 }
299
300 // An SSL protocol error triggers a captive portal check behind a captive
301 // portal.  The user then logs in.
302 TEST_F(CaptivePortalTabReloaderTest, SSLProtocolError) {
303   tab_reloader().OnLoadStart(true);
304
305   // The error page commits, which should trigger a captive portal check,
306   // since the timer's still running.
307   EXPECT_CALL(tab_reloader(), CheckForCaptivePortal()).Times(1);
308   tab_reloader().OnLoadCommitted(net::ERR_SSL_PROTOCOL_ERROR);
309   EXPECT_EQ(CaptivePortalTabReloader::STATE_MAYBE_BROKEN_BY_PORTAL,
310             tab_reloader().state());
311
312   // The captive portal service detects a captive portal.  The TabReloader
313   // should try and create a new login tab in response.
314   EXPECT_CALL(tab_reloader(), MaybeOpenCaptivePortalLoginTab()).Times(1);
315   tab_reloader().OnCaptivePortalResults(RESULT_INTERNET_CONNECTED,
316                                         RESULT_BEHIND_CAPTIVE_PORTAL);
317   EXPECT_EQ(CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL,
318             tab_reloader().state());
319   EXPECT_FALSE(tab_reloader().TimerRunning());
320
321   // The user logs on from another tab, and a captive portal check is triggered.
322   EXPECT_CALL(tab_reloader(), ReloadTab()).Times(1);
323   tab_reloader().OnCaptivePortalResults(RESULT_BEHIND_CAPTIVE_PORTAL,
324                                         RESULT_INTERNET_CONNECTED);
325   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, tab_reloader().state());
326 }
327
328 // An SSL protocol error triggers a captive portal check behind a captive
329 // portal.  The user logs in before the results from the captive portal check
330 // completes.
331 TEST_F(CaptivePortalTabReloaderTest, SSLProtocolErrorFastLogin) {
332   tab_reloader().OnLoadStart(true);
333
334   // The error page commits, which should trigger a captive portal check,
335   // since the timer's still running.
336   EXPECT_CALL(tab_reloader(), CheckForCaptivePortal()).Times(1);
337   tab_reloader().OnLoadCommitted(net::ERR_SSL_PROTOCOL_ERROR);
338   EXPECT_EQ(CaptivePortalTabReloader::STATE_MAYBE_BROKEN_BY_PORTAL,
339             tab_reloader().state());
340
341   // The user has logged in from another tab.  The tab automatically reloads.
342   EXPECT_CALL(tab_reloader(), ReloadTab()).Times(1);
343   tab_reloader().OnCaptivePortalResults(RESULT_BEHIND_CAPTIVE_PORTAL,
344                                         RESULT_INTERNET_CONNECTED);
345   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, tab_reloader().state());
346 }
347
348 // An SSL protocol error triggers a captive portal check behind a captive
349 // portal.  The user logs in before the results from the captive portal check
350 // completes.  This case is probably not too likely, but should be handled.
351 TEST_F(CaptivePortalTabReloaderTest, SSLProtocolErrorAlreadyLoggedIn) {
352   tab_reloader().OnLoadStart(true);
353
354   // The user logs in from another tab before the tab errors out.
355   tab_reloader().OnCaptivePortalResults(RESULT_BEHIND_CAPTIVE_PORTAL,
356                                         RESULT_INTERNET_CONNECTED);
357   EXPECT_EQ(CaptivePortalTabReloader::STATE_NEEDS_RELOAD,
358             tab_reloader().state());
359
360   // The error page commits, which should trigger a reload.
361   EXPECT_CALL(tab_reloader(), ReloadTab()).Times(1);
362   tab_reloader().OnLoadCommitted(net::ERR_SSL_PROTOCOL_ERROR);
363   base::MessageLoop::current()->RunUntilIdle();
364   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, tab_reloader().state());
365 }
366
367 // Simulate the case that a user has already logged in before the tab receives a
368 // captive portal result, but a RESULT_BEHIND_CAPTIVE_PORTAL was received
369 // before the tab started loading.
370 TEST_F(CaptivePortalTabReloaderTest, AlreadyLoggedIn) {
371   tab_reloader().OnLoadStart(true);
372
373   EXPECT_CALL(tab_reloader(), CheckForCaptivePortal()).Times(1);
374   base::MessageLoop::current()->RunUntilIdle();
375   EXPECT_FALSE(tab_reloader().TimerRunning());
376   EXPECT_EQ(CaptivePortalTabReloader::STATE_MAYBE_BROKEN_BY_PORTAL,
377             tab_reloader().state());
378
379   // The user has already logged in.  Since the last result found a captive
380   // portal, the tab will be reloaded if a timeout is committed.
381   tab_reloader().OnCaptivePortalResults(RESULT_BEHIND_CAPTIVE_PORTAL,
382                                         RESULT_INTERNET_CONNECTED);
383   EXPECT_EQ(CaptivePortalTabReloader::STATE_NEEDS_RELOAD,
384             tab_reloader().state());
385
386   // The error page commits, which should start an asynchronous reload.
387   tab_reloader().OnLoadCommitted(net::ERR_CONNECTION_TIMED_OUT);
388   EXPECT_EQ(CaptivePortalTabReloader::STATE_NEEDS_RELOAD,
389             tab_reloader().state());
390
391   EXPECT_CALL(tab_reloader(), ReloadTab()).Times(1);
392   base::MessageLoop::current()->RunUntilIdle();
393   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, tab_reloader().state());
394 }
395
396 // Same as above, except the result is received even before the timer triggers,
397 // due to a captive portal test request from some external source, like a login
398 // tab.
399 TEST_F(CaptivePortalTabReloaderTest, AlreadyLoggedInBeforeTimerTriggers) {
400   tab_reloader().OnLoadStart(true);
401
402   // The user has already logged in.  Since the last result indicated there is
403   // a captive portal, the tab will be reloaded if it times out.
404   tab_reloader().OnCaptivePortalResults(RESULT_BEHIND_CAPTIVE_PORTAL,
405                                         RESULT_INTERNET_CONNECTED);
406   EXPECT_EQ(CaptivePortalTabReloader::STATE_NEEDS_RELOAD,
407             tab_reloader().state());
408   EXPECT_FALSE(tab_reloader().TimerRunning());
409
410   // The error page commits, which should start an asynchronous reload.
411   tab_reloader().OnLoadCommitted(net::ERR_CONNECTION_TIMED_OUT);
412   EXPECT_EQ(CaptivePortalTabReloader::STATE_NEEDS_RELOAD,
413             tab_reloader().state());
414
415   EXPECT_CALL(tab_reloader(), ReloadTab()).Times(1);
416   base::MessageLoop::current()->RunUntilIdle();
417   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, tab_reloader().state());
418 }
419
420 // Simulate the user logging in while the timer is still running.  May happen
421 // if the tab is reloaded just before logging in on another tab.
422 TEST_F(CaptivePortalTabReloaderTest, LoginWhileTimerRunning) {
423   tab_reloader().OnLoadStart(true);
424   EXPECT_EQ(CaptivePortalTabReloader::STATE_TIMER_RUNNING,
425             tab_reloader().state());
426   EXPECT_TRUE(tab_reloader().TimerRunning());
427
428   // The user has already logged in.
429   tab_reloader().OnCaptivePortalResults(RESULT_BEHIND_CAPTIVE_PORTAL,
430                                         RESULT_INTERNET_CONNECTED);
431   EXPECT_EQ(CaptivePortalTabReloader::STATE_NEEDS_RELOAD,
432             tab_reloader().state());
433
434   // The error page commits, which should start an asynchronous reload.
435   tab_reloader().OnLoadCommitted(net::ERR_CONNECTION_TIMED_OUT);
436   EXPECT_EQ(CaptivePortalTabReloader::STATE_NEEDS_RELOAD,
437             tab_reloader().state());
438
439   EXPECT_CALL(tab_reloader(), ReloadTab()).Times(1);
440   base::MessageLoop::current()->RunUntilIdle();
441   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, tab_reloader().state());
442 }
443
444 // Simulate a captive portal being detected while the time is still running.
445 // The captive portal check triggered by the timer detects the captive portal
446 // again, and then the user logs in.
447 TEST_F(CaptivePortalTabReloaderTest, BehindPortalResultWhileTimerRunning) {
448   tab_reloader().OnLoadStart(true);
449   EXPECT_EQ(CaptivePortalTabReloader::STATE_TIMER_RUNNING,
450             tab_reloader().state());
451   EXPECT_TRUE(tab_reloader().TimerRunning());
452
453   // The user is behind a captive portal, but since the tab hasn't timed out,
454   // the message is ignored.
455   tab_reloader().OnCaptivePortalResults(RESULT_INTERNET_CONNECTED,
456                                         RESULT_BEHIND_CAPTIVE_PORTAL);
457   EXPECT_EQ(CaptivePortalTabReloader::STATE_TIMER_RUNNING,
458             tab_reloader().state());
459
460   // The rest proceeds as normal.
461   EXPECT_CALL(tab_reloader(), CheckForCaptivePortal()).Times(1);
462   base::MessageLoop::current()->RunUntilIdle();
463   EXPECT_EQ(CaptivePortalTabReloader::STATE_MAYBE_BROKEN_BY_PORTAL,
464             tab_reloader().state());
465
466   // The captive portal service detects a captive portal, and this time the
467   // tab tries to create a login tab.
468   EXPECT_CALL(tab_reloader(), MaybeOpenCaptivePortalLoginTab()).Times(1);
469   tab_reloader().OnCaptivePortalResults(RESULT_BEHIND_CAPTIVE_PORTAL,
470                                         RESULT_BEHIND_CAPTIVE_PORTAL);
471   EXPECT_EQ(CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL,
472             tab_reloader().state());
473   EXPECT_FALSE(tab_reloader().TimerRunning());
474
475   // The user logs on from another tab, and a captive portal check is triggered.
476   tab_reloader().OnCaptivePortalResults(RESULT_BEHIND_CAPTIVE_PORTAL,
477                                         RESULT_INTERNET_CONNECTED);
478   EXPECT_EQ(CaptivePortalTabReloader::STATE_NEEDS_RELOAD,
479             tab_reloader().state());
480
481   // The error page commits, which should start an asynchronous reload.
482   tab_reloader().OnLoadCommitted(net::ERR_CONNECTION_TIMED_OUT);
483   EXPECT_EQ(CaptivePortalTabReloader::STATE_NEEDS_RELOAD,
484             tab_reloader().state());
485
486   EXPECT_CALL(tab_reloader(), ReloadTab()).Times(1);
487   base::MessageLoop::current()->RunUntilIdle();
488   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, tab_reloader().state());
489 }
490
491 // The CaptivePortalService detects the user has logged in to a captive portal
492 // while the timer is still running, but the original load succeeds, so no
493 // reload is done.
494 TEST_F(CaptivePortalTabReloaderTest, LogInWhileTimerRunningNoError) {
495   tab_reloader().OnLoadStart(true);
496   EXPECT_EQ(CaptivePortalTabReloader::STATE_TIMER_RUNNING,
497             tab_reloader().state());
498   EXPECT_TRUE(tab_reloader().TimerRunning());
499
500   // The user has already logged in.
501   tab_reloader().OnCaptivePortalResults(RESULT_BEHIND_CAPTIVE_PORTAL,
502                                         RESULT_INTERNET_CONNECTED);
503   EXPECT_FALSE(tab_reloader().TimerRunning());
504   EXPECT_EQ(CaptivePortalTabReloader::STATE_NEEDS_RELOAD,
505             tab_reloader().state());
506
507   // The page successfully commits, so no reload is triggered.
508   tab_reloader().OnLoadCommitted(net::OK);
509   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, tab_reloader().state());
510 }
511
512 // Simulate the login process when there's an SSL certificate error.
513 TEST_F(CaptivePortalTabReloaderTest, SSLCertErrorLogin) {
514   tab_reloader().OnLoadStart(true);
515   EXPECT_EQ(CaptivePortalTabReloader::STATE_TIMER_RUNNING,
516             tab_reloader().state());
517
518   // The load is interrupted by an interstitial page.  The interstitial page
519   // is created after the TabReloader is notified.
520   EXPECT_CALL(tab_reloader(), CheckForCaptivePortal());
521   net::SSLInfo ssl_info;
522   ssl_info.SetCertError(net::CERT_STATUS_COMMON_NAME_INVALID);
523   tab_reloader().OnSSLCertError(ssl_info);
524   EXPECT_EQ(CaptivePortalTabReloader::STATE_MAYBE_BROKEN_BY_PORTAL,
525             tab_reloader().state());
526   EXPECT_FALSE(tab_reloader().TimerRunning());
527   // The MockInterstitialPageDelegate will cleaned up by the WebContents.
528   new MockInterstitialPageDelegate(web_contents());
529
530   // Captive portal probe finds a captive portal.
531   EXPECT_CALL(tab_reloader(), MaybeOpenCaptivePortalLoginTab()).Times(1);
532   tab_reloader().OnCaptivePortalResults(RESULT_INTERNET_CONNECTED,
533                                         RESULT_BEHIND_CAPTIVE_PORTAL);
534
535   // The user logs in.  Since the interstitial is showing, the page should
536   // be reloaded, despite still having a provisional load.
537   EXPECT_CALL(tab_reloader(), ReloadTab()).Times(1);
538   tab_reloader().OnCaptivePortalResults(RESULT_BEHIND_CAPTIVE_PORTAL,
539                                         RESULT_INTERNET_CONNECTED);
540 }
541
542 // Simulate an HTTP redirect to HTTPS, when the Internet is connected.
543 TEST_F(CaptivePortalTabReloaderTest, HttpToHttpsRedirectInternetConnected) {
544   tab_reloader().OnLoadStart(false);
545   // There should be no captive portal check pending.
546   base::MessageLoop::current()->RunUntilIdle();
547
548   // HTTP to HTTPS redirect.
549   tab_reloader().OnRedirect(true);
550   EXPECT_EQ(CaptivePortalTabReloader::STATE_TIMER_RUNNING,
551             tab_reloader().state());
552   EXPECT_TRUE(tab_reloader().TimerRunning());
553
554   EXPECT_CALL(tab_reloader(), CheckForCaptivePortal()).Times(1);
555   base::MessageLoop::current()->RunUntilIdle();
556   EXPECT_FALSE(tab_reloader().TimerRunning());
557   EXPECT_EQ(CaptivePortalTabReloader::STATE_MAYBE_BROKEN_BY_PORTAL,
558             tab_reloader().state());
559
560   tab_reloader().OnCaptivePortalResults(RESULT_INTERNET_CONNECTED,
561                                         RESULT_INTERNET_CONNECTED);
562
563   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, tab_reloader().state());
564   EXPECT_FALSE(tab_reloader().TimerRunning());
565
566   tab_reloader().OnLoadCommitted(net::OK);
567   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, tab_reloader().state());
568 }
569
570 // Simulate an HTTP redirect to HTTPS and subsequent Login, when the user logs
571 // in before the original page commits.
572 TEST_F(CaptivePortalTabReloaderTest, HttpToHttpsRedirectLogin) {
573   tab_reloader().OnLoadStart(false);
574   // There should be no captive portal check pending.
575   base::MessageLoop::current()->RunUntilIdle();
576
577   // HTTP to HTTPS redirect.
578   tab_reloader().OnRedirect(true);
579   EXPECT_EQ(CaptivePortalTabReloader::STATE_TIMER_RUNNING,
580             tab_reloader().state());
581
582   EXPECT_CALL(tab_reloader(), CheckForCaptivePortal()).Times(1);
583   base::MessageLoop::current()->RunUntilIdle();
584   EXPECT_FALSE(tab_reloader().TimerRunning());
585   EXPECT_EQ(CaptivePortalTabReloader::STATE_MAYBE_BROKEN_BY_PORTAL,
586             tab_reloader().state());
587
588   // The captive portal service detects a captive portal.  The TabReloader
589   // should try and create a new login tab in response.
590   EXPECT_CALL(tab_reloader(), MaybeOpenCaptivePortalLoginTab()).Times(1);
591   tab_reloader().OnCaptivePortalResults(RESULT_INTERNET_CONNECTED,
592                                         RESULT_BEHIND_CAPTIVE_PORTAL);
593   EXPECT_EQ(CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL,
594             tab_reloader().state());
595   EXPECT_FALSE(tab_reloader().TimerRunning());
596
597   // The user logs on from another tab, and a captive portal check is triggered.
598   tab_reloader().OnCaptivePortalResults(RESULT_BEHIND_CAPTIVE_PORTAL,
599                                         RESULT_INTERNET_CONNECTED);
600   EXPECT_EQ(CaptivePortalTabReloader::STATE_NEEDS_RELOAD,
601             tab_reloader().state());
602
603   // The error page commits, which should start an asynchronous reload.
604   tab_reloader().OnLoadCommitted(net::ERR_CONNECTION_TIMED_OUT);
605   EXPECT_EQ(CaptivePortalTabReloader::STATE_NEEDS_RELOAD,
606             tab_reloader().state());
607
608   EXPECT_CALL(tab_reloader(), ReloadTab()).Times(1);
609   base::MessageLoop::current()->RunUntilIdle();
610   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, tab_reloader().state());
611 }
612
613 // Simulate the case where an HTTPs page redirects to an HTTPS page, before
614 // the timer triggers.
615 TEST_F(CaptivePortalTabReloaderTest, HttpsToHttpRedirect) {
616   tab_reloader().OnLoadStart(true);
617   EXPECT_EQ(CaptivePortalTabReloader::STATE_TIMER_RUNNING,
618             tab_reloader().state());
619
620   tab_reloader().OnRedirect(false);
621   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, tab_reloader().state());
622   EXPECT_FALSE(tab_reloader().TimerRunning());
623
624   // There should be no captive portal check pending after the redirect.
625   base::MessageLoop::current()->RunUntilIdle();
626
627   // Logging in shouldn't do anything.
628   tab_reloader().OnCaptivePortalResults(RESULT_BEHIND_CAPTIVE_PORTAL,
629                                         RESULT_INTERNET_CONNECTED);
630   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, tab_reloader().state());
631 }
632
633 // Check that an HTTPS to HTTPS redirect results in no timer running.
634 TEST_F(CaptivePortalTabReloaderTest, HttpsToHttpsRedirect) {
635   tab_reloader().OnLoadStart(true);
636   EXPECT_EQ(CaptivePortalTabReloader::STATE_TIMER_RUNNING,
637             tab_reloader().state());
638
639   tab_reloader().OnRedirect(true);
640   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE,
641             tab_reloader().state());
642   EXPECT_FALSE(tab_reloader().TimerRunning());
643   // Nothing should happen.
644   base::MessageLoop::current()->RunUntilIdle();
645 }
646
647 // Check that an HTTPS to HTTP to HTTPS redirect results in no timer running.
648 TEST_F(CaptivePortalTabReloaderTest, HttpsToHttpToHttpsRedirect) {
649   tab_reloader().OnLoadStart(true);
650   EXPECT_EQ(CaptivePortalTabReloader::STATE_TIMER_RUNNING,
651             tab_reloader().state());
652
653   tab_reloader().OnRedirect(false);
654   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, tab_reloader().state());
655   EXPECT_FALSE(tab_reloader().TimerRunning());
656
657   tab_reloader().OnRedirect(true);
658   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE,
659             tab_reloader().state());
660   EXPECT_FALSE(tab_reloader().TimerRunning());
661   // Nothing should happen.
662   base::MessageLoop::current()->RunUntilIdle();
663 }
664
665 // Check that an HTTP to HTTP redirect results in the timer not running.
666 TEST_F(CaptivePortalTabReloaderTest, HttpToHttpRedirect) {
667   tab_reloader().OnLoadStart(false);
668   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, tab_reloader().state());
669
670   tab_reloader().OnRedirect(false);
671   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, tab_reloader().state());
672   EXPECT_FALSE(tab_reloader().TimerRunning());
673
674   // There should be no captive portal check pending after the redirect.
675   base::MessageLoop::current()->RunUntilIdle();
676
677   // Logging in shouldn't do anything.
678   tab_reloader().OnCaptivePortalResults(RESULT_BEHIND_CAPTIVE_PORTAL,
679                                         RESULT_INTERNET_CONNECTED);
680   EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, tab_reloader().state());
681 }
682
683 }  // namespace captive_portal