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.
8 #include "base/basictypes.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"
56 using captive_portal::CaptivePortalResult;
57 using content::BrowserThread;
58 using content::WebContents;
59 using net::URLRequestFailedJob;
60 using net::URLRequestMockHTTPJob;
64 // Path of the fake login page, when using the TestServer.
65 const char* const kTestServerLoginPath = "files/captive_portal/login.html";
67 // Path of a page with an iframe that has a mock SSL timeout, when using the
69 const char* const kTestServerIframeTimeoutPath =
70 "files/captive_portal/iframe_timeout.html";
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.
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";
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
88 const char* const kMockCaptivePortal511Url =
89 "http://mock.captive.portal.511/page511.html";
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.
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";
99 // Same as above, but different domain, so can be used to trigger cross-site
101 const char* const kMockHttpsUrl2 =
102 "https://mock.captive.portal.long.timeout2/title2.html";
104 // Same as kMockHttpsUrl, except the timeout happens instantly.
105 const char* const kMockHttpsQuickTimeoutUrl =
106 "https://mock.captive.portal.quick.timeout/title2.html";
108 // Expected title of a tab once an HTTPS load completes, when not behind a
110 const char* const kInternetConnectedTitle = "Title Of Awesomeness";
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 {
118 // net::URLRequestJob:
119 void Start() override;
121 // All the public static methods below can be called on any thread.
123 // Waits for exactly |num_jobs|.
124 static void WaitForJobs(int num_jobs);
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);
132 // Abandon all active URLRequestTimeoutOnDemandJobs. |expected_num_jobs|
133 // behaves just as in FailJobs.
134 static void AbandonJobs(int expected_num_jobs);
137 friend class URLRequestMockCaptivePortalJobFactory;
139 // Operation to perform on jobs when removing them from |job_list_|.
140 enum EndJobOperation {
145 URLRequestTimeoutOnDemandJob(net::URLRequest* request,
146 net::NetworkDelegate* network_delegate);
147 ~URLRequestTimeoutOnDemandJob() override;
149 // Attempts to removes |this| from |jobs_|. Returns true if it was removed
151 bool RemoveFromList();
153 static void WaitForJobsOnIOThread(int num_jobs);
154 static void FailOrAbandonJobsOnIOThread(
155 int expected_num_jobs,
156 EndJobOperation end_job_operation);
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();
164 // All class variables are only accessed on the IO thread.
166 // Number of jobs currently being waited for, or 0 if not currently
168 static int num_jobs_to_wait_for_;
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_;
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
178 static int num_jobs_started_;
180 // Head of linked list of jobs that have been started and are now waiting to
182 static URLRequestTimeoutOnDemandJob* job_list_;
184 // The next job that had been started but not yet timed out.
185 URLRequestTimeoutOnDemandJob* next_job_;
187 DISALLOW_COPY_AND_ASSIGN(URLRequestTimeoutOnDemandJob);
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;
195 void URLRequestTimeoutOnDemandJob::Start() {
196 EXPECT_TRUE(CalledOnValidThread());
198 // Insert at start of the list.
199 next_job_ = job_list_;
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();
211 void URLRequestTimeoutOnDemandJob::WaitForJobs(int num_jobs) {
212 content::BrowserThread::PostTask(
213 content::BrowserThread::IO, FROM_HERE,
214 base::Bind(&URLRequestTimeoutOnDemandJob::WaitForJobsOnIOThread,
216 content::RunMessageLoop();
220 void URLRequestTimeoutOnDemandJob::FailJobs(int expected_num_jobs) {
221 content::BrowserThread::PostTask(
222 content::BrowserThread::IO, FROM_HERE,
223 base::Bind(&URLRequestTimeoutOnDemandJob::FailOrAbandonJobsOnIOThread,
229 void URLRequestTimeoutOnDemandJob::AbandonJobs(int expected_num_jobs) {
230 content::BrowserThread::PostTask(
231 content::BrowserThread::IO, FROM_HERE,
232 base::Bind(&URLRequestTimeoutOnDemandJob::FailOrAbandonJobsOnIOThread,
237 URLRequestTimeoutOnDemandJob::URLRequestTimeoutOnDemandJob(
238 net::URLRequest* request, net::NetworkDelegate* network_delegate)
239 : net::URLRequestJob(request, network_delegate),
243 URLRequestTimeoutOnDemandJob::~URLRequestTimeoutOnDemandJob() {
244 // All hanging jobs should have failed or been abandoned before being
246 EXPECT_FALSE(RemoveFromList());
249 bool URLRequestTimeoutOnDemandJob::RemoveFromList() {
250 URLRequestTimeoutOnDemandJob** job = &job_list_;
260 // If the job wasn't in this list, |next_job_| should be NULL.
261 EXPECT_FALSE(next_job_);
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);
273 num_jobs_to_wait_for_ = num_jobs;
274 MaybeStopWaitingForJobsOnIOThread();
278 void URLRequestTimeoutOnDemandJob::MaybeStopWaitingForJobsOnIOThread() {
279 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
280 if (num_jobs_to_wait_for_ == 0)
283 // There shouldn't be any extra jobs.
284 EXPECT_LE(num_jobs_started_, num_jobs_to_wait_for_);
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());
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;
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));
319 EXPECT_EQ(expected_num_jobs, num_jobs_started_);
320 EXPECT_EQ(expected_num_jobs, num_jobs);
322 num_jobs_started_ -= expected_num_jobs;
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.
330 // It handles requests for kMockCaptivePortalTestUrl, kMockHttpsUrl, and
331 // kMockHttpsQuickTimeoutUrl.
332 class URLRequestMockCaptivePortalJobFactory {
334 // The public static methods below can be called on any thread.
336 // Adds the testing URLs to the net::URLRequestFilter. Should only be called
338 static void AddUrlHandlers();
340 // Sets whether or not there is a captive portal. Outstanding requests are
342 static void SetBehindCaptivePortal(bool behind_captive_portal);
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);
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
354 static net::URLRequestJob* Factory(net::URLRequest* request,
355 net::NetworkDelegate* network_delegate,
356 const std::string& scheme);
358 static bool behind_captive_portal_;
360 DISALLOW_IMPLICIT_CONSTRUCTORS(URLRequestMockCaptivePortalJobFactory);
363 bool URLRequestMockCaptivePortalJobFactory::behind_captive_portal_ = true;
366 void URLRequestMockCaptivePortalJobFactory::AddUrlHandlers() {
367 content::BrowserThread::PostTask(
368 content::BrowserThread::IO, FROM_HERE,
370 &URLRequestMockCaptivePortalJobFactory::AddUrlHandlersOnIOThread));
374 void URLRequestMockCaptivePortalJobFactory::SetBehindCaptivePortal(
375 bool behind_captive_portal) {
376 content::BrowserThread::PostTask(
377 content::BrowserThread::IO, FROM_HERE,
379 &URLRequestMockCaptivePortalJobFactory::
380 SetBehindCaptivePortalOnIOThread,
381 behind_captive_portal));
385 void URLRequestMockCaptivePortalJobFactory::AddUrlHandlersOnIOThread() {
386 EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
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);
404 void URLRequestMockCaptivePortalJobFactory::SetBehindCaptivePortalOnIOThread(
405 bool behind_captive_portal) {
406 EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
407 behind_captive_portal_ = behind_captive_portal;
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));
417 // The PathService is threadsafe.
418 base::FilePath root_http;
419 PathService::Get(chrome::DIR_TEST_DATA, &root_http);
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(
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(
442 root_http.Append(FILE_PATH_LITERAL("title2.html")),
443 BrowserThread::GetBlockingPool()->GetTaskRunnerWithShutdownBehavior(
444 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN));
446 // The URL should be the captive portal test URL.
447 EXPECT_TRUE(GURL(kMockCaptivePortalTestUrl) == request->url() ||
448 GURL(kMockCaptivePortal511Url) == request->url());
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(
457 root_http.Append(FILE_PATH_LITERAL("captive_portal/page511.html")),
458 BrowserThread::GetBlockingPool()->GetTaskRunnerWithShutdownBehavior(
459 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN));
461 return new URLRequestMockHTTPJob(
464 root_http.Append(FILE_PATH_LITERAL("captive_portal/login.html")),
465 BrowserThread::GetBlockingPool()->GetTaskRunnerWithShutdownBehavior(
466 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN));
469 // After logging in to the portal, the test URLs return a 204 response.
470 return new URLRequestMockHTTPJob(
473 root_http.Append(FILE_PATH_LITERAL("captive_portal/page204.html")),
474 BrowserThread::GetBlockingPool()->GetTaskRunnerWithShutdownBehavior(
475 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN));
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;
485 // Returns the total number of loading tabs across all Browsers, for all
487 int NumLoadingTabs() {
488 int num_loading_tabs = 0;
489 for (TabContentsIterator it; !it.done(); it.Next()) {
493 return num_loading_tabs;
496 bool IsLoginTab(WebContents* web_contents) {
497 return CaptivePortalTabHelper::FromWebContents(web_contents)->IsLoginTab();
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 {
505 MultiNavigationObserver();
506 ~MultiNavigationObserver() override;
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);
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;
517 // The number of LOAD_STOP events since |this| was created.
518 int num_navigations() const { return num_navigations_; }
521 typedef std::map<const WebContents*, int> TabNavigationMap;
523 // content::NotificationObserver:
524 void Observe(int type,
525 const content::NotificationSource& source,
526 const content::NotificationDetails& details) override;
528 int num_navigations_;
530 // Map of how many times each tab has navigated since |this| was created.
531 TabNavigationMap tab_navigation_map_;
533 // Total number of navigations to wait for. Value only matters when
534 // |waiting_for_navigation_| is true.
535 int num_navigations_to_wait_for_;
537 // True if WaitForNavigations has been called, until
538 // |num_navigations_to_wait_for_| have been observed.
539 bool waiting_for_navigation_;
541 content::NotificationRegistrar registrar_;
543 DISALLOW_COPY_AND_ASSIGN(MultiNavigationObserver);
546 MultiNavigationObserver::MultiNavigationObserver()
547 : num_navigations_(0),
548 num_navigations_to_wait_for_(0),
549 waiting_for_navigation_(false) {
550 registrar_.Add(this, content::NOTIFICATION_LOAD_STOP,
551 content::NotificationService::AllSources());
554 MultiNavigationObserver::~MultiNavigationObserver() {
557 void MultiNavigationObserver::WaitForNavigations(
558 int num_navigations_to_wait_for) {
559 // Shouldn't already be waiting for navigations.
560 EXPECT_FALSE(waiting_for_navigation_);
561 EXPECT_LT(0, num_navigations_to_wait_for);
562 if (num_navigations_ < num_navigations_to_wait_for) {
563 num_navigations_to_wait_for_ = num_navigations_to_wait_for;
564 waiting_for_navigation_ = true;
565 content::RunMessageLoop();
566 EXPECT_FALSE(waiting_for_navigation_);
568 EXPECT_EQ(num_navigations_, num_navigations_to_wait_for);
571 int MultiNavigationObserver::NumNavigationsForTab(
572 WebContents* web_contents) const {
573 TabNavigationMap::const_iterator tab_navigations =
574 tab_navigation_map_.find(web_contents);
575 if (tab_navigations == tab_navigation_map_.end())
577 return tab_navigations->second;
580 void MultiNavigationObserver::Observe(
582 const content::NotificationSource& source,
583 const content::NotificationDetails& details) {
584 ASSERT_EQ(type, content::NOTIFICATION_LOAD_STOP);
585 content::NavigationController* controller =
586 content::Source<content::NavigationController>(source).ptr();
588 ++tab_navigation_map_[controller->GetWebContents()];
589 if (waiting_for_navigation_ &&
590 num_navigations_to_wait_for_ == num_navigations_) {
591 waiting_for_navigation_ = false;
592 base::MessageLoopForUI::current()->Quit();
596 // This observer creates a list of loading tabs, and then waits for them all
597 // to stop loading and have the kInternetConnectedTitle.
599 // This is for the specific purpose of observing tabs time out after logging in
600 // to a captive portal, which will then cause them to reload.
601 // MultiNavigationObserver is insufficient for this because there may or may not
602 // be a LOAD_STOP event between the timeout and the reload.
603 // See bug http://crbug.com/133227
604 class FailLoadsAfterLoginObserver : public content::NotificationObserver {
606 FailLoadsAfterLoginObserver();
607 ~FailLoadsAfterLoginObserver() override;
609 void WaitForNavigations();
612 typedef std::set<const WebContents*> TabSet;
614 // content::NotificationObserver:
615 void Observe(int type,
616 const content::NotificationSource& source,
617 const content::NotificationDetails& details) override;
619 // The set of tabs that need to be navigated. This is the set of loading
620 // tabs when the observer is created.
621 TabSet tabs_needing_navigation_;
623 // Number of tabs that have stopped navigating with the expected title. These
624 // are expected not to be navigated again.
625 TabSet tabs_navigated_to_final_destination_;
627 // True if WaitForNavigations has been called, until
628 // |tabs_navigated_to_final_destination_| equals |tabs_needing_navigation_|.
629 bool waiting_for_navigation_;
631 content::NotificationRegistrar registrar_;
633 DISALLOW_COPY_AND_ASSIGN(FailLoadsAfterLoginObserver);
636 FailLoadsAfterLoginObserver::FailLoadsAfterLoginObserver()
637 : waiting_for_navigation_(false) {
638 registrar_.Add(this, content::NOTIFICATION_LOAD_STOP,
639 content::NotificationService::AllSources());
640 for (TabContentsIterator it; !it.done(); it.Next()) {
642 tabs_needing_navigation_.insert(*it);
646 FailLoadsAfterLoginObserver::~FailLoadsAfterLoginObserver() {
649 void FailLoadsAfterLoginObserver::WaitForNavigations() {
650 // Shouldn't already be waiting for navigations.
651 EXPECT_FALSE(waiting_for_navigation_);
652 if (tabs_needing_navigation_.size() !=
653 tabs_navigated_to_final_destination_.size()) {
654 waiting_for_navigation_ = true;
655 content::RunMessageLoop();
656 EXPECT_FALSE(waiting_for_navigation_);
658 EXPECT_EQ(tabs_needing_navigation_.size(),
659 tabs_navigated_to_final_destination_.size());
662 void FailLoadsAfterLoginObserver::Observe(
664 const content::NotificationSource& source,
665 const content::NotificationDetails& details) {
666 ASSERT_EQ(type, content::NOTIFICATION_LOAD_STOP);
667 content::NavigationController* controller =
668 content::Source<content::NavigationController>(source).ptr();
669 WebContents* contents = controller->GetWebContents();
671 ASSERT_EQ(1u, tabs_needing_navigation_.count(contents));
672 ASSERT_EQ(0u, tabs_navigated_to_final_destination_.count(contents));
674 if (contents->GetTitle() != base::ASCIIToUTF16(kInternetConnectedTitle))
676 tabs_navigated_to_final_destination_.insert(contents);
678 if (waiting_for_navigation_ &&
679 tabs_needing_navigation_.size() ==
680 tabs_navigated_to_final_destination_.size()) {
681 waiting_for_navigation_ = false;
682 base::MessageLoopForUI::current()->Quit();
686 // An observer for watching the CaptivePortalService. It tracks the last
687 // received result and the total number of received results.
688 class CaptivePortalObserver : public content::NotificationObserver {
690 explicit CaptivePortalObserver(Profile* profile);
692 // Runs the message loop until until at exactly |update_count| capitive portal
693 // results have been received, since this creation of |this|. Expects no
694 // additional captive portal results.
695 void WaitForResults(int num_results_to_wait_for);
697 int num_results_received() const { return num_results_received_; }
699 CaptivePortalResult captive_portal_result() const {
700 return captive_portal_result_;
704 // Records results and exits the message loop, if needed.
705 void Observe(int type,
706 const content::NotificationSource& source,
707 const content::NotificationDetails& details) override;
709 // Number of times OnPortalResult has been called since construction.
710 int num_results_received_;
712 // If WaitForResults was called, the total number of updates for which to
713 // wait. Value doesn't matter when |waiting_for_result_| is false.
714 int num_results_to_wait_for_;
716 bool waiting_for_result_;
720 CaptivePortalService* captive_portal_service_;
722 // Last result received.
723 CaptivePortalResult captive_portal_result_;
725 content::NotificationRegistrar registrar_;
727 DISALLOW_COPY_AND_ASSIGN(CaptivePortalObserver);
730 CaptivePortalObserver::CaptivePortalObserver(Profile* profile)
731 : num_results_received_(0),
732 num_results_to_wait_for_(0),
733 waiting_for_result_(false),
735 captive_portal_service_(
736 CaptivePortalServiceFactory::GetForProfile(profile)),
737 captive_portal_result_(
738 captive_portal_service_->last_detection_result()) {
740 chrome::NOTIFICATION_CAPTIVE_PORTAL_CHECK_RESULT,
741 content::Source<Profile>(profile_));
744 void CaptivePortalObserver::WaitForResults(int num_results_to_wait_for) {
745 EXPECT_LT(0, num_results_to_wait_for);
746 EXPECT_FALSE(waiting_for_result_);
747 if (num_results_received_ < num_results_to_wait_for) {
748 num_results_to_wait_for_ = num_results_to_wait_for;
749 waiting_for_result_ = true;
750 content::RunMessageLoop();
751 EXPECT_FALSE(waiting_for_result_);
753 EXPECT_EQ(num_results_to_wait_for, num_results_received_);
756 void CaptivePortalObserver::Observe(
758 const content::NotificationSource& source,
759 const content::NotificationDetails& details) {
760 ASSERT_EQ(type, chrome::NOTIFICATION_CAPTIVE_PORTAL_CHECK_RESULT);
761 ASSERT_EQ(profile_, content::Source<Profile>(source).ptr());
763 CaptivePortalService::Results* results =
764 content::Details<CaptivePortalService::Results>(details).ptr();
766 EXPECT_EQ(captive_portal_result_, results->previous_result);
767 EXPECT_EQ(captive_portal_service_->last_detection_result(),
770 captive_portal_result_ = results->result;
771 ++num_results_received_;
773 if (waiting_for_result_ &&
774 num_results_to_wait_for_ == num_results_received_) {
775 waiting_for_result_ = false;
776 base::MessageLoop::current()->Quit();
780 // Adds an HSTS rule for |host|, so that all HTTP requests sent to it will
781 // be switched to HTTPS requests.
782 void AddHstsHost(net::URLRequestContextGetter* context_getter,
783 const std::string& host) {
784 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
785 net::TransportSecurityState* transport_security_state =
786 context_getter->GetURLRequestContext()->transport_security_state();
787 if (!transport_security_state) {
792 base::Time expiry = base::Time::Now() + base::TimeDelta::FromDays(1000);
793 bool include_subdomains = false;
794 transport_security_state->AddHSTS(host, expiry, include_subdomains);
799 class CaptivePortalBrowserTest : public InProcessBrowserTest {
801 CaptivePortalBrowserTest();
803 // InProcessBrowserTest:
804 void SetUpOnMainThread() override;
805 void TearDownOnMainThread() override;
807 // Sets the captive portal checking preference. Does not affect the command
808 // line flag, which is set in SetUpCommandLine.
809 void EnableCaptivePortalDetection(Profile* profile, bool enabled);
811 // Sets up the captive portal service for the given profile so that
812 // all checks go to |test_url|. Also disables all timers.
813 void SetUpCaptivePortalService(Profile* profile, const GURL& test_url);
815 // Returns true if |browser|'s profile is currently running a captive portal
817 bool CheckPending(Browser* browser);
819 // Returns the CaptivePortalTabReloader::State of |web_contents|.
820 CaptivePortalTabReloader::State GetStateOfTabReloader(
821 WebContents* web_contents) const;
823 // Returns the CaptivePortalTabReloader::State of the indicated tab.
824 CaptivePortalTabReloader::State GetStateOfTabReloaderAt(Browser* browser,
827 // Returns the number of tabs with the given state, across all profiles.
828 int NumTabsWithState(CaptivePortalTabReloader::State state) const;
830 // Returns the number of tabs broken by captive portals, across all profiles.
831 int NumBrokenTabs() const;
833 // Returns the number of tabs that need to be reloaded due to having logged
834 // in to a captive portal, across all profiles.
835 int NumNeedReloadTabs() const;
837 // Navigates |browser|'s active tab to |url| and expects no captive portal
838 // test to be triggered. |expected_navigations| is the number of times the
839 // active tab will end up being navigated. It should be 1, except for the
840 // Link Doctor page, which acts like two navigations.
841 void NavigateToPageExpectNoTest(Browser* browser,
843 int expected_navigations);
845 // Navigates |browser|'s active tab to an SSL tab that takes a while to load,
846 // triggering a captive portal check, which is expected to give the result
847 // |expected_result|. The page finishes loading, with a timeout, after the
848 // captive portal check.
849 void SlowLoadNoCaptivePortal(Browser* browser,
850 CaptivePortalResult expected_result);
852 // Navigates |browser|'s active tab to an SSL timeout, expecting a captive
853 // portal check to be triggered and return a result which will indicates
854 // there's no detected captive portal.
855 void FastTimeoutNoCaptivePortal(Browser* browser,
856 CaptivePortalResult expected_result);
858 // Navigates the active tab to a slow loading SSL page, which will then
859 // trigger a captive portal test. The test is expected to find a captive
860 // portal. The slow loading page will continue to load after the function
861 // returns, until URLRequestTimeoutOnDemandJob::FailJobs() is called,
862 // at which point it will timeout.
864 // When |expect_login_tab| is false, no login tab is expected to be opened,
865 // because one already exists, and the function returns once the captive
866 // portal test is complete.
868 // If |expect_login_tab| is true, a login tab is then expected to be opened.
869 // It waits until both the login tab has finished loading, and two captive
870 // portal tests complete. The second test is triggered by the load of the
871 // captive portal tab completing.
873 // This function must not be called when the active tab is currently loading.
874 // Waits for the hanging request to be issued, so other functions can rely
875 // on URLRequestTimeoutOnDemandJob::WaitForJobs having been called.
876 void SlowLoadBehindCaptivePortal(Browser* browser, bool expect_login_tab);
878 // Same as above, but takes extra parameters.
880 // |hanging_url| should either be kMockHttpsUrl or redirect to kMockHttpsUrl.
882 // |expected_portal_checks| and |expected_login_tab_navigations| allow
883 // client-side redirects to be tested. |expected_login_tab_navigations| is
884 // ignored when |expect_open_login_tab| is false.
885 void SlowLoadBehindCaptivePortal(Browser* browser,
886 bool expect_open_login_tab,
887 const GURL& hanging_url,
888 int expected_portal_checks,
889 int expected_login_tab_navigations);
891 // Just like SlowLoadBehindCaptivePortal, except the navigated tab has
892 // a connection timeout rather having its time trigger, and the function
893 // waits until that timeout occurs.
894 void FastTimeoutBehindCaptivePortal(Browser* browser,
895 bool expect_open_login_tab);
897 // Much as above, but accepts a URL parameter and can be used for errors that
898 // trigger captive portal checks other than timeouts. |error_url| should
899 // result in an error rather than hanging.
900 void FastErrorBehindCaptivePortal(Browser* browser,
901 bool expect_open_login_tab,
902 const GURL& error_url);
904 // Navigates the login tab without logging in. The login tab must be the
905 // specified browser's active tab. Expects no other tab to change state.
906 // |num_loading_tabs| and |num_timed_out_tabs| are used as extra checks
907 // that nothing has gone wrong prior to the function call.
908 void NavigateLoginTab(Browser* browser,
909 int num_loading_tabs,
910 int num_timed_out_tabs);
912 // Simulates a login by updating the URLRequestMockCaptivePortalJob's
913 // behind captive portal state, and navigating the login tab. Waits for
914 // all broken but not loading tabs to be reloaded.
915 // |num_loading_tabs| and |num_timed_out_tabs| are used as extra checks
916 // that nothing has gone wrong prior to the function call.
917 void Login(Browser* browser, int num_loading_tabs, int num_timed_out_tabs);
919 // Makes the slow SSL loads of all active tabs time out at once, and waits for
920 // them to finish both that load and the automatic reload it should trigger.
921 // There should be no timed out tabs when this is called.
922 void FailLoadsAfterLogin(Browser* browser, int num_loading_tabs);
924 // Makes the slow SSL loads of all active tabs time out at once, and waits for
925 // them to finish displaying their error pages. The login tab should be the
926 // active tab. There should be no timed out tabs when this is called.
927 void FailLoadsWithoutLogin(Browser* browser, int num_loading_tabs);
929 // Navigates |browser|'s active tab to |starting_url| while not behind a
930 // captive portal. Then navigates to |interrupted_url|, which should create
931 // a URLRequestTimeoutOnDemandJob, which is then abandoned. The load should
932 // trigger a captive portal check, which finds a captive portal and opens a
935 // Then the navigation is interrupted by a navigation to |timeout_url|, which
936 // should trigger a captive portal check, and finally the test simulates
939 // The purpose of this test is to make sure the TabHelper triggers a captive
940 // portal check when a load is interrupted by another load, particularly in
941 // the case of cross-process navigations.
942 void RunNavigateLoadingTabToTimeoutTest(Browser* browser,
943 const GURL& starting_url,
944 const GURL& interrupted_url,
945 const GURL& timeout_url);
947 // Sets the timeout used by a CaptivePortalTabReloader on slow SSL loads
948 // before a captive portal check.
949 void SetSlowSSLLoadTime(CaptivePortalTabReloader* tab_reloader,
950 base::TimeDelta slow_ssl_load_time);
952 CaptivePortalTabReloader* GetTabReloader(WebContents* web_contents) const;
955 DISALLOW_COPY_AND_ASSIGN(CaptivePortalBrowserTest);
958 CaptivePortalBrowserTest::CaptivePortalBrowserTest() {
961 void CaptivePortalBrowserTest::SetUpOnMainThread() {
962 // Enable mock requests.
963 content::BrowserThread::PostTask(
964 content::BrowserThread::IO, FROM_HERE,
965 base::Bind(&chrome_browser_net::SetUrlRequestMocksEnabled, true));
966 URLRequestMockCaptivePortalJobFactory::AddUrlHandlers();
968 // Double-check that the captive portal service isn't enabled by default for
970 EXPECT_EQ(CaptivePortalService::DISABLED_FOR_TESTING,
971 CaptivePortalService::get_state_for_testing());
973 CaptivePortalService::set_state_for_testing(
974 CaptivePortalService::SKIP_OS_CHECK_FOR_TESTING);
975 EnableCaptivePortalDetection(browser()->profile(), true);
977 // Set the captive portal service to use URLRequestMockCaptivePortalJob's
978 // mock URL, by default.
979 SetUpCaptivePortalService(browser()->profile(),
980 GURL(kMockCaptivePortalTestUrl));
983 void CaptivePortalBrowserTest::TearDownOnMainThread() {
984 // No test should have a captive portal check pending on quit.
985 EXPECT_FALSE(CheckPending(browser()));
988 void CaptivePortalBrowserTest::EnableCaptivePortalDetection(
989 Profile* profile, bool enabled) {
990 profile->GetPrefs()->SetBoolean(prefs::kAlternateErrorPagesEnabled, enabled);
993 void CaptivePortalBrowserTest::SetUpCaptivePortalService(Profile* profile,
994 const GURL& test_url) {
995 CaptivePortalService* captive_portal_service =
996 CaptivePortalServiceFactory::GetForProfile(profile);
997 captive_portal_service->set_test_url(test_url);
999 // Don't use any non-zero timers. Timers are checked in unit tests.
1000 CaptivePortalService::RecheckPolicy* recheck_policy =
1001 &captive_portal_service->recheck_policy();
1002 recheck_policy->initial_backoff_no_portal_ms = 0;
1003 recheck_policy->initial_backoff_portal_ms = 0;
1004 recheck_policy->backoff_policy.maximum_backoff_ms = 0;
1007 bool CaptivePortalBrowserTest::CheckPending(Browser* browser) {
1008 CaptivePortalService* captive_portal_service =
1009 CaptivePortalServiceFactory::GetForProfile(browser->profile());
1011 return captive_portal_service->DetectionInProgress() ||
1012 captive_portal_service->TimerRunning();
1015 CaptivePortalTabReloader::State CaptivePortalBrowserTest::GetStateOfTabReloader(
1016 WebContents* web_contents) const {
1017 return GetTabReloader(web_contents)->state();
1020 CaptivePortalTabReloader::State
1021 CaptivePortalBrowserTest::GetStateOfTabReloaderAt(Browser* browser,
1023 return GetStateOfTabReloader(
1024 browser->tab_strip_model()->GetWebContentsAt(index));
1027 int CaptivePortalBrowserTest::NumTabsWithState(
1028 CaptivePortalTabReloader::State state) const {
1030 for (TabContentsIterator it; !it.done(); it.Next()) {
1031 if (GetStateOfTabReloader(*it) == state)
1037 int CaptivePortalBrowserTest::NumBrokenTabs() const {
1038 return NumTabsWithState(CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL);
1041 int CaptivePortalBrowserTest::NumNeedReloadTabs() const {
1042 return NumTabsWithState(CaptivePortalTabReloader::STATE_NEEDS_RELOAD);
1045 void CaptivePortalBrowserTest::NavigateToPageExpectNoTest(
1048 int expected_navigations) {
1049 MultiNavigationObserver navigation_observer;
1050 CaptivePortalObserver portal_observer(browser->profile());
1052 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
1053 browser, url, expected_navigations);
1055 // No captive portal checks should have ocurred or be pending, and there
1056 // should be no new tabs.
1057 EXPECT_EQ(0, portal_observer.num_results_received());
1058 EXPECT_FALSE(CheckPending(browser));
1059 EXPECT_EQ(1, browser->tab_strip_model()->count());
1060 EXPECT_EQ(expected_navigations, navigation_observer.num_navigations());
1061 EXPECT_EQ(0, NumLoadingTabs());
1062 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE,
1063 GetStateOfTabReloaderAt(browser, 0));
1066 void CaptivePortalBrowserTest::SlowLoadNoCaptivePortal(
1068 CaptivePortalResult expected_result) {
1069 CaptivePortalTabReloader* tab_reloader =
1070 GetTabReloader(browser->tab_strip_model()->GetActiveWebContents());
1071 ASSERT_TRUE(tab_reloader);
1072 SetSlowSSLLoadTime(tab_reloader, base::TimeDelta());
1074 MultiNavigationObserver navigation_observer;
1075 CaptivePortalObserver portal_observer(browser->profile());
1076 ui_test_utils::NavigateToURLWithDisposition(browser,
1077 GURL(kMockHttpsUrl),
1079 ui_test_utils::BROWSER_TEST_NONE);
1081 portal_observer.WaitForResults(1);
1083 ASSERT_EQ(1, browser->tab_strip_model()->count());
1084 EXPECT_EQ(expected_result, portal_observer.captive_portal_result());
1085 EXPECT_EQ(1, portal_observer.num_results_received());
1086 EXPECT_EQ(0, navigation_observer.num_navigations());
1087 EXPECT_FALSE(CheckPending(browser));
1089 // First tab should still be loading.
1090 EXPECT_EQ(1, NumLoadingTabs());
1092 // Wait for the request to be issued, then time it out.
1093 URLRequestTimeoutOnDemandJob::WaitForJobs(1);
1094 URLRequestTimeoutOnDemandJob::FailJobs(1);
1095 navigation_observer.WaitForNavigations(1);
1097 ASSERT_EQ(1, browser->tab_strip_model()->count());
1098 EXPECT_EQ(1, portal_observer.num_results_received());
1099 EXPECT_FALSE(CheckPending(browser));
1100 EXPECT_EQ(0, NumLoadingTabs());
1102 // Set a slow SSL load time to prevent the timer from triggering.
1103 SetSlowSSLLoadTime(tab_reloader, base::TimeDelta::FromDays(1));
1106 void CaptivePortalBrowserTest::FastTimeoutNoCaptivePortal(
1108 CaptivePortalResult expected_result) {
1109 ASSERT_NE(expected_result, captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL);
1111 // Set the load time to be large, so the timer won't trigger. The value is
1112 // not restored at the end of the function.
1113 CaptivePortalTabReloader* tab_reloader =
1114 GetTabReloader(browser->tab_strip_model()->GetActiveWebContents());
1115 ASSERT_TRUE(tab_reloader);
1116 SetSlowSSLLoadTime(tab_reloader, base::TimeDelta::FromHours(1));
1118 MultiNavigationObserver navigation_observer;
1119 CaptivePortalObserver portal_observer(browser->profile());
1121 // Neither of these should be changed by the navigation.
1122 int active_index = browser->tab_strip_model()->active_index();
1123 int expected_tab_count = browser->tab_strip_model()->count();
1125 ui_test_utils::NavigateToURL(
1127 URLRequestFailedJob::GetMockHttpsUrl(net::ERR_CONNECTION_TIMED_OUT));
1129 // An attempt to detect a captive portal should have started by now. If not,
1130 // abort early to prevent hanging.
1131 ASSERT_TRUE(portal_observer.num_results_received() > 0 ||
1132 CheckPending(browser));
1134 portal_observer.WaitForResults(1);
1135 navigation_observer.WaitForNavigations(1);
1137 // Check the result.
1138 EXPECT_EQ(1, portal_observer.num_results_received());
1139 EXPECT_EQ(expected_result, portal_observer.captive_portal_result());
1141 // Check that the right tab was navigated, and there were no extra
1143 EXPECT_EQ(1, navigation_observer.NumNavigationsForTab(
1144 browser->tab_strip_model()->GetWebContentsAt(active_index)));
1145 EXPECT_EQ(0, NumLoadingTabs());
1147 // Check the tab's state, and verify no captive portal check is pending.
1148 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE,
1149 GetStateOfTabReloaderAt(browser, 0));
1150 EXPECT_FALSE(CheckPending(browser));
1152 // Make sure no login tab was opened.
1153 EXPECT_EQ(expected_tab_count, browser->tab_strip_model()->count());
1156 void CaptivePortalBrowserTest::SlowLoadBehindCaptivePortal(
1158 bool expect_open_login_tab) {
1159 SlowLoadBehindCaptivePortal(browser,
1160 expect_open_login_tab,
1161 GURL(kMockHttpsUrl),
1166 void CaptivePortalBrowserTest::SlowLoadBehindCaptivePortal(
1168 bool expect_open_login_tab,
1169 const GURL& hanging_url,
1170 int expected_portal_checks,
1171 int expected_login_tab_navigations) {
1172 ASSERT_GE(expected_portal_checks, 1);
1173 TabStripModel* tab_strip_model = browser->tab_strip_model();
1174 // Calling this on a tab that's waiting for a load to manually be timed out
1175 // will result in a hang.
1176 ASSERT_FALSE(tab_strip_model->GetActiveWebContents()->IsLoading());
1178 // Trigger a captive portal check quickly.
1179 CaptivePortalTabReloader* tab_reloader =
1180 GetTabReloader(tab_strip_model->GetActiveWebContents());
1181 ASSERT_TRUE(tab_reloader);
1182 SetSlowSSLLoadTime(tab_reloader, base::TimeDelta());
1184 // Number of tabs expected to be open after the captive portal checks
1186 int initial_tab_count = tab_strip_model->count();
1187 int initial_active_index = tab_strip_model->active_index();
1188 int initial_loading_tabs = NumLoadingTabs();
1189 int expected_broken_tabs = NumBrokenTabs();
1190 if (CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL !=
1191 GetStateOfTabReloader(tab_strip_model->GetActiveWebContents())) {
1192 ++expected_broken_tabs;
1195 MultiNavigationObserver navigation_observer;
1196 CaptivePortalObserver portal_observer(browser->profile());
1197 ui_test_utils::NavigateToURLWithDisposition(browser,
1200 ui_test_utils::BROWSER_TEST_NONE);
1201 portal_observer.WaitForResults(expected_portal_checks);
1203 if (expect_open_login_tab) {
1204 ASSERT_GE(expected_login_tab_navigations, 1);
1206 navigation_observer.WaitForNavigations(expected_login_tab_navigations);
1208 ASSERT_EQ(initial_tab_count + 1, tab_strip_model->count());
1209 EXPECT_EQ(initial_tab_count, tab_strip_model->active_index());
1211 EXPECT_EQ(expected_login_tab_navigations,
1212 navigation_observer.NumNavigationsForTab(
1213 tab_strip_model->GetWebContentsAt(initial_tab_count)));
1214 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE,
1215 GetStateOfTabReloaderAt(browser, 1));
1216 EXPECT_TRUE(IsLoginTab(tab_strip_model->GetWebContentsAt(1)));
1218 EXPECT_EQ(0, navigation_observer.num_navigations());
1219 EXPECT_EQ(initial_active_index, tab_strip_model->active_index());
1220 ASSERT_EQ(initial_tab_count, tab_strip_model->count());
1221 EXPECT_EQ(initial_active_index, tab_strip_model->active_index());
1224 // Wait for all the expect resource loads to actually start, so subsequent
1225 // functions can rely on them having started.
1226 URLRequestTimeoutOnDemandJob::WaitForJobs(initial_loading_tabs + 1);
1228 EXPECT_EQ(initial_loading_tabs + 1, NumLoadingTabs());
1229 EXPECT_EQ(expected_broken_tabs, NumBrokenTabs());
1230 EXPECT_EQ(captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL,
1231 portal_observer.captive_portal_result());
1232 EXPECT_EQ(expected_portal_checks, portal_observer.num_results_received());
1233 EXPECT_FALSE(CheckPending(browser));
1235 EXPECT_EQ(CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL,
1236 GetStateOfTabReloaderAt(browser, initial_active_index));
1238 // Reset the load time to be large, so the timer won't trigger on a reload.
1239 SetSlowSSLLoadTime(tab_reloader, base::TimeDelta::FromHours(1));
1242 void CaptivePortalBrowserTest::FastTimeoutBehindCaptivePortal(
1244 bool expect_open_login_tab) {
1245 FastErrorBehindCaptivePortal(browser,
1246 expect_open_login_tab,
1247 GURL(kMockHttpsQuickTimeoutUrl));
1250 void CaptivePortalBrowserTest::FastErrorBehindCaptivePortal(
1252 bool expect_open_login_tab,
1253 const GURL& error_url) {
1254 TabStripModel* tab_strip_model = browser->tab_strip_model();
1255 // Calling this on a tab that's waiting for a load to manually be timed out
1256 // will result in a hang.
1257 ASSERT_FALSE(tab_strip_model->GetActiveWebContents()->IsLoading());
1259 // Set the load time to be large, so the timer won't trigger. The value is
1260 // not restored at the end of the function.
1261 CaptivePortalTabReloader* tab_reloader =
1262 GetTabReloader(tab_strip_model->GetActiveWebContents());
1263 ASSERT_TRUE(tab_reloader);
1264 SetSlowSSLLoadTime(tab_reloader, base::TimeDelta::FromHours(1));
1266 // Number of tabs expected to be open after the captive portal checks
1268 int initial_tab_count = tab_strip_model->count();
1269 int initial_active_index = tab_strip_model->active_index();
1270 int initial_loading_tabs = NumLoadingTabs();
1271 int expected_broken_tabs = NumBrokenTabs();
1272 if (CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL !=
1273 GetStateOfTabReloader(tab_strip_model->GetActiveWebContents())) {
1274 ++expected_broken_tabs;
1277 MultiNavigationObserver navigation_observer;
1278 CaptivePortalObserver portal_observer(browser->profile());
1279 ui_test_utils::NavigateToURLWithDisposition(browser,
1282 ui_test_utils::BROWSER_TEST_NONE);
1283 portal_observer.WaitForResults(1);
1285 if (expect_open_login_tab) {
1286 navigation_observer.WaitForNavigations(2);
1287 ASSERT_EQ(initial_tab_count + 1, tab_strip_model->count());
1288 EXPECT_EQ(initial_tab_count, tab_strip_model->active_index());
1289 // Make sure that the originally active tab and the captive portal tab have
1290 // each loaded once.
1291 EXPECT_EQ(1, navigation_observer.NumNavigationsForTab(
1292 tab_strip_model->GetWebContentsAt(initial_active_index)));
1293 EXPECT_EQ(1, navigation_observer.NumNavigationsForTab(
1294 tab_strip_model->GetWebContentsAt(initial_tab_count)));
1295 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE,
1296 GetStateOfTabReloaderAt(browser, 1));
1297 EXPECT_TRUE(IsLoginTab(tab_strip_model->GetWebContentsAt(1)));
1299 navigation_observer.WaitForNavigations(1);
1300 EXPECT_EQ(initial_active_index, tab_strip_model->active_index());
1301 EXPECT_EQ(1, navigation_observer.NumNavigationsForTab(
1302 tab_strip_model->GetWebContentsAt(initial_active_index)));
1303 ASSERT_EQ(initial_tab_count, tab_strip_model->count());
1304 EXPECT_EQ(initial_active_index, tab_strip_model->active_index());
1307 EXPECT_EQ(initial_loading_tabs, NumLoadingTabs());
1308 EXPECT_EQ(expected_broken_tabs, NumBrokenTabs());
1309 EXPECT_EQ(captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL,
1310 portal_observer.captive_portal_result());
1311 EXPECT_EQ(1, portal_observer.num_results_received());
1312 EXPECT_FALSE(CheckPending(browser));
1314 EXPECT_EQ(CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL,
1315 GetStateOfTabReloaderAt(browser, initial_active_index));
1318 void CaptivePortalBrowserTest::NavigateLoginTab(Browser* browser,
1319 int num_loading_tabs,
1320 int num_timed_out_tabs) {
1321 MultiNavigationObserver navigation_observer;
1322 CaptivePortalObserver portal_observer(browser->profile());
1324 TabStripModel* tab_strip_model = browser->tab_strip_model();
1325 int initial_tab_count = tab_strip_model->count();
1326 EXPECT_EQ(num_loading_tabs, NumLoadingTabs());
1327 EXPECT_EQ(num_timed_out_tabs, NumBrokenTabs() - NumLoadingTabs());
1329 int login_tab_index = tab_strip_model->active_index();
1330 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE,
1331 GetStateOfTabReloader(tab_strip_model->GetActiveWebContents()));
1332 ASSERT_TRUE(IsLoginTab(browser->tab_strip_model()->GetActiveWebContents()));
1334 // Do the navigation.
1335 content::RenderFrameHost* render_frame_host =
1336 tab_strip_model->GetActiveWebContents()->GetMainFrame();
1337 render_frame_host->ExecuteJavaScript(base::ASCIIToUTF16("submitForm()"));
1339 portal_observer.WaitForResults(1);
1340 navigation_observer.WaitForNavigations(1);
1342 // Check the captive portal result.
1343 EXPECT_EQ(captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL,
1344 portal_observer.captive_portal_result());
1345 EXPECT_EQ(1, portal_observer.num_results_received());
1346 EXPECT_FALSE(CheckPending(browser));
1348 // Make sure not much has changed.
1349 EXPECT_EQ(initial_tab_count, tab_strip_model->count());
1350 EXPECT_EQ(num_loading_tabs, NumLoadingTabs());
1351 EXPECT_EQ(num_loading_tabs + num_timed_out_tabs, NumBrokenTabs());
1352 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE,
1353 GetStateOfTabReloaderAt(browser, login_tab_index));
1354 EXPECT_TRUE(IsLoginTab(tab_strip_model->GetWebContentsAt(login_tab_index)));
1356 // Make sure there were no unexpected navigations.
1357 EXPECT_EQ(1, navigation_observer.NumNavigationsForTab(
1358 tab_strip_model->GetWebContentsAt(login_tab_index)));
1361 void CaptivePortalBrowserTest::Login(Browser* browser,
1362 int num_loading_tabs,
1363 int num_timed_out_tabs) {
1364 // Simulate logging in.
1365 URLRequestMockCaptivePortalJobFactory::SetBehindCaptivePortal(false);
1367 MultiNavigationObserver navigation_observer;
1368 CaptivePortalObserver portal_observer(browser->profile());
1370 TabStripModel* tab_strip_model = browser->tab_strip_model();
1371 int initial_tab_count = tab_strip_model->count();
1372 ASSERT_EQ(num_loading_tabs, NumLoadingTabs());
1373 EXPECT_EQ(num_timed_out_tabs, NumBrokenTabs() - NumLoadingTabs());
1375 // Verify that the login page is on top.
1376 int login_tab_index = tab_strip_model->active_index();
1377 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE,
1378 GetStateOfTabReloaderAt(browser, login_tab_index));
1379 ASSERT_TRUE(IsLoginTab(tab_strip_model->GetWebContentsAt(login_tab_index)));
1381 // Trigger a navigation.
1382 content::RenderFrameHost* render_frame_host =
1383 tab_strip_model->GetActiveWebContents()->GetMainFrame();
1384 render_frame_host->ExecuteJavaScript(base::ASCIIToUTF16("submitForm()"));
1386 portal_observer.WaitForResults(1);
1388 // Wait for all the timed out tabs to reload.
1389 navigation_observer.WaitForNavigations(1 + num_timed_out_tabs);
1390 EXPECT_EQ(1, portal_observer.num_results_received());
1392 // The tabs that were loading before should still be loading, and now be in
1393 // STATE_NEEDS_RELOAD.
1394 EXPECT_EQ(0, NumBrokenTabs());
1395 EXPECT_EQ(num_loading_tabs, NumLoadingTabs());
1396 EXPECT_EQ(num_loading_tabs, NumNeedReloadTabs());
1398 // Make sure that the broken tabs have reloaded, and there's no more
1399 // captive portal tab.
1400 EXPECT_EQ(initial_tab_count, tab_strip_model->count());
1401 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE,
1402 GetStateOfTabReloaderAt(browser, login_tab_index));
1403 EXPECT_FALSE(IsLoginTab(tab_strip_model->GetWebContentsAt(login_tab_index)));
1405 // Make sure there were no unexpected navigations of the login tab.
1406 EXPECT_EQ(1, navigation_observer.NumNavigationsForTab(
1407 tab_strip_model->GetWebContentsAt(login_tab_index)));
1410 void CaptivePortalBrowserTest::FailLoadsAfterLogin(Browser* browser,
1411 int num_loading_tabs) {
1412 ASSERT_EQ(num_loading_tabs, NumLoadingTabs());
1413 ASSERT_EQ(num_loading_tabs, NumNeedReloadTabs());
1414 EXPECT_EQ(0, NumBrokenTabs());
1416 TabStripModel* tab_strip_model = browser->tab_strip_model();
1417 int initial_num_tabs = tab_strip_model->count();
1418 int initial_active_tab = tab_strip_model->active_index();
1420 CaptivePortalObserver portal_observer(browser->profile());
1421 FailLoadsAfterLoginObserver fail_loads_observer;
1422 // Connection(s) finally time out. There should have already been a call
1423 // to wait for the requests to be issued before logging on.
1424 URLRequestTimeoutOnDemandJob::WaitForJobs(num_loading_tabs);
1425 URLRequestTimeoutOnDemandJob::FailJobs(num_loading_tabs);
1427 fail_loads_observer.WaitForNavigations();
1429 // No captive portal checks should have ocurred or be pending, and there
1430 // should be no new tabs.
1431 EXPECT_EQ(0, portal_observer.num_results_received());
1432 EXPECT_FALSE(CheckPending(browser));
1433 EXPECT_EQ(initial_num_tabs, tab_strip_model->count());
1435 EXPECT_EQ(initial_active_tab, tab_strip_model->active_index());
1437 EXPECT_EQ(0, NumNeedReloadTabs());
1438 EXPECT_EQ(0, NumLoadingTabs());
1441 void CaptivePortalBrowserTest::FailLoadsWithoutLogin(Browser* browser,
1442 int num_loading_tabs) {
1443 ASSERT_EQ(num_loading_tabs, NumLoadingTabs());
1444 ASSERT_EQ(0, NumNeedReloadTabs());
1445 EXPECT_EQ(num_loading_tabs, NumBrokenTabs());
1447 TabStripModel* tab_strip_model = browser->tab_strip_model();
1448 int initial_num_tabs = tab_strip_model->count();
1449 int login_tab = tab_strip_model->active_index();
1450 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE,
1451 GetStateOfTabReloader(tab_strip_model->GetActiveWebContents()));
1452 ASSERT_TRUE(IsLoginTab(tab_strip_model->GetActiveWebContents()));
1454 CaptivePortalObserver portal_observer(browser->profile());
1455 MultiNavigationObserver navigation_observer;
1456 // Connection(s) finally time out. There should have already been a call
1457 // to wait for the requests to be issued.
1458 URLRequestTimeoutOnDemandJob::FailJobs(num_loading_tabs);
1460 navigation_observer.WaitForNavigations(num_loading_tabs);
1462 // No captive portal checks should have ocurred or be pending, and there
1463 // should be no new tabs.
1464 EXPECT_EQ(0, portal_observer.num_results_received());
1465 EXPECT_FALSE(CheckPending(browser));
1466 EXPECT_EQ(initial_num_tabs, tab_strip_model->count());
1468 EXPECT_EQ(0, NumNeedReloadTabs());
1469 EXPECT_EQ(0, NumLoadingTabs());
1470 EXPECT_EQ(num_loading_tabs, NumBrokenTabs());
1471 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE,
1472 GetStateOfTabReloader(tab_strip_model->GetActiveWebContents()));
1473 EXPECT_TRUE(IsLoginTab(tab_strip_model->GetActiveWebContents()));
1474 EXPECT_EQ(login_tab, tab_strip_model->active_index());
1476 EXPECT_EQ(0, navigation_observer.NumNavigationsForTab(
1477 tab_strip_model->GetWebContentsAt(login_tab)));
1480 void CaptivePortalBrowserTest::RunNavigateLoadingTabToTimeoutTest(
1482 const GURL& starting_url,
1483 const GURL& hanging_url,
1484 const GURL& timeout_url) {
1485 // Temporarily disable the captive portal and navigate to the starting
1486 // URL, which may be a URL that will hang when behind a captive portal.
1487 URLRequestMockCaptivePortalJobFactory::SetBehindCaptivePortal(false);
1488 NavigateToPageExpectNoTest(browser, starting_url, 1);
1489 URLRequestMockCaptivePortalJobFactory::SetBehindCaptivePortal(true);
1491 // Go to the first hanging url.
1492 SlowLoadBehindCaptivePortal(browser, true, hanging_url, 1, 1);
1494 // Abandon the request.
1495 URLRequestTimeoutOnDemandJob::WaitForJobs(1);
1496 URLRequestTimeoutOnDemandJob::AbandonJobs(1);
1498 TabStripModel* tab_strip_model = browser->tab_strip_model();
1499 CaptivePortalTabReloader* tab_reloader =
1500 GetTabReloader(tab_strip_model->GetWebContentsAt(0));
1501 ASSERT_TRUE(tab_reloader);
1503 // A non-zero delay makes it more likely that CaptivePortalTabHelper will
1504 // be confused by events relating to canceling the old navigation.
1505 SetSlowSSLLoadTime(tab_reloader, base::TimeDelta::FromSeconds(2));
1506 CaptivePortalObserver portal_observer(browser->profile());
1508 // Navigate the error tab to another slow loading page. Can't have
1509 // ui_test_utils do the navigation because it will wait for loading tabs to
1510 // stop loading before navigating.
1512 // This may result in either 0 or 1 DidStopLoading events. If there is one,
1513 // it must happen before the CaptivePortalService sends out its test request,
1514 // so waiting for PortalObserver to see that request prevents it from
1515 // confusing the MultiNavigationObservers used later.
1516 tab_strip_model->ActivateTabAt(0, true);
1517 browser->OpenURL(content::OpenURLParams(timeout_url,
1518 content::Referrer(),
1520 ui::PAGE_TRANSITION_TYPED,
1522 portal_observer.WaitForResults(1);
1523 EXPECT_FALSE(CheckPending(browser));
1524 EXPECT_EQ(1, NumLoadingTabs());
1525 EXPECT_EQ(CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL,
1526 GetStateOfTabReloaderAt(browser, 0));
1527 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE,
1528 GetStateOfTabReloaderAt(browser, 1));
1529 ASSERT_TRUE(IsLoginTab(tab_strip_model->GetWebContentsAt(1)));
1531 // Need to make sure the request has been issued before logging in.
1532 URLRequestTimeoutOnDemandJob::WaitForJobs(1);
1534 // Simulate logging in.
1535 tab_strip_model->ActivateTabAt(1, true);
1536 SetSlowSSLLoadTime(tab_reloader, base::TimeDelta::FromDays(1));
1537 Login(browser, 1, 0);
1539 // Timeout occurs, and page is automatically reloaded.
1540 FailLoadsAfterLogin(browser, 1);
1543 void CaptivePortalBrowserTest::SetSlowSSLLoadTime(
1544 CaptivePortalTabReloader* tab_reloader,
1545 base::TimeDelta slow_ssl_load_time) {
1546 tab_reloader->set_slow_ssl_load_time(slow_ssl_load_time);
1549 CaptivePortalTabReloader* CaptivePortalBrowserTest::GetTabReloader(
1550 WebContents* web_contents) const {
1551 return CaptivePortalTabHelper::FromWebContents(web_contents)->
1552 GetTabReloaderForTest();
1555 // Make sure there's no test for a captive portal on HTTP timeouts. This will
1556 // also trigger the link doctor page, which results in the load of a second
1558 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, HttpTimeout) {
1559 GURL url = URLRequestFailedJob::GetMockHttpUrl(net::ERR_CONNECTION_TIMED_OUT);
1560 NavigateToPageExpectNoTest(browser(), url, 2);
1563 // Make sure there's no check for a captive portal on HTTPS errors other than
1564 // timeouts, when they preempt the slow load timer.
1565 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, HttpsNonTimeoutError) {
1566 GURL url = URLRequestFailedJob::GetMockHttpsUrl(net::ERR_UNEXPECTED);
1567 NavigateToPageExpectNoTest(browser(), url, 1);
1570 // Make sure no captive portal test triggers on HTTPS timeouts of iframes.
1571 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, HttpsIframeTimeout) {
1572 // Use an HTTPS server for the top level page.
1573 net::SpawnedTestServer https_server(
1574 net::SpawnedTestServer::TYPE_HTTPS, net::SpawnedTestServer::kLocalhost,
1575 base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
1576 ASSERT_TRUE(https_server.Start());
1578 GURL url = https_server.GetURL(kTestServerIframeTimeoutPath);
1579 NavigateToPageExpectNoTest(browser(), url, 1);
1582 // Check the captive portal result when the test request reports a network
1583 // error. The check is triggered by a slow loading page, and the page
1584 // errors out only after getting a captive portal result.
1585 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, RequestFails) {
1586 SetUpCaptivePortalService(
1587 browser()->profile(),
1588 URLRequestFailedJob::GetMockHttpUrl(net::ERR_CONNECTION_CLOSED));
1589 SlowLoadNoCaptivePortal(browser(), captive_portal::RESULT_NO_RESPONSE);
1592 // Same as above, but for the rather unlikely case that the connection times out
1593 // before the timer triggers.
1594 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, RequestFailsFastTimout) {
1595 SetUpCaptivePortalService(
1596 browser()->profile(),
1597 URLRequestFailedJob::GetMockHttpUrl(net::ERR_CONNECTION_CLOSED));
1598 FastTimeoutNoCaptivePortal(browser(), captive_portal::RESULT_NO_RESPONSE);
1601 // Checks the case that captive portal detection is disabled.
1602 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, Disabled) {
1603 EnableCaptivePortalDetection(browser()->profile(), false);
1604 SlowLoadNoCaptivePortal(browser(), captive_portal::RESULT_INTERNET_CONNECTED);
1607 // Checks that we look for a captive portal on HTTPS timeouts and don't reload
1608 // the error tab when the captive portal probe gets a 204 response, indicating
1609 // there is no captive portal.
1610 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, InternetConnected) {
1611 // Can't just use SetBehindCaptivePortal(false), since then there wouldn't
1613 ASSERT_TRUE(test_server()->Start());
1614 SetUpCaptivePortalService(browser()->profile(),
1615 test_server()->GetURL("nocontent"));
1616 SlowLoadNoCaptivePortal(browser(), captive_portal::RESULT_INTERNET_CONNECTED);
1619 // Checks that no login page is opened when the HTTP test URL redirects to an
1620 // SSL certificate error.
1621 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, RedirectSSLCertError) {
1622 // Need an HTTP TestServer to handle a dynamically created server redirect.
1623 ASSERT_TRUE(test_server()->Start());
1625 net::SpawnedTestServer::SSLOptions ssl_options;
1626 ssl_options.server_certificate =
1627 net::SpawnedTestServer::SSLOptions::CERT_MISMATCHED_NAME;
1628 net::SpawnedTestServer https_server(
1629 net::SpawnedTestServer::TYPE_HTTPS, ssl_options,
1630 base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
1631 ASSERT_TRUE(https_server.Start());
1633 GURL ssl_login_url = https_server.GetURL(kTestServerLoginPath);
1635 CaptivePortalService* captive_portal_service =
1636 CaptivePortalServiceFactory::GetForProfile(browser()->profile());
1637 ASSERT_TRUE(captive_portal_service);
1638 SetUpCaptivePortalService(
1639 browser()->profile(),
1640 test_server()->GetURL(CreateServerRedirect(ssl_login_url.spec())));
1642 SlowLoadNoCaptivePortal(browser(), captive_portal::RESULT_NO_RESPONSE);
1645 // A slow SSL load triggers a captive portal check. The user logs on before
1646 // the SSL page times out. We wait for the timeout and subsequent reload.
1647 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, Login) {
1648 // Load starts, detect captive portal and open up a login tab.
1649 SlowLoadBehindCaptivePortal(browser(), true);
1651 // Log in. One loading tab, no timed out ones.
1652 Login(browser(), 1, 0);
1654 // Timeout occurs, and page is automatically reloaded.
1655 FailLoadsAfterLogin(browser(), 1);
1658 // Same as above, except we make sure everything works with an incognito
1659 // profile. Main issues it tests for are that the incognito has its own
1660 // non-NULL captive portal service, and we open the tab in the correct
1662 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, LoginIncognito) {
1663 // This will watch tabs for both profiles, but only used to make sure no
1664 // navigations occur for the non-incognito profile.
1665 MultiNavigationObserver navigation_observer;
1666 CaptivePortalObserver non_incognito_portal_observer(browser()->profile());
1668 Browser* incognito_browser = CreateIncognitoBrowser();
1669 EnableCaptivePortalDetection(incognito_browser->profile(), true);
1670 SetUpCaptivePortalService(incognito_browser->profile(),
1671 GURL(kMockCaptivePortalTestUrl));
1673 SlowLoadBehindCaptivePortal(incognito_browser, true);
1675 TabStripModel* tab_strip_model = browser()->tab_strip_model();
1676 EXPECT_EQ(1, tab_strip_model->count());
1677 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE,
1678 GetStateOfTabReloaderAt(browser(), 0));
1680 Login(incognito_browser, 1, 0);
1681 FailLoadsAfterLogin(incognito_browser, 1);
1683 EXPECT_EQ(1, tab_strip_model->count());
1684 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE,
1685 GetStateOfTabReloaderAt(browser(), 0));
1687 EXPECT_EQ(0, navigation_observer.NumNavigationsForTab(
1688 tab_strip_model->GetWebContentsAt(0)));
1689 EXPECT_EQ(0, non_incognito_portal_observer.num_results_received());
1692 // The captive portal page is opened before the SSL page times out,
1693 // but the user logs in only after the page times out.
1694 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, LoginSlow) {
1695 SlowLoadBehindCaptivePortal(browser(), true);
1696 FailLoadsWithoutLogin(browser(), 1);
1697 Login(browser(), 0, 1);
1700 // Checks the unlikely case that the tab times out before the timer triggers.
1701 // This most likely won't happen, but should still work:
1702 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, LoginFastTimeout) {
1703 FastTimeoutBehindCaptivePortal(browser(), true);
1704 Login(browser(), 0, 1);
1707 // A cert error triggers a captive portal check and results in opening a login
1708 // tab. The user then logs in and the page with the error is reloaded.
1709 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, SSLCertErrorLogin) {
1710 // Need an HTTP TestServer to handle a dynamically created server redirect.
1711 ASSERT_TRUE(test_server()->Start());
1713 net::SpawnedTestServer::SSLOptions https_options;
1714 https_options.server_certificate =
1715 net::SpawnedTestServer::SSLOptions::CERT_MISMATCHED_NAME;
1716 net::SpawnedTestServer https_server(
1717 net::SpawnedTestServer::TYPE_HTTPS, https_options,
1718 base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
1719 ASSERT_TRUE(https_server.Start());
1721 // The path does not matter.
1722 GURL cert_error_url = https_server.GetURL(kTestServerLoginPath);
1723 // The interstitial should trigger a captive portal check when it opens, just
1724 // like navigating to kMockHttpsQuickTimeoutUrl.
1725 FastErrorBehindCaptivePortal(browser(), true, cert_error_url);
1727 // Simulate logging in. Can't use Login() because the interstitial tab looks
1728 // like a cross between a hung tab (Load was never committed) and a tab at an
1729 // error page (The load was stopped).
1730 URLRequestMockCaptivePortalJobFactory::SetBehindCaptivePortal(false);
1731 MultiNavigationObserver navigation_observer;
1732 CaptivePortalObserver portal_observer(browser()->profile());
1734 TabStripModel* tab_strip_model = browser()->tab_strip_model();
1735 content::RenderFrameHost* render_frame_host =
1736 tab_strip_model->GetActiveWebContents()->GetMainFrame();
1737 render_frame_host->ExecuteJavaScript(base::ASCIIToUTF16("submitForm()"));
1739 // The captive portal tab navigation will trigger a captive portal check,
1740 // and reloading the original tab will bring up the interstitial page again,
1741 // triggering a second captive portal check.
1742 portal_observer.WaitForResults(2);
1744 // Wait for both tabs to finish loading.
1745 navigation_observer.WaitForNavigations(2);
1746 EXPECT_EQ(2, portal_observer.num_results_received());
1747 EXPECT_FALSE(CheckPending(browser()));
1748 EXPECT_EQ(captive_portal::RESULT_INTERNET_CONNECTED,
1749 portal_observer.captive_portal_result());
1751 // Check state of tabs. While the first tab is still displaying an
1752 // interstitial page, since no portal was found, it should be in STATE_NONE,
1753 // as should the login tab.
1754 ASSERT_EQ(2, tab_strip_model->count());
1755 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE,
1756 GetStateOfTabReloaderAt(browser(), 0));
1757 EXPECT_FALSE(IsLoginTab(tab_strip_model->GetWebContentsAt(1)));
1758 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE,
1759 GetStateOfTabReloaderAt(browser(), 1));
1761 // Make sure only one navigation was for the login tab.
1762 EXPECT_EQ(1, navigation_observer.NumNavigationsForTab(
1763 tab_strip_model->GetWebContentsAt(1)));
1766 // Tries navigating both the tab that encounters an SSL timeout and the
1767 // login tab twice, only logging in the second time.
1768 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, LoginExtraNavigations) {
1769 FastTimeoutBehindCaptivePortal(browser(), true);
1771 // Activate the timed out tab and navigate it to a timeout again.
1772 TabStripModel* tab_strip_model = browser()->tab_strip_model();
1773 tab_strip_model->ActivateTabAt(0, true);
1774 FastTimeoutBehindCaptivePortal(browser(), false);
1776 // Activate and navigate the captive portal tab. This should not trigger a
1777 // reload of the tab with the error.
1778 tab_strip_model->ActivateTabAt(1, true);
1779 NavigateLoginTab(browser(), 0, 1);
1781 // Simulate logging in.
1782 Login(browser(), 0, 1);
1785 // After the first SSL timeout, closes the login tab and makes sure it's opened
1786 // it again on a second timeout.
1787 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, CloseLoginTab) {
1788 // First load starts, opens a login tab, and then times out.
1789 SlowLoadBehindCaptivePortal(browser(), true);
1790 FailLoadsWithoutLogin(browser(), 1);
1793 chrome::CloseTab(browser());
1795 // Go through the standard slow load login, and make sure it still works.
1796 SlowLoadBehindCaptivePortal(browser(), true);
1797 Login(browser(), 1, 0);
1798 FailLoadsAfterLogin(browser(), 1);
1801 // Checks that two tabs with SSL timeouts in the same window work. Both
1802 // tabs only timeout after logging in.
1803 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, TwoBrokenTabs) {
1804 SlowLoadBehindCaptivePortal(browser(), true);
1806 // Can't set the TabReloader HTTPS timeout on a new tab without doing some
1807 // acrobatics, so open a new tab at a normal page, and then navigate it to a
1809 MultiNavigationObserver navigation_observer;
1810 CaptivePortalObserver portal_observer(browser()->profile());
1811 ui_test_utils::NavigateToURLWithDisposition(
1813 URLRequestMockHTTPJob::GetMockUrl(
1814 base::FilePath(FILE_PATH_LITERAL("title2.html"))),
1816 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
1818 TabStripModel* tab_strip_model = browser()->tab_strip_model();
1819 ASSERT_EQ(3, tab_strip_model->count());
1820 EXPECT_FALSE(CheckPending(browser()));
1821 EXPECT_EQ(0, portal_observer.num_results_received());
1822 EXPECT_EQ(1, NumLoadingTabs());
1823 EXPECT_EQ(1, navigation_observer.num_navigations());
1824 EXPECT_EQ(1, navigation_observer.NumNavigationsForTab(
1825 tab_strip_model->GetWebContentsAt(2)));
1826 ASSERT_EQ(CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL,
1827 GetStateOfTabReloaderAt(browser(), 0));
1828 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE,
1829 GetStateOfTabReloaderAt(browser(), 1));
1830 ASSERT_TRUE(IsLoginTab(tab_strip_model->GetWebContentsAt(1)));
1831 ASSERT_EQ(CaptivePortalTabReloader::STATE_NONE,
1832 GetStateOfTabReloaderAt(browser(), 2));
1833 ASSERT_EQ(2, tab_strip_model->active_index());
1835 SlowLoadBehindCaptivePortal(browser(), false);
1837 tab_strip_model->ActivateTabAt(1, true);
1838 Login(browser(), 2, 0);
1839 FailLoadsAfterLogin(browser(), 2);
1842 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, AbortLoad) {
1843 SlowLoadBehindCaptivePortal(browser(), true);
1845 // Abandon the request.
1846 URLRequestTimeoutOnDemandJob::WaitForJobs(1);
1847 URLRequestTimeoutOnDemandJob::AbandonJobs(1);
1849 CaptivePortalObserver portal_observer(browser()->profile());
1850 MultiNavigationObserver navigation_observer;
1852 // Switch back to the hung tab from the login tab, and abort the navigation.
1853 TabStripModel* tab_strip_model = browser()->tab_strip_model();
1854 tab_strip_model->ActivateTabAt(0, true);
1855 chrome::Stop(browser());
1856 navigation_observer.WaitForNavigations(1);
1858 EXPECT_EQ(0, NumBrokenTabs());
1859 EXPECT_EQ(0, portal_observer.num_results_received());
1860 EXPECT_FALSE(CheckPending(browser()));
1861 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE,
1862 GetStateOfTabReloaderAt(browser(), 0));
1864 tab_strip_model->ActivateTabAt(1, true);
1865 Login(browser(), 0, 0);
1868 // Checks the case where the timed out tab is successfully navigated before
1870 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, NavigateBrokenTab) {
1871 // Go to the error page.
1872 SlowLoadBehindCaptivePortal(browser(), true);
1873 FailLoadsWithoutLogin(browser(), 1);
1875 // Navigate the error tab to a non-error page.
1876 TabStripModel* tab_strip_model = browser()->tab_strip_model();
1877 tab_strip_model->ActivateTabAt(0, true);
1878 ui_test_utils::NavigateToURL(
1879 browser(), URLRequestMockHTTPJob::GetMockUrl(
1880 base::FilePath(FILE_PATH_LITERAL("title2.html"))));
1881 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE,
1882 GetStateOfTabReloaderAt(browser(), 0));
1884 // Simulate logging in.
1885 tab_strip_model->ActivateTabAt(1, true);
1886 Login(browser(), 0, 0);
1889 // Checks that captive portal detection triggers correctly when a same-site
1890 // navigation is cancelled by a navigation to the same site.
1891 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest,
1892 NavigateLoadingTabToTimeoutSingleSite) {
1893 RunNavigateLoadingTabToTimeoutTest(
1895 GURL(kMockHttpsUrl),
1896 GURL(kMockHttpsUrl),
1897 GURL(kMockHttpsUrl));
1900 // Fails on Windows only, mostly on Win7. http://crbug.com/170033
1902 #define MAYBE_NavigateLoadingTabToTimeoutTwoSites \
1903 DISABLED_NavigateLoadingTabToTimeoutTwoSites
1905 #define MAYBE_NavigateLoadingTabToTimeoutTwoSites \
1906 NavigateLoadingTabToTimeoutTwoSites
1909 // Checks that captive portal detection triggers correctly when a same-site
1910 // navigation is cancelled by a navigation to another site.
1911 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest,
1912 MAYBE_NavigateLoadingTabToTimeoutTwoSites) {
1913 RunNavigateLoadingTabToTimeoutTest(
1915 GURL(kMockHttpsUrl),
1916 GURL(kMockHttpsUrl),
1917 GURL(kMockHttpsUrl2));
1920 // Checks that captive portal detection triggers correctly when a cross-site
1921 // navigation is cancelled by a navigation to yet another site.
1922 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest,
1923 NavigateLoadingTabToTimeoutThreeSites) {
1924 RunNavigateLoadingTabToTimeoutTest(
1926 URLRequestMockHTTPJob::GetMockUrl(
1927 base::FilePath(FILE_PATH_LITERAL("title.html"))),
1928 GURL(kMockHttpsUrl),
1929 GURL(kMockHttpsUrl2));
1932 // Checks that navigating a timed out tab back clears its state.
1933 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, GoBack) {
1934 // Navigate to a working page.
1935 ui_test_utils::NavigateToURL(
1937 URLRequestMockHTTPJob::GetMockUrl(
1938 base::FilePath(FILE_PATH_LITERAL("title2.html"))));
1940 // Go to the error page.
1941 SlowLoadBehindCaptivePortal(browser(), true);
1942 FailLoadsWithoutLogin(browser(), 1);
1944 CaptivePortalObserver portal_observer(browser()->profile());
1945 MultiNavigationObserver navigation_observer;
1947 // Activate the error page tab again and go back.
1948 TabStripModel* tab_strip_model = browser()->tab_strip_model();
1949 tab_strip_model->ActivateTabAt(0, true);
1950 chrome::GoBack(browser(), CURRENT_TAB);
1951 navigation_observer.WaitForNavigations(1);
1953 EXPECT_EQ(1, navigation_observer.NumNavigationsForTab(
1954 tab_strip_model->GetWebContentsAt(0)));
1955 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE,
1956 GetStateOfTabReloaderAt(browser(), 0));
1957 EXPECT_EQ(0, portal_observer.num_results_received());
1960 // Checks that navigating back to a timeout triggers captive portal detection.
1961 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, GoBackToTimeout) {
1962 // Disable captive portal detection so the first navigation doesn't open a
1964 EnableCaptivePortalDetection(browser()->profile(), false);
1966 SlowLoadNoCaptivePortal(browser(), captive_portal::RESULT_INTERNET_CONNECTED);
1968 // Navigate to a working page.
1969 ui_test_utils::NavigateToURL(
1970 browser(), URLRequestMockHTTPJob::GetMockUrl(
1971 base::FilePath(FILE_PATH_LITERAL("title2.html"))));
1972 ASSERT_EQ(CaptivePortalTabReloader::STATE_NONE,
1973 GetStateOfTabReloaderAt(browser(), 0));
1975 EnableCaptivePortalDetection(browser()->profile(), true);
1977 TabStripModel* tab_strip_model = browser()->tab_strip_model();
1978 CaptivePortalTabReloader* tab_reloader =
1979 GetTabReloader(tab_strip_model->GetActiveWebContents());
1980 ASSERT_TRUE(tab_reloader);
1981 SetSlowSSLLoadTime(tab_reloader, base::TimeDelta());
1983 // Go to the error page.
1984 MultiNavigationObserver navigation_observer;
1985 CaptivePortalObserver portal_observer(browser()->profile());
1986 chrome::GoBack(browser(), CURRENT_TAB);
1988 // Wait for the check triggered by the broken tab and for the login tab to
1990 portal_observer.WaitForResults(1);
1991 navigation_observer.WaitForNavigations(1);
1992 // Make sure the request has been issued.
1993 URLRequestTimeoutOnDemandJob::WaitForJobs(1);
1995 EXPECT_EQ(1, portal_observer.num_results_received());
1996 ASSERT_FALSE(CheckPending(browser()));
1997 ASSERT_EQ(captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL,
1998 portal_observer.captive_portal_result());
2000 ASSERT_EQ(CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL,
2001 GetStateOfTabReloaderAt(browser(), 0));
2002 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE,
2003 GetStateOfTabReloaderAt(browser(), 1));
2004 ASSERT_TRUE(IsLoginTab(browser()->tab_strip_model()->GetWebContentsAt(1)));
2006 ASSERT_EQ(2, tab_strip_model->count());
2007 EXPECT_EQ(1, tab_strip_model->active_index());
2008 EXPECT_EQ(1, navigation_observer.NumNavigationsForTab(
2009 tab_strip_model->GetWebContentsAt(1)));
2010 EXPECT_EQ(1, NumLoadingTabs());
2012 SetSlowSSLLoadTime(tab_reloader, base::TimeDelta::FromDays(1));
2013 Login(browser(), 1, 0);
2014 FailLoadsAfterLogin(browser(), 1);
2017 // Checks that reloading a timeout triggers captive portal detection.
2018 // Much like the last test, though the captive portal is disabled before
2019 // the inital navigation, rather than captive portal detection.
2020 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, ReloadTimeout) {
2021 URLRequestMockCaptivePortalJobFactory::SetBehindCaptivePortal(false);
2023 // Do the first navigation while not behind a captive portal.
2024 TabStripModel* tab_strip_model = browser()->tab_strip_model();
2025 CaptivePortalObserver portal_observer(browser()->profile());
2026 ui_test_utils::NavigateToURL(browser(), GURL(kMockHttpsUrl));
2027 ASSERT_EQ(0, portal_observer.num_results_received());
2028 ASSERT_EQ(1, tab_strip_model->count());
2030 // A captive portal spontaneously appears.
2031 URLRequestMockCaptivePortalJobFactory::SetBehindCaptivePortal(true);
2033 CaptivePortalTabReloader* tab_reloader =
2034 GetTabReloader(tab_strip_model->GetActiveWebContents());
2035 ASSERT_TRUE(tab_reloader);
2036 SetSlowSSLLoadTime(tab_reloader, base::TimeDelta());
2038 MultiNavigationObserver navigation_observer;
2039 tab_strip_model->GetActiveWebContents()->GetController().Reload(true);
2041 // Wait for the check triggered by the broken tab and for the login tab to
2043 portal_observer.WaitForResults(1);
2044 navigation_observer.WaitForNavigations(1);
2045 // Make sure the request has been issued.
2046 URLRequestTimeoutOnDemandJob::WaitForJobs(1);
2048 ASSERT_EQ(1, portal_observer.num_results_received());
2049 ASSERT_FALSE(CheckPending(browser()));
2050 ASSERT_EQ(captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL,
2051 portal_observer.captive_portal_result());
2053 ASSERT_EQ(CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL,
2054 GetStateOfTabReloaderAt(browser(), 0));
2055 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE,
2056 GetStateOfTabReloaderAt(browser(), 1));
2057 ASSERT_TRUE(IsLoginTab(tab_strip_model->GetWebContentsAt(1)));
2059 ASSERT_EQ(2, tab_strip_model->count());
2060 EXPECT_EQ(1, tab_strip_model->active_index());
2061 EXPECT_EQ(1, navigation_observer.NumNavigationsForTab(
2062 tab_strip_model->GetWebContentsAt(1)));
2063 EXPECT_EQ(1, NumLoadingTabs());
2065 SetSlowSSLLoadTime(tab_reloader, base::TimeDelta::FromDays(1));
2066 Login(browser(), 1, 0);
2067 FailLoadsAfterLogin(browser(), 1);
2070 // Checks the case where there are two windows, and there's an SSL timeout in
2071 // the background one.
2072 // Disabled: http://crbug.com/134357
2073 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, DISABLED_TwoWindows) {
2075 new Browser(Browser::CreateParams(browser()->profile(),
2076 browser()->host_desktop_type()));
2077 // Navigate the new browser window so it'll be shown and we can pick the
2079 ui_test_utils::NavigateToURL(browser2, GURL(url::kAboutBlankURL));
2081 // Generally, |browser2| will be the active window. However, if the
2082 // original browser window lost focus before creating the new one, such as
2083 // when running multiple tests at once, the original browser window may
2084 // remain the profile's active window.
2085 Browser* active_browser =
2086 chrome::FindTabbedBrowser(browser()->profile(), true,
2087 browser()->host_desktop_type());
2088 Browser* inactive_browser;
2089 if (active_browser == browser2) {
2090 // When only one test is running at a time, the new browser will probably be
2091 // on top, but when multiple tests are running at once, this is not
2093 inactive_browser = browser();
2095 ASSERT_EQ(active_browser, browser());
2096 inactive_browser = browser2;
2099 CaptivePortalObserver portal_observer(browser()->profile());
2100 MultiNavigationObserver navigation_observer;
2102 // Navigate the tab in the inactive browser to an SSL timeout. Have to use
2103 // chrome::NavigateParams and NEW_BACKGROUND_TAB to avoid activating the
2105 chrome::NavigateParams params(inactive_browser,
2106 GURL(kMockHttpsQuickTimeoutUrl),
2107 ui::PAGE_TRANSITION_TYPED);
2108 params.disposition = NEW_BACKGROUND_TAB;
2109 params.window_action = chrome::NavigateParams::NO_ACTION;
2110 ui_test_utils::NavigateToURL(¶ms);
2111 navigation_observer.WaitForNavigations(2);
2113 // Make sure the active window hasn't changed, and its new tab is
2115 ASSERT_EQ(active_browser,
2116 chrome::FindTabbedBrowser(browser()->profile(), true,
2117 browser()->host_desktop_type()));
2118 ASSERT_EQ(1, active_browser->tab_strip_model()->active_index());
2120 // Check that the only two navigated tabs were the new error tab in the
2121 // backround windows, and the login tab in the active window.
2122 EXPECT_EQ(1, navigation_observer.NumNavigationsForTab(
2123 inactive_browser->tab_strip_model()->GetWebContentsAt(1)));
2124 EXPECT_EQ(1, navigation_observer.NumNavigationsForTab(
2125 active_browser->tab_strip_model()->GetWebContentsAt(1)));
2126 EXPECT_EQ(0, NumLoadingTabs());
2128 // Check captive portal test results.
2129 portal_observer.WaitForResults(1);
2130 ASSERT_EQ(captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL,
2131 portal_observer.captive_portal_result());
2132 EXPECT_EQ(1, portal_observer.num_results_received());
2134 // Check the inactive browser.
2135 EXPECT_EQ(2, inactive_browser->tab_strip_model()->count());
2136 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE,
2137 GetStateOfTabReloaderAt(inactive_browser, 0));
2138 EXPECT_EQ(CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL,
2139 GetStateOfTabReloaderAt(inactive_browser, 1));
2141 // Check the active browser.
2142 ASSERT_EQ(2, active_browser->tab_strip_model()->count());
2143 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE,
2144 GetStateOfTabReloaderAt(active_browser, 0));
2145 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE,
2146 GetStateOfTabReloaderAt(active_browser, 1));
2148 IsLoginTab(active_browser->tab_strip_model()->GetWebContentsAt(1)));
2150 // Simulate logging in.
2151 Login(active_browser, 0, 1);
2154 // An HTTP page redirects to an HTTPS page loads slowly before timing out. A
2155 // captive portal is found, and then the user logs in before the original page
2157 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, HttpToHttpsRedirectLogin) {
2158 ASSERT_TRUE(test_server()->Start());
2159 SlowLoadBehindCaptivePortal(
2162 test_server()->GetURL(CreateServerRedirect(kMockHttpsUrl)),
2165 Login(browser(), 1, 0);
2166 FailLoadsAfterLogin(browser(), 1);
2169 // An HTTPS page redirects to an HTTP page.
2170 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, HttpsToHttpRedirect) {
2171 // Use an HTTPS server for the top level page.
2172 net::SpawnedTestServer https_server(
2173 net::SpawnedTestServer::TYPE_HTTPS, net::SpawnedTestServer::kLocalhost,
2174 base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
2175 ASSERT_TRUE(https_server.Start());
2177 GURL http_timeout_url =
2178 URLRequestFailedJob::GetMockHttpUrl(net::ERR_CONNECTION_TIMED_OUT);
2180 // 2 navigations due to the Link Doctor.
2181 NavigateToPageExpectNoTest(
2183 https_server.GetURL(CreateServerRedirect(http_timeout_url.spec())),
2187 // Tests the 511 response code, along with an HTML redirect to a login page.
2188 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, Status511) {
2189 SetUpCaptivePortalService(browser()->profile(),
2190 GURL(kMockCaptivePortal511Url));
2191 SlowLoadBehindCaptivePortal(browser(), true, GURL(kMockHttpsUrl), 2, 2);
2192 Login(browser(), 1, 0);
2193 FailLoadsAfterLogin(browser(), 1);
2196 // HSTS redirects an HTTP request to HTTPS, and the request then times out.
2197 // A captive portal is then detected, and a login tab opened, before logging
2199 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, HstsLogin) {
2200 GURL::Replacements replacements;
2201 std::string scheme = "http";
2202 replacements.SetSchemeStr(scheme);
2203 GURL http_timeout_url = GURL(kMockHttpsUrl).ReplaceComponents(replacements);
2205 URLRequestFailedJob::GetMockHttpUrl(net::ERR_CONNECTION_TIMED_OUT);
2206 content::BrowserThread::PostTask(
2207 content::BrowserThread::IO, FROM_HERE,
2208 base::Bind(&AddHstsHost,
2209 make_scoped_refptr(browser()->profile()->GetRequestContext()),
2210 http_timeout_url.host()));
2212 SlowLoadBehindCaptivePortal(browser(), true, http_timeout_url, 1, 1);
2213 Login(browser(), 1, 0);
2214 FailLoadsAfterLogin(browser(), 1);