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