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 22namespace captive_portal { 23 24// Used for testing CaptivePortalTabReloader in isolation from the observer. 25// Exposes a number of private functions and mocks out others. 26class 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. 63class 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 89class 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. 114TEST_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. 141TEST_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. 162TEST_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. 187TEST_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. 208TEST_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. 244TEST_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. 275TEST_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. 303TEST_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. 332TEST_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. 352TEST_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. 371TEST_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. 400TEST_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. 423TEST_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. 448TEST_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. 495TEST_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. 514TEST_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. 544TEST_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. 573TEST_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. 616TEST_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. 635TEST_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. 649TEST_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. 667TEST_F(CaptivePortalTabReloaderTest, HttpToHttpRedirect) { 668 tab_reloader().OnLoadStart(false); 669 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, tab_reloader().state()); 670 671 tab_reloader().OnRedirect(false); 672 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, tab_reloader().state()); 673 EXPECT_FALSE(tab_reloader().TimerRunning()); 674 675 // There should be no captive portal check pending after the redirect. 676 base::MessageLoop::current()->RunUntilIdle(); 677 678 // Logging in shouldn't do anything. 679 tab_reloader().OnCaptivePortalResults(RESULT_BEHIND_CAPTIVE_PORTAL, 680 RESULT_INTERNET_CONNECTED); 681 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, tab_reloader().state()); 682} 683 684} // namespace captive_portal 685