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