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 <map> 6 #include <set> 7 8 #include "base/basictypes.h" 9 #include "base/bind.h" 10 #include "base/command_line.h" 11 #include "base/compiler_specific.h" 12 #include "base/files/file_path.h" 13 #include "base/message_loop/message_loop.h" 14 #include "base/path_service.h" 15 #include "base/prefs/pref_service.h" 16 #include "base/strings/utf_string_conversions.h" 17 #include "chrome/browser/captive_portal/captive_portal_service.h" 18 #include "chrome/browser/captive_portal/captive_portal_service_factory.h" 19 #include "chrome/browser/captive_portal/captive_portal_tab_helper.h" 20 #include "chrome/browser/captive_portal/captive_portal_tab_reloader.h" 21 #include "chrome/browser/chrome_notification_types.h" 22 #include "chrome/browser/net/url_request_mock_util.h" 23 #include "chrome/browser/profiles/profile.h" 24 #include "chrome/browser/ui/browser.h" 25 #include "chrome/browser/ui/browser_commands.h" 26 #include "chrome/browser/ui/browser_finder.h" 27 #include "chrome/browser/ui/browser_navigator.h" 28 #include "chrome/browser/ui/tab_contents/tab_contents_iterator.h" 29 #include "chrome/browser/ui/tabs/tab_strip_model.h" 30 #include "chrome/common/chrome_paths.h" 31 #include "chrome/common/chrome_switches.h" 32 #include "chrome/common/pref_names.h" 33 #include "chrome/test/base/in_process_browser_test.h" 34 #include "chrome/test/base/ui_test_utils.h" 35 #include "content/public/browser/browser_thread.h" 36 #include "content/public/browser/navigation_controller.h" 37 #include "content/public/browser/notification_observer.h" 38 #include "content/public/browser/notification_registrar.h" 39 #include "content/public/browser/notification_service.h" 40 #include "content/public/browser/notification_types.h" 41 #include "content/public/browser/render_frame_host.h" 42 #include "content/public/browser/web_contents.h" 43 #include "content/public/common/url_constants.h" 44 #include "net/base/net_errors.h" 45 #include "net/http/transport_security_state.h" 46 #include "net/test/url_request/url_request_failed_job.h" 47 #include "net/test/url_request/url_request_mock_http_job.h" 48 #include "net/url_request/url_request.h" 49 #include "net/url_request/url_request_context.h" 50 #include "net/url_request/url_request_context_getter.h" 51 #include "net/url_request/url_request_filter.h" 52 #include "net/url_request/url_request_job.h" 53 #include "net/url_request/url_request_status.h" 54 #include "testing/gtest/include/gtest/gtest.h" 55 56 using captive_portal::CaptivePortalResult; 57 using content::BrowserThread; 58 using content::WebContents; 59 using net::URLRequestFailedJob; 60 using net::URLRequestMockHTTPJob; 61 62 namespace { 63 64 // Path of the fake login page, when using the TestServer. 65 const char* const kTestServerLoginPath = "files/captive_portal/login.html"; 66 67 // Path of a page with an iframe that has a mock SSL timeout, when using the 68 // TestServer. 69 const char* const kTestServerIframeTimeoutPath = 70 "files/captive_portal/iframe_timeout.html"; 71 72 // The following URLs each have two different behaviors, depending on whether 73 // URLRequestMockCaptivePortalJobFactory is currently simulating the presence 74 // of a captive portal or not. They use different domains so that HSTS can be 75 // applied to them independently. 76 77 // A mock URL for the CaptivePortalService's |test_url|. When behind a captive 78 // portal, this URL returns a mock login page. When connected to the Internet, 79 // it returns a 204 response. Uses the name of the login file so that reloading 80 // it will not request a different URL. 81 const char* const kMockCaptivePortalTestUrl = 82 "http://mock.captive.portal.test/login.html"; 83 84 // Another mock URL for the CaptivePortalService's |test_url|. When behind a 85 // captive portal, this URL returns a 511 status code and an HTML page that 86 // redirect to the above URL. When connected to the Internet, it returns a 204 87 // response. 88 const char* const kMockCaptivePortal511Url = 89 "http://mock.captive.portal.511/page511.html"; 90 91 // When behind a captive portal, this URL hangs without committing until a call 92 // to URLRequestTimeoutOnDemandJob::FailJobs. When that function is called, 93 // the request will time out. 94 // 95 // When connected to the Internet, this URL returns a non-error page. 96 const char* const kMockHttpsUrl = 97 "https://mock.captive.portal.long.timeout/title2.html"; 98 99 // Same as above, but different domain, so can be used to trigger cross-site 100 // navigations. 101 const char* const kMockHttpsUrl2 = 102 "https://mock.captive.portal.long.timeout2/title2.html"; 103 104 // Same as kMockHttpsUrl, except the timeout happens instantly. 105 const char* const kMockHttpsQuickTimeoutUrl = 106 "https://mock.captive.portal.quick.timeout/title2.html"; 107 108 // Expected title of a tab once an HTTPS load completes, when not behind a 109 // captive portal. 110 const char* const kInternetConnectedTitle = "Title Of Awesomeness"; 111 112 // A URL request job that hangs until FailJobs() is called. Started jobs 113 // are stored in a static class variable containing a linked list so that 114 // FailJobs() can locate them. 115 class URLRequestTimeoutOnDemandJob : public net::URLRequestJob, 116 public base::NonThreadSafe { 117 public: 118 // net::URLRequestJob: 119 virtual void Start() OVERRIDE; 120 121 // All the public static methods below can be called on any thread. 122 123 // Waits for exactly |num_jobs|. 124 static void WaitForJobs(int num_jobs); 125 126 // Fails all active URLRequestTimeoutOnDemandJobs with connection timeouts. 127 // There are expected to be exactly |expected_num_jobs| waiting for 128 // failure. The only way to gaurantee this is with an earlier call to 129 // WaitForJobs, so makes sure there has been a matching WaitForJobs call. 130 static void FailJobs(int expected_num_jobs); 131 132 // Abandon all active URLRequestTimeoutOnDemandJobs. |expected_num_jobs| 133 // behaves just as in FailJobs. 134 static void AbandonJobs(int expected_num_jobs); 135 136 private: 137 friend class URLRequestMockCaptivePortalJobFactory; 138 139 // Operation to perform on jobs when removing them from |job_list_|. 140 enum EndJobOperation { 141 FAIL_JOBS, 142 ABANDON_JOBS, 143 }; 144 145 URLRequestTimeoutOnDemandJob(net::URLRequest* request, 146 net::NetworkDelegate* network_delegate); 147 virtual ~URLRequestTimeoutOnDemandJob(); 148 149 // Attempts to removes |this| from |jobs_|. Returns true if it was removed 150 // from the list. 151 bool RemoveFromList(); 152 153 static void WaitForJobsOnIOThread(int num_jobs); 154 static void FailOrAbandonJobsOnIOThread( 155 int expected_num_jobs, 156 EndJobOperation end_job_operation); 157 158 // Checks if there are at least |num_jobs_to_wait_for_| jobs in 159 // |job_list_|. If so, exits the message loop on the UI thread, which 160 // should be spinning in a call to WaitForJobs. Does nothing when 161 // |num_jobs_to_wait_for_| is 0. 162 static void MaybeStopWaitingForJobsOnIOThread(); 163 164 // All class variables are only accessed on the IO thread. 165 166 // Number of jobs currently being waited for, or 0 if not currently 167 // waiting for jobs. 168 static int num_jobs_to_wait_for_; 169 170 // The last number of jobs that were waited for. When FailJobs or 171 // AbandonJobs is called, this should match |expected_num_jobs|. 172 static int last_num_jobs_to_wait_for_; 173 174 // Number of jobs that have been started, but not yet waited for. If jobs 175 // are deleted unexpectedly, they're still included in this count, even though 176 // they've been removed from |job_list_|. Intended to reduce chance of stalls 177 // on regressions. 178 static int num_jobs_started_; 179 180 // Head of linked list of jobs that have been started and are now waiting to 181 // be timed out. 182 static URLRequestTimeoutOnDemandJob* job_list_; 183 184 // The next job that had been started but not yet timed out. 185 URLRequestTimeoutOnDemandJob* next_job_; 186 187 DISALLOW_COPY_AND_ASSIGN(URLRequestTimeoutOnDemandJob); 188 }; 189 190 int URLRequestTimeoutOnDemandJob::num_jobs_to_wait_for_ = 0; 191 int URLRequestTimeoutOnDemandJob::last_num_jobs_to_wait_for_ = 0; 192 int URLRequestTimeoutOnDemandJob::num_jobs_started_ = 0; 193 URLRequestTimeoutOnDemandJob* URLRequestTimeoutOnDemandJob::job_list_ = NULL; 194 195 void URLRequestTimeoutOnDemandJob::Start() { 196 EXPECT_TRUE(CalledOnValidThread()); 197 198 // Insert at start of the list. 199 next_job_ = job_list_; 200 job_list_ = this; 201 ++num_jobs_started_; 202 203 // Checks if there are at least |num_jobs_to_wait_for_| jobs in 204 // |job_list_|. If so, exits the message loop on the UI thread, which 205 // should be spinning in a call to WaitForJobs. Does nothing if 206 // |num_jobs_to_wait_for_| is 0. 207 MaybeStopWaitingForJobsOnIOThread(); 208 } 209 210 // static 211 void URLRequestTimeoutOnDemandJob::WaitForJobs(int num_jobs) { 212 content::BrowserThread::PostTask( 213 content::BrowserThread::IO, FROM_HERE, 214 base::Bind(&URLRequestTimeoutOnDemandJob::WaitForJobsOnIOThread, 215 num_jobs)); 216 content::RunMessageLoop(); 217 } 218 219 // static 220 void URLRequestTimeoutOnDemandJob::FailJobs(int expected_num_jobs) { 221 content::BrowserThread::PostTask( 222 content::BrowserThread::IO, FROM_HERE, 223 base::Bind(&URLRequestTimeoutOnDemandJob::FailOrAbandonJobsOnIOThread, 224 expected_num_jobs, 225 FAIL_JOBS)); 226 } 227 228 // static 229 void URLRequestTimeoutOnDemandJob::AbandonJobs(int expected_num_jobs) { 230 content::BrowserThread::PostTask( 231 content::BrowserThread::IO, FROM_HERE, 232 base::Bind(&URLRequestTimeoutOnDemandJob::FailOrAbandonJobsOnIOThread, 233 expected_num_jobs, 234 ABANDON_JOBS)); 235 } 236 237 URLRequestTimeoutOnDemandJob::URLRequestTimeoutOnDemandJob( 238 net::URLRequest* request, net::NetworkDelegate* network_delegate) 239 : net::URLRequestJob(request, network_delegate), 240 next_job_(NULL) { 241 } 242 243 URLRequestTimeoutOnDemandJob::~URLRequestTimeoutOnDemandJob() { 244 // All hanging jobs should have failed or been abandoned before being 245 // destroyed. 246 EXPECT_FALSE(RemoveFromList()); 247 } 248 249 bool URLRequestTimeoutOnDemandJob::RemoveFromList() { 250 URLRequestTimeoutOnDemandJob** job = &job_list_; 251 while (*job) { 252 if (*job == this) { 253 *job = next_job_; 254 next_job_ = NULL; 255 return true; 256 } 257 job = &next_job_; 258 } 259 260 // If the job wasn't in this list, |next_job_| should be NULL. 261 EXPECT_FALSE(next_job_); 262 return false; 263 } 264 265 // static 266 void URLRequestTimeoutOnDemandJob::WaitForJobsOnIOThread(int num_jobs) { 267 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO)); 268 ASSERT_EQ(0, num_jobs_to_wait_for_); 269 ASSERT_LT(0, num_jobs); 270 // Number of tabs being waited on should be strictly increasing. 271 ASSERT_LE(last_num_jobs_to_wait_for_, num_jobs); 272 273 num_jobs_to_wait_for_ = num_jobs; 274 MaybeStopWaitingForJobsOnIOThread(); 275 } 276 277 // static 278 void URLRequestTimeoutOnDemandJob::MaybeStopWaitingForJobsOnIOThread() { 279 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO)); 280 if (num_jobs_to_wait_for_ == 0) 281 return; 282 283 // There shouldn't be any extra jobs. 284 EXPECT_LE(num_jobs_started_, num_jobs_to_wait_for_); 285 286 // Should never be greater, but if it is, go ahead and exit the message loop 287 // to try and avoid hanging. 288 if (num_jobs_started_ >= num_jobs_to_wait_for_) { 289 last_num_jobs_to_wait_for_ = num_jobs_to_wait_for_; 290 num_jobs_to_wait_for_ = 0; 291 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, 292 base::MessageLoop::QuitClosure()); 293 } 294 } 295 296 // static 297 void URLRequestTimeoutOnDemandJob::FailOrAbandonJobsOnIOThread( 298 int expected_num_jobs, 299 EndJobOperation end_job_operation) { 300 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO)); 301 ASSERT_LT(0, expected_num_jobs); 302 EXPECT_EQ(last_num_jobs_to_wait_for_, expected_num_jobs); 303 last_num_jobs_to_wait_for_ = 0; 304 305 int num_jobs = 0; 306 while (job_list_) { 307 ++num_jobs; 308 URLRequestTimeoutOnDemandJob* job = job_list_; 309 // Since the error notification may result in the job's destruction, remove 310 // it from the job list before the error. 311 EXPECT_TRUE(job->RemoveFromList()); 312 if (end_job_operation == FAIL_JOBS) { 313 job->NotifyStartError(net::URLRequestStatus( 314 net::URLRequestStatus::FAILED, 315 net::ERR_CONNECTION_TIMED_OUT)); 316 } 317 } 318 319 EXPECT_EQ(expected_num_jobs, num_jobs_started_); 320 EXPECT_EQ(expected_num_jobs, num_jobs); 321 322 num_jobs_started_ -= expected_num_jobs; 323 } 324 325 // URLRequestCaptivePortalJobFactory emulates captive portal behavior. 326 // Initially, it emulates being behind a captive portal. When 327 // SetBehindCaptivePortal(false) is called, it emulates behavior when not behind 328 // a captive portal. The class itself is never instantiated. 329 // 330 // It handles requests for kMockCaptivePortalTestUrl, kMockHttpsUrl, and 331 // kMockHttpsQuickTimeoutUrl. 332 class URLRequestMockCaptivePortalJobFactory { 333 public: 334 // The public static methods below can be called on any thread. 335 336 // Adds the testing URLs to the net::URLRequestFilter. Should only be called 337 // once. 338 static void AddUrlHandlers(); 339 340 // Sets whether or not there is a captive portal. Outstanding requests are 341 // not affected. 342 static void SetBehindCaptivePortal(bool behind_captive_portal); 343 344 private: 345 // These do all the work of the corresponding public functions, with the only 346 // difference being that they must be called on the IO thread. 347 static void AddUrlHandlersOnIOThread(); 348 static void SetBehindCaptivePortalOnIOThread(bool behind_captive_portal); 349 350 // Returns a URLRequestJob that reflects the current captive portal state 351 // for the URLs: kMockCaptivePortalTestUrl, kMockHttpsUrl, and 352 // kMockHttpsQuickTimeoutUrl. See documentation of individual URLs for 353 // actual behavior. 354 static net::URLRequestJob* Factory(net::URLRequest* request, 355 net::NetworkDelegate* network_delegate, 356 const std::string& scheme); 357 358 static bool behind_captive_portal_; 359 360 DISALLOW_IMPLICIT_CONSTRUCTORS(URLRequestMockCaptivePortalJobFactory); 361 }; 362 363 bool URLRequestMockCaptivePortalJobFactory::behind_captive_portal_ = true; 364 365 // static 366 void URLRequestMockCaptivePortalJobFactory::AddUrlHandlers() { 367 content::BrowserThread::PostTask( 368 content::BrowserThread::IO, FROM_HERE, 369 base::Bind( 370 &URLRequestMockCaptivePortalJobFactory::AddUrlHandlersOnIOThread)); 371 } 372 373 // static 374 void URLRequestMockCaptivePortalJobFactory::SetBehindCaptivePortal( 375 bool behind_captive_portal) { 376 content::BrowserThread::PostTask( 377 content::BrowserThread::IO, FROM_HERE, 378 base::Bind( 379 &URLRequestMockCaptivePortalJobFactory:: 380 SetBehindCaptivePortalOnIOThread, 381 behind_captive_portal)); 382 } 383 384 // static 385 void URLRequestMockCaptivePortalJobFactory::AddUrlHandlersOnIOThread() { 386 EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO)); 387 388 // Handle only exact matches, so any related requests, such as those for 389 // favicons, are not handled by the factory. 390 net::URLRequestFilter* filter = net::URLRequestFilter::GetInstance(); 391 filter->AddUrlHandler(GURL(kMockCaptivePortalTestUrl), 392 URLRequestMockCaptivePortalJobFactory::Factory); 393 filter->AddUrlHandler(GURL(kMockCaptivePortal511Url), 394 URLRequestMockCaptivePortalJobFactory::Factory); 395 filter->AddUrlHandler(GURL(kMockHttpsUrl), 396 URLRequestMockCaptivePortalJobFactory::Factory); 397 filter->AddUrlHandler(GURL(kMockHttpsUrl2), 398 URLRequestMockCaptivePortalJobFactory::Factory); 399 filter->AddUrlHandler(GURL(kMockHttpsQuickTimeoutUrl), 400 URLRequestMockCaptivePortalJobFactory::Factory); 401 } 402 403 // static 404 void URLRequestMockCaptivePortalJobFactory::SetBehindCaptivePortalOnIOThread( 405 bool behind_captive_portal) { 406 EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO)); 407 behind_captive_portal_ = behind_captive_portal; 408 } 409 410 // static 411 net::URLRequestJob* URLRequestMockCaptivePortalJobFactory::Factory( 412 net::URLRequest* request, 413 net::NetworkDelegate* network_delegate, 414 const std::string& scheme) { 415 EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO)); 416 417 // The PathService is threadsafe. 418 base::FilePath root_http; 419 PathService::Get(chrome::DIR_TEST_DATA, &root_http); 420 421 if (request->url() == GURL(kMockHttpsUrl) || 422 request->url() == GURL(kMockHttpsUrl2)) { 423 if (behind_captive_portal_) 424 return new URLRequestTimeoutOnDemandJob(request, network_delegate); 425 // Once logged in to the portal, HTTPS requests return the page that was 426 // actually requested. 427 return new URLRequestMockHTTPJob( 428 request, 429 network_delegate, 430 root_http.Append(FILE_PATH_LITERAL("title2.html")), 431 BrowserThread::GetBlockingPool()->GetTaskRunnerWithShutdownBehavior( 432 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN)); 433 } else if (request->url() == GURL(kMockHttpsQuickTimeoutUrl)) { 434 if (behind_captive_portal_) 435 return new URLRequestFailedJob( 436 request, network_delegate, net::ERR_CONNECTION_TIMED_OUT); 437 // Once logged in to the portal, HTTPS requests return the page that was 438 // actually requested. 439 return new URLRequestMockHTTPJob( 440 request, 441 network_delegate, 442 root_http.Append(FILE_PATH_LITERAL("title2.html")), 443 BrowserThread::GetBlockingPool()->GetTaskRunnerWithShutdownBehavior( 444 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN)); 445 } else { 446 // The URL should be the captive portal test URL. 447 EXPECT_TRUE(GURL(kMockCaptivePortalTestUrl) == request->url() || 448 GURL(kMockCaptivePortal511Url) == request->url()); 449 450 if (behind_captive_portal_) { 451 // Prior to logging in to the portal, the HTTP test URLs are intercepted 452 // by the captive portal. 453 if (GURL(kMockCaptivePortal511Url) == request->url()) { 454 return new URLRequestMockHTTPJob( 455 request, 456 network_delegate, 457 root_http.Append(FILE_PATH_LITERAL("captive_portal/page511.html")), 458 BrowserThread::GetBlockingPool()->GetTaskRunnerWithShutdownBehavior( 459 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN)); 460 } 461 return new URLRequestMockHTTPJob( 462 request, 463 network_delegate, 464 root_http.Append(FILE_PATH_LITERAL("captive_portal/login.html")), 465 BrowserThread::GetBlockingPool()->GetTaskRunnerWithShutdownBehavior( 466 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN)); 467 } 468 469 // After logging in to the portal, the test URLs return a 204 response. 470 return new URLRequestMockHTTPJob( 471 request, 472 network_delegate, 473 root_http.Append(FILE_PATH_LITERAL("captive_portal/page204.html")), 474 BrowserThread::GetBlockingPool()->GetTaskRunnerWithShutdownBehavior( 475 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN)); 476 } 477 } 478 479 // Creates a server-side redirect for use with the TestServer. 480 std::string CreateServerRedirect(const std::string& dest_url) { 481 const char* const kServerRedirectBase = "server-redirect?"; 482 return kServerRedirectBase + dest_url; 483 } 484 485 // Returns the total number of loading tabs across all Browsers, for all 486 // Profiles. 487 int NumLoadingTabs() { 488 int num_loading_tabs = 0; 489 for (TabContentsIterator it; !it.done(); it.Next()) { 490 if (it->IsLoading()) 491 ++num_loading_tabs; 492 } 493 return num_loading_tabs; 494 } 495 496 bool IsLoginTab(WebContents* web_contents) { 497 return CaptivePortalTabHelper::FromWebContents(web_contents)->IsLoginTab(); 498 } 499 500 // Tracks how many times each tab has been navigated since the Observer was 501 // created. The standard TestNavigationObserver can only watch specific 502 // pre-existing tabs or loads in serial for all tabs. 503 class MultiNavigationObserver : public content::NotificationObserver { 504 public: 505 MultiNavigationObserver(); 506 virtual ~MultiNavigationObserver(); 507 508 // Waits for exactly |num_navigations_to_wait_for| LOAD_STOP 509 // notifications to have occurred since the construction of |this|. More 510 // navigations than expected occuring will trigger a expect failure. 511 void WaitForNavigations(int num_navigations_to_wait_for); 512 513 // Returns the number of LOAD_STOP events that have occurred for 514 // |web_contents| since this was constructed. 515 int NumNavigationsForTab(WebContents* web_contents) const; 516 517 // The number of LOAD_STOP events since |this| was created. 518 int num_navigations() const { return num_navigations_; } 519 520 private: 521 typedef std::map<const WebContents*, int> TabNavigationMap; 522 523 // content::NotificationObserver: 524 virtual void Observe(int type, const content::NotificationSource& source, 525 const content::NotificationDetails& details) OVERRIDE; 526 527 int num_navigations_; 528 529 // Map of how many times each tab has navigated since |this| was created. 530 TabNavigationMap tab_navigation_map_; 531 532 // Total number of navigations to wait for. Value only matters when 533 // |waiting_for_navigation_| is true. 534 int num_navigations_to_wait_for_; 535 536 // True if WaitForNavigations has been called, until 537 // |num_navigations_to_wait_for_| have been observed. 538 bool waiting_for_navigation_; 539 540 content::NotificationRegistrar registrar_; 541 542 DISALLOW_COPY_AND_ASSIGN(MultiNavigationObserver); 543 }; 544 545 MultiNavigationObserver::MultiNavigationObserver() 546 : num_navigations_(0), 547 num_navigations_to_wait_for_(0), 548 waiting_for_navigation_(false) { 549 registrar_.Add(this, content::NOTIFICATION_LOAD_STOP, 550 content::NotificationService::AllSources()); 551 } 552 553 MultiNavigationObserver::~MultiNavigationObserver() { 554 } 555 556 void MultiNavigationObserver::WaitForNavigations( 557 int num_navigations_to_wait_for) { 558 // Shouldn't already be waiting for navigations. 559 EXPECT_FALSE(waiting_for_navigation_); 560 EXPECT_LT(0, num_navigations_to_wait_for); 561 if (num_navigations_ < num_navigations_to_wait_for) { 562 num_navigations_to_wait_for_ = num_navigations_to_wait_for; 563 waiting_for_navigation_ = true; 564 content::RunMessageLoop(); 565 EXPECT_FALSE(waiting_for_navigation_); 566 } 567 EXPECT_EQ(num_navigations_, num_navigations_to_wait_for); 568 } 569 570 int MultiNavigationObserver::NumNavigationsForTab( 571 WebContents* web_contents) const { 572 TabNavigationMap::const_iterator tab_navigations = 573 tab_navigation_map_.find(web_contents); 574 if (tab_navigations == tab_navigation_map_.end()) 575 return 0; 576 return tab_navigations->second; 577 } 578 579 void MultiNavigationObserver::Observe( 580 int type, 581 const content::NotificationSource& source, 582 const content::NotificationDetails& details) { 583 ASSERT_EQ(type, content::NOTIFICATION_LOAD_STOP); 584 content::NavigationController* controller = 585 content::Source<content::NavigationController>(source).ptr(); 586 ++num_navigations_; 587 ++tab_navigation_map_[controller->GetWebContents()]; 588 if (waiting_for_navigation_ && 589 num_navigations_to_wait_for_ == num_navigations_) { 590 waiting_for_navigation_ = false; 591 base::MessageLoopForUI::current()->Quit(); 592 } 593 } 594 595 // This observer creates a list of loading tabs, and then waits for them all 596 // to stop loading and have the kInternetConnectedTitle. 597 // 598 // This is for the specific purpose of observing tabs time out after logging in 599 // to a captive portal, which will then cause them to reload. 600 // MultiNavigationObserver is insufficient for this because there may or may not 601 // be a LOAD_STOP event between the timeout and the reload. 602 // See bug http://crbug.com/133227 603 class FailLoadsAfterLoginObserver : public content::NotificationObserver { 604 public: 605 FailLoadsAfterLoginObserver(); 606 virtual ~FailLoadsAfterLoginObserver(); 607 608 void WaitForNavigations(); 609 610 private: 611 typedef std::set<const WebContents*> TabSet; 612 613 // content::NotificationObserver: 614 virtual void Observe(int type, const content::NotificationSource& source, 615 const content::NotificationDetails& details) OVERRIDE; 616 617 // The set of tabs that need to be navigated. This is the set of loading 618 // tabs when the observer is created. 619 TabSet tabs_needing_navigation_; 620 621 // Number of tabs that have stopped navigating with the expected title. These 622 // are expected not to be navigated again. 623 TabSet tabs_navigated_to_final_destination_; 624 625 // True if WaitForNavigations has been called, until 626 // |tabs_navigated_to_final_destination_| equals |tabs_needing_navigation_|. 627 bool waiting_for_navigation_; 628 629 content::NotificationRegistrar registrar_; 630 631 DISALLOW_COPY_AND_ASSIGN(FailLoadsAfterLoginObserver); 632 }; 633 634 FailLoadsAfterLoginObserver::FailLoadsAfterLoginObserver() 635 : waiting_for_navigation_(false) { 636 registrar_.Add(this, content::NOTIFICATION_LOAD_STOP, 637 content::NotificationService::AllSources()); 638 for (TabContentsIterator it; !it.done(); it.Next()) { 639 if (it->IsLoading()) 640 tabs_needing_navigation_.insert(*it); 641 } 642 } 643 644 FailLoadsAfterLoginObserver::~FailLoadsAfterLoginObserver() { 645 } 646 647 void FailLoadsAfterLoginObserver::WaitForNavigations() { 648 // Shouldn't already be waiting for navigations. 649 EXPECT_FALSE(waiting_for_navigation_); 650 if (tabs_needing_navigation_.size() != 651 tabs_navigated_to_final_destination_.size()) { 652 waiting_for_navigation_ = true; 653 content::RunMessageLoop(); 654 EXPECT_FALSE(waiting_for_navigation_); 655 } 656 EXPECT_EQ(tabs_needing_navigation_.size(), 657 tabs_navigated_to_final_destination_.size()); 658 } 659 660 void FailLoadsAfterLoginObserver::Observe( 661 int type, 662 const content::NotificationSource& source, 663 const content::NotificationDetails& details) { 664 ASSERT_EQ(type, content::NOTIFICATION_LOAD_STOP); 665 content::NavigationController* controller = 666 content::Source<content::NavigationController>(source).ptr(); 667 WebContents* contents = controller->GetWebContents(); 668 669 ASSERT_EQ(1u, tabs_needing_navigation_.count(contents)); 670 ASSERT_EQ(0u, tabs_navigated_to_final_destination_.count(contents)); 671 672 if (contents->GetTitle() != base::ASCIIToUTF16(kInternetConnectedTitle)) 673 return; 674 tabs_navigated_to_final_destination_.insert(contents); 675 676 if (waiting_for_navigation_ && 677 tabs_needing_navigation_.size() == 678 tabs_navigated_to_final_destination_.size()) { 679 waiting_for_navigation_ = false; 680 base::MessageLoopForUI::current()->Quit(); 681 } 682 } 683 684 // An observer for watching the CaptivePortalService. It tracks the last 685 // received result and the total number of received results. 686 class CaptivePortalObserver : public content::NotificationObserver { 687 public: 688 explicit CaptivePortalObserver(Profile* profile); 689 690 // Runs the message loop until until at exactly |update_count| capitive portal 691 // results have been received, since this creation of |this|. Expects no 692 // additional captive portal results. 693 void WaitForResults(int num_results_to_wait_for); 694 695 int num_results_received() const { return num_results_received_; } 696 697 CaptivePortalResult captive_portal_result() const { 698 return captive_portal_result_; 699 } 700 701 private: 702 // Records results and exits the message loop, if needed. 703 virtual void Observe(int type, 704 const content::NotificationSource& source, 705 const content::NotificationDetails& details) OVERRIDE; 706 707 // Number of times OnPortalResult has been called since construction. 708 int num_results_received_; 709 710 // If WaitForResults was called, the total number of updates for which to 711 // wait. Value doesn't matter when |waiting_for_result_| is false. 712 int num_results_to_wait_for_; 713 714 bool waiting_for_result_; 715 716 Profile* profile_; 717 718 CaptivePortalService* captive_portal_service_; 719 720 // Last result received. 721 CaptivePortalResult captive_portal_result_; 722 723 content::NotificationRegistrar registrar_; 724 725 DISALLOW_COPY_AND_ASSIGN(CaptivePortalObserver); 726 }; 727 728 CaptivePortalObserver::CaptivePortalObserver(Profile* profile) 729 : num_results_received_(0), 730 num_results_to_wait_for_(0), 731 waiting_for_result_(false), 732 profile_(profile), 733 captive_portal_service_( 734 CaptivePortalServiceFactory::GetForProfile(profile)), 735 captive_portal_result_( 736 captive_portal_service_->last_detection_result()) { 737 registrar_.Add(this, 738 chrome::NOTIFICATION_CAPTIVE_PORTAL_CHECK_RESULT, 739 content::Source<Profile>(profile_)); 740 } 741 742 void CaptivePortalObserver::WaitForResults(int num_results_to_wait_for) { 743 EXPECT_LT(0, num_results_to_wait_for); 744 EXPECT_FALSE(waiting_for_result_); 745 if (num_results_received_ < num_results_to_wait_for) { 746 num_results_to_wait_for_ = num_results_to_wait_for; 747 waiting_for_result_ = true; 748 content::RunMessageLoop(); 749 EXPECT_FALSE(waiting_for_result_); 750 } 751 EXPECT_EQ(num_results_to_wait_for, num_results_received_); 752 } 753 754 void CaptivePortalObserver::Observe( 755 int type, 756 const content::NotificationSource& source, 757 const content::NotificationDetails& details) { 758 ASSERT_EQ(type, chrome::NOTIFICATION_CAPTIVE_PORTAL_CHECK_RESULT); 759 ASSERT_EQ(profile_, content::Source<Profile>(source).ptr()); 760 761 CaptivePortalService::Results* results = 762 content::Details<CaptivePortalService::Results>(details).ptr(); 763 764 EXPECT_EQ(captive_portal_result_, results->previous_result); 765 EXPECT_EQ(captive_portal_service_->last_detection_result(), 766 results->result); 767 768 captive_portal_result_ = results->result; 769 ++num_results_received_; 770 771 if (waiting_for_result_ && 772 num_results_to_wait_for_ == num_results_received_) { 773 waiting_for_result_ = false; 774 base::MessageLoop::current()->Quit(); 775 } 776 } 777 778 // Adds an HSTS rule for |host|, so that all HTTP requests sent to it will 779 // be switched to HTTPS requests. 780 void AddHstsHost(net::URLRequestContextGetter* context_getter, 781 const std::string& host) { 782 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO)); 783 net::TransportSecurityState* transport_security_state = 784 context_getter->GetURLRequestContext()->transport_security_state(); 785 if (!transport_security_state) { 786 FAIL(); 787 return; 788 } 789 790 base::Time expiry = base::Time::Now() + base::TimeDelta::FromDays(1000); 791 bool include_subdomains = false; 792 transport_security_state->AddHSTS(host, expiry, include_subdomains); 793 } 794 795 } // namespace 796 797 class CaptivePortalBrowserTest : public InProcessBrowserTest { 798 public: 799 CaptivePortalBrowserTest(); 800 801 // InProcessBrowserTest: 802 virtual void SetUpOnMainThread() OVERRIDE; 803 virtual void TearDownOnMainThread() OVERRIDE; 804 805 // Sets the captive portal checking preference. Does not affect the command 806 // line flag, which is set in SetUpCommandLine. 807 void EnableCaptivePortalDetection(Profile* profile, bool enabled); 808 809 // Sets up the captive portal service for the given profile so that 810 // all checks go to |test_url|. Also disables all timers. 811 void SetUpCaptivePortalService(Profile* profile, const GURL& test_url); 812 813 // Returns true if |browser|'s profile is currently running a captive portal 814 // check. 815 bool CheckPending(Browser* browser); 816 817 // Returns the CaptivePortalTabReloader::State of |web_contents|. 818 CaptivePortalTabReloader::State GetStateOfTabReloader( 819 WebContents* web_contents) const; 820 821 // Returns the CaptivePortalTabReloader::State of the indicated tab. 822 CaptivePortalTabReloader::State GetStateOfTabReloaderAt(Browser* browser, 823 int index) const; 824 825 // Returns the number of tabs with the given state, across all profiles. 826 int NumTabsWithState(CaptivePortalTabReloader::State state) const; 827 828 // Returns the number of tabs broken by captive portals, across all profiles. 829 int NumBrokenTabs() const; 830 831 // Returns the number of tabs that need to be reloaded due to having logged 832 // in to a captive portal, across all profiles. 833 int NumNeedReloadTabs() const; 834 835 // Navigates |browser|'s active tab to |url| and expects no captive portal 836 // test to be triggered. |expected_navigations| is the number of times the 837 // active tab will end up being navigated. It should be 1, except for the 838 // Link Doctor page, which acts like two navigations. 839 void NavigateToPageExpectNoTest(Browser* browser, 840 const GURL& url, 841 int expected_navigations); 842 843 // Navigates |browser|'s active tab to an SSL tab that takes a while to load, 844 // triggering a captive portal check, which is expected to give the result 845 // |expected_result|. The page finishes loading, with a timeout, after the 846 // captive portal check. 847 void SlowLoadNoCaptivePortal(Browser* browser, 848 CaptivePortalResult expected_result); 849 850 // Navigates |browser|'s active tab to an SSL timeout, expecting a captive 851 // portal check to be triggered and return a result which will indicates 852 // there's no detected captive portal. 853 void FastTimeoutNoCaptivePortal(Browser* browser, 854 CaptivePortalResult expected_result); 855 856 // Navigates the active tab to a slow loading SSL page, which will then 857 // trigger a captive portal test. The test is expected to find a captive 858 // portal. The slow loading page will continue to load after the function 859 // returns, until URLRequestTimeoutOnDemandJob::FailJobs() is called, 860 // at which point it will timeout. 861 // 862 // When |expect_login_tab| is false, no login tab is expected to be opened, 863 // because one already exists, and the function returns once the captive 864 // portal test is complete. 865 // 866 // If |expect_login_tab| is true, a login tab is then expected to be opened. 867 // It waits until both the login tab has finished loading, and two captive 868 // portal tests complete. The second test is triggered by the load of the 869 // captive portal tab completing. 870 // 871 // This function must not be called when the active tab is currently loading. 872 // Waits for the hanging request to be issued, so other functions can rely 873 // on URLRequestTimeoutOnDemandJob::WaitForJobs having been called. 874 void SlowLoadBehindCaptivePortal(Browser* browser, bool expect_login_tab); 875 876 // Same as above, but takes extra parameters. 877 // 878 // |hanging_url| should either be kMockHttpsUrl or redirect to kMockHttpsUrl. 879 // 880 // |expected_portal_checks| and |expected_login_tab_navigations| allow 881 // client-side redirects to be tested. |expected_login_tab_navigations| is 882 // ignored when |expect_open_login_tab| is false. 883 void SlowLoadBehindCaptivePortal(Browser* browser, 884 bool expect_open_login_tab, 885 const GURL& hanging_url, 886 int expected_portal_checks, 887 int expected_login_tab_navigations); 888 889 // Just like SlowLoadBehindCaptivePortal, except the navigated tab has 890 // a connection timeout rather having its time trigger, and the function 891 // waits until that timeout occurs. 892 void FastTimeoutBehindCaptivePortal(Browser* browser, 893 bool expect_open_login_tab); 894 895 // Much as above, but accepts a URL parameter and can be used for errors that 896 // trigger captive portal checks other than timeouts. |error_url| should 897 // result in an error rather than hanging. 898 void FastErrorBehindCaptivePortal(Browser* browser, 899 bool expect_open_login_tab, 900 const GURL& error_url); 901 902 // Navigates the login tab without logging in. The login tab must be the 903 // specified browser's active tab. Expects no other tab to change state. 904 // |num_loading_tabs| and |num_timed_out_tabs| are used as extra checks 905 // that nothing has gone wrong prior to the function call. 906 void NavigateLoginTab(Browser* browser, 907 int num_loading_tabs, 908 int num_timed_out_tabs); 909 910 // Simulates a login by updating the URLRequestMockCaptivePortalJob's 911 // behind captive portal state, and navigating the login tab. Waits for 912 // all broken but not loading tabs to be reloaded. 913 // |num_loading_tabs| and |num_timed_out_tabs| are used as extra checks 914 // that nothing has gone wrong prior to the function call. 915 void Login(Browser* browser, int num_loading_tabs, int num_timed_out_tabs); 916 917 // Makes the slow SSL loads of all active tabs time out at once, and waits for 918 // them to finish both that load and the automatic reload it should trigger. 919 // There should be no timed out tabs when this is called. 920 void FailLoadsAfterLogin(Browser* browser, int num_loading_tabs); 921 922 // Makes the slow SSL loads of all active tabs time out at once, and waits for 923 // them to finish displaying their error pages. The login tab should be the 924 // active tab. There should be no timed out tabs when this is called. 925 void FailLoadsWithoutLogin(Browser* browser, int num_loading_tabs); 926 927 // Navigates |browser|'s active tab to |starting_url| while not behind a 928 // captive portal. Then navigates to |interrupted_url|, which should create 929 // a URLRequestTimeoutOnDemandJob, which is then abandoned. The load should 930 // trigger a captive portal check, which finds a captive portal and opens a 931 // tab. 932 // 933 // Then the navigation is interrupted by a navigation to |timeout_url|, which 934 // should trigger a captive portal check, and finally the test simulates 935 // logging in. 936 // 937 // The purpose of this test is to make sure the TabHelper triggers a captive 938 // portal check when a load is interrupted by another load, particularly in 939 // the case of cross-process navigations. 940 void RunNavigateLoadingTabToTimeoutTest(Browser* browser, 941 const GURL& starting_url, 942 const GURL& interrupted_url, 943 const GURL& timeout_url); 944 945 // Sets the timeout used by a CaptivePortalTabReloader on slow SSL loads 946 // before a captive portal check. 947 void SetSlowSSLLoadTime(CaptivePortalTabReloader* tab_reloader, 948 base::TimeDelta slow_ssl_load_time); 949 950 CaptivePortalTabReloader* GetTabReloader(WebContents* web_contents) const; 951 952 private: 953 DISALLOW_COPY_AND_ASSIGN(CaptivePortalBrowserTest); 954 }; 955 956 CaptivePortalBrowserTest::CaptivePortalBrowserTest() { 957 } 958 959 void CaptivePortalBrowserTest::SetUpOnMainThread() { 960 // Enable mock requests. 961 content::BrowserThread::PostTask( 962 content::BrowserThread::IO, FROM_HERE, 963 base::Bind(&chrome_browser_net::SetUrlRequestMocksEnabled, true)); 964 URLRequestMockCaptivePortalJobFactory::AddUrlHandlers(); 965 966 // Double-check that the captive portal service isn't enabled by default for 967 // browser tests. 968 EXPECT_EQ(CaptivePortalService::DISABLED_FOR_TESTING, 969 CaptivePortalService::get_state_for_testing()); 970 971 CaptivePortalService::set_state_for_testing( 972 CaptivePortalService::SKIP_OS_CHECK_FOR_TESTING); 973 EnableCaptivePortalDetection(browser()->profile(), true); 974 975 // Set the captive portal service to use URLRequestMockCaptivePortalJob's 976 // mock URL, by default. 977 SetUpCaptivePortalService(browser()->profile(), 978 GURL(kMockCaptivePortalTestUrl)); 979 } 980 981 void CaptivePortalBrowserTest::TearDownOnMainThread() { 982 // No test should have a captive portal check pending on quit. 983 EXPECT_FALSE(CheckPending(browser())); 984 } 985 986 void CaptivePortalBrowserTest::EnableCaptivePortalDetection( 987 Profile* profile, bool enabled) { 988 profile->GetPrefs()->SetBoolean(prefs::kAlternateErrorPagesEnabled, enabled); 989 } 990 991 void CaptivePortalBrowserTest::SetUpCaptivePortalService(Profile* profile, 992 const GURL& test_url) { 993 CaptivePortalService* captive_portal_service = 994 CaptivePortalServiceFactory::GetForProfile(profile); 995 captive_portal_service->set_test_url(test_url); 996 997 // Don't use any non-zero timers. Timers are checked in unit tests. 998 CaptivePortalService::RecheckPolicy* recheck_policy = 999 &captive_portal_service->recheck_policy(); 1000 recheck_policy->initial_backoff_no_portal_ms = 0; 1001 recheck_policy->initial_backoff_portal_ms = 0; 1002 recheck_policy->backoff_policy.maximum_backoff_ms = 0; 1003 } 1004 1005 bool CaptivePortalBrowserTest::CheckPending(Browser* browser) { 1006 CaptivePortalService* captive_portal_service = 1007 CaptivePortalServiceFactory::GetForProfile(browser->profile()); 1008 1009 return captive_portal_service->DetectionInProgress() || 1010 captive_portal_service->TimerRunning(); 1011 } 1012 1013 CaptivePortalTabReloader::State CaptivePortalBrowserTest::GetStateOfTabReloader( 1014 WebContents* web_contents) const { 1015 return GetTabReloader(web_contents)->state(); 1016 } 1017 1018 CaptivePortalTabReloader::State 1019 CaptivePortalBrowserTest::GetStateOfTabReloaderAt(Browser* browser, 1020 int index) const { 1021 return GetStateOfTabReloader( 1022 browser->tab_strip_model()->GetWebContentsAt(index)); 1023 } 1024 1025 int CaptivePortalBrowserTest::NumTabsWithState( 1026 CaptivePortalTabReloader::State state) const { 1027 int num_tabs = 0; 1028 for (TabContentsIterator it; !it.done(); it.Next()) { 1029 if (GetStateOfTabReloader(*it) == state) 1030 ++num_tabs; 1031 } 1032 return num_tabs; 1033 } 1034 1035 int CaptivePortalBrowserTest::NumBrokenTabs() const { 1036 return NumTabsWithState(CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL); 1037 } 1038 1039 int CaptivePortalBrowserTest::NumNeedReloadTabs() const { 1040 return NumTabsWithState(CaptivePortalTabReloader::STATE_NEEDS_RELOAD); 1041 } 1042 1043 void CaptivePortalBrowserTest::NavigateToPageExpectNoTest( 1044 Browser* browser, 1045 const GURL& url, 1046 int expected_navigations) { 1047 MultiNavigationObserver navigation_observer; 1048 CaptivePortalObserver portal_observer(browser->profile()); 1049 1050 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete( 1051 browser, url, expected_navigations); 1052 1053 // No captive portal checks should have ocurred or be pending, and there 1054 // should be no new tabs. 1055 EXPECT_EQ(0, portal_observer.num_results_received()); 1056 EXPECT_FALSE(CheckPending(browser)); 1057 EXPECT_EQ(1, browser->tab_strip_model()->count()); 1058 EXPECT_EQ(expected_navigations, navigation_observer.num_navigations()); 1059 EXPECT_EQ(0, NumLoadingTabs()); 1060 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, 1061 GetStateOfTabReloaderAt(browser, 0)); 1062 } 1063 1064 void CaptivePortalBrowserTest::SlowLoadNoCaptivePortal( 1065 Browser* browser, 1066 CaptivePortalResult expected_result) { 1067 CaptivePortalTabReloader* tab_reloader = 1068 GetTabReloader(browser->tab_strip_model()->GetActiveWebContents()); 1069 ASSERT_TRUE(tab_reloader); 1070 SetSlowSSLLoadTime(tab_reloader, base::TimeDelta()); 1071 1072 MultiNavigationObserver navigation_observer; 1073 CaptivePortalObserver portal_observer(browser->profile()); 1074 ui_test_utils::NavigateToURLWithDisposition(browser, 1075 GURL(kMockHttpsUrl), 1076 CURRENT_TAB, 1077 ui_test_utils::BROWSER_TEST_NONE); 1078 1079 portal_observer.WaitForResults(1); 1080 1081 ASSERT_EQ(1, browser->tab_strip_model()->count()); 1082 EXPECT_EQ(expected_result, portal_observer.captive_portal_result()); 1083 EXPECT_EQ(1, portal_observer.num_results_received()); 1084 EXPECT_EQ(0, navigation_observer.num_navigations()); 1085 EXPECT_FALSE(CheckPending(browser)); 1086 1087 // First tab should still be loading. 1088 EXPECT_EQ(1, NumLoadingTabs()); 1089 1090 // Wait for the request to be issued, then time it out. 1091 URLRequestTimeoutOnDemandJob::WaitForJobs(1); 1092 URLRequestTimeoutOnDemandJob::FailJobs(1); 1093 navigation_observer.WaitForNavigations(1); 1094 1095 ASSERT_EQ(1, browser->tab_strip_model()->count()); 1096 EXPECT_EQ(1, portal_observer.num_results_received()); 1097 EXPECT_FALSE(CheckPending(browser)); 1098 EXPECT_EQ(0, NumLoadingTabs()); 1099 1100 // Set a slow SSL load time to prevent the timer from triggering. 1101 SetSlowSSLLoadTime(tab_reloader, base::TimeDelta::FromDays(1)); 1102 } 1103 1104 void CaptivePortalBrowserTest::FastTimeoutNoCaptivePortal( 1105 Browser* browser, 1106 CaptivePortalResult expected_result) { 1107 ASSERT_NE(expected_result, captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL); 1108 1109 // Set the load time to be large, so the timer won't trigger. The value is 1110 // not restored at the end of the function. 1111 CaptivePortalTabReloader* tab_reloader = 1112 GetTabReloader(browser->tab_strip_model()->GetActiveWebContents()); 1113 ASSERT_TRUE(tab_reloader); 1114 SetSlowSSLLoadTime(tab_reloader, base::TimeDelta::FromHours(1)); 1115 1116 MultiNavigationObserver navigation_observer; 1117 CaptivePortalObserver portal_observer(browser->profile()); 1118 1119 // Neither of these should be changed by the navigation. 1120 int active_index = browser->tab_strip_model()->active_index(); 1121 int expected_tab_count = browser->tab_strip_model()->count(); 1122 1123 ui_test_utils::NavigateToURL( 1124 browser, 1125 URLRequestFailedJob::GetMockHttpsUrl(net::ERR_CONNECTION_TIMED_OUT)); 1126 1127 // An attempt to detect a captive portal should have started by now. If not, 1128 // abort early to prevent hanging. 1129 ASSERT_TRUE(portal_observer.num_results_received() > 0 || 1130 CheckPending(browser)); 1131 1132 portal_observer.WaitForResults(1); 1133 navigation_observer.WaitForNavigations(1); 1134 1135 // Check the result. 1136 EXPECT_EQ(1, portal_observer.num_results_received()); 1137 EXPECT_EQ(expected_result, portal_observer.captive_portal_result()); 1138 1139 // Check that the right tab was navigated, and there were no extra 1140 // navigations. 1141 EXPECT_EQ(1, navigation_observer.NumNavigationsForTab( 1142 browser->tab_strip_model()->GetWebContentsAt(active_index))); 1143 EXPECT_EQ(0, NumLoadingTabs()); 1144 1145 // Check the tab's state, and verify no captive portal check is pending. 1146 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, 1147 GetStateOfTabReloaderAt(browser, 0)); 1148 EXPECT_FALSE(CheckPending(browser)); 1149 1150 // Make sure no login tab was opened. 1151 EXPECT_EQ(expected_tab_count, browser->tab_strip_model()->count()); 1152 } 1153 1154 void CaptivePortalBrowserTest::SlowLoadBehindCaptivePortal( 1155 Browser* browser, 1156 bool expect_open_login_tab) { 1157 SlowLoadBehindCaptivePortal(browser, 1158 expect_open_login_tab, 1159 GURL(kMockHttpsUrl), 1160 1, 1161 1); 1162 } 1163 1164 void CaptivePortalBrowserTest::SlowLoadBehindCaptivePortal( 1165 Browser* browser, 1166 bool expect_open_login_tab, 1167 const GURL& hanging_url, 1168 int expected_portal_checks, 1169 int expected_login_tab_navigations) { 1170 ASSERT_GE(expected_portal_checks, 1); 1171 TabStripModel* tab_strip_model = browser->tab_strip_model(); 1172 // Calling this on a tab that's waiting for a load to manually be timed out 1173 // will result in a hang. 1174 ASSERT_FALSE(tab_strip_model->GetActiveWebContents()->IsLoading()); 1175 1176 // Trigger a captive portal check quickly. 1177 CaptivePortalTabReloader* tab_reloader = 1178 GetTabReloader(tab_strip_model->GetActiveWebContents()); 1179 ASSERT_TRUE(tab_reloader); 1180 SetSlowSSLLoadTime(tab_reloader, base::TimeDelta()); 1181 1182 // Number of tabs expected to be open after the captive portal checks 1183 // have completed. 1184 int initial_tab_count = tab_strip_model->count(); 1185 int initial_active_index = tab_strip_model->active_index(); 1186 int initial_loading_tabs = NumLoadingTabs(); 1187 int expected_broken_tabs = NumBrokenTabs(); 1188 if (CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL != 1189 GetStateOfTabReloader(tab_strip_model->GetActiveWebContents())) { 1190 ++expected_broken_tabs; 1191 } 1192 1193 MultiNavigationObserver navigation_observer; 1194 CaptivePortalObserver portal_observer(browser->profile()); 1195 ui_test_utils::NavigateToURLWithDisposition(browser, 1196 hanging_url, 1197 CURRENT_TAB, 1198 ui_test_utils::BROWSER_TEST_NONE); 1199 portal_observer.WaitForResults(expected_portal_checks); 1200 1201 if (expect_open_login_tab) { 1202 ASSERT_GE(expected_login_tab_navigations, 1); 1203 1204 navigation_observer.WaitForNavigations(expected_login_tab_navigations); 1205 1206 ASSERT_EQ(initial_tab_count + 1, tab_strip_model->count()); 1207 EXPECT_EQ(initial_tab_count, tab_strip_model->active_index()); 1208 1209 EXPECT_EQ(expected_login_tab_navigations, 1210 navigation_observer.NumNavigationsForTab( 1211 tab_strip_model->GetWebContentsAt(initial_tab_count))); 1212 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, 1213 GetStateOfTabReloaderAt(browser, 1)); 1214 EXPECT_TRUE(IsLoginTab(tab_strip_model->GetWebContentsAt(1))); 1215 } else { 1216 EXPECT_EQ(0, navigation_observer.num_navigations()); 1217 EXPECT_EQ(initial_active_index, tab_strip_model->active_index()); 1218 ASSERT_EQ(initial_tab_count, tab_strip_model->count()); 1219 EXPECT_EQ(initial_active_index, tab_strip_model->active_index()); 1220 } 1221 1222 // Wait for all the expect resource loads to actually start, so subsequent 1223 // functions can rely on them having started. 1224 URLRequestTimeoutOnDemandJob::WaitForJobs(initial_loading_tabs + 1); 1225 1226 EXPECT_EQ(initial_loading_tabs + 1, NumLoadingTabs()); 1227 EXPECT_EQ(expected_broken_tabs, NumBrokenTabs()); 1228 EXPECT_EQ(captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL, 1229 portal_observer.captive_portal_result()); 1230 EXPECT_EQ(expected_portal_checks, portal_observer.num_results_received()); 1231 EXPECT_FALSE(CheckPending(browser)); 1232 1233 EXPECT_EQ(CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL, 1234 GetStateOfTabReloaderAt(browser, initial_active_index)); 1235 1236 // Reset the load time to be large, so the timer won't trigger on a reload. 1237 SetSlowSSLLoadTime(tab_reloader, base::TimeDelta::FromHours(1)); 1238 } 1239 1240 void CaptivePortalBrowserTest::FastTimeoutBehindCaptivePortal( 1241 Browser* browser, 1242 bool expect_open_login_tab) { 1243 FastErrorBehindCaptivePortal(browser, 1244 expect_open_login_tab, 1245 GURL(kMockHttpsQuickTimeoutUrl)); 1246 } 1247 1248 void CaptivePortalBrowserTest::FastErrorBehindCaptivePortal( 1249 Browser* browser, 1250 bool expect_open_login_tab, 1251 const GURL& error_url) { 1252 TabStripModel* tab_strip_model = browser->tab_strip_model(); 1253 // Calling this on a tab that's waiting for a load to manually be timed out 1254 // will result in a hang. 1255 ASSERT_FALSE(tab_strip_model->GetActiveWebContents()->IsLoading()); 1256 1257 // Set the load time to be large, so the timer won't trigger. The value is 1258 // not restored at the end of the function. 1259 CaptivePortalTabReloader* tab_reloader = 1260 GetTabReloader(tab_strip_model->GetActiveWebContents()); 1261 ASSERT_TRUE(tab_reloader); 1262 SetSlowSSLLoadTime(tab_reloader, base::TimeDelta::FromHours(1)); 1263 1264 // Number of tabs expected to be open after the captive portal checks 1265 // have completed. 1266 int initial_tab_count = tab_strip_model->count(); 1267 int initial_active_index = tab_strip_model->active_index(); 1268 int initial_loading_tabs = NumLoadingTabs(); 1269 int expected_broken_tabs = NumBrokenTabs(); 1270 if (CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL != 1271 GetStateOfTabReloader(tab_strip_model->GetActiveWebContents())) { 1272 ++expected_broken_tabs; 1273 } 1274 1275 MultiNavigationObserver navigation_observer; 1276 CaptivePortalObserver portal_observer(browser->profile()); 1277 ui_test_utils::NavigateToURLWithDisposition(browser, 1278 error_url, 1279 CURRENT_TAB, 1280 ui_test_utils::BROWSER_TEST_NONE); 1281 portal_observer.WaitForResults(1); 1282 1283 if (expect_open_login_tab) { 1284 navigation_observer.WaitForNavigations(2); 1285 ASSERT_EQ(initial_tab_count + 1, tab_strip_model->count()); 1286 EXPECT_EQ(initial_tab_count, tab_strip_model->active_index()); 1287 // Make sure that the originally active tab and the captive portal tab have 1288 // each loaded once. 1289 EXPECT_EQ(1, navigation_observer.NumNavigationsForTab( 1290 tab_strip_model->GetWebContentsAt(initial_active_index))); 1291 EXPECT_EQ(1, navigation_observer.NumNavigationsForTab( 1292 tab_strip_model->GetWebContentsAt(initial_tab_count))); 1293 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, 1294 GetStateOfTabReloaderAt(browser, 1)); 1295 EXPECT_TRUE(IsLoginTab(tab_strip_model->GetWebContentsAt(1))); 1296 } else { 1297 navigation_observer.WaitForNavigations(1); 1298 EXPECT_EQ(initial_active_index, tab_strip_model->active_index()); 1299 EXPECT_EQ(1, navigation_observer.NumNavigationsForTab( 1300 tab_strip_model->GetWebContentsAt(initial_active_index))); 1301 ASSERT_EQ(initial_tab_count, tab_strip_model->count()); 1302 EXPECT_EQ(initial_active_index, tab_strip_model->active_index()); 1303 } 1304 1305 EXPECT_EQ(initial_loading_tabs, NumLoadingTabs()); 1306 EXPECT_EQ(expected_broken_tabs, NumBrokenTabs()); 1307 EXPECT_EQ(captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL, 1308 portal_observer.captive_portal_result()); 1309 EXPECT_EQ(1, portal_observer.num_results_received()); 1310 EXPECT_FALSE(CheckPending(browser)); 1311 1312 EXPECT_EQ(CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL, 1313 GetStateOfTabReloaderAt(browser, initial_active_index)); 1314 } 1315 1316 void CaptivePortalBrowserTest::NavigateLoginTab(Browser* browser, 1317 int num_loading_tabs, 1318 int num_timed_out_tabs) { 1319 MultiNavigationObserver navigation_observer; 1320 CaptivePortalObserver portal_observer(browser->profile()); 1321 1322 TabStripModel* tab_strip_model = browser->tab_strip_model(); 1323 int initial_tab_count = tab_strip_model->count(); 1324 EXPECT_EQ(num_loading_tabs, NumLoadingTabs()); 1325 EXPECT_EQ(num_timed_out_tabs, NumBrokenTabs() - NumLoadingTabs()); 1326 1327 int login_tab_index = tab_strip_model->active_index(); 1328 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, 1329 GetStateOfTabReloader(tab_strip_model->GetActiveWebContents())); 1330 ASSERT_TRUE(IsLoginTab(browser->tab_strip_model()->GetActiveWebContents())); 1331 1332 // Do the navigation. 1333 content::RenderFrameHost* render_frame_host = 1334 tab_strip_model->GetActiveWebContents()->GetMainFrame(); 1335 render_frame_host->ExecuteJavaScript(base::ASCIIToUTF16("submitForm()")); 1336 1337 portal_observer.WaitForResults(1); 1338 navigation_observer.WaitForNavigations(1); 1339 1340 // Check the captive portal result. 1341 EXPECT_EQ(captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL, 1342 portal_observer.captive_portal_result()); 1343 EXPECT_EQ(1, portal_observer.num_results_received()); 1344 EXPECT_FALSE(CheckPending(browser)); 1345 1346 // Make sure not much has changed. 1347 EXPECT_EQ(initial_tab_count, tab_strip_model->count()); 1348 EXPECT_EQ(num_loading_tabs, NumLoadingTabs()); 1349 EXPECT_EQ(num_loading_tabs + num_timed_out_tabs, NumBrokenTabs()); 1350 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, 1351 GetStateOfTabReloaderAt(browser, login_tab_index)); 1352 EXPECT_TRUE(IsLoginTab(tab_strip_model->GetWebContentsAt(login_tab_index))); 1353 1354 // Make sure there were no unexpected navigations. 1355 EXPECT_EQ(1, navigation_observer.NumNavigationsForTab( 1356 tab_strip_model->GetWebContentsAt(login_tab_index))); 1357 } 1358 1359 void CaptivePortalBrowserTest::Login(Browser* browser, 1360 int num_loading_tabs, 1361 int num_timed_out_tabs) { 1362 // Simulate logging in. 1363 URLRequestMockCaptivePortalJobFactory::SetBehindCaptivePortal(false); 1364 1365 MultiNavigationObserver navigation_observer; 1366 CaptivePortalObserver portal_observer(browser->profile()); 1367 1368 TabStripModel* tab_strip_model = browser->tab_strip_model(); 1369 int initial_tab_count = tab_strip_model->count(); 1370 ASSERT_EQ(num_loading_tabs, NumLoadingTabs()); 1371 EXPECT_EQ(num_timed_out_tabs, NumBrokenTabs() - NumLoadingTabs()); 1372 1373 // Verify that the login page is on top. 1374 int login_tab_index = tab_strip_model->active_index(); 1375 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, 1376 GetStateOfTabReloaderAt(browser, login_tab_index)); 1377 ASSERT_TRUE(IsLoginTab(tab_strip_model->GetWebContentsAt(login_tab_index))); 1378 1379 // Trigger a navigation. 1380 content::RenderFrameHost* render_frame_host = 1381 tab_strip_model->GetActiveWebContents()->GetMainFrame(); 1382 render_frame_host->ExecuteJavaScript(base::ASCIIToUTF16("submitForm()")); 1383 1384 portal_observer.WaitForResults(1); 1385 1386 // Wait for all the timed out tabs to reload. 1387 navigation_observer.WaitForNavigations(1 + num_timed_out_tabs); 1388 EXPECT_EQ(1, portal_observer.num_results_received()); 1389 1390 // The tabs that were loading before should still be loading, and now be in 1391 // STATE_NEEDS_RELOAD. 1392 EXPECT_EQ(0, NumBrokenTabs()); 1393 EXPECT_EQ(num_loading_tabs, NumLoadingTabs()); 1394 EXPECT_EQ(num_loading_tabs, NumNeedReloadTabs()); 1395 1396 // Make sure that the broken tabs have reloaded, and there's no more 1397 // captive portal tab. 1398 EXPECT_EQ(initial_tab_count, tab_strip_model->count()); 1399 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, 1400 GetStateOfTabReloaderAt(browser, login_tab_index)); 1401 EXPECT_FALSE(IsLoginTab(tab_strip_model->GetWebContentsAt(login_tab_index))); 1402 1403 // Make sure there were no unexpected navigations of the login tab. 1404 EXPECT_EQ(1, navigation_observer.NumNavigationsForTab( 1405 tab_strip_model->GetWebContentsAt(login_tab_index))); 1406 } 1407 1408 void CaptivePortalBrowserTest::FailLoadsAfterLogin(Browser* browser, 1409 int num_loading_tabs) { 1410 ASSERT_EQ(num_loading_tabs, NumLoadingTabs()); 1411 ASSERT_EQ(num_loading_tabs, NumNeedReloadTabs()); 1412 EXPECT_EQ(0, NumBrokenTabs()); 1413 1414 TabStripModel* tab_strip_model = browser->tab_strip_model(); 1415 int initial_num_tabs = tab_strip_model->count(); 1416 int initial_active_tab = tab_strip_model->active_index(); 1417 1418 CaptivePortalObserver portal_observer(browser->profile()); 1419 FailLoadsAfterLoginObserver fail_loads_observer; 1420 // Connection(s) finally time out. There should have already been a call 1421 // to wait for the requests to be issued before logging on. 1422 URLRequestTimeoutOnDemandJob::WaitForJobs(num_loading_tabs); 1423 URLRequestTimeoutOnDemandJob::FailJobs(num_loading_tabs); 1424 1425 fail_loads_observer.WaitForNavigations(); 1426 1427 // No captive portal checks should have ocurred or be pending, and there 1428 // should be no new tabs. 1429 EXPECT_EQ(0, portal_observer.num_results_received()); 1430 EXPECT_FALSE(CheckPending(browser)); 1431 EXPECT_EQ(initial_num_tabs, tab_strip_model->count()); 1432 1433 EXPECT_EQ(initial_active_tab, tab_strip_model->active_index()); 1434 1435 EXPECT_EQ(0, NumNeedReloadTabs()); 1436 EXPECT_EQ(0, NumLoadingTabs()); 1437 } 1438 1439 void CaptivePortalBrowserTest::FailLoadsWithoutLogin(Browser* browser, 1440 int num_loading_tabs) { 1441 ASSERT_EQ(num_loading_tabs, NumLoadingTabs()); 1442 ASSERT_EQ(0, NumNeedReloadTabs()); 1443 EXPECT_EQ(num_loading_tabs, NumBrokenTabs()); 1444 1445 TabStripModel* tab_strip_model = browser->tab_strip_model(); 1446 int initial_num_tabs = tab_strip_model->count(); 1447 int login_tab = tab_strip_model->active_index(); 1448 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, 1449 GetStateOfTabReloader(tab_strip_model->GetActiveWebContents())); 1450 ASSERT_TRUE(IsLoginTab(tab_strip_model->GetActiveWebContents())); 1451 1452 CaptivePortalObserver portal_observer(browser->profile()); 1453 MultiNavigationObserver navigation_observer; 1454 // Connection(s) finally time out. There should have already been a call 1455 // to wait for the requests to be issued. 1456 URLRequestTimeoutOnDemandJob::FailJobs(num_loading_tabs); 1457 1458 navigation_observer.WaitForNavigations(num_loading_tabs); 1459 1460 // No captive portal checks should have ocurred or be pending, and there 1461 // should be no new tabs. 1462 EXPECT_EQ(0, portal_observer.num_results_received()); 1463 EXPECT_FALSE(CheckPending(browser)); 1464 EXPECT_EQ(initial_num_tabs, tab_strip_model->count()); 1465 1466 EXPECT_EQ(0, NumNeedReloadTabs()); 1467 EXPECT_EQ(0, NumLoadingTabs()); 1468 EXPECT_EQ(num_loading_tabs, NumBrokenTabs()); 1469 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, 1470 GetStateOfTabReloader(tab_strip_model->GetActiveWebContents())); 1471 EXPECT_TRUE(IsLoginTab(tab_strip_model->GetActiveWebContents())); 1472 EXPECT_EQ(login_tab, tab_strip_model->active_index()); 1473 1474 EXPECT_EQ(0, navigation_observer.NumNavigationsForTab( 1475 tab_strip_model->GetWebContentsAt(login_tab))); 1476 } 1477 1478 void CaptivePortalBrowserTest::RunNavigateLoadingTabToTimeoutTest( 1479 Browser* browser, 1480 const GURL& starting_url, 1481 const GURL& hanging_url, 1482 const GURL& timeout_url) { 1483 // Temporarily disable the captive portal and navigate to the starting 1484 // URL, which may be a URL that will hang when behind a captive portal. 1485 URLRequestMockCaptivePortalJobFactory::SetBehindCaptivePortal(false); 1486 NavigateToPageExpectNoTest(browser, starting_url, 1); 1487 URLRequestMockCaptivePortalJobFactory::SetBehindCaptivePortal(true); 1488 1489 // Go to the first hanging url. 1490 SlowLoadBehindCaptivePortal(browser, true, hanging_url, 1, 1); 1491 1492 // Abandon the request. 1493 URLRequestTimeoutOnDemandJob::WaitForJobs(1); 1494 URLRequestTimeoutOnDemandJob::AbandonJobs(1); 1495 1496 TabStripModel* tab_strip_model = browser->tab_strip_model(); 1497 CaptivePortalTabReloader* tab_reloader = 1498 GetTabReloader(tab_strip_model->GetWebContentsAt(0)); 1499 ASSERT_TRUE(tab_reloader); 1500 1501 // A non-zero delay makes it more likely that CaptivePortalTabHelper will 1502 // be confused by events relating to canceling the old navigation. 1503 SetSlowSSLLoadTime(tab_reloader, base::TimeDelta::FromSeconds(2)); 1504 CaptivePortalObserver portal_observer(browser->profile()); 1505 1506 // Navigate the error tab to another slow loading page. Can't have 1507 // ui_test_utils do the navigation because it will wait for loading tabs to 1508 // stop loading before navigating. 1509 // 1510 // This may result in either 0 or 1 DidStopLoading events. If there is one, 1511 // it must happen before the CaptivePortalService sends out its test request, 1512 // so waiting for PortalObserver to see that request prevents it from 1513 // confusing the MultiNavigationObservers used later. 1514 tab_strip_model->ActivateTabAt(0, true); 1515 browser->OpenURL(content::OpenURLParams(timeout_url, 1516 content::Referrer(), 1517 CURRENT_TAB, 1518 ui::PAGE_TRANSITION_TYPED, 1519 false)); 1520 portal_observer.WaitForResults(1); 1521 EXPECT_FALSE(CheckPending(browser)); 1522 EXPECT_EQ(1, NumLoadingTabs()); 1523 EXPECT_EQ(CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL, 1524 GetStateOfTabReloaderAt(browser, 0)); 1525 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, 1526 GetStateOfTabReloaderAt(browser, 1)); 1527 ASSERT_TRUE(IsLoginTab(tab_strip_model->GetWebContentsAt(1))); 1528 1529 // Need to make sure the request has been issued before logging in. 1530 URLRequestTimeoutOnDemandJob::WaitForJobs(1); 1531 1532 // Simulate logging in. 1533 tab_strip_model->ActivateTabAt(1, true); 1534 SetSlowSSLLoadTime(tab_reloader, base::TimeDelta::FromDays(1)); 1535 Login(browser, 1, 0); 1536 1537 // Timeout occurs, and page is automatically reloaded. 1538 FailLoadsAfterLogin(browser, 1); 1539 } 1540 1541 void CaptivePortalBrowserTest::SetSlowSSLLoadTime( 1542 CaptivePortalTabReloader* tab_reloader, 1543 base::TimeDelta slow_ssl_load_time) { 1544 tab_reloader->set_slow_ssl_load_time(slow_ssl_load_time); 1545 } 1546 1547 CaptivePortalTabReloader* CaptivePortalBrowserTest::GetTabReloader( 1548 WebContents* web_contents) const { 1549 return CaptivePortalTabHelper::FromWebContents(web_contents)-> 1550 GetTabReloaderForTest(); 1551 } 1552 1553 // Make sure there's no test for a captive portal on HTTP timeouts. This will 1554 // also trigger the link doctor page, which results in the load of a second 1555 // error page. 1556 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, HttpTimeout) { 1557 GURL url = URLRequestFailedJob::GetMockHttpUrl(net::ERR_CONNECTION_TIMED_OUT); 1558 NavigateToPageExpectNoTest(browser(), url, 2); 1559 } 1560 1561 // Make sure there's no check for a captive portal on HTTPS errors other than 1562 // timeouts, when they preempt the slow load timer. 1563 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, HttpsNonTimeoutError) { 1564 GURL url = URLRequestFailedJob::GetMockHttpsUrl(net::ERR_UNEXPECTED); 1565 NavigateToPageExpectNoTest(browser(), url, 1); 1566 } 1567 1568 // Make sure no captive portal test triggers on HTTPS timeouts of iframes. 1569 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, HttpsIframeTimeout) { 1570 // Use an HTTPS server for the top level page. 1571 net::SpawnedTestServer https_server( 1572 net::SpawnedTestServer::TYPE_HTTPS, net::SpawnedTestServer::kLocalhost, 1573 base::FilePath(FILE_PATH_LITERAL("chrome/test/data"))); 1574 ASSERT_TRUE(https_server.Start()); 1575 1576 GURL url = https_server.GetURL(kTestServerIframeTimeoutPath); 1577 NavigateToPageExpectNoTest(browser(), url, 1); 1578 } 1579 1580 // Check the captive portal result when the test request reports a network 1581 // error. The check is triggered by a slow loading page, and the page 1582 // errors out only after getting a captive portal result. 1583 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, RequestFails) { 1584 SetUpCaptivePortalService( 1585 browser()->profile(), 1586 URLRequestFailedJob::GetMockHttpUrl(net::ERR_CONNECTION_CLOSED)); 1587 SlowLoadNoCaptivePortal(browser(), captive_portal::RESULT_NO_RESPONSE); 1588 } 1589 1590 // Same as above, but for the rather unlikely case that the connection times out 1591 // before the timer triggers. 1592 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, RequestFailsFastTimout) { 1593 SetUpCaptivePortalService( 1594 browser()->profile(), 1595 URLRequestFailedJob::GetMockHttpUrl(net::ERR_CONNECTION_CLOSED)); 1596 FastTimeoutNoCaptivePortal(browser(), captive_portal::RESULT_NO_RESPONSE); 1597 } 1598 1599 // Checks the case that captive portal detection is disabled. 1600 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, Disabled) { 1601 EnableCaptivePortalDetection(browser()->profile(), false); 1602 SlowLoadNoCaptivePortal(browser(), captive_portal::RESULT_INTERNET_CONNECTED); 1603 } 1604 1605 // Checks that we look for a captive portal on HTTPS timeouts and don't reload 1606 // the error tab when the captive portal probe gets a 204 response, indicating 1607 // there is no captive portal. 1608 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, InternetConnected) { 1609 // Can't just use SetBehindCaptivePortal(false), since then there wouldn't 1610 // be a timeout. 1611 ASSERT_TRUE(test_server()->Start()); 1612 SetUpCaptivePortalService(browser()->profile(), 1613 test_server()->GetURL("nocontent")); 1614 SlowLoadNoCaptivePortal(browser(), captive_portal::RESULT_INTERNET_CONNECTED); 1615 } 1616 1617 // Checks that no login page is opened when the HTTP test URL redirects to an 1618 // SSL certificate error. 1619 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, RedirectSSLCertError) { 1620 // Need an HTTP TestServer to handle a dynamically created server redirect. 1621 ASSERT_TRUE(test_server()->Start()); 1622 1623 net::SpawnedTestServer::SSLOptions ssl_options; 1624 ssl_options.server_certificate = 1625 net::SpawnedTestServer::SSLOptions::CERT_MISMATCHED_NAME; 1626 net::SpawnedTestServer https_server( 1627 net::SpawnedTestServer::TYPE_HTTPS, ssl_options, 1628 base::FilePath(FILE_PATH_LITERAL("chrome/test/data"))); 1629 ASSERT_TRUE(https_server.Start()); 1630 1631 GURL ssl_login_url = https_server.GetURL(kTestServerLoginPath); 1632 1633 CaptivePortalService* captive_portal_service = 1634 CaptivePortalServiceFactory::GetForProfile(browser()->profile()); 1635 ASSERT_TRUE(captive_portal_service); 1636 SetUpCaptivePortalService( 1637 browser()->profile(), 1638 test_server()->GetURL(CreateServerRedirect(ssl_login_url.spec()))); 1639 1640 SlowLoadNoCaptivePortal(browser(), captive_portal::RESULT_NO_RESPONSE); 1641 } 1642 1643 // A slow SSL load triggers a captive portal check. The user logs on before 1644 // the SSL page times out. We wait for the timeout and subsequent reload. 1645 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, Login) { 1646 // Load starts, detect captive portal and open up a login tab. 1647 SlowLoadBehindCaptivePortal(browser(), true); 1648 1649 // Log in. One loading tab, no timed out ones. 1650 Login(browser(), 1, 0); 1651 1652 // Timeout occurs, and page is automatically reloaded. 1653 FailLoadsAfterLogin(browser(), 1); 1654 } 1655 1656 // Same as above, except we make sure everything works with an incognito 1657 // profile. Main issues it tests for are that the incognito has its own 1658 // non-NULL captive portal service, and we open the tab in the correct 1659 // window. 1660 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, LoginIncognito) { 1661 // This will watch tabs for both profiles, but only used to make sure no 1662 // navigations occur for the non-incognito profile. 1663 MultiNavigationObserver navigation_observer; 1664 CaptivePortalObserver non_incognito_portal_observer(browser()->profile()); 1665 1666 Browser* incognito_browser = CreateIncognitoBrowser(); 1667 EnableCaptivePortalDetection(incognito_browser->profile(), true); 1668 SetUpCaptivePortalService(incognito_browser->profile(), 1669 GURL(kMockCaptivePortalTestUrl)); 1670 1671 SlowLoadBehindCaptivePortal(incognito_browser, true); 1672 1673 TabStripModel* tab_strip_model = browser()->tab_strip_model(); 1674 EXPECT_EQ(1, tab_strip_model->count()); 1675 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, 1676 GetStateOfTabReloaderAt(browser(), 0)); 1677 1678 Login(incognito_browser, 1, 0); 1679 FailLoadsAfterLogin(incognito_browser, 1); 1680 1681 EXPECT_EQ(1, tab_strip_model->count()); 1682 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, 1683 GetStateOfTabReloaderAt(browser(), 0)); 1684 1685 EXPECT_EQ(0, navigation_observer.NumNavigationsForTab( 1686 tab_strip_model->GetWebContentsAt(0))); 1687 EXPECT_EQ(0, non_incognito_portal_observer.num_results_received()); 1688 } 1689 1690 // The captive portal page is opened before the SSL page times out, 1691 // but the user logs in only after the page times out. 1692 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, LoginSlow) { 1693 SlowLoadBehindCaptivePortal(browser(), true); 1694 FailLoadsWithoutLogin(browser(), 1); 1695 Login(browser(), 0, 1); 1696 } 1697 1698 // Checks the unlikely case that the tab times out before the timer triggers. 1699 // This most likely won't happen, but should still work: 1700 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, LoginFastTimeout) { 1701 FastTimeoutBehindCaptivePortal(browser(), true); 1702 Login(browser(), 0, 1); 1703 } 1704 1705 // A cert error triggers a captive portal check and results in opening a login 1706 // tab. The user then logs in and the page with the error is reloaded. 1707 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, SSLCertErrorLogin) { 1708 // Need an HTTP TestServer to handle a dynamically created server redirect. 1709 ASSERT_TRUE(test_server()->Start()); 1710 1711 net::SpawnedTestServer::SSLOptions https_options; 1712 https_options.server_certificate = 1713 net::SpawnedTestServer::SSLOptions::CERT_MISMATCHED_NAME; 1714 net::SpawnedTestServer https_server( 1715 net::SpawnedTestServer::TYPE_HTTPS, https_options, 1716 base::FilePath(FILE_PATH_LITERAL("chrome/test/data"))); 1717 ASSERT_TRUE(https_server.Start()); 1718 1719 // The path does not matter. 1720 GURL cert_error_url = https_server.GetURL(kTestServerLoginPath); 1721 // The interstitial should trigger a captive portal check when it opens, just 1722 // like navigating to kMockHttpsQuickTimeoutUrl. 1723 FastErrorBehindCaptivePortal(browser(), true, cert_error_url); 1724 1725 // Simulate logging in. Can't use Login() because the interstitial tab looks 1726 // like a cross between a hung tab (Load was never committed) and a tab at an 1727 // error page (The load was stopped). 1728 URLRequestMockCaptivePortalJobFactory::SetBehindCaptivePortal(false); 1729 MultiNavigationObserver navigation_observer; 1730 CaptivePortalObserver portal_observer(browser()->profile()); 1731 1732 TabStripModel* tab_strip_model = browser()->tab_strip_model(); 1733 content::RenderFrameHost* render_frame_host = 1734 tab_strip_model->GetActiveWebContents()->GetMainFrame(); 1735 render_frame_host->ExecuteJavaScript(base::ASCIIToUTF16("submitForm()")); 1736 1737 // The captive portal tab navigation will trigger a captive portal check, 1738 // and reloading the original tab will bring up the interstitial page again, 1739 // triggering a second captive portal check. 1740 portal_observer.WaitForResults(2); 1741 1742 // Wait for both tabs to finish loading. 1743 navigation_observer.WaitForNavigations(2); 1744 EXPECT_EQ(2, portal_observer.num_results_received()); 1745 EXPECT_FALSE(CheckPending(browser())); 1746 EXPECT_EQ(captive_portal::RESULT_INTERNET_CONNECTED, 1747 portal_observer.captive_portal_result()); 1748 1749 // Check state of tabs. While the first tab is still displaying an 1750 // interstitial page, since no portal was found, it should be in STATE_NONE, 1751 // as should the login tab. 1752 ASSERT_EQ(2, tab_strip_model->count()); 1753 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, 1754 GetStateOfTabReloaderAt(browser(), 0)); 1755 EXPECT_FALSE(IsLoginTab(tab_strip_model->GetWebContentsAt(1))); 1756 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, 1757 GetStateOfTabReloaderAt(browser(), 1)); 1758 1759 // Make sure only one navigation was for the login tab. 1760 EXPECT_EQ(1, navigation_observer.NumNavigationsForTab( 1761 tab_strip_model->GetWebContentsAt(1))); 1762 } 1763 1764 // Tries navigating both the tab that encounters an SSL timeout and the 1765 // login tab twice, only logging in the second time. 1766 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, LoginExtraNavigations) { 1767 FastTimeoutBehindCaptivePortal(browser(), true); 1768 1769 // Activate the timed out tab and navigate it to a timeout again. 1770 TabStripModel* tab_strip_model = browser()->tab_strip_model(); 1771 tab_strip_model->ActivateTabAt(0, true); 1772 FastTimeoutBehindCaptivePortal(browser(), false); 1773 1774 // Activate and navigate the captive portal tab. This should not trigger a 1775 // reload of the tab with the error. 1776 tab_strip_model->ActivateTabAt(1, true); 1777 NavigateLoginTab(browser(), 0, 1); 1778 1779 // Simulate logging in. 1780 Login(browser(), 0, 1); 1781 } 1782 1783 // After the first SSL timeout, closes the login tab and makes sure it's opened 1784 // it again on a second timeout. 1785 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, CloseLoginTab) { 1786 // First load starts, opens a login tab, and then times out. 1787 SlowLoadBehindCaptivePortal(browser(), true); 1788 FailLoadsWithoutLogin(browser(), 1); 1789 1790 // Close login tab. 1791 chrome::CloseTab(browser()); 1792 1793 // Go through the standard slow load login, and make sure it still works. 1794 SlowLoadBehindCaptivePortal(browser(), true); 1795 Login(browser(), 1, 0); 1796 FailLoadsAfterLogin(browser(), 1); 1797 } 1798 1799 // Checks that two tabs with SSL timeouts in the same window work. Both 1800 // tabs only timeout after logging in. 1801 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, TwoBrokenTabs) { 1802 SlowLoadBehindCaptivePortal(browser(), true); 1803 1804 // Can't set the TabReloader HTTPS timeout on a new tab without doing some 1805 // acrobatics, so open a new tab at a normal page, and then navigate it to a 1806 // timeout. 1807 MultiNavigationObserver navigation_observer; 1808 CaptivePortalObserver portal_observer(browser()->profile()); 1809 ui_test_utils::NavigateToURLWithDisposition( 1810 browser(), 1811 URLRequestMockHTTPJob::GetMockUrl( 1812 base::FilePath(FILE_PATH_LITERAL("title2.html"))), 1813 NEW_FOREGROUND_TAB, 1814 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); 1815 1816 TabStripModel* tab_strip_model = browser()->tab_strip_model(); 1817 ASSERT_EQ(3, tab_strip_model->count()); 1818 EXPECT_FALSE(CheckPending(browser())); 1819 EXPECT_EQ(0, portal_observer.num_results_received()); 1820 EXPECT_EQ(1, NumLoadingTabs()); 1821 EXPECT_EQ(1, navigation_observer.num_navigations()); 1822 EXPECT_EQ(1, navigation_observer.NumNavigationsForTab( 1823 tab_strip_model->GetWebContentsAt(2))); 1824 ASSERT_EQ(CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL, 1825 GetStateOfTabReloaderAt(browser(), 0)); 1826 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, 1827 GetStateOfTabReloaderAt(browser(), 1)); 1828 ASSERT_TRUE(IsLoginTab(tab_strip_model->GetWebContentsAt(1))); 1829 ASSERT_EQ(CaptivePortalTabReloader::STATE_NONE, 1830 GetStateOfTabReloaderAt(browser(), 2)); 1831 ASSERT_EQ(2, tab_strip_model->active_index()); 1832 1833 SlowLoadBehindCaptivePortal(browser(), false); 1834 1835 tab_strip_model->ActivateTabAt(1, true); 1836 Login(browser(), 2, 0); 1837 FailLoadsAfterLogin(browser(), 2); 1838 } 1839 1840 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, AbortLoad) { 1841 SlowLoadBehindCaptivePortal(browser(), true); 1842 1843 // Abandon the request. 1844 URLRequestTimeoutOnDemandJob::WaitForJobs(1); 1845 URLRequestTimeoutOnDemandJob::AbandonJobs(1); 1846 1847 CaptivePortalObserver portal_observer(browser()->profile()); 1848 MultiNavigationObserver navigation_observer; 1849 1850 // Switch back to the hung tab from the login tab, and abort the navigation. 1851 TabStripModel* tab_strip_model = browser()->tab_strip_model(); 1852 tab_strip_model->ActivateTabAt(0, true); 1853 chrome::Stop(browser()); 1854 navigation_observer.WaitForNavigations(1); 1855 1856 EXPECT_EQ(0, NumBrokenTabs()); 1857 EXPECT_EQ(0, portal_observer.num_results_received()); 1858 EXPECT_FALSE(CheckPending(browser())); 1859 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, 1860 GetStateOfTabReloaderAt(browser(), 0)); 1861 1862 tab_strip_model->ActivateTabAt(1, true); 1863 Login(browser(), 0, 0); 1864 } 1865 1866 // Checks the case where the timed out tab is successfully navigated before 1867 // logging in. 1868 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, NavigateBrokenTab) { 1869 // Go to the error page. 1870 SlowLoadBehindCaptivePortal(browser(), true); 1871 FailLoadsWithoutLogin(browser(), 1); 1872 1873 // Navigate the error tab to a non-error page. 1874 TabStripModel* tab_strip_model = browser()->tab_strip_model(); 1875 tab_strip_model->ActivateTabAt(0, true); 1876 ui_test_utils::NavigateToURL( 1877 browser(), URLRequestMockHTTPJob::GetMockUrl( 1878 base::FilePath(FILE_PATH_LITERAL("title2.html")))); 1879 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, 1880 GetStateOfTabReloaderAt(browser(), 0)); 1881 1882 // Simulate logging in. 1883 tab_strip_model->ActivateTabAt(1, true); 1884 Login(browser(), 0, 0); 1885 } 1886 1887 // Checks that captive portal detection triggers correctly when a same-site 1888 // navigation is cancelled by a navigation to the same site. 1889 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, 1890 NavigateLoadingTabToTimeoutSingleSite) { 1891 RunNavigateLoadingTabToTimeoutTest( 1892 browser(), 1893 GURL(kMockHttpsUrl), 1894 GURL(kMockHttpsUrl), 1895 GURL(kMockHttpsUrl)); 1896 } 1897 1898 // Fails on Windows only, mostly on Win7. http://crbug.com/170033 1899 #if defined(OS_WIN) 1900 #define MAYBE_NavigateLoadingTabToTimeoutTwoSites \ 1901 DISABLED_NavigateLoadingTabToTimeoutTwoSites 1902 #else 1903 #define MAYBE_NavigateLoadingTabToTimeoutTwoSites \ 1904 NavigateLoadingTabToTimeoutTwoSites 1905 #endif 1906 1907 // Checks that captive portal detection triggers correctly when a same-site 1908 // navigation is cancelled by a navigation to another site. 1909 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, 1910 MAYBE_NavigateLoadingTabToTimeoutTwoSites) { 1911 RunNavigateLoadingTabToTimeoutTest( 1912 browser(), 1913 GURL(kMockHttpsUrl), 1914 GURL(kMockHttpsUrl), 1915 GURL(kMockHttpsUrl2)); 1916 } 1917 1918 // Checks that captive portal detection triggers correctly when a cross-site 1919 // navigation is cancelled by a navigation to yet another site. 1920 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, 1921 NavigateLoadingTabToTimeoutThreeSites) { 1922 RunNavigateLoadingTabToTimeoutTest( 1923 browser(), 1924 URLRequestMockHTTPJob::GetMockUrl( 1925 base::FilePath(FILE_PATH_LITERAL("title.html"))), 1926 GURL(kMockHttpsUrl), 1927 GURL(kMockHttpsUrl2)); 1928 } 1929 1930 // Checks that navigating a timed out tab back clears its state. 1931 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, GoBack) { 1932 // Navigate to a working page. 1933 ui_test_utils::NavigateToURL( 1934 browser(), 1935 URLRequestMockHTTPJob::GetMockUrl( 1936 base::FilePath(FILE_PATH_LITERAL("title2.html")))); 1937 1938 // Go to the error page. 1939 SlowLoadBehindCaptivePortal(browser(), true); 1940 FailLoadsWithoutLogin(browser(), 1); 1941 1942 CaptivePortalObserver portal_observer(browser()->profile()); 1943 MultiNavigationObserver navigation_observer; 1944 1945 // Activate the error page tab again and go back. 1946 TabStripModel* tab_strip_model = browser()->tab_strip_model(); 1947 tab_strip_model->ActivateTabAt(0, true); 1948 chrome::GoBack(browser(), CURRENT_TAB); 1949 navigation_observer.WaitForNavigations(1); 1950 1951 EXPECT_EQ(1, navigation_observer.NumNavigationsForTab( 1952 tab_strip_model->GetWebContentsAt(0))); 1953 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, 1954 GetStateOfTabReloaderAt(browser(), 0)); 1955 EXPECT_EQ(0, portal_observer.num_results_received()); 1956 } 1957 1958 // Checks that navigating back to a timeout triggers captive portal detection. 1959 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, GoBackToTimeout) { 1960 // Disable captive portal detection so the first navigation doesn't open a 1961 // login tab. 1962 EnableCaptivePortalDetection(browser()->profile(), false); 1963 1964 SlowLoadNoCaptivePortal(browser(), captive_portal::RESULT_INTERNET_CONNECTED); 1965 1966 // Navigate to a working page. 1967 ui_test_utils::NavigateToURL( 1968 browser(), URLRequestMockHTTPJob::GetMockUrl( 1969 base::FilePath(FILE_PATH_LITERAL("title2.html")))); 1970 ASSERT_EQ(CaptivePortalTabReloader::STATE_NONE, 1971 GetStateOfTabReloaderAt(browser(), 0)); 1972 1973 EnableCaptivePortalDetection(browser()->profile(), true); 1974 1975 TabStripModel* tab_strip_model = browser()->tab_strip_model(); 1976 CaptivePortalTabReloader* tab_reloader = 1977 GetTabReloader(tab_strip_model->GetActiveWebContents()); 1978 ASSERT_TRUE(tab_reloader); 1979 SetSlowSSLLoadTime(tab_reloader, base::TimeDelta()); 1980 1981 // Go to the error page. 1982 MultiNavigationObserver navigation_observer; 1983 CaptivePortalObserver portal_observer(browser()->profile()); 1984 chrome::GoBack(browser(), CURRENT_TAB); 1985 1986 // Wait for the check triggered by the broken tab and for the login tab to 1987 // stop loading. 1988 portal_observer.WaitForResults(1); 1989 navigation_observer.WaitForNavigations(1); 1990 // Make sure the request has been issued. 1991 URLRequestTimeoutOnDemandJob::WaitForJobs(1); 1992 1993 EXPECT_EQ(1, portal_observer.num_results_received()); 1994 ASSERT_FALSE(CheckPending(browser())); 1995 ASSERT_EQ(captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL, 1996 portal_observer.captive_portal_result()); 1997 1998 ASSERT_EQ(CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL, 1999 GetStateOfTabReloaderAt(browser(), 0)); 2000 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, 2001 GetStateOfTabReloaderAt(browser(), 1)); 2002 ASSERT_TRUE(IsLoginTab(browser()->tab_strip_model()->GetWebContentsAt(1))); 2003 2004 ASSERT_EQ(2, tab_strip_model->count()); 2005 EXPECT_EQ(1, tab_strip_model->active_index()); 2006 EXPECT_EQ(1, navigation_observer.NumNavigationsForTab( 2007 tab_strip_model->GetWebContentsAt(1))); 2008 EXPECT_EQ(1, NumLoadingTabs()); 2009 2010 SetSlowSSLLoadTime(tab_reloader, base::TimeDelta::FromDays(1)); 2011 Login(browser(), 1, 0); 2012 FailLoadsAfterLogin(browser(), 1); 2013 } 2014 2015 // Checks that reloading a timeout triggers captive portal detection. 2016 // Much like the last test, though the captive portal is disabled before 2017 // the inital navigation, rather than captive portal detection. 2018 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, ReloadTimeout) { 2019 URLRequestMockCaptivePortalJobFactory::SetBehindCaptivePortal(false); 2020 2021 // Do the first navigation while not behind a captive portal. 2022 TabStripModel* tab_strip_model = browser()->tab_strip_model(); 2023 CaptivePortalObserver portal_observer(browser()->profile()); 2024 ui_test_utils::NavigateToURL(browser(), GURL(kMockHttpsUrl)); 2025 ASSERT_EQ(0, portal_observer.num_results_received()); 2026 ASSERT_EQ(1, tab_strip_model->count()); 2027 2028 // A captive portal spontaneously appears. 2029 URLRequestMockCaptivePortalJobFactory::SetBehindCaptivePortal(true); 2030 2031 CaptivePortalTabReloader* tab_reloader = 2032 GetTabReloader(tab_strip_model->GetActiveWebContents()); 2033 ASSERT_TRUE(tab_reloader); 2034 SetSlowSSLLoadTime(tab_reloader, base::TimeDelta()); 2035 2036 MultiNavigationObserver navigation_observer; 2037 tab_strip_model->GetActiveWebContents()->GetController().Reload(true); 2038 2039 // Wait for the check triggered by the broken tab and for the login tab to 2040 // stop loading. 2041 portal_observer.WaitForResults(1); 2042 navigation_observer.WaitForNavigations(1); 2043 // Make sure the request has been issued. 2044 URLRequestTimeoutOnDemandJob::WaitForJobs(1); 2045 2046 ASSERT_EQ(1, portal_observer.num_results_received()); 2047 ASSERT_FALSE(CheckPending(browser())); 2048 ASSERT_EQ(captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL, 2049 portal_observer.captive_portal_result()); 2050 2051 ASSERT_EQ(CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL, 2052 GetStateOfTabReloaderAt(browser(), 0)); 2053 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, 2054 GetStateOfTabReloaderAt(browser(), 1)); 2055 ASSERT_TRUE(IsLoginTab(tab_strip_model->GetWebContentsAt(1))); 2056 2057 ASSERT_EQ(2, tab_strip_model->count()); 2058 EXPECT_EQ(1, tab_strip_model->active_index()); 2059 EXPECT_EQ(1, navigation_observer.NumNavigationsForTab( 2060 tab_strip_model->GetWebContentsAt(1))); 2061 EXPECT_EQ(1, NumLoadingTabs()); 2062 2063 SetSlowSSLLoadTime(tab_reloader, base::TimeDelta::FromDays(1)); 2064 Login(browser(), 1, 0); 2065 FailLoadsAfterLogin(browser(), 1); 2066 } 2067 2068 // Checks the case where there are two windows, and there's an SSL timeout in 2069 // the background one. 2070 // Disabled: http://crbug.com/134357 2071 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, DISABLED_TwoWindows) { 2072 Browser* browser2 = 2073 new Browser(Browser::CreateParams(browser()->profile(), 2074 browser()->host_desktop_type())); 2075 // Navigate the new browser window so it'll be shown and we can pick the 2076 // active window. 2077 ui_test_utils::NavigateToURL(browser2, GURL(url::kAboutBlankURL)); 2078 2079 // Generally, |browser2| will be the active window. However, if the 2080 // original browser window lost focus before creating the new one, such as 2081 // when running multiple tests at once, the original browser window may 2082 // remain the profile's active window. 2083 Browser* active_browser = 2084 chrome::FindTabbedBrowser(browser()->profile(), true, 2085 browser()->host_desktop_type()); 2086 Browser* inactive_browser; 2087 if (active_browser == browser2) { 2088 // When only one test is running at a time, the new browser will probably be 2089 // on top, but when multiple tests are running at once, this is not 2090 // guaranteed. 2091 inactive_browser = browser(); 2092 } else { 2093 ASSERT_EQ(active_browser, browser()); 2094 inactive_browser = browser2; 2095 } 2096 2097 CaptivePortalObserver portal_observer(browser()->profile()); 2098 MultiNavigationObserver navigation_observer; 2099 2100 // Navigate the tab in the inactive browser to an SSL timeout. Have to use 2101 // chrome::NavigateParams and NEW_BACKGROUND_TAB to avoid activating the 2102 // window. 2103 chrome::NavigateParams params(inactive_browser, 2104 GURL(kMockHttpsQuickTimeoutUrl), 2105 ui::PAGE_TRANSITION_TYPED); 2106 params.disposition = NEW_BACKGROUND_TAB; 2107 params.window_action = chrome::NavigateParams::NO_ACTION; 2108 ui_test_utils::NavigateToURL(¶ms); 2109 navigation_observer.WaitForNavigations(2); 2110 2111 // Make sure the active window hasn't changed, and its new tab is 2112 // active. 2113 ASSERT_EQ(active_browser, 2114 chrome::FindTabbedBrowser(browser()->profile(), true, 2115 browser()->host_desktop_type())); 2116 ASSERT_EQ(1, active_browser->tab_strip_model()->active_index()); 2117 2118 // Check that the only two navigated tabs were the new error tab in the 2119 // backround windows, and the login tab in the active window. 2120 EXPECT_EQ(1, navigation_observer.NumNavigationsForTab( 2121 inactive_browser->tab_strip_model()->GetWebContentsAt(1))); 2122 EXPECT_EQ(1, navigation_observer.NumNavigationsForTab( 2123 active_browser->tab_strip_model()->GetWebContentsAt(1))); 2124 EXPECT_EQ(0, NumLoadingTabs()); 2125 2126 // Check captive portal test results. 2127 portal_observer.WaitForResults(1); 2128 ASSERT_EQ(captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL, 2129 portal_observer.captive_portal_result()); 2130 EXPECT_EQ(1, portal_observer.num_results_received()); 2131 2132 // Check the inactive browser. 2133 EXPECT_EQ(2, inactive_browser->tab_strip_model()->count()); 2134 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, 2135 GetStateOfTabReloaderAt(inactive_browser, 0)); 2136 EXPECT_EQ(CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL, 2137 GetStateOfTabReloaderAt(inactive_browser, 1)); 2138 2139 // Check the active browser. 2140 ASSERT_EQ(2, active_browser->tab_strip_model()->count()); 2141 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, 2142 GetStateOfTabReloaderAt(active_browser, 0)); 2143 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, 2144 GetStateOfTabReloaderAt(active_browser, 1)); 2145 EXPECT_TRUE( 2146 IsLoginTab(active_browser->tab_strip_model()->GetWebContentsAt(1))); 2147 2148 // Simulate logging in. 2149 Login(active_browser, 0, 1); 2150 } 2151 2152 // An HTTP page redirects to an HTTPS page loads slowly before timing out. A 2153 // captive portal is found, and then the user logs in before the original page 2154 // times out. 2155 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, HttpToHttpsRedirectLogin) { 2156 ASSERT_TRUE(test_server()->Start()); 2157 SlowLoadBehindCaptivePortal( 2158 browser(), 2159 true, 2160 test_server()->GetURL(CreateServerRedirect(kMockHttpsUrl)), 2161 1, 2162 1); 2163 Login(browser(), 1, 0); 2164 FailLoadsAfterLogin(browser(), 1); 2165 } 2166 2167 // An HTTPS page redirects to an HTTP page. 2168 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, HttpsToHttpRedirect) { 2169 // Use an HTTPS server for the top level page. 2170 net::SpawnedTestServer https_server( 2171 net::SpawnedTestServer::TYPE_HTTPS, net::SpawnedTestServer::kLocalhost, 2172 base::FilePath(FILE_PATH_LITERAL("chrome/test/data"))); 2173 ASSERT_TRUE(https_server.Start()); 2174 2175 GURL http_timeout_url = 2176 URLRequestFailedJob::GetMockHttpUrl(net::ERR_CONNECTION_TIMED_OUT); 2177 2178 // 2 navigations due to the Link Doctor. 2179 NavigateToPageExpectNoTest( 2180 browser(), 2181 https_server.GetURL(CreateServerRedirect(http_timeout_url.spec())), 2182 2); 2183 } 2184 2185 // Tests the 511 response code, along with an HTML redirect to a login page. 2186 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, Status511) { 2187 SetUpCaptivePortalService(browser()->profile(), 2188 GURL(kMockCaptivePortal511Url)); 2189 SlowLoadBehindCaptivePortal(browser(), true, GURL(kMockHttpsUrl), 2, 2); 2190 Login(browser(), 1, 0); 2191 FailLoadsAfterLogin(browser(), 1); 2192 } 2193 2194 // HSTS redirects an HTTP request to HTTPS, and the request then times out. 2195 // A captive portal is then detected, and a login tab opened, before logging 2196 // in. 2197 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, HstsLogin) { 2198 GURL::Replacements replacements; 2199 std::string scheme = "http"; 2200 replacements.SetSchemeStr(scheme); 2201 GURL http_timeout_url = GURL(kMockHttpsUrl).ReplaceComponents(replacements); 2202 2203 URLRequestFailedJob::GetMockHttpUrl(net::ERR_CONNECTION_TIMED_OUT); 2204 content::BrowserThread::PostTask( 2205 content::BrowserThread::IO, FROM_HERE, 2206 base::Bind(&AddHstsHost, 2207 make_scoped_refptr(browser()->profile()->GetRequestContext()), 2208 http_timeout_url.host())); 2209 2210 SlowLoadBehindCaptivePortal(browser(), true, http_timeout_url, 1, 1); 2211 Login(browser(), 1, 0); 2212 FailLoadsAfterLogin(browser(), 1); 2213 } 2214