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.
5 #include "chrome/browser/captive_portal/captive_portal_tab_reloader.h"
7 #include "base/callback.h"
8 #include "base/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 "content/public/test/test_browser_thread.h"
16 #include "googleurl/src/gurl.h"
17 #include "net/base/net_errors.h"
18 #include "net/cert/cert_status_flags.h"
19 #include "net/ssl/ssl_info.h"
20 #include "testing/gmock/include/gmock/gmock.h"
21 #include "testing/gtest/include/gtest/gtest.h"
23 namespace captive_portal
{
25 // Used for testing CaptivePortalTabReloader in isolation from the observer.
26 // Exposes a number of private functions and mocks out others.
27 class TestCaptivePortalTabReloader
: public CaptivePortalTabReloader
{
29 explicit TestCaptivePortalTabReloader(content::WebContents
* web_contents
)
30 : CaptivePortalTabReloader(NULL
,
32 base::Callback
<void(void)>()) {
35 virtual ~TestCaptivePortalTabReloader() {
39 return slow_ssl_load_timer_
.IsRunning();
42 // The following methods are aliased so they can be publicly accessed by the
46 return CaptivePortalTabReloader::state();
49 void set_slow_ssl_load_time(base::TimeDelta slow_ssl_load_time
) {
50 EXPECT_FALSE(TimerRunning());
51 CaptivePortalTabReloader::set_slow_ssl_load_time(slow_ssl_load_time
);
54 // CaptivePortalTabReloader:
55 MOCK_METHOD0(ReloadTab
, void());
56 MOCK_METHOD0(MaybeOpenCaptivePortalLoginTab
, void());
57 MOCK_METHOD0(CheckForCaptivePortal
, void());
60 DISALLOW_COPY_AND_ASSIGN(TestCaptivePortalTabReloader
);
63 // Used to test behavior when a WebContents is showing an interstitial page.
64 class MockInterstitialPageDelegate
: public content::InterstitialPageDelegate
{
66 // The newly created MockInterstitialPageDelegate will be owned by the
67 // WebContents' InterstitialPage, and cleaned up when the WebContents
69 explicit MockInterstitialPageDelegate(
70 content::WebContents
* web_contents
) {
71 content::InterstitialPage
* interstitial_page
=
72 content::InterstitialPage::Create(
73 web_contents
, true, GURL("http://blah"), this);
74 interstitial_page
->DontCreateViewForTesting();
75 interstitial_page
->Show();
78 virtual ~MockInterstitialPageDelegate() {
82 // InterstitialPageDelegate implementation:
83 virtual std::string
GetHTMLContents() OVERRIDE
{
84 return "HTML Contents";
87 DISALLOW_COPY_AND_ASSIGN(MockInterstitialPageDelegate
);
90 class CaptivePortalTabReloaderTest
: public ChromeRenderViewHostTestHarness
{
92 CaptivePortalTabReloaderTest()
93 : ui_thread_(content::BrowserThread::UI
, &message_loop_
),
94 file_user_blocking_thread_(content::BrowserThread::FILE_USER_BLOCKING
,
96 io_thread_(content::BrowserThread::IO
, &message_loop_
) {
99 virtual ~CaptivePortalTabReloaderTest() {
103 virtual void SetUp() OVERRIDE
{
104 ChromeRenderViewHostTestHarness::SetUp();
105 tab_reloader_
.reset(new testing::StrictMock
<TestCaptivePortalTabReloader
>(
108 // Most tests don't run the message loop, so don't use a timer for them.
109 tab_reloader_
->set_slow_ssl_load_time(base::TimeDelta());
112 virtual void TearDown() OVERRIDE
{
113 EXPECT_FALSE(tab_reloader().TimerRunning());
114 tab_reloader_
.reset(NULL
);
115 ChromeRenderViewHostTestHarness::TearDown();
118 TestCaptivePortalTabReloader
& tab_reloader() { return *tab_reloader_
.get(); }
121 content::TestBrowserThread ui_thread_
;
122 content::TestBrowserThread file_user_blocking_thread_
;
123 content::TestBrowserThread io_thread_
;
125 scoped_ptr
<TestCaptivePortalTabReloader
> tab_reloader_
;
128 // Simulates a slow SSL load when the Internet is connected.
129 TEST_F(CaptivePortalTabReloaderTest
, InternetConnected
) {
130 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
, tab_reloader().state());
132 tab_reloader().OnLoadStart(true);
133 EXPECT_EQ(CaptivePortalTabReloader::STATE_TIMER_RUNNING
,
134 tab_reloader().state());
135 EXPECT_TRUE(tab_reloader().TimerRunning());
137 EXPECT_CALL(tab_reloader(), CheckForCaptivePortal()).Times(1);
138 MessageLoop::current()->RunUntilIdle();
139 EXPECT_FALSE(tab_reloader().TimerRunning());
140 EXPECT_EQ(CaptivePortalTabReloader::STATE_MAYBE_BROKEN_BY_PORTAL
,
141 tab_reloader().state());
143 tab_reloader().OnCaptivePortalResults(RESULT_INTERNET_CONNECTED
,
144 RESULT_INTERNET_CONNECTED
);
146 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
, tab_reloader().state());
147 EXPECT_FALSE(tab_reloader().TimerRunning());
149 tab_reloader().OnLoadCommitted(net::OK
);
150 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
, tab_reloader().state());
153 // Simulates a slow SSL load when the Internet is connected. In this case,
154 // the timeout error occurs before the timer triggers. Unlikely to happen
155 // in practice, but best if it still works.
156 TEST_F(CaptivePortalTabReloaderTest
, InternetConnectedTimeout
) {
157 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
, tab_reloader().state());
159 tab_reloader().OnLoadStart(true);
160 EXPECT_EQ(CaptivePortalTabReloader::STATE_TIMER_RUNNING
,
161 tab_reloader().state());
162 EXPECT_TRUE(tab_reloader().TimerRunning());
164 EXPECT_CALL(tab_reloader(), CheckForCaptivePortal()).Times(1);
165 tab_reloader().OnLoadCommitted(net::ERR_CONNECTION_TIMED_OUT
);
166 EXPECT_FALSE(tab_reloader().TimerRunning());
167 EXPECT_EQ(CaptivePortalTabReloader::STATE_MAYBE_BROKEN_BY_PORTAL
,
168 tab_reloader().state());
170 tab_reloader().OnCaptivePortalResults(RESULT_INTERNET_CONNECTED
,
171 RESULT_INTERNET_CONNECTED
);
173 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
, tab_reloader().state());
176 // Simulates a slow SSL load when captive portal checks return no response.
177 TEST_F(CaptivePortalTabReloaderTest
, NoResponse
) {
178 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
, tab_reloader().state());
180 tab_reloader().OnLoadStart(true);
181 EXPECT_EQ(CaptivePortalTabReloader::STATE_TIMER_RUNNING
,
182 tab_reloader().state());
183 EXPECT_TRUE(tab_reloader().TimerRunning());
185 EXPECT_CALL(tab_reloader(), CheckForCaptivePortal()).Times(1);
186 MessageLoop::current()->RunUntilIdle();
187 EXPECT_FALSE(tab_reloader().TimerRunning());
188 EXPECT_EQ(CaptivePortalTabReloader::STATE_MAYBE_BROKEN_BY_PORTAL
,
189 tab_reloader().state());
191 tab_reloader().OnCaptivePortalResults(RESULT_NO_RESPONSE
, RESULT_NO_RESPONSE
);
193 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
, tab_reloader().state());
194 EXPECT_FALSE(tab_reloader().TimerRunning());
196 tab_reloader().OnLoadCommitted(net::OK
);
197 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
, tab_reloader().state());
200 // Simulates a slow HTTP load when behind a captive portal, that eventually.
201 // tiems out. Since it's HTTP, the TabReloader should do nothing.
202 TEST_F(CaptivePortalTabReloaderTest
, DoesNothingOnHttp
) {
203 tab_reloader().OnLoadStart(false);
204 EXPECT_FALSE(tab_reloader().TimerRunning());
205 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
, tab_reloader().state());
207 tab_reloader().OnCaptivePortalResults(RESULT_INTERNET_CONNECTED
,
208 RESULT_BEHIND_CAPTIVE_PORTAL
);
209 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
, tab_reloader().state());
212 tab_reloader().OnCaptivePortalResults(RESULT_BEHIND_CAPTIVE_PORTAL
,
213 RESULT_INTERNET_CONNECTED
);
214 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
, tab_reloader().state());
216 // The page times out.
217 tab_reloader().OnLoadCommitted(net::ERR_CONNECTION_TIMED_OUT
);
218 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
, tab_reloader().state());
221 // Simulate the normal login process. The user logs in before the error page
222 // in the original tab commits.
223 TEST_F(CaptivePortalTabReloaderTest
, Login
) {
224 tab_reloader().OnLoadStart(true);
226 EXPECT_CALL(tab_reloader(), CheckForCaptivePortal()).Times(1);
227 MessageLoop::current()->RunUntilIdle();
228 EXPECT_FALSE(tab_reloader().TimerRunning());
229 EXPECT_EQ(CaptivePortalTabReloader::STATE_MAYBE_BROKEN_BY_PORTAL
,
230 tab_reloader().state());
232 // The captive portal service detects a captive portal. The TabReloader
233 // should try and create a new login tab in response.
234 EXPECT_CALL(tab_reloader(), MaybeOpenCaptivePortalLoginTab()).Times(1);
235 tab_reloader().OnCaptivePortalResults(RESULT_INTERNET_CONNECTED
,
236 RESULT_BEHIND_CAPTIVE_PORTAL
);
237 EXPECT_EQ(CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL
,
238 tab_reloader().state());
239 EXPECT_FALSE(tab_reloader().TimerRunning());
241 // The user logs on from another tab, and a captive portal check is triggered.
242 tab_reloader().OnCaptivePortalResults(RESULT_BEHIND_CAPTIVE_PORTAL
,
243 RESULT_INTERNET_CONNECTED
);
244 EXPECT_EQ(CaptivePortalTabReloader::STATE_NEEDS_RELOAD
,
245 tab_reloader().state());
247 // The error page commits, which should start an asynchronous reload.
248 tab_reloader().OnLoadCommitted(net::ERR_CONNECTION_TIMED_OUT
);
249 EXPECT_EQ(CaptivePortalTabReloader::STATE_NEEDS_RELOAD
,
250 tab_reloader().state());
252 EXPECT_CALL(tab_reloader(), ReloadTab()).Times(1);
253 MessageLoop::current()->RunUntilIdle();
254 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
, tab_reloader().state());
257 // Simulate the normal login process. The user logs in after the tab finishes
258 // loading the error page.
259 TEST_F(CaptivePortalTabReloaderTest
, LoginLate
) {
260 tab_reloader().OnLoadStart(true);
262 EXPECT_CALL(tab_reloader(), CheckForCaptivePortal()).Times(1);
263 MessageLoop::current()->RunUntilIdle();
264 EXPECT_FALSE(tab_reloader().TimerRunning());
265 EXPECT_EQ(CaptivePortalTabReloader::STATE_MAYBE_BROKEN_BY_PORTAL
,
266 tab_reloader().state());
268 // The captive portal service detects a captive portal. The TabReloader
269 // should try and create a new login tab in response.
270 EXPECT_CALL(tab_reloader(), MaybeOpenCaptivePortalLoginTab()).Times(1);
271 tab_reloader().OnCaptivePortalResults(RESULT_INTERNET_CONNECTED
,
272 RESULT_BEHIND_CAPTIVE_PORTAL
);
273 EXPECT_EQ(CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL
,
274 tab_reloader().state());
275 EXPECT_FALSE(tab_reloader().TimerRunning());
277 // The error page commits.
278 tab_reloader().OnLoadCommitted(net::ERR_CONNECTION_TIMED_OUT
);
279 EXPECT_EQ(CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL
,
280 tab_reloader().state());
282 // The user logs on from another tab, and a captive portal check is triggered.
283 EXPECT_CALL(tab_reloader(), ReloadTab()).Times(1);
284 tab_reloader().OnCaptivePortalResults(RESULT_BEHIND_CAPTIVE_PORTAL
,
285 RESULT_INTERNET_CONNECTED
);
286 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
, tab_reloader().state());
289 // Simulate a login after the tab times out unexpectedly quickly.
290 TEST_F(CaptivePortalTabReloaderTest
, TimeoutFast
) {
291 tab_reloader().OnLoadStart(true);
293 // The error page commits, which should trigger a captive portal check,
294 // since the timer's still running.
295 EXPECT_CALL(tab_reloader(), CheckForCaptivePortal()).Times(1);
296 tab_reloader().OnLoadCommitted(net::ERR_CONNECTION_TIMED_OUT
);
297 EXPECT_EQ(CaptivePortalTabReloader::STATE_MAYBE_BROKEN_BY_PORTAL
,
298 tab_reloader().state());
300 // The captive portal service detects a captive portal. The TabReloader
301 // should try and create a new login tab in response.
302 EXPECT_CALL(tab_reloader(), MaybeOpenCaptivePortalLoginTab()).Times(1);
303 tab_reloader().OnCaptivePortalResults(RESULT_INTERNET_CONNECTED
,
304 RESULT_BEHIND_CAPTIVE_PORTAL
);
305 EXPECT_EQ(CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL
,
306 tab_reloader().state());
307 EXPECT_FALSE(tab_reloader().TimerRunning());
309 // The user logs on from another tab, and a captive portal check is triggered.
310 EXPECT_CALL(tab_reloader(), ReloadTab()).Times(1);
311 tab_reloader().OnCaptivePortalResults(RESULT_BEHIND_CAPTIVE_PORTAL
,
312 RESULT_INTERNET_CONNECTED
);
313 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
, tab_reloader().state());
316 // An SSL protocol error triggers a captive portal check behind a captive
317 // portal. The user then logs in.
318 TEST_F(CaptivePortalTabReloaderTest
, SSLProtocolError
) {
319 tab_reloader().OnLoadStart(true);
321 // The error page commits, which should trigger a captive portal check,
322 // since the timer's still running.
323 EXPECT_CALL(tab_reloader(), CheckForCaptivePortal()).Times(1);
324 tab_reloader().OnLoadCommitted(net::ERR_SSL_PROTOCOL_ERROR
);
325 EXPECT_EQ(CaptivePortalTabReloader::STATE_MAYBE_BROKEN_BY_PORTAL
,
326 tab_reloader().state());
328 // The captive portal service detects a captive portal. The TabReloader
329 // should try and create a new login tab in response.
330 EXPECT_CALL(tab_reloader(), MaybeOpenCaptivePortalLoginTab()).Times(1);
331 tab_reloader().OnCaptivePortalResults(RESULT_INTERNET_CONNECTED
,
332 RESULT_BEHIND_CAPTIVE_PORTAL
);
333 EXPECT_EQ(CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL
,
334 tab_reloader().state());
335 EXPECT_FALSE(tab_reloader().TimerRunning());
337 // The user logs on from another tab, and a captive portal check is triggered.
338 EXPECT_CALL(tab_reloader(), ReloadTab()).Times(1);
339 tab_reloader().OnCaptivePortalResults(RESULT_BEHIND_CAPTIVE_PORTAL
,
340 RESULT_INTERNET_CONNECTED
);
341 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
, tab_reloader().state());
344 // An SSL protocol error triggers a captive portal check behind a captive
345 // portal. The user logs in before the results from the captive portal check
347 TEST_F(CaptivePortalTabReloaderTest
, SSLProtocolErrorFastLogin
) {
348 tab_reloader().OnLoadStart(true);
350 // The error page commits, which should trigger a captive portal check,
351 // since the timer's still running.
352 EXPECT_CALL(tab_reloader(), CheckForCaptivePortal()).Times(1);
353 tab_reloader().OnLoadCommitted(net::ERR_SSL_PROTOCOL_ERROR
);
354 EXPECT_EQ(CaptivePortalTabReloader::STATE_MAYBE_BROKEN_BY_PORTAL
,
355 tab_reloader().state());
357 // The user has logged in from another tab. The tab automatically reloads.
358 EXPECT_CALL(tab_reloader(), ReloadTab()).Times(1);
359 tab_reloader().OnCaptivePortalResults(RESULT_BEHIND_CAPTIVE_PORTAL
,
360 RESULT_INTERNET_CONNECTED
);
361 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
, tab_reloader().state());
364 // An SSL protocol error triggers a captive portal check behind a captive
365 // portal. The user logs in before the results from the captive portal check
366 // completes. This case is probably not too likely, but should be handled.
367 TEST_F(CaptivePortalTabReloaderTest
, SSLProtocolErrorAlreadyLoggedIn
) {
368 tab_reloader().OnLoadStart(true);
370 // The user logs in from another tab before the tab errors out.
371 tab_reloader().OnCaptivePortalResults(RESULT_BEHIND_CAPTIVE_PORTAL
,
372 RESULT_INTERNET_CONNECTED
);
373 EXPECT_EQ(CaptivePortalTabReloader::STATE_NEEDS_RELOAD
,
374 tab_reloader().state());
376 // The error page commits, which should trigger a reload.
377 EXPECT_CALL(tab_reloader(), ReloadTab()).Times(1);
378 tab_reloader().OnLoadCommitted(net::ERR_SSL_PROTOCOL_ERROR
);
379 MessageLoop::current()->RunUntilIdle();
380 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
, tab_reloader().state());
383 // Simulate the case that a user has already logged in before the tab receives a
384 // captive portal result, but a RESULT_BEHIND_CAPTIVE_PORTAL was received
385 // before the tab started loading.
386 TEST_F(CaptivePortalTabReloaderTest
, AlreadyLoggedIn
) {
387 tab_reloader().OnLoadStart(true);
389 EXPECT_CALL(tab_reloader(), CheckForCaptivePortal()).Times(1);
390 MessageLoop::current()->RunUntilIdle();
391 EXPECT_FALSE(tab_reloader().TimerRunning());
392 EXPECT_EQ(CaptivePortalTabReloader::STATE_MAYBE_BROKEN_BY_PORTAL
,
393 tab_reloader().state());
395 // The user has already logged in. Since the last result found a captive
396 // portal, the tab will be reloaded if a timeout is committed.
397 tab_reloader().OnCaptivePortalResults(RESULT_BEHIND_CAPTIVE_PORTAL
,
398 RESULT_INTERNET_CONNECTED
);
399 EXPECT_EQ(CaptivePortalTabReloader::STATE_NEEDS_RELOAD
,
400 tab_reloader().state());
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());
407 EXPECT_CALL(tab_reloader(), ReloadTab()).Times(1);
408 MessageLoop::current()->RunUntilIdle();
409 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
, tab_reloader().state());
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
415 TEST_F(CaptivePortalTabReloaderTest
, AlreadyLoggedInBeforeTimerTriggers
) {
416 tab_reloader().OnLoadStart(true);
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(RESULT_BEHIND_CAPTIVE_PORTAL
,
421 RESULT_INTERNET_CONNECTED
);
422 EXPECT_EQ(CaptivePortalTabReloader::STATE_NEEDS_RELOAD
,
423 tab_reloader().state());
424 EXPECT_FALSE(tab_reloader().TimerRunning());
426 // The error page commits, which should start an asynchronous reload.
427 tab_reloader().OnLoadCommitted(net::ERR_CONNECTION_TIMED_OUT
);
428 EXPECT_EQ(CaptivePortalTabReloader::STATE_NEEDS_RELOAD
,
429 tab_reloader().state());
431 EXPECT_CALL(tab_reloader(), ReloadTab()).Times(1);
432 MessageLoop::current()->RunUntilIdle();
433 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
, tab_reloader().state());
436 // Simulate the user logging in while the timer is still running. May happen
437 // if the tab is reloaded just before logging in on another tab.
438 TEST_F(CaptivePortalTabReloaderTest
, LoginWhileTimerRunning
) {
439 tab_reloader().OnLoadStart(true);
440 EXPECT_EQ(CaptivePortalTabReloader::STATE_TIMER_RUNNING
,
441 tab_reloader().state());
442 EXPECT_TRUE(tab_reloader().TimerRunning());
444 // The user has already logged in.
445 tab_reloader().OnCaptivePortalResults(RESULT_BEHIND_CAPTIVE_PORTAL
,
446 RESULT_INTERNET_CONNECTED
);
447 EXPECT_EQ(CaptivePortalTabReloader::STATE_NEEDS_RELOAD
,
448 tab_reloader().state());
450 // The error page commits, which should start an asynchronous reload.
451 tab_reloader().OnLoadCommitted(net::ERR_CONNECTION_TIMED_OUT
);
452 EXPECT_EQ(CaptivePortalTabReloader::STATE_NEEDS_RELOAD
,
453 tab_reloader().state());
455 EXPECT_CALL(tab_reloader(), ReloadTab()).Times(1);
456 MessageLoop::current()->RunUntilIdle();
457 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
, tab_reloader().state());
460 // Simulate a captive portal being detected while the time is still running.
461 // The captive portal check triggered by the timer detects the captive portal
462 // again, and then the user logs in.
463 TEST_F(CaptivePortalTabReloaderTest
, BehindPortalResultWhileTimerRunning
) {
464 tab_reloader().OnLoadStart(true);
465 EXPECT_EQ(CaptivePortalTabReloader::STATE_TIMER_RUNNING
,
466 tab_reloader().state());
467 EXPECT_TRUE(tab_reloader().TimerRunning());
469 // The user is behind a captive portal, but since the tab hasn't timed out,
470 // the message is ignored.
471 tab_reloader().OnCaptivePortalResults(RESULT_INTERNET_CONNECTED
,
472 RESULT_BEHIND_CAPTIVE_PORTAL
);
473 EXPECT_EQ(CaptivePortalTabReloader::STATE_TIMER_RUNNING
,
474 tab_reloader().state());
476 // The rest proceeds as normal.
477 EXPECT_CALL(tab_reloader(), CheckForCaptivePortal()).Times(1);
478 MessageLoop::current()->RunUntilIdle();
479 EXPECT_EQ(CaptivePortalTabReloader::STATE_MAYBE_BROKEN_BY_PORTAL
,
480 tab_reloader().state());
482 // The captive portal service detects a captive portal, and this time the
483 // tab tries to create a login tab.
484 EXPECT_CALL(tab_reloader(), MaybeOpenCaptivePortalLoginTab()).Times(1);
485 tab_reloader().OnCaptivePortalResults(RESULT_BEHIND_CAPTIVE_PORTAL
,
486 RESULT_BEHIND_CAPTIVE_PORTAL
);
487 EXPECT_EQ(CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL
,
488 tab_reloader().state());
489 EXPECT_FALSE(tab_reloader().TimerRunning());
491 // The user logs on from another tab, and a captive portal check is triggered.
492 tab_reloader().OnCaptivePortalResults(RESULT_BEHIND_CAPTIVE_PORTAL
,
493 RESULT_INTERNET_CONNECTED
);
494 EXPECT_EQ(CaptivePortalTabReloader::STATE_NEEDS_RELOAD
,
495 tab_reloader().state());
497 // The error page commits, which should start an asynchronous reload.
498 tab_reloader().OnLoadCommitted(net::ERR_CONNECTION_TIMED_OUT
);
499 EXPECT_EQ(CaptivePortalTabReloader::STATE_NEEDS_RELOAD
,
500 tab_reloader().state());
502 EXPECT_CALL(tab_reloader(), ReloadTab()).Times(1);
503 MessageLoop::current()->RunUntilIdle();
504 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
, tab_reloader().state());
507 // The CaptivePortalService detects the user has logged in to a captive portal
508 // while the timer is still running, but the original load succeeds, so no
510 TEST_F(CaptivePortalTabReloaderTest
, LogInWhileTimerRunningNoError
) {
511 tab_reloader().OnLoadStart(true);
512 EXPECT_EQ(CaptivePortalTabReloader::STATE_TIMER_RUNNING
,
513 tab_reloader().state());
514 EXPECT_TRUE(tab_reloader().TimerRunning());
516 // The user has already logged in.
517 tab_reloader().OnCaptivePortalResults(RESULT_BEHIND_CAPTIVE_PORTAL
,
518 RESULT_INTERNET_CONNECTED
);
519 EXPECT_FALSE(tab_reloader().TimerRunning());
520 EXPECT_EQ(CaptivePortalTabReloader::STATE_NEEDS_RELOAD
,
521 tab_reloader().state());
523 // The page successfully commits, so no reload is triggered.
524 tab_reloader().OnLoadCommitted(net::OK
);
525 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
, tab_reloader().state());
528 // Simulate the login process when there's an SSL certificate error.
529 TEST_F(CaptivePortalTabReloaderTest
, SSLCertErrorLogin
) {
530 tab_reloader().OnLoadStart(true);
531 EXPECT_EQ(CaptivePortalTabReloader::STATE_TIMER_RUNNING
,
532 tab_reloader().state());
534 // The load is interrupted by an interstitial page. The interstitial page
535 // is created after the TabReloader is notified.
536 EXPECT_CALL(tab_reloader(), CheckForCaptivePortal());
537 net::SSLInfo ssl_info
;
538 ssl_info
.SetCertError(net::CERT_STATUS_COMMON_NAME_INVALID
);
539 tab_reloader().OnSSLCertError(ssl_info
);
540 EXPECT_EQ(CaptivePortalTabReloader::STATE_MAYBE_BROKEN_BY_PORTAL
,
541 tab_reloader().state());
542 EXPECT_FALSE(tab_reloader().TimerRunning());
543 // The MockInterstitialPageDelegate will cleaned up by the WebContents.
544 new MockInterstitialPageDelegate(web_contents());
546 // Captive portal probe finds a captive portal.
547 EXPECT_CALL(tab_reloader(), MaybeOpenCaptivePortalLoginTab()).Times(1);
548 tab_reloader().OnCaptivePortalResults(RESULT_INTERNET_CONNECTED
,
549 RESULT_BEHIND_CAPTIVE_PORTAL
);
551 // The user logs in. Since the interstitial is showing, the page should
552 // be reloaded, despite still having a provisional load.
553 EXPECT_CALL(tab_reloader(), ReloadTab()).Times(1);
554 tab_reloader().OnCaptivePortalResults(RESULT_BEHIND_CAPTIVE_PORTAL
,
555 RESULT_INTERNET_CONNECTED
);
558 // Simulate an HTTP redirect to HTTPS, when the Internet is connected.
559 TEST_F(CaptivePortalTabReloaderTest
, HttpToHttpsRedirectInternetConnected
) {
560 tab_reloader().OnLoadStart(false);
561 // There should be no captive portal check pending.
562 MessageLoop::current()->RunUntilIdle();
564 // HTTP to HTTPS redirect.
565 tab_reloader().OnRedirect(true);
566 EXPECT_EQ(CaptivePortalTabReloader::STATE_TIMER_RUNNING
,
567 tab_reloader().state());
568 EXPECT_TRUE(tab_reloader().TimerRunning());
570 EXPECT_CALL(tab_reloader(), CheckForCaptivePortal()).Times(1);
571 MessageLoop::current()->RunUntilIdle();
572 EXPECT_FALSE(tab_reloader().TimerRunning());
573 EXPECT_EQ(CaptivePortalTabReloader::STATE_MAYBE_BROKEN_BY_PORTAL
,
574 tab_reloader().state());
576 tab_reloader().OnCaptivePortalResults(RESULT_INTERNET_CONNECTED
,
577 RESULT_INTERNET_CONNECTED
);
579 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
, tab_reloader().state());
580 EXPECT_FALSE(tab_reloader().TimerRunning());
582 tab_reloader().OnLoadCommitted(net::OK
);
583 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
, tab_reloader().state());
586 // Simulate an HTTP redirect to HTTPS and subsequent Login, when the user logs
587 // in before the original page commits.
588 TEST_F(CaptivePortalTabReloaderTest
, HttpToHttpsRedirectLogin
) {
589 tab_reloader().OnLoadStart(false);
590 // There should be no captive portal check pending.
591 MessageLoop::current()->RunUntilIdle();
593 // HTTP to HTTPS redirect.
594 tab_reloader().OnRedirect(true);
595 EXPECT_EQ(CaptivePortalTabReloader::STATE_TIMER_RUNNING
,
596 tab_reloader().state());
598 EXPECT_CALL(tab_reloader(), CheckForCaptivePortal()).Times(1);
599 MessageLoop::current()->RunUntilIdle();
600 EXPECT_FALSE(tab_reloader().TimerRunning());
601 EXPECT_EQ(CaptivePortalTabReloader::STATE_MAYBE_BROKEN_BY_PORTAL
,
602 tab_reloader().state());
604 // The captive portal service detects a captive portal. The TabReloader
605 // should try and create a new login tab in response.
606 EXPECT_CALL(tab_reloader(), MaybeOpenCaptivePortalLoginTab()).Times(1);
607 tab_reloader().OnCaptivePortalResults(RESULT_INTERNET_CONNECTED
,
608 RESULT_BEHIND_CAPTIVE_PORTAL
);
609 EXPECT_EQ(CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL
,
610 tab_reloader().state());
611 EXPECT_FALSE(tab_reloader().TimerRunning());
613 // The user logs on from another tab, and a captive portal check is triggered.
614 tab_reloader().OnCaptivePortalResults(RESULT_BEHIND_CAPTIVE_PORTAL
,
615 RESULT_INTERNET_CONNECTED
);
616 EXPECT_EQ(CaptivePortalTabReloader::STATE_NEEDS_RELOAD
,
617 tab_reloader().state());
619 // The error page commits, which should start an asynchronous reload.
620 tab_reloader().OnLoadCommitted(net::ERR_CONNECTION_TIMED_OUT
);
621 EXPECT_EQ(CaptivePortalTabReloader::STATE_NEEDS_RELOAD
,
622 tab_reloader().state());
624 EXPECT_CALL(tab_reloader(), ReloadTab()).Times(1);
625 MessageLoop::current()->RunUntilIdle();
626 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
, tab_reloader().state());
629 // Simulate the case where an HTTPs page redirects to an HTTPS page, before
630 // the timer triggers.
631 TEST_F(CaptivePortalTabReloaderTest
, HttpsToHttpRedirect
) {
632 tab_reloader().OnLoadStart(true);
633 EXPECT_EQ(CaptivePortalTabReloader::STATE_TIMER_RUNNING
,
634 tab_reloader().state());
636 tab_reloader().OnRedirect(false);
637 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
, tab_reloader().state());
638 EXPECT_FALSE(tab_reloader().TimerRunning());
640 // There should be no captive portal check pending after the redirect.
641 MessageLoop::current()->RunUntilIdle();
643 // Logging in shouldn't do anything.
644 tab_reloader().OnCaptivePortalResults(RESULT_BEHIND_CAPTIVE_PORTAL
,
645 RESULT_INTERNET_CONNECTED
);
646 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
, tab_reloader().state());
649 // Check that an HTTPS to HTTPS redirect results in no timer running.
650 TEST_F(CaptivePortalTabReloaderTest
, HttpsToHttpsRedirect
) {
651 tab_reloader().OnLoadStart(true);
652 EXPECT_EQ(CaptivePortalTabReloader::STATE_TIMER_RUNNING
,
653 tab_reloader().state());
655 tab_reloader().OnRedirect(true);
656 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
,
657 tab_reloader().state());
658 EXPECT_FALSE(tab_reloader().TimerRunning());
659 // Nothing should happen.
660 MessageLoop::current()->RunUntilIdle();
663 // Check that an HTTPS to HTTP to HTTPS redirect results in no timer running.
664 TEST_F(CaptivePortalTabReloaderTest
, HttpsToHttpToHttpsRedirect
) {
665 tab_reloader().OnLoadStart(true);
666 EXPECT_EQ(CaptivePortalTabReloader::STATE_TIMER_RUNNING
,
667 tab_reloader().state());
669 tab_reloader().OnRedirect(false);
670 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
, tab_reloader().state());
671 EXPECT_FALSE(tab_reloader().TimerRunning());
673 tab_reloader().OnRedirect(true);
674 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
,
675 tab_reloader().state());
676 EXPECT_FALSE(tab_reloader().TimerRunning());
677 // Nothing should happen.
678 MessageLoop::current()->RunUntilIdle();
681 // Check that an HTTP to HTTP redirect results in the timer not running.
682 TEST_F(CaptivePortalTabReloaderTest
, HttpToHttpRedirect
) {
683 tab_reloader().OnLoadStart(false);
684 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
, tab_reloader().state());
686 tab_reloader().OnRedirect(false);
687 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
, tab_reloader().state());
688 EXPECT_FALSE(tab_reloader().TimerRunning());
690 // There should be no captive portal check pending after the redirect.
691 MessageLoop::current()->RunUntilIdle();
693 // Logging in shouldn't do anything.
694 tab_reloader().OnCaptivePortalResults(RESULT_BEHIND_CAPTIVE_PORTAL
,
695 RESULT_INTERNET_CONNECTED
);
696 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
, tab_reloader().state());
699 } // namespace captive_portal