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_helper.h" 6 7 #include "base/callback.h" 8 #include "base/memory/scoped_ptr.h" 9 #include "chrome/browser/captive_portal/captive_portal_service.h" 10 #include "chrome/browser/captive_portal/captive_portal_tab_reloader.h" 11 #include "chrome/browser/chrome_notification_types.h" 12 #include "chrome/test/base/chrome_render_view_host_test_harness.h" 13 #include "content/public/browser/notification_details.h" 14 #include "content/public/browser/notification_service.h" 15 #include "content/public/browser/notification_source.h" 16 #include "content/public/browser/notification_types.h" 17 #include "content/public/browser/render_view_host.h" 18 #include "content/public/browser/render_process_host.h" 19 #include "content/public/browser/web_contents.h" 20 #include "net/base/net_errors.h" 21 #include "testing/gmock/include/gmock/gmock.h" 22 #include "testing/gtest/include/gtest/gtest.h" 23 24 using captive_portal::CaptivePortalResult; 25 26 namespace { 27 28 const char* const kHttpUrl = "http://whatever.com/"; 29 const char* const kHttpsUrl = "https://whatever.com/"; 30 31 // Used for cross-process navigations. Shouldn't actually matter whether this 32 // is different from kHttpsUrl, but best to keep things consistent. 33 const char* const kHttpsUrl2 = "https://cross_process.com/"; 34 35 // Error pages use a "data:" URL. Shouldn't actually matter what this is. 36 const char* const kErrorPageUrl = "data:blah"; 37 38 // Some navigations behave differently depending on if they're cross-process 39 // or not. 40 enum NavigationType { 41 kSameProcess, 42 kCrossProcess, 43 }; 44 45 } // namespace 46 47 class MockCaptivePortalTabReloader : public CaptivePortalTabReloader { 48 public: 49 MockCaptivePortalTabReloader() 50 : CaptivePortalTabReloader(NULL, NULL, base::Callback<void()>()) { 51 } 52 53 MOCK_METHOD1(OnLoadStart, void(bool)); 54 MOCK_METHOD1(OnLoadCommitted, void(int)); 55 MOCK_METHOD0(OnAbort, void()); 56 MOCK_METHOD1(OnRedirect, void(bool)); 57 MOCK_METHOD2(OnCaptivePortalResults, 58 void(CaptivePortalResult, CaptivePortalResult)); 59 }; 60 61 // Inherits from the ChromeRenderViewHostTestHarness to gain access to 62 // CreateTestWebContents. Since the tests need to micromanage order of 63 // WebContentsObserver function calls, does not actually make sure of 64 // the harness in any other way. 65 class CaptivePortalTabHelperTest : public ChromeRenderViewHostTestHarness { 66 public: 67 CaptivePortalTabHelperTest() 68 : tab_helper_(NULL), 69 mock_reloader_(new testing::StrictMock<MockCaptivePortalTabReloader>) { 70 tab_helper_.SetTabReloaderForTest(mock_reloader_); 71 } 72 virtual ~CaptivePortalTabHelperTest() {} 73 74 virtual void SetUp() OVERRIDE { 75 ChromeRenderViewHostTestHarness::SetUp(); 76 web_contents1_.reset(CreateTestWebContents()); 77 web_contents2_.reset(CreateTestWebContents()); 78 } 79 80 virtual void TearDown() OVERRIDE { 81 web_contents2_.reset(NULL); 82 web_contents1_.reset(NULL); 83 ChromeRenderViewHostTestHarness::TearDown(); 84 } 85 86 // Simulates a successful load of |url|. 87 void SimulateSuccess(const GURL& url, 88 content::RenderViewHost* render_view_host) { 89 EXPECT_CALL(mock_reloader(), OnLoadStart(url.SchemeIsSecure())).Times(1); 90 tab_helper().DidStartProvisionalLoadForFrame( 91 1, -1, true, url, false, false, render_view_host); 92 93 EXPECT_CALL(mock_reloader(), OnLoadCommitted(net::OK)).Times(1); 94 tab_helper().DidCommitProvisionalLoadForFrame( 95 1, base::string16(), true, url, content::PAGE_TRANSITION_LINK, 96 render_view_host); 97 } 98 99 // Simulates a connection timeout while requesting |url|. 100 void SimulateTimeout(const GURL& url, 101 content::RenderViewHost* render_view_host) { 102 EXPECT_CALL(mock_reloader(), OnLoadStart(url.SchemeIsSecure())).Times(1); 103 tab_helper().DidStartProvisionalLoadForFrame( 104 1, -1, true, url, false, false, render_view_host); 105 106 tab_helper().DidFailProvisionalLoad( 107 1, base::string16(), true, url, net::ERR_TIMED_OUT, base::string16(), 108 render_view_host); 109 110 // Provisional load starts for the error page. 111 tab_helper().DidStartProvisionalLoadForFrame( 112 1, -1, true, GURL(kErrorPageUrl), true, false, render_view_host); 113 114 EXPECT_CALL(mock_reloader(), OnLoadCommitted(net::ERR_TIMED_OUT)).Times(1); 115 tab_helper().DidCommitProvisionalLoadForFrame( 116 1, base::string16(), true, GURL(kErrorPageUrl), 117 content::PAGE_TRANSITION_LINK, render_view_host); 118 } 119 120 // Simulates an abort while requesting |url|. 121 void SimulateAbort(const GURL& url, 122 content::RenderViewHost* render_view_host, 123 NavigationType navigation_type) { 124 EXPECT_CALL(mock_reloader(), OnLoadStart(url.SchemeIsSecure())).Times(1); 125 tab_helper().DidStartProvisionalLoadForFrame( 126 1, -1, true, url, false, false, render_view_host); 127 128 EXPECT_CALL(mock_reloader(), OnAbort()).Times(1); 129 if (navigation_type == kSameProcess) { 130 tab_helper().DidFailProvisionalLoad( 131 1, base::string16(), true, url, net::ERR_ABORTED, base::string16(), 132 render_view_host); 133 } else { 134 // For interrupted provisional cross-process navigations, the 135 // RenderViewHost is destroyed without sending a DidFailProvisionalLoad 136 // notification. 137 tab_helper().RenderViewDeleted(render_view_host); 138 } 139 140 // Make sure that above call resulted in abort, for tests that continue 141 // after the abort. 142 EXPECT_CALL(mock_reloader(), OnAbort()).Times(0); 143 } 144 145 // Simulates an abort while loading an error page. 146 void SimulateAbortTimeout(const GURL& url, 147 content::RenderViewHost* render_view_host, 148 NavigationType navigation_type) { 149 EXPECT_CALL(mock_reloader(), OnLoadStart(url.SchemeIsSecure())).Times(1); 150 tab_helper().DidStartProvisionalLoadForFrame( 151 1, -1, true, url, false, false, render_view_host); 152 153 tab_helper().DidFailProvisionalLoad( 154 1, base::string16(), true, url, net::ERR_TIMED_OUT, base::string16(), 155 render_view_host); 156 157 // Start event for the error page. 158 tab_helper().DidStartProvisionalLoadForFrame( 159 1, -1, true, url, true, false, render_view_host); 160 161 EXPECT_CALL(mock_reloader(), OnAbort()).Times(1); 162 if (navigation_type == kSameProcess) { 163 tab_helper().DidFailProvisionalLoad( 164 1, base::string16(), true, url, net::ERR_ABORTED, base::string16(), 165 render_view_host); 166 } else { 167 // For interrupted provisional cross-process navigations, the 168 // RenderViewHost is destroyed without sending a DidFailProvisionalLoad 169 // notification. 170 tab_helper().RenderViewDeleted(render_view_host); 171 } 172 173 // Make sure that above call resulted in abort, for tests that continue 174 // after the abort. 175 EXPECT_CALL(mock_reloader(), OnAbort()).Times(0); 176 } 177 178 CaptivePortalTabHelper& tab_helper() { 179 return tab_helper_; 180 } 181 182 // Simulates a captive portal redirect by calling the Observe method. 183 void ObservePortalResult(CaptivePortalResult previous_result, 184 CaptivePortalResult result) { 185 content::Source<Profile> source_profile(NULL); 186 187 CaptivePortalService::Results results; 188 results.previous_result = previous_result; 189 results.result = result; 190 content::Details<CaptivePortalService::Results> details_results(&results); 191 192 EXPECT_CALL(mock_reloader(), OnCaptivePortalResults(previous_result, 193 result)).Times(1); 194 tab_helper().Observe(chrome::NOTIFICATION_CAPTIVE_PORTAL_CHECK_RESULT, 195 source_profile, 196 details_results); 197 } 198 199 // Simulates a redirect. Uses OnRedirect rather than Observe, for simplicity. 200 void OnRedirect(ResourceType::Type type, const GURL& new_url, int child_id) { 201 tab_helper().OnRedirect(child_id, type, new_url); 202 } 203 204 MockCaptivePortalTabReloader& mock_reloader() { return *mock_reloader_; } 205 206 void SetIsLoginTab() { 207 tab_helper().SetIsLoginTab(); 208 } 209 210 content::RenderViewHost* render_view_host1() { 211 return web_contents1_->GetRenderViewHost(); 212 } 213 214 content::RenderViewHost* render_view_host2() { 215 return web_contents2_->GetRenderViewHost(); 216 } 217 218 private: 219 // Only the RenderViewHosts are used. 220 scoped_ptr<content::WebContents> web_contents1_; 221 scoped_ptr<content::WebContents> web_contents2_; 222 223 CaptivePortalTabHelper tab_helper_; 224 225 // Owned by |tab_helper_|. 226 testing::StrictMock<MockCaptivePortalTabReloader>* mock_reloader_; 227 228 DISALLOW_COPY_AND_ASSIGN(CaptivePortalTabHelperTest); 229 }; 230 231 TEST_F(CaptivePortalTabHelperTest, HttpSuccess) { 232 SimulateSuccess(GURL(kHttpUrl), render_view_host1()); 233 tab_helper().DidStopLoading(render_view_host1()); 234 } 235 236 TEST_F(CaptivePortalTabHelperTest, HttpTimeout) { 237 SimulateTimeout(GURL(kHttpUrl), render_view_host1()); 238 tab_helper().DidStopLoading(render_view_host1()); 239 } 240 241 // Same as above, but simulates what happens when the Link Doctor is enabled, 242 // which adds another provisional load/commit for the error page, after the 243 // first two. 244 TEST_F(CaptivePortalTabHelperTest, HttpTimeoutLinkDoctor) { 245 SimulateTimeout(GURL(kHttpUrl), render_view_host1()); 246 247 EXPECT_CALL(mock_reloader(), OnLoadStart(false)).Times(1); 248 // Provisional load starts for the error page. 249 tab_helper().DidStartProvisionalLoadForFrame( 250 1, -1, true, GURL(kErrorPageUrl), true, false, render_view_host1()); 251 252 EXPECT_CALL(mock_reloader(), OnLoadCommitted(net::OK)).Times(1); 253 tab_helper().DidCommitProvisionalLoadForFrame( 254 1, base::string16(), true, GURL(kErrorPageUrl), 255 content::PAGE_TRANSITION_LINK, render_view_host1()); 256 tab_helper().DidStopLoading(render_view_host1()); 257 } 258 259 TEST_F(CaptivePortalTabHelperTest, HttpsSuccess) { 260 SimulateSuccess(GURL(kHttpsUrl), render_view_host1()); 261 tab_helper().DidStopLoading(render_view_host1()); 262 EXPECT_FALSE(tab_helper().IsLoginTab()); 263 } 264 265 TEST_F(CaptivePortalTabHelperTest, HttpsTimeout) { 266 SimulateTimeout(GURL(kHttpsUrl), render_view_host1()); 267 // Make sure no state was carried over from the timeout. 268 SimulateSuccess(GURL(kHttpsUrl), render_view_host1()); 269 EXPECT_FALSE(tab_helper().IsLoginTab()); 270 } 271 272 TEST_F(CaptivePortalTabHelperTest, HttpsAbort) { 273 SimulateAbort(GURL(kHttpsUrl), render_view_host1(), kSameProcess); 274 // Make sure no state was carried over from the abort. 275 SimulateSuccess(GURL(kHttpsUrl), render_view_host1()); 276 EXPECT_FALSE(tab_helper().IsLoginTab()); 277 } 278 279 // A cross-process navigation is aborted by a same-site navigation. 280 TEST_F(CaptivePortalTabHelperTest, AbortCrossProcess) { 281 SimulateAbort(GURL(kHttpsUrl2), render_view_host2(), kCrossProcess); 282 // Make sure no state was carried over from the abort. 283 SimulateSuccess(GURL(kHttpUrl), render_view_host1()); 284 EXPECT_FALSE(tab_helper().IsLoginTab()); 285 } 286 287 // Abort while there's a provisional timeout error page loading. 288 TEST_F(CaptivePortalTabHelperTest, HttpsAbortTimeout) { 289 SimulateAbortTimeout(GURL(kHttpsUrl), render_view_host1(), kSameProcess); 290 // Make sure no state was carried over from the timeout or the abort. 291 SimulateSuccess(GURL(kHttpsUrl), render_view_host1()); 292 EXPECT_FALSE(tab_helper().IsLoginTab()); 293 } 294 295 // Abort a cross-process navigation while there's a provisional timeout error 296 // page loading. 297 TEST_F(CaptivePortalTabHelperTest, AbortTimeoutCrossProcess) { 298 SimulateAbortTimeout(GURL(kHttpsUrl2), render_view_host2(), 299 kCrossProcess); 300 // Make sure no state was carried over from the timeout or the abort. 301 SimulateSuccess(GURL(kHttpsUrl), render_view_host1()); 302 EXPECT_FALSE(tab_helper().IsLoginTab()); 303 } 304 305 // Opposite case from above - a same-process error page is aborted in favor of 306 // a cross-process one. 307 TEST_F(CaptivePortalTabHelperTest, HttpsAbortTimeoutForCrossProcess) { 308 SimulateAbortTimeout(GURL(kHttpsUrl), render_view_host1(), kSameProcess); 309 // Make sure no state was carried over from the timeout or the abort. 310 SimulateSuccess(GURL(kHttpsUrl2), render_view_host2()); 311 EXPECT_FALSE(tab_helper().IsLoginTab()); 312 } 313 314 // A provisional same-site navigation is interrupted by a cross-process 315 // navigation without sending an abort first. 316 TEST_F(CaptivePortalTabHelperTest, UnexpectedProvisionalLoad) { 317 GURL same_site_url = GURL(kHttpUrl); 318 GURL cross_process_url = GURL(kHttpsUrl2); 319 320 // A same-site load for the original RenderViewHost starts. 321 EXPECT_CALL(mock_reloader(), 322 OnLoadStart(same_site_url.SchemeIsSecure())).Times(1); 323 tab_helper().DidStartProvisionalLoadForFrame( 324 1, -1, true, same_site_url, false, false, render_view_host1()); 325 326 // It's unexpectedly interrupted by a cross-process navigation, which starts 327 // navigating before the old navigation cancels. We generate an abort message 328 // for the old navigation. 329 EXPECT_CALL(mock_reloader(), OnAbort()).Times(1); 330 EXPECT_CALL(mock_reloader(), 331 OnLoadStart(cross_process_url.SchemeIsSecure())).Times(1); 332 tab_helper().DidStartProvisionalLoadForFrame( 333 1, -1, true, cross_process_url, false, false, render_view_host2()); 334 335 // The cross-process navigation fails. 336 tab_helper().DidFailProvisionalLoad( 337 1, base::string16(), true, cross_process_url, net::ERR_FAILED, 338 base::string16(), render_view_host2()); 339 340 // The same-site navigation finally is aborted. 341 tab_helper().DidFailProvisionalLoad( 342 1, base::string16(), true, same_site_url, net::ERR_ABORTED, 343 base::string16(), render_view_host1()); 344 345 // The provisional load starts for the error page for the cross-process 346 // navigation. 347 tab_helper().DidStartProvisionalLoadForFrame( 348 1, -1, true, GURL(kErrorPageUrl), true, false, render_view_host2()); 349 350 EXPECT_CALL(mock_reloader(), OnLoadCommitted(net::ERR_FAILED)).Times(1); 351 tab_helper().DidCommitProvisionalLoadForFrame( 352 1, base::string16(), true, GURL(kErrorPageUrl), 353 content::PAGE_TRANSITION_TYPED, render_view_host2()); 354 } 355 356 // Similar to the above test, except the original RenderViewHost manages to 357 // commit before its navigation is aborted. 358 TEST_F(CaptivePortalTabHelperTest, UnexpectedCommit) { 359 GURL same_site_url = GURL(kHttpUrl); 360 GURL cross_process_url = GURL(kHttpsUrl2); 361 362 // A same-site load for the original RenderViewHost starts. 363 EXPECT_CALL(mock_reloader(), 364 OnLoadStart(same_site_url.SchemeIsSecure())).Times(1); 365 tab_helper().DidStartProvisionalLoadForFrame( 366 1, -1, true, same_site_url, false, false, render_view_host1()); 367 368 // It's unexpectedly interrupted by a cross-process navigation, which starts 369 // navigating before the old navigation cancels. We generate an abort message 370 // for the old navigation. 371 EXPECT_CALL(mock_reloader(), OnAbort()).Times(1); 372 EXPECT_CALL(mock_reloader(), 373 OnLoadStart(cross_process_url.SchemeIsSecure())).Times(1); 374 tab_helper().DidStartProvisionalLoadForFrame( 375 1, -1, true, cross_process_url, false, false, render_view_host2()); 376 377 // The cross-process navigation fails. 378 tab_helper().DidFailProvisionalLoad( 379 1, base::string16(), true, cross_process_url, net::ERR_FAILED, 380 base::string16(), 381 render_view_host2()); 382 383 // The same-site navigation succeeds. 384 EXPECT_CALL(mock_reloader(), OnAbort()).Times(1); 385 EXPECT_CALL(mock_reloader(), 386 OnLoadStart(same_site_url.SchemeIsSecure())).Times(1); 387 EXPECT_CALL(mock_reloader(), OnLoadCommitted(net::OK)).Times(1); 388 tab_helper().DidCommitProvisionalLoadForFrame( 389 1, base::string16(), true, same_site_url, content::PAGE_TRANSITION_LINK, 390 render_view_host1()); 391 } 392 393 // Simulates navigations for a number of subframes, and makes sure no 394 // CaptivePortalTabHelper function is called. 395 TEST_F(CaptivePortalTabHelperTest, HttpsSubframe) { 396 GURL url = GURL(kHttpsUrl); 397 // Normal load. 398 tab_helper().DidStartProvisionalLoadForFrame( 399 1, -1, false, url, false, false, render_view_host1()); 400 tab_helper().DidCommitProvisionalLoadForFrame( 401 1, base::string16(), false, url, content::PAGE_TRANSITION_LINK, 402 render_view_host1()); 403 404 // Timeout. 405 tab_helper().DidStartProvisionalLoadForFrame( 406 2, -1, false, url, false, false, render_view_host1()); 407 tab_helper().DidFailProvisionalLoad( 408 2, base::string16(), false, url, net::ERR_TIMED_OUT, base::string16(), 409 render_view_host1()); 410 tab_helper().DidStartProvisionalLoadForFrame( 411 2, -1, false, url, true, false, render_view_host1()); 412 tab_helper().DidFailProvisionalLoad( 413 2, base::string16(), false, url, net::ERR_ABORTED, base::string16(), 414 render_view_host1()); 415 416 // Abort. 417 tab_helper().DidStartProvisionalLoadForFrame( 418 3, -1, false, url, false, false, render_view_host1()); 419 tab_helper().DidFailProvisionalLoad( 420 3, base::string16(), false, url, net::ERR_ABORTED, base::string16(), 421 render_view_host1()); 422 } 423 424 // Simulates a subframe erroring out at the same time as a provisional load, 425 // but with a different error code. Make sure the TabHelper sees the correct 426 // error. 427 TEST_F(CaptivePortalTabHelperTest, HttpsSubframeParallelError) { 428 // URL used by both frames. 429 GURL url = GURL(kHttpsUrl); 430 431 int frame_id = 2; 432 int subframe_id = 1; 433 434 // Loads start. 435 EXPECT_CALL(mock_reloader(), OnLoadStart(url.SchemeIsSecure())).Times(1); 436 tab_helper().DidStartProvisionalLoadForFrame( 437 frame_id, -1, true, url, false, false, render_view_host1()); 438 tab_helper().DidStartProvisionalLoadForFrame( 439 subframe_id, frame_id, false, url, false, false, render_view_host1()); 440 441 // Loads return errors. 442 tab_helper().DidFailProvisionalLoad( 443 frame_id, base::string16(), true, url, net::ERR_UNEXPECTED, 444 base::string16(), render_view_host1()); 445 tab_helper().DidFailProvisionalLoad( 446 subframe_id, base::string16(), false, url, net::ERR_TIMED_OUT, 447 base::string16(), render_view_host1()); 448 449 // Provisional load starts for the error pages. 450 tab_helper().DidStartProvisionalLoadForFrame( 451 frame_id, -1, true, url, true, false, render_view_host1()); 452 tab_helper().DidStartProvisionalLoadForFrame( 453 subframe_id, frame_id, false, url, true, false, render_view_host1()); 454 455 // Error page load finishes. 456 tab_helper().DidCommitProvisionalLoadForFrame( 457 subframe_id, base::string16(), false, url, 458 content::PAGE_TRANSITION_AUTO_SUBFRAME, render_view_host1()); 459 EXPECT_CALL(mock_reloader(), OnLoadCommitted(net::ERR_UNEXPECTED)).Times(1); 460 tab_helper().DidCommitProvisionalLoadForFrame( 461 frame_id, base::string16(), true, url, content::PAGE_TRANSITION_LINK, 462 render_view_host1()); 463 } 464 465 // Simulates an HTTP to HTTPS redirect, which then times out. 466 TEST_F(CaptivePortalTabHelperTest, HttpToHttpsRedirectTimeout) { 467 GURL http_url(kHttpUrl); 468 EXPECT_CALL(mock_reloader(), OnLoadStart(false)).Times(1); 469 tab_helper().DidStartProvisionalLoadForFrame( 470 1, -1, true, http_url, false, false, render_view_host1()); 471 472 GURL https_url(kHttpsUrl); 473 EXPECT_CALL(mock_reloader(), OnRedirect(true)).Times(1); 474 OnRedirect(ResourceType::MAIN_FRAME, https_url, 475 render_view_host1()->GetProcess()->GetID()); 476 477 tab_helper().DidFailProvisionalLoad( 478 1, base::string16(), true, https_url, net::ERR_TIMED_OUT, 479 base::string16(), render_view_host1()); 480 481 // Provisional load starts for the error page. 482 tab_helper().DidStartProvisionalLoadForFrame( 483 1, -1, true, GURL(kErrorPageUrl), true, false, render_view_host1()); 484 485 EXPECT_CALL(mock_reloader(), OnLoadCommitted(net::ERR_TIMED_OUT)).Times(1); 486 tab_helper().DidCommitProvisionalLoadForFrame( 487 1, base::string16(), true, GURL(kErrorPageUrl), 488 content::PAGE_TRANSITION_LINK, render_view_host1()); 489 } 490 491 // Simulates an HTTPS to HTTP redirect. 492 TEST_F(CaptivePortalTabHelperTest, HttpsToHttpRedirect) { 493 GURL https_url(kHttpsUrl); 494 EXPECT_CALL(mock_reloader(), 495 OnLoadStart(https_url.SchemeIsSecure())).Times(1); 496 tab_helper().DidStartProvisionalLoadForFrame(1, -1, true, https_url, false, 497 false, render_view_host1()); 498 499 GURL http_url(kHttpUrl); 500 EXPECT_CALL(mock_reloader(), OnRedirect(http_url.SchemeIsSecure())).Times(1); 501 OnRedirect(ResourceType::MAIN_FRAME, http_url, 502 render_view_host1()->GetProcess()->GetID()); 503 504 EXPECT_CALL(mock_reloader(), OnLoadCommitted(net::OK)).Times(1); 505 tab_helper().DidCommitProvisionalLoadForFrame( 506 1, base::string16(), true, http_url, content::PAGE_TRANSITION_LINK, 507 render_view_host1()); 508 } 509 510 // Simulates an HTTPS to HTTPS redirect. 511 TEST_F(CaptivePortalTabHelperTest, HttpToHttpRedirect) { 512 GURL http_url(kHttpUrl); 513 EXPECT_CALL(mock_reloader(), 514 OnLoadStart(http_url.SchemeIsSecure())).Times(1); 515 tab_helper().DidStartProvisionalLoadForFrame( 516 1, -1, true, http_url, false, false, render_view_host1()); 517 518 EXPECT_CALL(mock_reloader(), OnRedirect(http_url.SchemeIsSecure())).Times(1); 519 OnRedirect(ResourceType::MAIN_FRAME, http_url, 520 render_view_host1()->GetProcess()->GetID()); 521 522 EXPECT_CALL(mock_reloader(), OnLoadCommitted(net::OK)).Times(1); 523 tab_helper().DidCommitProvisionalLoadForFrame( 524 1, base::string16(), true, http_url, content::PAGE_TRANSITION_LINK, 525 render_view_host1()); 526 } 527 528 // Simulates redirect of a subframe. 529 TEST_F(CaptivePortalTabHelperTest, SubframeRedirect) { 530 GURL http_url(kHttpUrl); 531 EXPECT_CALL(mock_reloader(), OnLoadStart(false)).Times(1); 532 tab_helper().DidStartProvisionalLoadForFrame( 533 1, -1, true, http_url, false, false, render_view_host1()); 534 535 GURL https_url(kHttpsUrl); 536 OnRedirect(ResourceType::SUB_FRAME, https_url, 537 render_view_host1()->GetProcess()->GetID()); 538 539 EXPECT_CALL(mock_reloader(), OnLoadCommitted(net::OK)).Times(1); 540 tab_helper().DidCommitProvisionalLoadForFrame( 541 1, base::string16(), true, GURL(kErrorPageUrl), 542 content::PAGE_TRANSITION_LINK, render_view_host1()); 543 } 544 545 // Simulates a redirect, for another RenderViewHost. 546 TEST_F(CaptivePortalTabHelperTest, OtherRenderViewHostRedirect) { 547 GURL http_url(kHttpUrl); 548 EXPECT_CALL(mock_reloader(), OnLoadStart(false)).Times(1); 549 tab_helper().DidStartProvisionalLoadForFrame( 550 1, -1, true, http_url, false, false, render_view_host1()); 551 552 // Another RenderViewHost sees a redirect. None of the reloader's functions 553 // should be called. 554 GURL https_url(kHttpsUrl); 555 OnRedirect(ResourceType::MAIN_FRAME, https_url, 556 render_view_host2()->GetProcess()->GetID()); 557 558 tab_helper().DidFailProvisionalLoad( 559 1, base::string16(), true, https_url, net::ERR_TIMED_OUT, 560 base::string16(), render_view_host1()); 561 562 // Provisional load starts for the error page. 563 tab_helper().DidStartProvisionalLoadForFrame( 564 1, -1, true, GURL(kErrorPageUrl), true, false, render_view_host1()); 565 566 EXPECT_CALL(mock_reloader(), OnLoadCommitted(net::ERR_TIMED_OUT)).Times(1); 567 tab_helper().DidCommitProvisionalLoadForFrame( 568 1, base::string16(), true, GURL(kErrorPageUrl), 569 content::PAGE_TRANSITION_LINK, render_view_host1()); 570 } 571 572 TEST_F(CaptivePortalTabHelperTest, LoginTabLogin) { 573 EXPECT_FALSE(tab_helper().IsLoginTab()); 574 SetIsLoginTab(); 575 EXPECT_TRUE(tab_helper().IsLoginTab()); 576 577 ObservePortalResult(captive_portal::RESULT_INTERNET_CONNECTED, 578 captive_portal::RESULT_INTERNET_CONNECTED); 579 EXPECT_FALSE(tab_helper().IsLoginTab()); 580 } 581 582 TEST_F(CaptivePortalTabHelperTest, LoginTabError) { 583 EXPECT_FALSE(tab_helper().IsLoginTab()); 584 585 SetIsLoginTab(); 586 EXPECT_TRUE(tab_helper().IsLoginTab()); 587 588 ObservePortalResult(captive_portal::RESULT_INTERNET_CONNECTED, 589 captive_portal::RESULT_NO_RESPONSE); 590 EXPECT_FALSE(tab_helper().IsLoginTab()); 591 } 592 593 TEST_F(CaptivePortalTabHelperTest, LoginTabMultipleResultsBeforeLogin) { 594 EXPECT_FALSE(tab_helper().IsLoginTab()); 595 596 SetIsLoginTab(); 597 EXPECT_TRUE(tab_helper().IsLoginTab()); 598 599 ObservePortalResult(captive_portal::RESULT_INTERNET_CONNECTED, 600 captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL); 601 EXPECT_TRUE(tab_helper().IsLoginTab()); 602 603 ObservePortalResult(captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL, 604 captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL); 605 EXPECT_TRUE(tab_helper().IsLoginTab()); 606 607 ObservePortalResult(captive_portal::RESULT_NO_RESPONSE, 608 captive_portal::RESULT_INTERNET_CONNECTED); 609 EXPECT_FALSE(tab_helper().IsLoginTab()); 610 } 611 612 TEST_F(CaptivePortalTabHelperTest, NoLoginTab) { 613 EXPECT_FALSE(tab_helper().IsLoginTab()); 614 615 ObservePortalResult(captive_portal::RESULT_INTERNET_CONNECTED, 616 captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL); 617 EXPECT_FALSE(tab_helper().IsLoginTab()); 618 619 ObservePortalResult(captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL, 620 captive_portal::RESULT_NO_RESPONSE); 621 EXPECT_FALSE(tab_helper().IsLoginTab()); 622 623 ObservePortalResult(captive_portal::RESULT_NO_RESPONSE, 624 captive_portal::RESULT_INTERNET_CONNECTED); 625 EXPECT_FALSE(tab_helper().IsLoginTab()); 626 } 627