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.
10 #include "base/basictypes.h"
11 #include "base/bind.h"
12 #include "base/command_line.h"
13 #include "base/compiler_specific.h"
14 #include "base/files/file_path.h"
15 #include "base/memory/scoped_ptr.h"
16 #include "base/message_loop/message_loop.h"
17 #include "base/path_service.h"
18 #include "base/prefs/pref_service.h"
19 #include "base/strings/utf_string_conversions.h"
20 #include "base/values.h"
21 #include "chrome/browser/captive_portal/captive_portal_service.h"
22 #include "chrome/browser/captive_portal/captive_portal_service_factory.h"
23 #include "chrome/browser/captive_portal/captive_portal_tab_helper.h"
24 #include "chrome/browser/captive_portal/captive_portal_tab_reloader.h"
25 #include "chrome/browser/chrome_notification_types.h"
26 #include "chrome/browser/interstitials/security_interstitial_page.h"
27 #include "chrome/browser/net/url_request_mock_util.h"
28 #include "chrome/browser/profiles/profile.h"
29 #include "chrome/browser/ssl/captive_portal_blocking_page.h"
30 #include "chrome/browser/ssl/ssl_blocking_page.h"
31 #include "chrome/browser/ssl/ssl_error_handler.h"
32 #include "chrome/browser/ui/browser.h"
33 #include "chrome/browser/ui/browser_commands.h"
34 #include "chrome/browser/ui/browser_finder.h"
35 #include "chrome/browser/ui/browser_navigator.h"
36 #include "chrome/browser/ui/tab_contents/tab_contents_iterator.h"
37 #include "chrome/browser/ui/tabs/tab_strip_model.h"
38 #include "chrome/common/chrome_paths.h"
39 #include "chrome/common/chrome_switches.h"
40 #include "chrome/common/pref_names.h"
41 #include "chrome/test/base/in_process_browser_test.h"
42 #include "chrome/test/base/ui_test_utils.h"
43 #include "content/public/browser/browser_thread.h"
44 #include "content/public/browser/interstitial_page.h"
45 #include "content/public/browser/interstitial_page_delegate.h"
46 #include "content/public/browser/navigation_controller.h"
47 #include "content/public/browser/navigation_entry.h"
48 #include "content/public/browser/notification_observer.h"
49 #include "content/public/browser/notification_registrar.h"
50 #include "content/public/browser/notification_service.h"
51 #include "content/public/browser/notification_types.h"
52 #include "content/public/browser/render_frame_host.h"
53 #include "content/public/browser/web_contents.h"
54 #include "content/public/common/url_constants.h"
55 #include "content/public/test/browser_test_utils.h"
56 #include "net/base/net_errors.h"
57 #include "net/http/transport_security_state.h"
58 #include "net/test/url_request/url_request_failed_job.h"
59 #include "net/test/url_request/url_request_mock_http_job.h"
60 #include "net/url_request/url_request.h"
61 #include "net/url_request/url_request_context.h"
62 #include "net/url_request/url_request_context_getter.h"
63 #include "net/url_request/url_request_filter.h"
64 #include "net/url_request/url_request_interceptor.h"
65 #include "net/url_request/url_request_job.h"
66 #include "net/url_request/url_request_status.h"
67 #include "testing/gtest/include/gtest/gtest.h"
69 using captive_portal::CaptivePortalResult
;
70 using content::BrowserThread
;
71 using content::WebContents
;
72 using net::URLRequestFailedJob
;
73 using net::URLRequestMockHTTPJob
;
77 // Path of the fake login page, when using the TestServer.
78 const char* const kTestServerLoginPath
= "files/captive_portal/login.html";
80 // Path of a page with an iframe that has a mock SSL timeout, when using the
82 const char* const kTestServerIframeTimeoutPath
=
83 "files/captive_portal/iframe_timeout.html";
85 // The following URLs each have two different behaviors, depending on whether
86 // URLRequestMockCaptivePortalJobFactory is currently simulating the presence
87 // of a captive portal or not. They use different domains so that HSTS can be
88 // applied to them independently.
90 // A mock URL for the CaptivePortalService's |test_url|. When behind a captive
91 // portal, this URL returns a mock login page. When connected to the Internet,
92 // it returns a 204 response. Uses the name of the login file so that reloading
93 // it will not request a different URL.
94 const char* const kMockCaptivePortalTestUrl
=
95 "http://mock.captive.portal.test/login.html";
97 // Another mock URL for the CaptivePortalService's |test_url|. When behind a
98 // captive portal, this URL returns a 511 status code and an HTML page that
99 // redirect to the above URL. When connected to the Internet, it returns a 204
101 const char* const kMockCaptivePortal511Url
=
102 "http://mock.captive.portal.511/page511.html";
104 // When behind a captive portal, this URL hangs without committing until a call
105 // to URLRequestTimeoutOnDemandJob::FailJobs. When that function is called,
106 // the request will time out.
108 // When connected to the Internet, this URL returns a non-error page.
109 const char* const kMockHttpsUrl
=
110 "https://mock.captive.portal.long.timeout/title2.html";
112 // Same as above, but different domain, so can be used to trigger cross-site
114 const char* const kMockHttpsUrl2
=
115 "https://mock.captive.portal.long.timeout2/title2.html";
117 // Same as kMockHttpsUrl, except the timeout happens instantly.
118 const char* const kMockHttpsQuickTimeoutUrl
=
119 "https://mock.captive.portal.quick.timeout/title2.html";
121 // Expected title of a tab once an HTTPS load completes, when not behind a
123 const char* const kInternetConnectedTitle
= "Title Of Awesomeness";
125 // A URL request job that hangs until FailJobs() is called. Started jobs
126 // are stored in a static class variable containing a linked list so that
127 // FailJobs() can locate them.
128 class URLRequestTimeoutOnDemandJob
: public net::URLRequestJob
,
129 public base::NonThreadSafe
{
131 // net::URLRequestJob:
132 void Start() override
;
134 // All the public static methods below can be called on any thread.
136 // Waits for exactly |num_jobs|.
137 static void WaitForJobs(int num_jobs
);
139 // Fails all active URLRequestTimeoutOnDemandJobs with connection timeouts.
140 // There are expected to be exactly |expected_num_jobs| waiting for
141 // failure. The only way to guarantee this is with an earlier call to
142 // WaitForJobs, so makes sure there has been a matching WaitForJobs call.
143 static void FailJobs(int expected_num_jobs
);
145 // Fails all active URLRequestTimeoutOnDemandJobs with SSL cert errors.
146 // |expected_num_jobs| behaves just as in FailJobs.
147 static void FailJobsWithCertError(int expected_num_jobs
);
149 // Abandon all active URLRequestTimeoutOnDemandJobs. |expected_num_jobs|
150 // behaves just as in FailJobs.
151 static void AbandonJobs(int expected_num_jobs
);
154 friend class URLRequestMockCaptivePortalJobFactory
;
156 // Operation to perform on jobs when removing them from |job_list_|.
157 enum EndJobOperation
{
160 FAIL_JOBS_WITH_CERT_ERROR
163 URLRequestTimeoutOnDemandJob(net::URLRequest
* request
,
164 net::NetworkDelegate
* network_delegate
);
165 ~URLRequestTimeoutOnDemandJob() override
;
167 // Attempts to removes |this| from |jobs_|. Returns true if it was removed
169 bool RemoveFromList();
171 static void WaitForJobsOnIOThread(int num_jobs
);
172 static void FailOrAbandonJobsOnIOThread(
173 int expected_num_jobs
,
174 EndJobOperation end_job_operation
);
176 // Checks if there are at least |num_jobs_to_wait_for_| jobs in
177 // |job_list_|. If so, exits the message loop on the UI thread, which
178 // should be spinning in a call to WaitForJobs. Does nothing when
179 // |num_jobs_to_wait_for_| is 0.
180 static void MaybeStopWaitingForJobsOnIOThread();
182 // All class variables are only accessed on the IO thread.
184 // Number of jobs currently being waited for, or 0 if not currently
186 static int num_jobs_to_wait_for_
;
188 // The last number of jobs that were waited for. When FailJobs or
189 // AbandonJobs is called, this should match |expected_num_jobs|.
190 static int last_num_jobs_to_wait_for_
;
192 // Number of jobs that have been started, but not yet waited for. If jobs
193 // are deleted unexpectedly, they're still included in this count, even though
194 // they've been removed from |job_list_|. Intended to reduce chance of stalls
196 static int num_jobs_started_
;
198 // Head of linked list of jobs that have been started and are now waiting to
200 static URLRequestTimeoutOnDemandJob
* job_list_
;
202 // The next job that had been started but not yet timed out.
203 URLRequestTimeoutOnDemandJob
* next_job_
;
205 DISALLOW_COPY_AND_ASSIGN(URLRequestTimeoutOnDemandJob
);
208 int URLRequestTimeoutOnDemandJob::num_jobs_to_wait_for_
= 0;
209 int URLRequestTimeoutOnDemandJob::last_num_jobs_to_wait_for_
= 0;
210 int URLRequestTimeoutOnDemandJob::num_jobs_started_
= 0;
211 URLRequestTimeoutOnDemandJob
* URLRequestTimeoutOnDemandJob::job_list_
= NULL
;
213 void URLRequestTimeoutOnDemandJob::Start() {
214 EXPECT_TRUE(CalledOnValidThread());
216 // Insert at start of the list.
217 next_job_
= job_list_
;
221 // Checks if there are at least |num_jobs_to_wait_for_| jobs in
222 // |job_list_|. If so, exits the message loop on the UI thread, which
223 // should be spinning in a call to WaitForJobs. Does nothing if
224 // |num_jobs_to_wait_for_| is 0.
225 MaybeStopWaitingForJobsOnIOThread();
229 void URLRequestTimeoutOnDemandJob::WaitForJobs(int num_jobs
) {
230 content::BrowserThread::PostTask(
231 content::BrowserThread::IO
, FROM_HERE
,
232 base::Bind(&URLRequestTimeoutOnDemandJob::WaitForJobsOnIOThread
,
234 content::RunMessageLoop();
238 void URLRequestTimeoutOnDemandJob::FailJobs(int expected_num_jobs
) {
239 content::BrowserThread::PostTask(
240 content::BrowserThread::IO
, FROM_HERE
,
241 base::Bind(&URLRequestTimeoutOnDemandJob::FailOrAbandonJobsOnIOThread
,
247 void URLRequestTimeoutOnDemandJob::FailJobsWithCertError(
248 int expected_num_jobs
) {
249 content::BrowserThread::PostTask(
250 content::BrowserThread::IO
, FROM_HERE
,
251 base::Bind(&URLRequestTimeoutOnDemandJob::FailOrAbandonJobsOnIOThread
,
253 FAIL_JOBS_WITH_CERT_ERROR
));
257 void URLRequestTimeoutOnDemandJob::AbandonJobs(int expected_num_jobs
) {
258 content::BrowserThread::PostTask(
259 content::BrowserThread::IO
, FROM_HERE
,
260 base::Bind(&URLRequestTimeoutOnDemandJob::FailOrAbandonJobsOnIOThread
,
265 URLRequestTimeoutOnDemandJob::URLRequestTimeoutOnDemandJob(
266 net::URLRequest
* request
, net::NetworkDelegate
* network_delegate
)
267 : net::URLRequestJob(request
, network_delegate
),
271 URLRequestTimeoutOnDemandJob::~URLRequestTimeoutOnDemandJob() {
272 // All hanging jobs should have failed or been abandoned before being
274 EXPECT_FALSE(RemoveFromList());
277 bool URLRequestTimeoutOnDemandJob::RemoveFromList() {
278 URLRequestTimeoutOnDemandJob
** job
= &job_list_
;
288 // If the job wasn't in this list, |next_job_| should be NULL.
289 EXPECT_FALSE(next_job_
);
294 void URLRequestTimeoutOnDemandJob::WaitForJobsOnIOThread(int num_jobs
) {
295 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO
));
296 ASSERT_EQ(0, num_jobs_to_wait_for_
);
297 ASSERT_LT(0, num_jobs
);
298 // Number of tabs being waited on should be strictly increasing.
299 ASSERT_LE(last_num_jobs_to_wait_for_
, num_jobs
);
301 num_jobs_to_wait_for_
= num_jobs
;
302 MaybeStopWaitingForJobsOnIOThread();
306 void URLRequestTimeoutOnDemandJob::MaybeStopWaitingForJobsOnIOThread() {
307 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO
));
308 if (num_jobs_to_wait_for_
== 0)
311 // There shouldn't be any extra jobs.
312 EXPECT_LE(num_jobs_started_
, num_jobs_to_wait_for_
);
314 // Should never be greater, but if it is, go ahead and exit the message loop
315 // to try and avoid hanging.
316 if (num_jobs_started_
>= num_jobs_to_wait_for_
) {
317 last_num_jobs_to_wait_for_
= num_jobs_to_wait_for_
;
318 num_jobs_to_wait_for_
= 0;
319 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
320 base::MessageLoop::QuitClosure());
325 void URLRequestTimeoutOnDemandJob::FailOrAbandonJobsOnIOThread(
326 int expected_num_jobs
,
327 EndJobOperation end_job_operation
) {
328 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO
));
329 ASSERT_LT(0, expected_num_jobs
);
330 EXPECT_EQ(last_num_jobs_to_wait_for_
, expected_num_jobs
);
331 last_num_jobs_to_wait_for_
= 0;
336 URLRequestTimeoutOnDemandJob
* job
= job_list_
;
337 // Since the error notification may result in the job's destruction, remove
338 // it from the job list before the error.
339 EXPECT_TRUE(job
->RemoveFromList());
340 if (end_job_operation
== FAIL_JOBS
) {
341 job
->NotifyStartError(net::URLRequestStatus(
342 net::URLRequestStatus::FAILED
,
343 net::ERR_CONNECTION_TIMED_OUT
));
344 } else if (end_job_operation
== FAIL_JOBS_WITH_CERT_ERROR
) {
345 DCHECK(job
->request()->url().SchemeIsCryptographic());
347 info
.cert_status
= net::CERT_STATUS_COMMON_NAME_INVALID
;
348 info
.cert
= new net::X509Certificate(
349 "bad.host", "CA", base::Time::Max(), base::Time::Max());
350 job
->NotifySSLCertificateError(info
, true);
354 EXPECT_EQ(expected_num_jobs
, num_jobs_started_
);
355 EXPECT_EQ(expected_num_jobs
, num_jobs
);
357 num_jobs_started_
-= expected_num_jobs
;
360 // URLRequestCaptivePortalJobFactory emulates captive portal behavior.
361 // Initially, it emulates being behind a captive portal. When
362 // SetBehindCaptivePortal(false) is called, it emulates behavior when not behind
363 // a captive portal. The class itself is never instantiated.
365 // It handles requests for kMockCaptivePortalTestUrl, kMockHttpsUrl, and
366 // kMockHttpsQuickTimeoutUrl.
367 class URLRequestMockCaptivePortalJobFactory
{
369 URLRequestMockCaptivePortalJobFactory() : behind_captive_portal_(true) {}
370 virtual ~URLRequestMockCaptivePortalJobFactory() {}
372 // Adds the testing URLs to the net::URLRequestFilter. Should only be called
374 void AddUrlHandlers();
376 // Sets whether or not there is a captive portal. Outstanding requests are
378 void SetBehindCaptivePortal(bool behind_captive_portal
);
381 class Interceptor
: public net::URLRequestInterceptor
{
383 explicit Interceptor(bool behind_captive_portal
)
384 : behind_captive_portal_(behind_captive_portal
) {}
385 ~Interceptor() override
{}
387 // Returns a URLRequestJob that reflects the current captive portal state
388 // for the URLs: kMockCaptivePortalTestUrl, kMockHttpsUrl, and
389 // kMockHttpsQuickTimeoutUrl. See documentation of individual URLs for
391 net::URLRequestJob
* MaybeInterceptRequest(
392 net::URLRequest
* request
,
393 net::NetworkDelegate
* network_delegate
) const override
;
395 void SetBehindCaptivePortal(bool behind_captive_portal
) {
396 behind_captive_portal_
= behind_captive_portal
;
400 bool behind_captive_portal_
;
402 DISALLOW_COPY_AND_ASSIGN(Interceptor
);
405 // These do all the work of the corresponding public functions, with the only
406 // difference being that they must be called on the IO thread.
407 void AddUrlHandlersOnIOThread();
408 void SetBehindCaptivePortalOnIOThread(bool behind_captive_portal
);
410 // Create a new Interceptor and add it to |interceptors_|, though it returns
412 scoped_ptr
<net::URLRequestInterceptor
> CreateInterceptor();
414 // These variables are only accessed on IO thread, though
415 // URLRequestMockCaptivePortalJobFactory is created and
416 // destroyed on the UI thread.
417 // The Interceptors are owned by URLRequestFilter and live on the IO thread;
418 // these are just references.
419 std::vector
<Interceptor
*> interceptors_
;
420 bool behind_captive_portal_
;
422 DISALLOW_COPY_AND_ASSIGN(URLRequestMockCaptivePortalJobFactory
);
425 void URLRequestMockCaptivePortalJobFactory::AddUrlHandlers() {
426 content::BrowserThread::PostTask(
427 content::BrowserThread::IO
, FROM_HERE
,
429 &URLRequestMockCaptivePortalJobFactory::AddUrlHandlersOnIOThread
,
430 base::Unretained(this)));
433 void URLRequestMockCaptivePortalJobFactory::SetBehindCaptivePortal(
434 bool behind_captive_portal
) {
435 content::BrowserThread::PostTask(
436 content::BrowserThread::IO
, FROM_HERE
,
437 base::Bind(&URLRequestMockCaptivePortalJobFactory::
438 SetBehindCaptivePortalOnIOThread
,
439 base::Unretained(this), behind_captive_portal
));
442 scoped_ptr
<net::URLRequestInterceptor
>
443 URLRequestMockCaptivePortalJobFactory::CreateInterceptor() {
444 EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO
));
445 scoped_ptr
<Interceptor
> interceptor(new Interceptor(behind_captive_portal_
));
446 interceptors_
.push_back(interceptor
.get());
447 return interceptor
.Pass();
450 void URLRequestMockCaptivePortalJobFactory::AddUrlHandlersOnIOThread() {
451 EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO
));
453 // Handle only exact matches, so any related requests, such as those for
454 // favicons, are not handled by the factory.
455 net::URLRequestFilter
* filter
= net::URLRequestFilter::GetInstance();
456 filter
->AddUrlInterceptor(GURL(kMockCaptivePortalTestUrl
),
457 CreateInterceptor());
458 filter
->AddUrlInterceptor(GURL(kMockCaptivePortal511Url
),
459 CreateInterceptor());
460 filter
->AddUrlInterceptor(GURL(kMockHttpsUrl
), CreateInterceptor());
461 filter
->AddUrlInterceptor(GURL(kMockHttpsUrl2
), CreateInterceptor());
462 filter
->AddUrlInterceptor(GURL(kMockHttpsQuickTimeoutUrl
),
463 CreateInterceptor());
466 void URLRequestMockCaptivePortalJobFactory::SetBehindCaptivePortalOnIOThread(
467 bool behind_captive_portal
) {
468 EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO
));
469 behind_captive_portal_
= behind_captive_portal
;
470 for (auto* interceptor
: interceptors_
)
471 interceptor
->SetBehindCaptivePortal(behind_captive_portal
);
475 URLRequestMockCaptivePortalJobFactory::Interceptor::MaybeInterceptRequest(
476 net::URLRequest
* request
,
477 net::NetworkDelegate
* network_delegate
) const {
478 EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO
));
480 // The PathService is threadsafe.
481 base::FilePath root_http
;
482 PathService::Get(chrome::DIR_TEST_DATA
, &root_http
);
484 if (request
->url() == GURL(kMockHttpsUrl
) ||
485 request
->url() == GURL(kMockHttpsUrl2
)) {
486 if (behind_captive_portal_
)
487 return new URLRequestTimeoutOnDemandJob(request
, network_delegate
);
488 // Once logged in to the portal, HTTPS requests return the page that was
489 // actually requested.
490 return new URLRequestMockHTTPJob(
493 root_http
.Append(FILE_PATH_LITERAL("title2.html")),
494 BrowserThread::GetBlockingPool()->GetTaskRunnerWithShutdownBehavior(
495 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN
));
496 } else if (request
->url() == GURL(kMockHttpsQuickTimeoutUrl
)) {
497 if (behind_captive_portal_
)
498 return new URLRequestFailedJob(
499 request
, network_delegate
, net::ERR_CONNECTION_TIMED_OUT
);
500 // Once logged in to the portal, HTTPS requests return the page that was
501 // actually requested.
502 return new URLRequestMockHTTPJob(
505 root_http
.Append(FILE_PATH_LITERAL("title2.html")),
506 BrowserThread::GetBlockingPool()->GetTaskRunnerWithShutdownBehavior(
507 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN
));
509 // The URL should be the captive portal test URL.
510 EXPECT_TRUE(GURL(kMockCaptivePortalTestUrl
) == request
->url() ||
511 GURL(kMockCaptivePortal511Url
) == request
->url());
513 if (behind_captive_portal_
) {
514 // Prior to logging in to the portal, the HTTP test URLs are intercepted
515 // by the captive portal.
516 if (GURL(kMockCaptivePortal511Url
) == request
->url()) {
517 return new URLRequestMockHTTPJob(
520 root_http
.Append(FILE_PATH_LITERAL("captive_portal/page511.html")),
521 BrowserThread::GetBlockingPool()->GetTaskRunnerWithShutdownBehavior(
522 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN
));
524 return new URLRequestMockHTTPJob(
527 root_http
.Append(FILE_PATH_LITERAL("captive_portal/login.html")),
528 BrowserThread::GetBlockingPool()->GetTaskRunnerWithShutdownBehavior(
529 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN
));
532 // After logging in to the portal, the test URLs return a 204 response.
533 return new URLRequestMockHTTPJob(
536 root_http
.Append(FILE_PATH_LITERAL("captive_portal/page204.html")),
537 BrowserThread::GetBlockingPool()->GetTaskRunnerWithShutdownBehavior(
538 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN
));
542 // Creates a server-side redirect for use with the TestServer.
543 std::string
CreateServerRedirect(const std::string
& dest_url
) {
544 const char* const kServerRedirectBase
= "server-redirect?";
545 return kServerRedirectBase
+ dest_url
;
548 // Returns the total number of loading tabs across all Browsers, for all
550 int NumLoadingTabs() {
551 int num_loading_tabs
= 0;
552 for (TabContentsIterator it
; !it
.done(); it
.Next()) {
556 return num_loading_tabs
;
559 bool IsLoginTab(WebContents
* web_contents
) {
560 return CaptivePortalTabHelper::FromWebContents(web_contents
)->IsLoginTab();
563 // Tracks how many times each tab has been navigated since the Observer was
564 // created. The standard TestNavigationObserver can only watch specific
565 // pre-existing tabs or loads in serial for all tabs.
566 class MultiNavigationObserver
: public content::NotificationObserver
{
568 MultiNavigationObserver();
569 ~MultiNavigationObserver() override
;
571 // Waits for exactly |num_navigations_to_wait_for| LOAD_STOP
572 // notifications to have occurred since the construction of |this|. More
573 // navigations than expected occuring will trigger a expect failure.
574 void WaitForNavigations(int num_navigations_to_wait_for
);
576 // Returns the number of LOAD_STOP events that have occurred for
577 // |web_contents| since this was constructed.
578 int NumNavigationsForTab(WebContents
* web_contents
) const;
580 // The number of LOAD_STOP events since |this| was created.
581 int num_navigations() const { return num_navigations_
; }
584 typedef std::map
<const WebContents
*, int> TabNavigationMap
;
586 // content::NotificationObserver:
587 void Observe(int type
,
588 const content::NotificationSource
& source
,
589 const content::NotificationDetails
& details
) override
;
591 int num_navigations_
;
593 // Map of how many times each tab has navigated since |this| was created.
594 TabNavigationMap tab_navigation_map_
;
596 // Total number of navigations to wait for. Value only matters when
597 // |waiting_for_navigation_| is true.
598 int num_navigations_to_wait_for_
;
600 // True if WaitForNavigations has been called, until
601 // |num_navigations_to_wait_for_| have been observed.
602 bool waiting_for_navigation_
;
604 content::NotificationRegistrar registrar_
;
606 DISALLOW_COPY_AND_ASSIGN(MultiNavigationObserver
);
609 MultiNavigationObserver::MultiNavigationObserver()
610 : num_navigations_(0),
611 num_navigations_to_wait_for_(0),
612 waiting_for_navigation_(false) {
613 registrar_
.Add(this, content::NOTIFICATION_LOAD_STOP
,
614 content::NotificationService::AllSources());
617 MultiNavigationObserver::~MultiNavigationObserver() {
620 void MultiNavigationObserver::WaitForNavigations(
621 int num_navigations_to_wait_for
) {
622 // Shouldn't already be waiting for navigations.
623 EXPECT_FALSE(waiting_for_navigation_
);
624 EXPECT_LT(0, num_navigations_to_wait_for
);
625 if (num_navigations_
< num_navigations_to_wait_for
) {
626 num_navigations_to_wait_for_
= num_navigations_to_wait_for
;
627 waiting_for_navigation_
= true;
628 content::RunMessageLoop();
629 EXPECT_FALSE(waiting_for_navigation_
);
631 EXPECT_EQ(num_navigations_
, num_navigations_to_wait_for
);
634 int MultiNavigationObserver::NumNavigationsForTab(
635 WebContents
* web_contents
) const {
636 TabNavigationMap::const_iterator tab_navigations
=
637 tab_navigation_map_
.find(web_contents
);
638 if (tab_navigations
== tab_navigation_map_
.end())
640 return tab_navigations
->second
;
643 void MultiNavigationObserver::Observe(
645 const content::NotificationSource
& source
,
646 const content::NotificationDetails
& details
) {
647 ASSERT_EQ(type
, content::NOTIFICATION_LOAD_STOP
);
648 content::NavigationController
* controller
=
649 content::Source
<content::NavigationController
>(source
).ptr();
651 ++tab_navigation_map_
[controller
->GetWebContents()];
652 if (waiting_for_navigation_
&&
653 num_navigations_to_wait_for_
== num_navigations_
) {
654 waiting_for_navigation_
= false;
655 base::MessageLoopForUI::current()->Quit();
659 // This observer creates a list of loading tabs, and then waits for them all
660 // to stop loading and have the kInternetConnectedTitle.
662 // This is for the specific purpose of observing tabs time out after logging in
663 // to a captive portal, which will then cause them to reload.
664 // MultiNavigationObserver is insufficient for this because there may or may not
665 // be a LOAD_STOP event between the timeout and the reload.
666 // See bug http://crbug.com/133227
667 class FailLoadsAfterLoginObserver
: public content::NotificationObserver
{
669 FailLoadsAfterLoginObserver();
670 ~FailLoadsAfterLoginObserver() override
;
672 void WaitForNavigations();
675 typedef std::set
<const WebContents
*> TabSet
;
677 // content::NotificationObserver:
678 void Observe(int type
,
679 const content::NotificationSource
& source
,
680 const content::NotificationDetails
& details
) override
;
682 // The set of tabs that need to be navigated. This is the set of loading
683 // tabs when the observer is created.
684 TabSet tabs_needing_navigation_
;
686 // Number of tabs that have stopped navigating with the expected title. These
687 // are expected not to be navigated again.
688 TabSet tabs_navigated_to_final_destination_
;
690 // True if WaitForNavigations has been called, until
691 // |tabs_navigated_to_final_destination_| equals |tabs_needing_navigation_|.
692 bool waiting_for_navigation_
;
694 content::NotificationRegistrar registrar_
;
696 DISALLOW_COPY_AND_ASSIGN(FailLoadsAfterLoginObserver
);
699 FailLoadsAfterLoginObserver::FailLoadsAfterLoginObserver()
700 : waiting_for_navigation_(false) {
701 registrar_
.Add(this, content::NOTIFICATION_LOAD_STOP
,
702 content::NotificationService::AllSources());
703 for (TabContentsIterator it
; !it
.done(); it
.Next()) {
705 tabs_needing_navigation_
.insert(*it
);
709 FailLoadsAfterLoginObserver::~FailLoadsAfterLoginObserver() {
712 void FailLoadsAfterLoginObserver::WaitForNavigations() {
713 // Shouldn't already be waiting for navigations.
714 EXPECT_FALSE(waiting_for_navigation_
);
715 if (tabs_needing_navigation_
.size() !=
716 tabs_navigated_to_final_destination_
.size()) {
717 waiting_for_navigation_
= true;
718 content::RunMessageLoop();
719 EXPECT_FALSE(waiting_for_navigation_
);
721 EXPECT_EQ(tabs_needing_navigation_
.size(),
722 tabs_navigated_to_final_destination_
.size());
725 void FailLoadsAfterLoginObserver::Observe(
727 const content::NotificationSource
& source
,
728 const content::NotificationDetails
& details
) {
729 ASSERT_EQ(type
, content::NOTIFICATION_LOAD_STOP
);
730 content::NavigationController
* controller
=
731 content::Source
<content::NavigationController
>(source
).ptr();
732 WebContents
* contents
= controller
->GetWebContents();
734 ASSERT_EQ(1u, tabs_needing_navigation_
.count(contents
));
735 ASSERT_EQ(0u, tabs_navigated_to_final_destination_
.count(contents
));
737 if (contents
->GetTitle() != base::ASCIIToUTF16(kInternetConnectedTitle
))
739 tabs_navigated_to_final_destination_
.insert(contents
);
741 if (waiting_for_navigation_
&&
742 tabs_needing_navigation_
.size() ==
743 tabs_navigated_to_final_destination_
.size()) {
744 waiting_for_navigation_
= false;
745 base::MessageLoopForUI::current()->Quit();
749 // An observer for watching the CaptivePortalService. It tracks the last
750 // received result and the total number of received results.
751 class CaptivePortalObserver
: public content::NotificationObserver
{
753 explicit CaptivePortalObserver(Profile
* profile
);
755 // Runs the message loop until exactly |update_count| captive portal
756 // results have been received, since the creation of |this|. Expects no
757 // additional captive portal results.
758 void WaitForResults(int num_results_to_wait_for
);
760 int num_results_received() const { return num_results_received_
; }
762 CaptivePortalResult
captive_portal_result() const {
763 return captive_portal_result_
;
767 // Records results and exits the message loop, if needed.
768 void Observe(int type
,
769 const content::NotificationSource
& source
,
770 const content::NotificationDetails
& details
) override
;
772 // Number of times OnPortalResult has been called since construction.
773 int num_results_received_
;
775 // If WaitForResults was called, the total number of updates for which to
776 // wait. Value doesn't matter when |waiting_for_result_| is false.
777 int num_results_to_wait_for_
;
779 bool waiting_for_result_
;
783 CaptivePortalService
* captive_portal_service_
;
785 // Last result received.
786 CaptivePortalResult captive_portal_result_
;
788 content::NotificationRegistrar registrar_
;
790 DISALLOW_COPY_AND_ASSIGN(CaptivePortalObserver
);
793 CaptivePortalObserver::CaptivePortalObserver(Profile
* profile
)
794 : num_results_received_(0),
795 num_results_to_wait_for_(0),
796 waiting_for_result_(false),
798 captive_portal_service_(
799 CaptivePortalServiceFactory::GetForProfile(profile
)),
800 captive_portal_result_(
801 captive_portal_service_
->last_detection_result()) {
803 chrome::NOTIFICATION_CAPTIVE_PORTAL_CHECK_RESULT
,
804 content::Source
<Profile
>(profile_
));
807 void CaptivePortalObserver::WaitForResults(int num_results_to_wait_for
) {
808 EXPECT_LT(0, num_results_to_wait_for
);
809 EXPECT_FALSE(waiting_for_result_
);
810 if (num_results_received_
< num_results_to_wait_for
) {
811 num_results_to_wait_for_
= num_results_to_wait_for
;
812 waiting_for_result_
= true;
813 content::RunMessageLoop();
814 EXPECT_FALSE(waiting_for_result_
);
816 EXPECT_EQ(num_results_to_wait_for
, num_results_received_
);
819 void CaptivePortalObserver::Observe(
821 const content::NotificationSource
& source
,
822 const content::NotificationDetails
& details
) {
823 ASSERT_EQ(type
, chrome::NOTIFICATION_CAPTIVE_PORTAL_CHECK_RESULT
);
824 ASSERT_EQ(profile_
, content::Source
<Profile
>(source
).ptr());
826 CaptivePortalService::Results
* results
=
827 content::Details
<CaptivePortalService::Results
>(details
).ptr();
829 EXPECT_EQ(captive_portal_result_
, results
->previous_result
);
830 EXPECT_EQ(captive_portal_service_
->last_detection_result(),
833 captive_portal_result_
= results
->result
;
834 ++num_results_received_
;
836 if (waiting_for_result_
&&
837 num_results_to_wait_for_
== num_results_received_
) {
838 waiting_for_result_
= false;
839 base::MessageLoop::current()->Quit();
843 // This observer waits for the SSLErrorHandler to start an interstitial timer
844 // for the given web contents.
845 class SSLInterstitialTimerObserver
{
847 explicit SSLInterstitialTimerObserver(content::WebContents
* web_contents
);
848 ~SSLInterstitialTimerObserver();
850 // Waits until the interstitial delay timer in SSLErrorHandler is started.
851 void WaitForTimerStarted();
854 void OnTimerStarted(content::WebContents
* web_contents
);
856 const content::WebContents
* web_contents_
;
857 SSLErrorHandler::TimerStartedCallback callback_
;
859 scoped_refptr
<content::MessageLoopRunner
> message_loop_runner_
;
861 DISALLOW_COPY_AND_ASSIGN(SSLInterstitialTimerObserver
);
864 SSLInterstitialTimerObserver::SSLInterstitialTimerObserver(
865 content::WebContents
* web_contents
)
866 : web_contents_(web_contents
),
867 message_loop_runner_(new content::MessageLoopRunner
) {
868 callback_
= base::Bind(&SSLInterstitialTimerObserver::OnTimerStarted
,
869 base::Unretained(this));
870 SSLErrorHandler::SetInterstitialTimerStartedCallbackForTest(&callback_
);
873 SSLInterstitialTimerObserver::~SSLInterstitialTimerObserver() {
874 SSLErrorHandler::SetInterstitialTimerStartedCallbackForTest(nullptr);
877 void SSLInterstitialTimerObserver::WaitForTimerStarted() {
878 message_loop_runner_
->Run();
881 void SSLInterstitialTimerObserver::OnTimerStarted(
882 content::WebContents
* web_contents
) {
883 if (web_contents_
== web_contents
&& message_loop_runner_
.get())
884 message_loop_runner_
->Quit();
887 // Adds an HSTS rule for |host|, so that all HTTP requests sent to it will
888 // be switched to HTTPS requests.
889 void AddHstsHost(net::URLRequestContextGetter
* context_getter
,
890 const std::string
& host
) {
891 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO
));
892 net::TransportSecurityState
* transport_security_state
=
893 context_getter
->GetURLRequestContext()->transport_security_state();
894 if (!transport_security_state
) {
899 base::Time expiry
= base::Time::Now() + base::TimeDelta::FromDays(1000);
900 bool include_subdomains
= false;
901 transport_security_state
->AddHSTS(host
, expiry
, include_subdomains
);
906 class CaptivePortalBrowserTest
: public InProcessBrowserTest
{
908 CaptivePortalBrowserTest();
910 // InProcessBrowserTest:
911 void SetUpOnMainThread() override
;
912 void TearDownOnMainThread() override
;
913 void SetUpCommandLine(base::CommandLine
* command_line
) override
;
915 // Sets the captive portal checking preference. Does not affect the command
916 // line flag, which is set in SetUpCommandLine.
917 void EnableCaptivePortalDetection(Profile
* profile
, bool enabled
);
919 // Enables or disables actual captive portal probes. Should only be called
920 // after captive portal service setup is done. When disabled, probe requests
921 // are silently ignored, never receiving a response.
922 void RespondToProbeRequests(bool enabled
);
924 // Sets up the captive portal service for the given profile so that
925 // all checks go to |test_url|. Also disables all timers.
926 void SetUpCaptivePortalService(Profile
* profile
, const GURL
& test_url
);
928 // Returns true if |browser|'s profile is currently running a captive portal
930 bool CheckPending(Browser
* browser
);
932 // Returns the type of the interstitial being shown.
933 content::InterstitialPageDelegate::TypeID
GetInterstitialType(
934 WebContents
* contents
) const;
936 // Returns the CaptivePortalTabReloader::State of |web_contents|.
937 CaptivePortalTabReloader::State
GetStateOfTabReloader(
938 WebContents
* web_contents
) const;
940 // Returns the CaptivePortalTabReloader::State of the indicated tab.
941 CaptivePortalTabReloader::State
GetStateOfTabReloaderAt(Browser
* browser
,
944 // Returns the number of tabs with the given state, across all profiles.
945 int NumTabsWithState(CaptivePortalTabReloader::State state
) const;
947 // Returns the number of tabs broken by captive portals, across all profiles.
948 int NumBrokenTabs() const;
950 // Returns the number of tabs that need to be reloaded due to having logged
951 // in to a captive portal, across all profiles.
952 int NumNeedReloadTabs() const;
954 // Navigates |browser|'s active tab to |url| and expects no captive portal
955 // test to be triggered. |expected_navigations| is the number of times the
956 // active tab will end up being navigated. It should be 1, except for the
957 // Link Doctor page, which acts like two navigations.
958 void NavigateToPageExpectNoTest(Browser
* browser
,
960 int expected_navigations
);
962 // Navigates |browser|'s active tab to an SSL tab that takes a while to load,
963 // triggering a captive portal check, which is expected to give the result
964 // |expected_result|. The page finishes loading, with a timeout, after the
965 // captive portal check.
966 void SlowLoadNoCaptivePortal(Browser
* browser
,
967 CaptivePortalResult expected_result
);
969 // Navigates |browser|'s active tab to an SSL timeout, expecting a captive
970 // portal check to be triggered and return a result which will indicates
971 // there's no detected captive portal.
972 void FastTimeoutNoCaptivePortal(Browser
* browser
,
973 CaptivePortalResult expected_result
);
975 // Navigates the active tab to a slow loading SSL page, which will then
976 // trigger a captive portal test. The test is expected to find a captive
977 // portal. The slow loading page will continue to load after the function
978 // returns, until URLRequestTimeoutOnDemandJob::FailJobs() is called,
979 // at which point it will timeout.
981 // When |expect_open_login_tab| is false, no login tab is expected to be
982 // opened, because one already exists, and the function returns once the
983 // captive portal test is complete.
985 // If |expect_open_login_tab| is true, a login tab is then expected to be
986 // opened. It waits until both the login tab has finished loading, and two
987 // captive portal tests complete. The second test is triggered by the load of
988 // the captive portal tab completing.
990 // This function must not be called when the active tab is currently loading.
991 // Waits for the hanging request to be issued, so other functions can rely
992 // on URLRequestTimeoutOnDemandJob::WaitForJobs having been called.
993 void SlowLoadBehindCaptivePortal(Browser
* browser
,
994 bool expect_open_login_tab
);
996 // Same as above, but takes extra parameters.
998 // |hanging_url| should either be kMockHttpsUrl or redirect to kMockHttpsUrl.
1000 // |expected_portal_checks| and |expected_login_tab_navigations| allow
1001 // client-side redirects to be tested. |expected_login_tab_navigations| is
1002 // ignored when |expect_open_login_tab| is false.
1003 void SlowLoadBehindCaptivePortal(Browser
* browser
,
1004 bool expect_open_login_tab
,
1005 const GURL
& hanging_url
,
1006 int expected_portal_checks
,
1007 int expected_login_tab_navigations
);
1009 // Just like SlowLoadBehindCaptivePortal, except the navigated tab has
1010 // a connection timeout rather having its time trigger, and the function
1011 // waits until that timeout occurs.
1012 void FastTimeoutBehindCaptivePortal(Browser
* browser
,
1013 bool expect_open_login_tab
);
1015 // Much as above, but accepts a URL parameter and can be used for errors that
1016 // trigger captive portal checks other than timeouts. |error_url| should
1017 // result in an error rather than hanging.
1018 // If |delay_portal_response_until_interstital| is true, captive portal probe
1019 // request are ignored until the interstitial is shown, at which point a
1020 // captive portal result is sent. This allows testing in conjunction with the
1021 // certificate error interstitial.
1022 void FastErrorBehindCaptivePortal(
1024 bool expect_open_login_tab
,
1025 const GURL
& error_url
,
1026 bool delay_portal_response_until_interstital
);
1028 // Navigates the active tab to an SSL error page which triggers an
1029 // interstitial timer. Also disables captive portal checks indefinitely, so
1030 // the page appears to be hanging.
1031 void FastErrorWithInterstitialTimer(Browser
* browser
,
1032 const GURL
& cert_error_url
);
1034 // Navigates the login tab without logging in. The login tab must be the
1035 // specified browser's active tab. Expects no other tab to change state.
1036 // |num_loading_tabs| and |num_timed_out_tabs| are used as extra checks
1037 // that nothing has gone wrong prior to the function call.
1038 void NavigateLoginTab(Browser
* browser
,
1039 int num_loading_tabs
,
1040 int num_timed_out_tabs
);
1042 // Simulates a login by updating the URLRequestMockCaptivePortalJob's
1043 // behind captive portal state, and navigating the login tab. Waits for
1044 // all broken but not loading tabs to be reloaded.
1045 // |num_loading_tabs| and |num_timed_out_tabs| are used as extra checks
1046 // that nothing has gone wrong prior to the function call.
1047 void Login(Browser
* browser
, int num_loading_tabs
, int num_timed_out_tabs
);
1049 // Simulates a login when the broken tab shows an SSL or captive portal
1050 // interstitial. Can't use Login() in those cases because the interstitial
1051 // tab looks like a cross between a hung tab (Load was never committed) and a
1052 // tab at an error page (The load was stopped).
1053 void LoginCertError(Browser
* browser
);
1055 // Makes the slow SSL loads of all active tabs time out at once, and waits for
1056 // them to finish both that load and the automatic reload it should trigger.
1057 // There should be no timed out tabs when this is called.
1058 void FailLoadsAfterLogin(Browser
* browser
, int num_loading_tabs
);
1060 // Makes the slow SSL loads of all active tabs time out at once, and waits for
1061 // them to finish displaying their error pages. The login tab should be the
1062 // active tab. There should be no timed out tabs when this is called.
1063 void FailLoadsWithoutLogin(Browser
* browser
, int num_loading_tabs
);
1065 // Navigates |browser|'s active tab to |starting_url| while not behind a
1066 // captive portal. Then navigates to |interrupted_url|, which should create
1067 // a URLRequestTimeoutOnDemandJob, which is then abandoned. The load should
1068 // trigger a captive portal check, which finds a captive portal and opens a
1071 // Then the navigation is interrupted by a navigation to |timeout_url|, which
1072 // should trigger a captive portal check, and finally the test simulates
1075 // The purpose of this test is to make sure the TabHelper triggers a captive
1076 // portal check when a load is interrupted by another load, particularly in
1077 // the case of cross-process navigations.
1078 void RunNavigateLoadingTabToTimeoutTest(Browser
* browser
,
1079 const GURL
& starting_url
,
1080 const GURL
& interrupted_url
,
1081 const GURL
& timeout_url
);
1083 // Sets the timeout used by a CaptivePortalTabReloader on slow SSL loads
1084 // before a captive portal check.
1085 void SetSlowSSLLoadTime(CaptivePortalTabReloader
* tab_reloader
,
1086 base::TimeDelta slow_ssl_load_time
);
1088 CaptivePortalTabReloader
* GetTabReloader(WebContents
* web_contents
) const;
1091 URLRequestMockCaptivePortalJobFactory factory_
;
1094 DISALLOW_COPY_AND_ASSIGN(CaptivePortalBrowserTest
);
1097 CaptivePortalBrowserTest::CaptivePortalBrowserTest() {
1100 void CaptivePortalBrowserTest::SetUpOnMainThread() {
1101 // Enable mock requests.
1102 content::BrowserThread::PostTask(
1103 content::BrowserThread::IO
, FROM_HERE
,
1104 base::Bind(&chrome_browser_net::SetUrlRequestMocksEnabled
, true));
1105 factory_
.AddUrlHandlers();
1107 // Double-check that the captive portal service isn't enabled by default for
1109 EXPECT_EQ(CaptivePortalService::DISABLED_FOR_TESTING
,
1110 CaptivePortalService::get_state_for_testing());
1112 CaptivePortalService::set_state_for_testing(
1113 CaptivePortalService::SKIP_OS_CHECK_FOR_TESTING
);
1114 EnableCaptivePortalDetection(browser()->profile(), true);
1116 // Set the captive portal service to use URLRequestMockCaptivePortalJob's
1117 // mock URL, by default.
1118 SetUpCaptivePortalService(browser()->profile(),
1119 GURL(kMockCaptivePortalTestUrl
));
1121 // Set SSL interstitial delay long enough so that a captive portal result
1122 // is guaranteed to arrive during this window, and a captive portal
1123 // error page is displayed instead of an SSL interstitial.
1124 SSLErrorHandler::SetInterstitialDelayTypeForTest(SSLErrorHandler::LONG
);
1127 void CaptivePortalBrowserTest::TearDownOnMainThread() {
1128 // No test should have a captive portal check pending on quit.
1129 EXPECT_FALSE(CheckPending(browser()));
1132 void CaptivePortalBrowserTest::SetUpCommandLine(
1133 base::CommandLine
* command_line
) {
1134 // Enable finch experiment for captive portal interstitials.
1135 command_line
->AppendSwitchASCII(
1136 switches::kForceFieldTrials
, "CaptivePortalInterstitial/Enabled/");
1139 void CaptivePortalBrowserTest::EnableCaptivePortalDetection(
1140 Profile
* profile
, bool enabled
) {
1141 profile
->GetPrefs()->SetBoolean(prefs::kAlternateErrorPagesEnabled
, enabled
);
1144 void CaptivePortalBrowserTest::RespondToProbeRequests(bool enabled
) {
1146 EXPECT_EQ(CaptivePortalService::IGNORE_REQUESTS_FOR_TESTING
,
1147 CaptivePortalService::get_state_for_testing());
1148 CaptivePortalService::set_state_for_testing(
1149 CaptivePortalService::SKIP_OS_CHECK_FOR_TESTING
);
1151 EXPECT_EQ(CaptivePortalService::SKIP_OS_CHECK_FOR_TESTING
,
1152 CaptivePortalService::get_state_for_testing());
1153 CaptivePortalService::set_state_for_testing(
1154 CaptivePortalService::IGNORE_REQUESTS_FOR_TESTING
);
1158 void CaptivePortalBrowserTest::SetUpCaptivePortalService(Profile
* profile
,
1159 const GURL
& test_url
) {
1160 CaptivePortalService
* captive_portal_service
=
1161 CaptivePortalServiceFactory::GetForProfile(profile
);
1162 captive_portal_service
->set_test_url(test_url
);
1164 // Don't use any non-zero timers. Timers are checked in unit tests.
1165 CaptivePortalService::RecheckPolicy
* recheck_policy
=
1166 &captive_portal_service
->recheck_policy();
1167 recheck_policy
->initial_backoff_no_portal_ms
= 0;
1168 recheck_policy
->initial_backoff_portal_ms
= 0;
1169 recheck_policy
->backoff_policy
.maximum_backoff_ms
= 0;
1172 bool CaptivePortalBrowserTest::CheckPending(Browser
* browser
) {
1173 CaptivePortalService
* captive_portal_service
=
1174 CaptivePortalServiceFactory::GetForProfile(browser
->profile());
1176 return captive_portal_service
->DetectionInProgress() ||
1177 captive_portal_service
->TimerRunning();
1180 content::InterstitialPageDelegate::TypeID
1181 CaptivePortalBrowserTest::GetInterstitialType(WebContents
* contents
) const {
1182 if (!contents
->ShowingInterstitialPage())
1184 return contents
->GetInterstitialPage()
1185 ->GetDelegateForTesting()
1186 ->GetTypeForTesting();
1189 CaptivePortalTabReloader::State
CaptivePortalBrowserTest::GetStateOfTabReloader(
1190 WebContents
* web_contents
) const {
1191 return GetTabReloader(web_contents
)->state();
1194 CaptivePortalTabReloader::State
1195 CaptivePortalBrowserTest::GetStateOfTabReloaderAt(Browser
* browser
,
1197 return GetStateOfTabReloader(
1198 browser
->tab_strip_model()->GetWebContentsAt(index
));
1201 int CaptivePortalBrowserTest::NumTabsWithState(
1202 CaptivePortalTabReloader::State state
) const {
1204 for (TabContentsIterator it
; !it
.done(); it
.Next()) {
1205 if (GetStateOfTabReloader(*it
) == state
)
1211 int CaptivePortalBrowserTest::NumBrokenTabs() const {
1212 return NumTabsWithState(CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL
);
1215 int CaptivePortalBrowserTest::NumNeedReloadTabs() const {
1216 return NumTabsWithState(CaptivePortalTabReloader::STATE_NEEDS_RELOAD
);
1219 void CaptivePortalBrowserTest::NavigateToPageExpectNoTest(
1222 int expected_navigations
) {
1223 MultiNavigationObserver navigation_observer
;
1224 CaptivePortalObserver
portal_observer(browser
->profile());
1226 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
1227 browser
, url
, expected_navigations
);
1229 // No captive portal checks should have ocurred or be pending, and there
1230 // should be no new tabs.
1231 EXPECT_EQ(0, portal_observer
.num_results_received());
1232 EXPECT_FALSE(CheckPending(browser
));
1233 EXPECT_EQ(1, browser
->tab_strip_model()->count());
1234 EXPECT_EQ(expected_navigations
, navigation_observer
.num_navigations());
1235 EXPECT_EQ(0, NumLoadingTabs());
1236 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
,
1237 GetStateOfTabReloaderAt(browser
, 0));
1240 void CaptivePortalBrowserTest::SlowLoadNoCaptivePortal(
1242 CaptivePortalResult expected_result
) {
1243 CaptivePortalTabReloader
* tab_reloader
=
1244 GetTabReloader(browser
->tab_strip_model()->GetActiveWebContents());
1245 ASSERT_TRUE(tab_reloader
);
1246 SetSlowSSLLoadTime(tab_reloader
, base::TimeDelta());
1248 MultiNavigationObserver navigation_observer
;
1249 CaptivePortalObserver
portal_observer(browser
->profile());
1250 ui_test_utils::NavigateToURLWithDisposition(browser
,
1251 GURL(kMockHttpsUrl
),
1253 ui_test_utils::BROWSER_TEST_NONE
);
1255 portal_observer
.WaitForResults(1);
1257 ASSERT_EQ(1, browser
->tab_strip_model()->count());
1258 EXPECT_EQ(expected_result
, portal_observer
.captive_portal_result());
1259 EXPECT_EQ(1, portal_observer
.num_results_received());
1260 EXPECT_EQ(0, navigation_observer
.num_navigations());
1261 EXPECT_FALSE(CheckPending(browser
));
1263 // First tab should still be loading.
1264 EXPECT_EQ(1, NumLoadingTabs());
1266 // Wait for the request to be issued, then time it out.
1267 URLRequestTimeoutOnDemandJob::WaitForJobs(1);
1268 URLRequestTimeoutOnDemandJob::FailJobs(1);
1269 navigation_observer
.WaitForNavigations(1);
1271 ASSERT_EQ(1, browser
->tab_strip_model()->count());
1272 EXPECT_EQ(1, portal_observer
.num_results_received());
1273 EXPECT_FALSE(CheckPending(browser
));
1274 EXPECT_EQ(0, NumLoadingTabs());
1276 // Set a slow SSL load time to prevent the timer from triggering.
1277 SetSlowSSLLoadTime(tab_reloader
, base::TimeDelta::FromDays(1));
1280 void CaptivePortalBrowserTest::FastTimeoutNoCaptivePortal(
1282 CaptivePortalResult expected_result
) {
1283 ASSERT_NE(expected_result
, captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL
);
1285 // Set the load time to be large, so the timer won't trigger. The value is
1286 // not restored at the end of the function.
1287 CaptivePortalTabReloader
* tab_reloader
=
1288 GetTabReloader(browser
->tab_strip_model()->GetActiveWebContents());
1289 ASSERT_TRUE(tab_reloader
);
1290 SetSlowSSLLoadTime(tab_reloader
, base::TimeDelta::FromHours(1));
1292 MultiNavigationObserver navigation_observer
;
1293 CaptivePortalObserver
portal_observer(browser
->profile());
1295 // Neither of these should be changed by the navigation.
1296 int active_index
= browser
->tab_strip_model()->active_index();
1297 int expected_tab_count
= browser
->tab_strip_model()->count();
1299 ui_test_utils::NavigateToURL(
1301 URLRequestFailedJob::GetMockHttpsUrl(net::ERR_CONNECTION_TIMED_OUT
));
1303 // An attempt to detect a captive portal should have started by now. If not,
1304 // abort early to prevent hanging.
1305 ASSERT_TRUE(portal_observer
.num_results_received() > 0 ||
1306 CheckPending(browser
));
1308 portal_observer
.WaitForResults(1);
1309 navigation_observer
.WaitForNavigations(1);
1311 // Check the result.
1312 EXPECT_EQ(1, portal_observer
.num_results_received());
1313 EXPECT_EQ(expected_result
, portal_observer
.captive_portal_result());
1315 // Check that the right tab was navigated, and there were no extra
1317 EXPECT_EQ(1, navigation_observer
.NumNavigationsForTab(
1318 browser
->tab_strip_model()->GetWebContentsAt(active_index
)));
1319 EXPECT_EQ(0, NumLoadingTabs());
1321 // Check the tab's state, and verify no captive portal check is pending.
1322 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
,
1323 GetStateOfTabReloaderAt(browser
, 0));
1324 EXPECT_FALSE(CheckPending(browser
));
1326 // Make sure no login tab was opened.
1327 EXPECT_EQ(expected_tab_count
, browser
->tab_strip_model()->count());
1330 void CaptivePortalBrowserTest::SlowLoadBehindCaptivePortal(
1332 bool expect_open_login_tab
) {
1333 SlowLoadBehindCaptivePortal(browser
,
1334 expect_open_login_tab
,
1335 GURL(kMockHttpsUrl
),
1340 void CaptivePortalBrowserTest::SlowLoadBehindCaptivePortal(
1342 bool expect_open_login_tab
,
1343 const GURL
& hanging_url
,
1344 int expected_portal_checks
,
1345 int expected_login_tab_navigations
) {
1346 ASSERT_GE(expected_portal_checks
, 1);
1347 TabStripModel
* tab_strip_model
= browser
->tab_strip_model();
1348 // Calling this on a tab that's waiting for a load to manually be timed out
1349 // will result in a hang.
1350 ASSERT_FALSE(tab_strip_model
->GetActiveWebContents()->IsLoading());
1352 // Trigger a captive portal check quickly.
1353 CaptivePortalTabReloader
* tab_reloader
=
1354 GetTabReloader(tab_strip_model
->GetActiveWebContents());
1355 ASSERT_TRUE(tab_reloader
);
1356 SetSlowSSLLoadTime(tab_reloader
, base::TimeDelta());
1358 // Number of tabs expected to be open after the captive portal checks
1360 int initial_tab_count
= tab_strip_model
->count();
1361 int initial_active_index
= tab_strip_model
->active_index();
1362 int initial_loading_tabs
= NumLoadingTabs();
1363 int expected_broken_tabs
= NumBrokenTabs();
1364 if (CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL
!=
1365 GetStateOfTabReloader(tab_strip_model
->GetActiveWebContents())) {
1366 ++expected_broken_tabs
;
1369 MultiNavigationObserver navigation_observer
;
1370 CaptivePortalObserver
portal_observer(browser
->profile());
1371 ui_test_utils::NavigateToURLWithDisposition(browser
,
1374 ui_test_utils::BROWSER_TEST_NONE
);
1375 portal_observer
.WaitForResults(expected_portal_checks
);
1377 if (expect_open_login_tab
) {
1378 ASSERT_GE(expected_login_tab_navigations
, 1);
1380 navigation_observer
.WaitForNavigations(expected_login_tab_navigations
);
1382 ASSERT_EQ(initial_tab_count
+ 1, tab_strip_model
->count());
1383 EXPECT_EQ(initial_tab_count
, tab_strip_model
->active_index());
1385 EXPECT_EQ(expected_login_tab_navigations
,
1386 navigation_observer
.NumNavigationsForTab(
1387 tab_strip_model
->GetWebContentsAt(initial_tab_count
)));
1388 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
,
1389 GetStateOfTabReloaderAt(browser
, 1));
1390 EXPECT_TRUE(IsLoginTab(tab_strip_model
->GetWebContentsAt(1)));
1392 EXPECT_EQ(0, navigation_observer
.num_navigations());
1393 EXPECT_EQ(initial_active_index
, tab_strip_model
->active_index());
1394 ASSERT_EQ(initial_tab_count
, tab_strip_model
->count());
1395 EXPECT_EQ(initial_active_index
, tab_strip_model
->active_index());
1398 // Wait for all the expect resource loads to actually start, so subsequent
1399 // functions can rely on them having started.
1400 URLRequestTimeoutOnDemandJob::WaitForJobs(initial_loading_tabs
+ 1);
1402 EXPECT_EQ(initial_loading_tabs
+ 1, NumLoadingTabs());
1403 EXPECT_EQ(expected_broken_tabs
, NumBrokenTabs());
1404 EXPECT_EQ(captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL
,
1405 portal_observer
.captive_portal_result());
1406 EXPECT_EQ(expected_portal_checks
, portal_observer
.num_results_received());
1407 EXPECT_FALSE(CheckPending(browser
));
1409 EXPECT_EQ(CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL
,
1410 GetStateOfTabReloaderAt(browser
, initial_active_index
));
1412 // Reset the load time to be large, so the timer won't trigger on a reload.
1413 SetSlowSSLLoadTime(tab_reloader
, base::TimeDelta::FromHours(1));
1416 void CaptivePortalBrowserTest::FastTimeoutBehindCaptivePortal(
1418 bool expect_open_login_tab
) {
1419 FastErrorBehindCaptivePortal(browser
,
1420 expect_open_login_tab
,
1421 GURL(kMockHttpsQuickTimeoutUrl
),
1425 void CaptivePortalBrowserTest::FastErrorBehindCaptivePortal(
1427 bool expect_open_login_tab
,
1428 const GURL
& error_url
,
1429 bool delay_portal_response_until_interstital
) {
1430 TabStripModel
* tab_strip_model
= browser
->tab_strip_model();
1431 // Calling this on a tab that's waiting for a load to manually be timed out
1432 // will result in a hang.
1433 ASSERT_FALSE(tab_strip_model
->GetActiveWebContents()->IsLoading());
1435 // Set the load time to be large, so the timer won't trigger. The value is
1436 // not restored at the end of the function.
1437 CaptivePortalTabReloader
* tab_reloader
=
1438 GetTabReloader(tab_strip_model
->GetActiveWebContents());
1439 ASSERT_TRUE(tab_reloader
);
1440 SetSlowSSLLoadTime(tab_reloader
, base::TimeDelta::FromHours(1));
1442 // Number of tabs expected to be open after the captive portal checks
1444 int initial_tab_count
= tab_strip_model
->count();
1445 int initial_active_index
= tab_strip_model
->active_index();
1446 int initial_loading_tabs
= NumLoadingTabs();
1447 int expected_broken_tabs
= NumBrokenTabs();
1448 if (CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL
!=
1449 GetStateOfTabReloader(tab_strip_model
->GetActiveWebContents())) {
1450 ++expected_broken_tabs
;
1453 CaptivePortalService
* captive_portal_service
=
1454 CaptivePortalServiceFactory::GetForProfile(browser
->profile());
1455 if (delay_portal_response_until_interstital
)
1456 RespondToProbeRequests(false);
1458 MultiNavigationObserver navigation_observer
;
1459 CaptivePortalObserver
portal_observer(browser
->profile());
1460 ui_test_utils::NavigateToURLWithDisposition(browser
,
1463 ui_test_utils::BROWSER_TEST_NONE
);
1465 if (delay_portal_response_until_interstital
) {
1466 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
,
1467 GetStateOfTabReloaderAt(browser
, initial_active_index
));
1468 // Once the interstitial is attached, probe for captive portal.
1469 WaitForInterstitialAttach(tab_strip_model
->GetActiveWebContents());
1470 RespondToProbeRequests(true);
1471 captive_portal_service
->DetectCaptivePortal();
1474 portal_observer
.WaitForResults(1);
1476 if (expect_open_login_tab
) {
1477 navigation_observer
.WaitForNavigations(2);
1478 ASSERT_EQ(initial_tab_count
+ 1, tab_strip_model
->count());
1479 EXPECT_EQ(initial_tab_count
, tab_strip_model
->active_index());
1480 // Make sure that the originally active tab and the captive portal tab have
1481 // each loaded once.
1482 EXPECT_EQ(1, navigation_observer
.NumNavigationsForTab(
1483 tab_strip_model
->GetWebContentsAt(initial_active_index
)));
1484 EXPECT_EQ(1, navigation_observer
.NumNavigationsForTab(
1485 tab_strip_model
->GetWebContentsAt(initial_tab_count
)));
1486 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
,
1487 GetStateOfTabReloaderAt(browser
, 1));
1488 EXPECT_TRUE(IsLoginTab(tab_strip_model
->GetWebContentsAt(1)));
1490 navigation_observer
.WaitForNavigations(1);
1491 EXPECT_EQ(initial_active_index
, tab_strip_model
->active_index());
1492 EXPECT_EQ(1, navigation_observer
.NumNavigationsForTab(
1493 tab_strip_model
->GetWebContentsAt(initial_active_index
)));
1494 ASSERT_EQ(initial_tab_count
, tab_strip_model
->count());
1495 EXPECT_EQ(initial_active_index
, tab_strip_model
->active_index());
1498 EXPECT_EQ(initial_loading_tabs
, NumLoadingTabs());
1499 EXPECT_EQ(expected_broken_tabs
, NumBrokenTabs());
1500 EXPECT_EQ(captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL
,
1501 portal_observer
.captive_portal_result());
1502 EXPECT_EQ(1, portal_observer
.num_results_received());
1503 EXPECT_FALSE(CheckPending(browser
));
1505 EXPECT_EQ(CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL
,
1506 GetStateOfTabReloaderAt(browser
, initial_active_index
));
1509 void CaptivePortalBrowserTest::FastErrorWithInterstitialTimer(
1511 const GURL
& cert_error_url
) {
1512 TabStripModel
* tab_strip_model
= browser
->tab_strip_model();
1513 WebContents
* broken_tab_contents
= tab_strip_model
->GetActiveWebContents();
1515 // Disable captive portal checks indefinitely.
1516 RespondToProbeRequests(false);
1518 SSLInterstitialTimerObserver
interstitial_timer_observer(broken_tab_contents
);
1519 ui_test_utils::NavigateToURLWithDisposition(browser
,
1522 ui_test_utils::BROWSER_TEST_NONE
);
1523 interstitial_timer_observer
.WaitForTimerStarted();
1525 // The tab should be in loading state, waiting for the interstitial timer to
1526 // expire or a captive portal result to arrive. Since captive portal checks
1527 // are disabled and timer set to expire after a very long time, the tab should
1528 // hang indefinitely.
1529 EXPECT_TRUE(broken_tab_contents
->IsLoading());
1530 EXPECT_EQ(1, NumLoadingTabs());
1533 void CaptivePortalBrowserTest::NavigateLoginTab(Browser
* browser
,
1534 int num_loading_tabs
,
1535 int num_timed_out_tabs
) {
1536 MultiNavigationObserver navigation_observer
;
1537 CaptivePortalObserver
portal_observer(browser
->profile());
1539 TabStripModel
* tab_strip_model
= browser
->tab_strip_model();
1540 int initial_tab_count
= tab_strip_model
->count();
1541 EXPECT_EQ(num_loading_tabs
, NumLoadingTabs());
1542 EXPECT_EQ(num_timed_out_tabs
, NumBrokenTabs() - NumLoadingTabs());
1544 int login_tab_index
= tab_strip_model
->active_index();
1545 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
,
1546 GetStateOfTabReloader(tab_strip_model
->GetActiveWebContents()));
1547 ASSERT_TRUE(IsLoginTab(browser
->tab_strip_model()->GetActiveWebContents()));
1549 // Do the navigation.
1550 EXPECT_TRUE(content::ExecuteScript(tab_strip_model
->GetActiveWebContents(),
1553 portal_observer
.WaitForResults(1);
1554 navigation_observer
.WaitForNavigations(1);
1556 // Check the captive portal result.
1557 EXPECT_EQ(captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL
,
1558 portal_observer
.captive_portal_result());
1559 EXPECT_EQ(1, portal_observer
.num_results_received());
1560 EXPECT_FALSE(CheckPending(browser
));
1562 // Make sure not much has changed.
1563 EXPECT_EQ(initial_tab_count
, tab_strip_model
->count());
1564 EXPECT_EQ(num_loading_tabs
, NumLoadingTabs());
1565 EXPECT_EQ(num_loading_tabs
+ num_timed_out_tabs
, NumBrokenTabs());
1566 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
,
1567 GetStateOfTabReloaderAt(browser
, login_tab_index
));
1568 EXPECT_TRUE(IsLoginTab(tab_strip_model
->GetWebContentsAt(login_tab_index
)));
1570 // Make sure there were no unexpected navigations.
1571 EXPECT_EQ(1, navigation_observer
.NumNavigationsForTab(
1572 tab_strip_model
->GetWebContentsAt(login_tab_index
)));
1575 void CaptivePortalBrowserTest::Login(Browser
* browser
,
1576 int num_loading_tabs
,
1577 int num_timed_out_tabs
) {
1578 // Simulate logging in.
1579 factory_
.SetBehindCaptivePortal(false);
1581 MultiNavigationObserver navigation_observer
;
1582 CaptivePortalObserver
portal_observer(browser
->profile());
1584 TabStripModel
* tab_strip_model
= browser
->tab_strip_model();
1585 int initial_tab_count
= tab_strip_model
->count();
1586 ASSERT_EQ(num_loading_tabs
, NumLoadingTabs());
1587 EXPECT_EQ(num_timed_out_tabs
, NumBrokenTabs() - NumLoadingTabs());
1589 // Verify that the login page is on top.
1590 int login_tab_index
= tab_strip_model
->active_index();
1591 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
,
1592 GetStateOfTabReloaderAt(browser
, login_tab_index
));
1593 ASSERT_TRUE(IsLoginTab(tab_strip_model
->GetWebContentsAt(login_tab_index
)));
1595 // Trigger a navigation.
1596 EXPECT_TRUE(content::ExecuteScript(tab_strip_model
->GetActiveWebContents(),
1599 portal_observer
.WaitForResults(1);
1601 // Wait for all the timed out tabs to reload.
1602 navigation_observer
.WaitForNavigations(1 + num_timed_out_tabs
);
1603 EXPECT_EQ(1, portal_observer
.num_results_received());
1605 // The tabs that were loading before should still be loading, and now be in
1606 // STATE_NEEDS_RELOAD.
1607 EXPECT_EQ(0, NumBrokenTabs());
1608 EXPECT_EQ(num_loading_tabs
, NumLoadingTabs());
1609 EXPECT_EQ(num_loading_tabs
, NumNeedReloadTabs());
1611 // Make sure that the broken tabs have reloaded, and there's no more
1612 // captive portal tab.
1613 EXPECT_EQ(initial_tab_count
, tab_strip_model
->count());
1614 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
,
1615 GetStateOfTabReloaderAt(browser
, login_tab_index
));
1616 EXPECT_FALSE(IsLoginTab(tab_strip_model
->GetWebContentsAt(login_tab_index
)));
1618 // Make sure there were no unexpected navigations of the login tab.
1619 EXPECT_EQ(1, navigation_observer
.NumNavigationsForTab(
1620 tab_strip_model
->GetWebContentsAt(login_tab_index
)));
1623 void CaptivePortalBrowserTest::LoginCertError(Browser
* browser
) {
1624 factory_
.SetBehindCaptivePortal(false);
1626 MultiNavigationObserver navigation_observer
;
1627 CaptivePortalObserver
portal_observer(browser
->profile());
1629 TabStripModel
* tab_strip_model
= browser
->tab_strip_model();
1631 // Verify that the login page is on top.
1632 int login_tab_index
= tab_strip_model
->active_index();
1633 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
,
1634 GetStateOfTabReloaderAt(browser
, login_tab_index
));
1635 ASSERT_TRUE(IsLoginTab(tab_strip_model
->GetWebContentsAt(login_tab_index
)));
1637 // Trigger a navigation.
1638 EXPECT_TRUE(content::ExecuteScript(tab_strip_model
->GetActiveWebContents(),
1641 // The captive portal tab navigation will trigger a captive portal check,
1642 // and reloading the original tab will bring up the interstitial page again,
1643 // triggering a second captive portal check.
1644 portal_observer
.WaitForResults(2);
1646 // Wait for both tabs to finish loading.
1647 navigation_observer
.WaitForNavigations(2);
1648 EXPECT_EQ(2, portal_observer
.num_results_received());
1649 EXPECT_FALSE(CheckPending(browser
));
1650 EXPECT_EQ(captive_portal::RESULT_INTERNET_CONNECTED
,
1651 portal_observer
.captive_portal_result());
1653 // Check state of tabs. While the first tab is still displaying an
1654 // interstitial page, since no portal was found, it should be in STATE_NONE,
1655 // as should the login tab.
1656 ASSERT_EQ(2, tab_strip_model
->count());
1657 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
,
1658 GetStateOfTabReloaderAt(browser
, 0));
1659 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
,
1660 GetStateOfTabReloaderAt(browser
, login_tab_index
));
1661 EXPECT_FALSE(IsLoginTab(tab_strip_model
->GetWebContentsAt(login_tab_index
)));
1663 // Make sure only one navigation was for the login tab.
1664 EXPECT_EQ(1, navigation_observer
.NumNavigationsForTab(
1665 tab_strip_model
->GetWebContentsAt(login_tab_index
)));
1668 void CaptivePortalBrowserTest::FailLoadsAfterLogin(Browser
* browser
,
1669 int num_loading_tabs
) {
1670 ASSERT_EQ(num_loading_tabs
, NumLoadingTabs());
1671 ASSERT_EQ(num_loading_tabs
, NumNeedReloadTabs());
1672 EXPECT_EQ(0, NumBrokenTabs());
1674 TabStripModel
* tab_strip_model
= browser
->tab_strip_model();
1675 int initial_num_tabs
= tab_strip_model
->count();
1676 int initial_active_tab
= tab_strip_model
->active_index();
1678 CaptivePortalObserver
portal_observer(browser
->profile());
1679 FailLoadsAfterLoginObserver fail_loads_observer
;
1680 // Connection(s) finally time out. There should have already been a call
1681 // to wait for the requests to be issued before logging on.
1682 URLRequestTimeoutOnDemandJob::WaitForJobs(num_loading_tabs
);
1683 URLRequestTimeoutOnDemandJob::FailJobs(num_loading_tabs
);
1685 fail_loads_observer
.WaitForNavigations();
1687 // No captive portal checks should have ocurred or be pending, and there
1688 // should be no new tabs.
1689 EXPECT_EQ(0, portal_observer
.num_results_received());
1690 EXPECT_FALSE(CheckPending(browser
));
1691 EXPECT_EQ(initial_num_tabs
, tab_strip_model
->count());
1693 EXPECT_EQ(initial_active_tab
, tab_strip_model
->active_index());
1695 EXPECT_EQ(0, NumNeedReloadTabs());
1696 EXPECT_EQ(0, NumLoadingTabs());
1699 void CaptivePortalBrowserTest::FailLoadsWithoutLogin(Browser
* browser
,
1700 int num_loading_tabs
) {
1701 ASSERT_EQ(num_loading_tabs
, NumLoadingTabs());
1702 ASSERT_EQ(0, NumNeedReloadTabs());
1703 EXPECT_EQ(num_loading_tabs
, NumBrokenTabs());
1705 TabStripModel
* tab_strip_model
= browser
->tab_strip_model();
1706 int initial_num_tabs
= tab_strip_model
->count();
1707 int login_tab
= tab_strip_model
->active_index();
1708 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
,
1709 GetStateOfTabReloader(tab_strip_model
->GetActiveWebContents()));
1710 ASSERT_TRUE(IsLoginTab(tab_strip_model
->GetActiveWebContents()));
1712 CaptivePortalObserver
portal_observer(browser
->profile());
1713 MultiNavigationObserver navigation_observer
;
1714 // Connection(s) finally time out. There should have already been a call
1715 // to wait for the requests to be issued.
1716 URLRequestTimeoutOnDemandJob::FailJobs(num_loading_tabs
);
1718 navigation_observer
.WaitForNavigations(num_loading_tabs
);
1720 // No captive portal checks should have ocurred or be pending, and there
1721 // should be no new tabs.
1722 EXPECT_EQ(0, portal_observer
.num_results_received());
1723 EXPECT_FALSE(CheckPending(browser
));
1724 EXPECT_EQ(initial_num_tabs
, tab_strip_model
->count());
1726 EXPECT_EQ(0, NumNeedReloadTabs());
1727 EXPECT_EQ(0, NumLoadingTabs());
1728 EXPECT_EQ(num_loading_tabs
, NumBrokenTabs());
1729 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
,
1730 GetStateOfTabReloader(tab_strip_model
->GetActiveWebContents()));
1731 EXPECT_TRUE(IsLoginTab(tab_strip_model
->GetActiveWebContents()));
1732 EXPECT_EQ(login_tab
, tab_strip_model
->active_index());
1734 EXPECT_EQ(0, navigation_observer
.NumNavigationsForTab(
1735 tab_strip_model
->GetWebContentsAt(login_tab
)));
1738 void CaptivePortalBrowserTest::RunNavigateLoadingTabToTimeoutTest(
1740 const GURL
& starting_url
,
1741 const GURL
& hanging_url
,
1742 const GURL
& timeout_url
) {
1743 // Temporarily disable the captive portal and navigate to the starting
1744 // URL, which may be a URL that will hang when behind a captive portal.
1745 factory_
.SetBehindCaptivePortal(false);
1746 NavigateToPageExpectNoTest(browser
, starting_url
, 1);
1747 factory_
.SetBehindCaptivePortal(true);
1749 // Go to the first hanging url.
1750 SlowLoadBehindCaptivePortal(browser
, true, hanging_url
, 1, 1);
1752 // Abandon the request.
1753 URLRequestTimeoutOnDemandJob::WaitForJobs(1);
1754 URLRequestTimeoutOnDemandJob::AbandonJobs(1);
1756 TabStripModel
* tab_strip_model
= browser
->tab_strip_model();
1757 CaptivePortalTabReloader
* tab_reloader
=
1758 GetTabReloader(tab_strip_model
->GetWebContentsAt(0));
1759 ASSERT_TRUE(tab_reloader
);
1761 // A non-zero delay makes it more likely that CaptivePortalTabHelper will
1762 // be confused by events relating to canceling the old navigation.
1763 SetSlowSSLLoadTime(tab_reloader
, base::TimeDelta::FromSeconds(2));
1764 CaptivePortalObserver
portal_observer(browser
->profile());
1766 // Navigate the error tab to another slow loading page. Can't have
1767 // ui_test_utils do the navigation because it will wait for loading tabs to
1768 // stop loading before navigating.
1770 // This may result in either 0 or 1 DidStopLoading events. If there is one,
1771 // it must happen before the CaptivePortalService sends out its test request,
1772 // so waiting for PortalObserver to see that request prevents it from
1773 // confusing the MultiNavigationObservers used later.
1774 tab_strip_model
->ActivateTabAt(0, true);
1775 browser
->OpenURL(content::OpenURLParams(timeout_url
,
1776 content::Referrer(),
1778 ui::PAGE_TRANSITION_TYPED
,
1780 portal_observer
.WaitForResults(1);
1781 EXPECT_FALSE(CheckPending(browser
));
1782 EXPECT_EQ(1, NumLoadingTabs());
1783 EXPECT_EQ(CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL
,
1784 GetStateOfTabReloaderAt(browser
, 0));
1785 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
,
1786 GetStateOfTabReloaderAt(browser
, 1));
1787 ASSERT_TRUE(IsLoginTab(tab_strip_model
->GetWebContentsAt(1)));
1789 // Need to make sure the request has been issued before logging in.
1790 URLRequestTimeoutOnDemandJob::WaitForJobs(1);
1792 // Simulate logging in.
1793 tab_strip_model
->ActivateTabAt(1, true);
1794 SetSlowSSLLoadTime(tab_reloader
, base::TimeDelta::FromDays(1));
1795 Login(browser
, 1, 0);
1797 // Timeout occurs, and page is automatically reloaded.
1798 FailLoadsAfterLogin(browser
, 1);
1801 void CaptivePortalBrowserTest::SetSlowSSLLoadTime(
1802 CaptivePortalTabReloader
* tab_reloader
,
1803 base::TimeDelta slow_ssl_load_time
) {
1804 tab_reloader
->set_slow_ssl_load_time(slow_ssl_load_time
);
1807 CaptivePortalTabReloader
* CaptivePortalBrowserTest::GetTabReloader(
1808 WebContents
* web_contents
) const {
1809 return CaptivePortalTabHelper::FromWebContents(web_contents
)->
1810 GetTabReloaderForTest();
1813 // Make sure there's no test for a captive portal on HTTP timeouts. This will
1814 // also trigger the link doctor page, which results in the load of a second
1816 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest
, HttpTimeout
) {
1817 GURL url
= URLRequestFailedJob::GetMockHttpUrl(net::ERR_CONNECTION_TIMED_OUT
);
1818 NavigateToPageExpectNoTest(browser(), url
, 2);
1821 // Make sure there's no check for a captive portal on HTTPS errors other than
1822 // timeouts, when they preempt the slow load timer.
1823 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest
, HttpsNonTimeoutError
) {
1824 GURL url
= URLRequestFailedJob::GetMockHttpsUrl(net::ERR_UNEXPECTED
);
1825 NavigateToPageExpectNoTest(browser(), url
, 1);
1828 // Make sure no captive portal test triggers on HTTPS timeouts of iframes.
1829 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest
, HttpsIframeTimeout
) {
1830 // Use an HTTPS server for the top level page.
1831 net::SpawnedTestServer
https_server(
1832 net::SpawnedTestServer::TYPE_HTTPS
, net::SpawnedTestServer::kLocalhost
,
1833 base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
1834 ASSERT_TRUE(https_server
.Start());
1836 GURL url
= https_server
.GetURL(kTestServerIframeTimeoutPath
);
1837 NavigateToPageExpectNoTest(browser(), url
, 1);
1840 // Check the captive portal result when the test request reports a network
1841 // error. The check is triggered by a slow loading page, and the page
1842 // errors out only after getting a captive portal result.
1843 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest
, RequestFails
) {
1844 SetUpCaptivePortalService(
1845 browser()->profile(),
1846 URLRequestFailedJob::GetMockHttpUrl(net::ERR_CONNECTION_CLOSED
));
1847 SlowLoadNoCaptivePortal(browser(), captive_portal::RESULT_NO_RESPONSE
);
1850 // Same as above, but for the rather unlikely case that the connection times out
1851 // before the timer triggers.
1852 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest
, RequestFailsFastTimout
) {
1853 SetUpCaptivePortalService(
1854 browser()->profile(),
1855 URLRequestFailedJob::GetMockHttpUrl(net::ERR_CONNECTION_CLOSED
));
1856 FastTimeoutNoCaptivePortal(browser(), captive_portal::RESULT_NO_RESPONSE
);
1859 // Checks the case that captive portal detection is disabled.
1860 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest
, Disabled
) {
1861 EnableCaptivePortalDetection(browser()->profile(), false);
1862 SlowLoadNoCaptivePortal(browser(), captive_portal::RESULT_INTERNET_CONNECTED
);
1865 // Checks that we look for a captive portal on HTTPS timeouts and don't reload
1866 // the error tab when the captive portal probe gets a 204 response, indicating
1867 // there is no captive portal.
1868 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest
, InternetConnected
) {
1869 // Can't just use SetBehindCaptivePortal(false), since then there wouldn't
1871 ASSERT_TRUE(test_server()->Start());
1872 SetUpCaptivePortalService(browser()->profile(),
1873 test_server()->GetURL("nocontent"));
1874 SlowLoadNoCaptivePortal(browser(), captive_portal::RESULT_INTERNET_CONNECTED
);
1877 // Checks that no login page is opened when the HTTP test URL redirects to an
1878 // SSL certificate error.
1879 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest
, RedirectSSLCertError
) {
1880 // Need an HTTP TestServer to handle a dynamically created server redirect.
1881 ASSERT_TRUE(test_server()->Start());
1883 net::SpawnedTestServer::SSLOptions ssl_options
;
1884 ssl_options
.server_certificate
=
1885 net::SpawnedTestServer::SSLOptions::CERT_MISMATCHED_NAME
;
1886 net::SpawnedTestServer
https_server(
1887 net::SpawnedTestServer::TYPE_HTTPS
, ssl_options
,
1888 base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
1889 ASSERT_TRUE(https_server
.Start());
1891 GURL ssl_login_url
= https_server
.GetURL(kTestServerLoginPath
);
1893 CaptivePortalService
* captive_portal_service
=
1894 CaptivePortalServiceFactory::GetForProfile(browser()->profile());
1895 ASSERT_TRUE(captive_portal_service
);
1896 SetUpCaptivePortalService(
1897 browser()->profile(),
1898 test_server()->GetURL(CreateServerRedirect(ssl_login_url
.spec())));
1900 SlowLoadNoCaptivePortal(browser(), captive_portal::RESULT_NO_RESPONSE
);
1903 // A slow SSL load triggers a captive portal check. The user logs on before
1904 // the SSL page times out. We wait for the timeout and subsequent reload.
1905 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest
, Login
) {
1906 // Load starts, detect captive portal and open up a login tab.
1907 SlowLoadBehindCaptivePortal(browser(), true);
1909 // Log in. One loading tab, no timed out ones.
1910 Login(browser(), 1, 0);
1912 // Timeout occurs, and page is automatically reloaded.
1913 FailLoadsAfterLogin(browser(), 1);
1916 // Same as above, except we make sure everything works with an incognito
1917 // profile. Main issues it tests for are that the incognito has its own
1918 // non-NULL captive portal service, and we open the tab in the correct
1920 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest
, LoginIncognito
) {
1921 // This will watch tabs for both profiles, but only used to make sure no
1922 // navigations occur for the non-incognito profile.
1923 MultiNavigationObserver navigation_observer
;
1924 CaptivePortalObserver
non_incognito_portal_observer(browser()->profile());
1926 Browser
* incognito_browser
= CreateIncognitoBrowser();
1927 EnableCaptivePortalDetection(incognito_browser
->profile(), true);
1928 SetUpCaptivePortalService(incognito_browser
->profile(),
1929 GURL(kMockCaptivePortalTestUrl
));
1931 SlowLoadBehindCaptivePortal(incognito_browser
, true);
1933 TabStripModel
* tab_strip_model
= browser()->tab_strip_model();
1934 EXPECT_EQ(1, tab_strip_model
->count());
1935 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
,
1936 GetStateOfTabReloaderAt(browser(), 0));
1938 Login(incognito_browser
, 1, 0);
1939 FailLoadsAfterLogin(incognito_browser
, 1);
1941 EXPECT_EQ(1, tab_strip_model
->count());
1942 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
,
1943 GetStateOfTabReloaderAt(browser(), 0));
1945 EXPECT_EQ(0, navigation_observer
.NumNavigationsForTab(
1946 tab_strip_model
->GetWebContentsAt(0)));
1947 EXPECT_EQ(0, non_incognito_portal_observer
.num_results_received());
1950 // The captive portal page is opened before the SSL page times out,
1951 // but the user logs in only after the page times out.
1952 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest
, LoginSlow
) {
1953 SlowLoadBehindCaptivePortal(browser(), true);
1954 FailLoadsWithoutLogin(browser(), 1);
1955 Login(browser(), 0, 1);
1958 // Checks the unlikely case that the tab times out before the timer triggers.
1959 // This most likely won't happen, but should still work:
1960 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest
, LoginFastTimeout
) {
1961 FastTimeoutBehindCaptivePortal(browser(), true);
1962 Login(browser(), 0, 1);
1965 // A cert error triggers a captive portal check and results in opening a login
1967 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest
,
1968 ShowCaptivePortalInterstitialOnCertError
) {
1969 net::SpawnedTestServer::SSLOptions https_options
;
1970 https_options
.server_certificate
=
1971 net::SpawnedTestServer::SSLOptions::CERT_MISMATCHED_NAME
;
1972 net::SpawnedTestServer
https_server(
1973 net::SpawnedTestServer::TYPE_HTTPS
, https_options
,
1974 base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
1975 ASSERT_TRUE(https_server
.Start());
1977 TabStripModel
* tab_strip_model
= browser()->tab_strip_model();
1978 WebContents
* broken_tab_contents
= tab_strip_model
->GetActiveWebContents();
1980 // The path does not matter.
1981 GURL cert_error_url
= https_server
.GetURL(kTestServerLoginPath
);
1982 int cert_error_tab_index
= tab_strip_model
->active_index();
1983 // The interstitial should trigger a captive portal check when it opens, just
1984 // like navigating to kMockHttpsQuickTimeoutUrl.
1985 FastErrorBehindCaptivePortal(browser(), true, cert_error_url
, false);
1986 EXPECT_EQ(CaptivePortalBlockingPage::kTypeForTesting
,
1987 GetInterstitialType(broken_tab_contents
));
1989 // Switch to the interstitial and click the |Connect| button. Should switch
1990 // active tab to the captive portal landing page.
1991 int login_tab_index
= tab_strip_model
->active_index();
1992 tab_strip_model
->ActivateTabAt(cert_error_tab_index
, false);
1993 // Wait for the interstitial to load all the JavaScript code. Otherwise,
1994 // trying to click on a button will fail.
1995 content::RenderFrameHost
* rfh
=
1996 broken_tab_contents
->GetInterstitialPage()->GetMainFrame();
1997 EXPECT_TRUE(WaitForRenderFrameReady(rfh
));
1998 const char kClickConnectButtonJS
[] =
1999 "document.getElementById('primary-button').click();";
2001 content::ExecuteScript(rfh
, kClickConnectButtonJS
));
2002 EXPECT_EQ(login_tab_index
, tab_strip_model
->active_index());
2004 // For completeness, close the login tab and try clicking |Connect| again.
2005 // A new login tab should open.
2006 EXPECT_EQ(1, login_tab_index
);
2007 content::WebContentsDestroyedWatcher
destroyed_watcher(
2008 tab_strip_model
->GetActiveWebContents());
2010 tab_strip_model
->CloseWebContentsAt(tab_strip_model
->active_index(), 0));
2011 destroyed_watcher
.Wait();
2012 MultiNavigationObserver navigation_observer
;
2014 content::ExecuteScript(rfh
, kClickConnectButtonJS
));
2015 navigation_observer
.WaitForNavigations(1);
2016 EXPECT_EQ(login_tab_index
, tab_strip_model
->active_index());
2018 LoginCertError(browser());
2020 // Once logged in, broken tab should reload and display the SSL interstitial.
2021 WaitForInterstitialAttach(broken_tab_contents
);
2022 tab_strip_model
->ActivateTabAt(cert_error_tab_index
, false);
2024 EXPECT_EQ(SSLBlockingPage::kTypeForTesting
,
2025 GetInterstitialType(tab_strip_model
->GetActiveWebContents()));
2027 // Trigger another captive portal check while the SSL interstitial is showing.
2028 // At this point the user is logged in to the captive portal, so the captive
2029 // portal interstitial shouldn't get recreated.
2030 CaptivePortalObserver
portal_observer(browser()->profile());
2031 CaptivePortalService
* captive_portal_service
=
2032 CaptivePortalServiceFactory::GetForProfile(browser()->profile());
2033 captive_portal_service
->DetectCaptivePortal();
2034 portal_observer
.WaitForResults(1);
2035 EXPECT_EQ(SSLBlockingPage::kTypeForTesting
,
2036 GetInterstitialType(broken_tab_contents
));
2038 // A captive portal appears. Trigger a final captive portal check. The
2039 // captive portal interstitial should still not get recreated.
2040 factory_
.SetBehindCaptivePortal(true);
2041 CaptivePortalObserver
final_portal_observer(browser()->profile());
2042 captive_portal_service
->DetectCaptivePortal();
2043 final_portal_observer
.WaitForResults(1);
2044 EXPECT_EQ(SSLBlockingPage::kTypeForTesting
,
2045 GetInterstitialType(broken_tab_contents
));
2048 // Tests this scenario:
2049 // - Portal probe requests are ignored, so that no captive portal result can
2051 // - A cert error triggers an interstitial timer with a very long timeout.
2052 // - No captive portal results arrive, causing the tab to appear as loading
2053 // indefinitely (because probe requests are ignored).
2054 // - Stopping the page load shouldn't result in any interstitials.
2055 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest
,
2056 InterstitialTimerStopNavigationWhileLoading
) {
2057 net::SpawnedTestServer::SSLOptions https_options
;
2058 https_options
.server_certificate
=
2059 net::SpawnedTestServer::SSLOptions::CERT_MISMATCHED_NAME
;
2060 net::SpawnedTestServer
https_server(
2061 net::SpawnedTestServer::TYPE_HTTPS
, https_options
,
2062 base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
2063 ASSERT_TRUE(https_server
.Start());
2064 // The path does not matter.
2065 GURL cert_error_url
= https_server
.GetURL(kTestServerLoginPath
);
2067 TabStripModel
* tab_strip_model
= browser()->tab_strip_model();
2068 WebContents
* broken_tab_contents
= tab_strip_model
->GetActiveWebContents();
2070 CaptivePortalObserver
portal_observer1(browser()->profile());
2071 FastErrorWithInterstitialTimer(browser(), cert_error_url
);
2073 // Page appears loading. Stop the navigation. There should be no interstitial.
2074 MultiNavigationObserver test_navigation_observer
;
2075 broken_tab_contents
->Stop();
2076 test_navigation_observer
.WaitForNavigations(1);
2078 EXPECT_FALSE(broken_tab_contents
->ShowingInterstitialPage());
2079 EXPECT_FALSE(broken_tab_contents
->IsLoading());
2080 EXPECT_EQ(0, portal_observer1
.num_results_received());
2081 EXPECT_EQ(0, NumLoadingTabs());
2082 EXPECT_FALSE(CheckPending(browser()));
2083 EXPECT_EQ(1, browser()->tab_strip_model()->count());
2084 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
,
2085 GetStateOfTabReloaderAt(browser(), 0));
2087 // Re-enable captive portal checks and fire one. The result should be ignored.
2088 RespondToProbeRequests(true);
2089 CaptivePortalObserver
portal_observer2(browser()->profile());
2090 CaptivePortalService
* captive_portal_service
=
2091 CaptivePortalServiceFactory::GetForProfile(browser()->profile());
2092 captive_portal_service
->DetectCaptivePortal();
2093 portal_observer2
.WaitForResults(1);
2095 EXPECT_FALSE(broken_tab_contents
->ShowingInterstitialPage());
2096 EXPECT_FALSE(broken_tab_contents
->IsLoading());
2097 EXPECT_EQ(1, portal_observer2
.num_results_received());
2098 EXPECT_EQ(captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL
,
2099 portal_observer2
.captive_portal_result());
2100 EXPECT_EQ(0, NumLoadingTabs());
2101 EXPECT_FALSE(CheckPending(browser()));
2102 EXPECT_EQ(1, browser()->tab_strip_model()->count());
2103 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
,
2104 GetStateOfTabReloaderAt(browser(), 0));
2107 // Same as above, but instead of stopping, the loading page is reloaded. The end
2108 // result is the same. (i.e. page load stops, no interstitials shown)
2109 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest
,
2110 InterstitialTimerReloadWhileLoading
) {
2111 net::SpawnedTestServer::SSLOptions https_options
;
2112 https_options
.server_certificate
=
2113 net::SpawnedTestServer::SSLOptions::CERT_MISMATCHED_NAME
;
2114 net::SpawnedTestServer
https_server(
2115 net::SpawnedTestServer::TYPE_HTTPS
, https_options
,
2116 base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
2117 ASSERT_TRUE(https_server
.Start());
2118 // The path does not matter.
2119 GURL cert_error_url
= https_server
.GetURL(kTestServerLoginPath
);
2121 TabStripModel
* tab_strip_model
= browser()->tab_strip_model();
2122 WebContents
* broken_tab_contents
= tab_strip_model
->GetActiveWebContents();
2124 CaptivePortalObserver
portal_observer(browser()->profile());
2125 FastErrorWithInterstitialTimer(browser(), cert_error_url
);
2127 // Page appears loading. Reloading it cancels the page load. Since the load is
2128 // stopped, no cert error occurs and SSLErrorHandler isn't instantiated.
2129 MultiNavigationObserver test_navigation_observer
;
2130 chrome::Reload(browser(), CURRENT_TAB
);
2131 test_navigation_observer
.WaitForNavigations(2);
2133 EXPECT_FALSE(broken_tab_contents
->ShowingInterstitialPage());
2134 EXPECT_FALSE(broken_tab_contents
->IsLoading());
2135 EXPECT_EQ(0, portal_observer
.num_results_received());
2136 EXPECT_EQ(2, test_navigation_observer
.num_navigations());
2137 EXPECT_EQ(0, NumLoadingTabs());
2138 EXPECT_FALSE(CheckPending(browser()));
2139 EXPECT_EQ(1, browser()->tab_strip_model()->count());
2140 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
,
2141 GetStateOfTabReloaderAt(browser(), 0));
2143 // Re-enable captive portal checks and fire one. The result should be ignored.
2144 RespondToProbeRequests(true);
2145 CaptivePortalObserver
portal_observer2(browser()->profile());
2146 CaptivePortalService
* captive_portal_service
=
2147 CaptivePortalServiceFactory::GetForProfile(browser()->profile());
2148 captive_portal_service
->DetectCaptivePortal();
2149 portal_observer2
.WaitForResults(1);
2151 EXPECT_FALSE(broken_tab_contents
->ShowingInterstitialPage());
2152 EXPECT_FALSE(broken_tab_contents
->IsLoading());
2153 EXPECT_EQ(1, portal_observer2
.num_results_received());
2154 EXPECT_EQ(captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL
,
2155 portal_observer2
.captive_portal_result());
2156 EXPECT_EQ(0, NumLoadingTabs());
2157 EXPECT_FALSE(CheckPending(browser()));
2158 EXPECT_EQ(1, browser()->tab_strip_model()->count());
2159 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
,
2160 GetStateOfTabReloaderAt(browser(), 0));
2163 // Same as |InterstitialTimerReloadWhileLoading_NoSSLError|, but instead of
2164 // reloading, the page is navigated away. The new page should load, and no
2165 // interstitials should be shown.
2166 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest
,
2167 InterstitialTimerNavigateAwayWhileLoading
) {
2168 net::SpawnedTestServer::SSLOptions https_options
;
2169 https_options
.server_certificate
=
2170 net::SpawnedTestServer::SSLOptions::CERT_MISMATCHED_NAME
;
2171 net::SpawnedTestServer
https_server(
2172 net::SpawnedTestServer::TYPE_HTTPS
, https_options
,
2173 base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
2174 ASSERT_TRUE(https_server
.Start());
2175 // The path does not matter.
2176 GURL cert_error_url
= https_server
.GetURL(kTestServerLoginPath
);
2178 TabStripModel
* tab_strip_model
= browser()->tab_strip_model();
2179 WebContents
* broken_tab_contents
= tab_strip_model
->GetActiveWebContents();
2181 CaptivePortalObserver
portal_observer(browser()->profile());
2182 FastErrorWithInterstitialTimer(browser(), cert_error_url
);
2184 // Page appears loading. Navigating away shouldn't result in any interstitial.
2185 // Can't use ui_test_utils::NavigateToURLWithDisposition because it waits for
2186 // a load stop notification before starting a new navigation.
2187 MultiNavigationObserver test_navigation_observer
;
2188 browser()->OpenURL(content::OpenURLParams(
2189 URLRequestMockHTTPJob::GetMockUrl(
2190 base::FilePath(FILE_PATH_LITERAL("title2.html"))),
2191 content::Referrer(),
2193 ui::PAGE_TRANSITION_TYPED
, false));
2194 // Expect two navigations: First one for stopping the hanging page, second one
2195 // for completing the load of the above navigation.
2196 test_navigation_observer
.WaitForNavigations(2);
2198 EXPECT_FALSE(broken_tab_contents
->ShowingInterstitialPage());
2199 EXPECT_FALSE(broken_tab_contents
->IsLoading());
2200 EXPECT_EQ(0, portal_observer
.num_results_received());
2201 EXPECT_EQ(2, test_navigation_observer
.num_navigations());
2202 EXPECT_EQ(0, NumLoadingTabs());
2203 EXPECT_FALSE(CheckPending(browser()));
2204 EXPECT_EQ(1, browser()->tab_strip_model()->count());
2205 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
,
2206 GetStateOfTabReloaderAt(browser(), 0));
2208 // Re-enable captive portal checks and fire one. The result should be ignored.
2209 RespondToProbeRequests(true);
2210 CaptivePortalObserver
portal_observer2(browser()->profile());
2211 CaptivePortalService
* captive_portal_service
=
2212 CaptivePortalServiceFactory::GetForProfile(browser()->profile());
2213 captive_portal_service
->DetectCaptivePortal();
2214 portal_observer2
.WaitForResults(1);
2216 EXPECT_FALSE(broken_tab_contents
->ShowingInterstitialPage());
2217 EXPECT_FALSE(broken_tab_contents
->IsLoading());
2218 EXPECT_EQ(1, portal_observer2
.num_results_received());
2219 EXPECT_EQ(captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL
,
2220 portal_observer2
.captive_portal_result());
2221 EXPECT_EQ(0, NumLoadingTabs());
2222 EXPECT_FALSE(CheckPending(browser()));
2223 EXPECT_EQ(1, browser()->tab_strip_model()->count());
2224 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
,
2225 GetStateOfTabReloaderAt(browser(), 0));
2228 // Same as above, but the hanging load is interrupted by a navigation to the
2229 // same page, this time committing the navigation. This should end up with an
2230 // SSL interstitial when not behind a captive portal. This ensures that a new
2231 // |SSLErrorHandler| is created on a new navigation, even though the tab's
2232 // WebContents doesn't change.
2233 IN_PROC_BROWSER_TEST_F(
2234 CaptivePortalBrowserTest
,
2235 InterstitialTimerNavigateWhileLoading_EndWithSSLInterstitial
) {
2236 net::SpawnedTestServer::SSLOptions https_options
;
2237 https_options
.server_certificate
=
2238 net::SpawnedTestServer::SSLOptions::CERT_MISMATCHED_NAME
;
2239 net::SpawnedTestServer
https_server(
2240 net::SpawnedTestServer::TYPE_HTTPS
, https_options
,
2241 base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
2242 ASSERT_TRUE(https_server
.Start());
2243 // The path does not matter.
2244 GURL cert_error_url
= https_server
.GetURL(kTestServerLoginPath
);
2245 factory_
.SetBehindCaptivePortal(false);
2247 TabStripModel
* tab_strip_model
= browser()->tab_strip_model();
2248 WebContents
* broken_tab_contents
= tab_strip_model
->GetActiveWebContents();
2250 FastErrorWithInterstitialTimer(browser(), cert_error_url
);
2251 // Page appears loading. Turn on response to probe request again, and navigate
2252 // to the same page. This should result in a cert error which should
2253 // instantiate an |SSLErrorHandler| and end up showing an SSL interstitial.
2254 RespondToProbeRequests(true);
2255 // Can't have ui_test_utils do the navigation because it will wait for loading
2256 // tabs to stop loading before navigating.
2257 CaptivePortalObserver
portal_observer(browser()->profile());
2258 MultiNavigationObserver test_navigation_observer
;
2259 browser()->OpenURL(content::OpenURLParams(cert_error_url
, content::Referrer(),
2261 ui::PAGE_TRANSITION_TYPED
, false));
2262 // Expect two navigations: First one for stopping the hanging page, second one
2263 // for completing the load of the above navigation.
2264 test_navigation_observer
.WaitForNavigations(2);
2265 // Should end up with an SSL interstitial.
2266 WaitForInterstitialAttach(broken_tab_contents
);
2267 ASSERT_TRUE(broken_tab_contents
->ShowingInterstitialPage());
2268 EXPECT_EQ(SSLBlockingPage::kTypeForTesting
,
2269 broken_tab_contents
->GetInterstitialPage()
2270 ->GetDelegateForTesting()
2271 ->GetTypeForTesting());
2272 EXPECT_FALSE(broken_tab_contents
->IsLoading());
2273 EXPECT_EQ(1, portal_observer
.num_results_received());
2274 EXPECT_EQ(captive_portal::RESULT_INTERNET_CONNECTED
,
2275 portal_observer
.captive_portal_result());
2276 EXPECT_EQ(0, NumLoadingTabs());
2277 EXPECT_FALSE(CheckPending(browser()));
2278 EXPECT_EQ(1, browser()->tab_strip_model()->count());
2279 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
,
2280 GetStateOfTabReloaderAt(browser(), 0));
2283 // Same as above, but this time behind a captive portal.
2284 IN_PROC_BROWSER_TEST_F(
2285 CaptivePortalBrowserTest
,
2286 InterstitialTimerNavigateWhileLoading_EndWithCaptivePortalInterstitial
) {
2287 net::SpawnedTestServer::SSLOptions https_options
;
2288 https_options
.server_certificate
=
2289 net::SpawnedTestServer::SSLOptions::CERT_MISMATCHED_NAME
;
2290 net::SpawnedTestServer
https_server(
2291 net::SpawnedTestServer::TYPE_HTTPS
, https_options
,
2292 base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
2293 ASSERT_TRUE(https_server
.Start());
2294 // The path does not matter.
2295 GURL cert_error_url
= https_server
.GetURL(kTestServerLoginPath
);
2296 factory_
.SetBehindCaptivePortal(true);
2298 TabStripModel
* tab_strip_model
= browser()->tab_strip_model();
2299 WebContents
* broken_tab_contents
= tab_strip_model
->GetActiveWebContents();
2300 int initial_tab_count
= tab_strip_model
->count();
2302 FastErrorWithInterstitialTimer(browser(), cert_error_url
);
2303 // Page appears loading. Turn on response to probe request again, and navigate
2304 // to the same page. This should result in a cert error which should
2305 // instantiate an |SSLErrorHandler| and end up showing an SSL.
2306 RespondToProbeRequests(true);
2307 // Can't have ui_test_utils do the navigation because it will wait for loading
2308 // tabs to stop loading before navigating.
2309 CaptivePortalObserver
portal_observer(browser()->profile());
2310 MultiNavigationObserver test_navigation_observer
;
2311 browser()->OpenURL(content::OpenURLParams(cert_error_url
, content::Referrer(),
2313 ui::PAGE_TRANSITION_TYPED
, false));
2314 // Expect three navigations:
2315 // 1- For stopping the hanging page.
2316 // 2- For completing the load of the above navigation.
2317 // 3- For completing the load of the login tab.
2318 test_navigation_observer
.WaitForNavigations(3);
2319 // Should end up with a captive portal interstitial and a new login tab.
2320 WaitForInterstitialAttach(broken_tab_contents
);
2321 ASSERT_TRUE(broken_tab_contents
->ShowingInterstitialPage());
2322 EXPECT_EQ(CaptivePortalBlockingPage::kTypeForTesting
,
2323 broken_tab_contents
->GetInterstitialPage()
2324 ->GetDelegateForTesting()
2325 ->GetTypeForTesting());
2326 ASSERT_EQ(initial_tab_count
+ 1, tab_strip_model
->count());
2327 EXPECT_EQ(initial_tab_count
, tab_strip_model
->active_index());
2328 EXPECT_FALSE(broken_tab_contents
->IsLoading());
2329 EXPECT_EQ(1, portal_observer
.num_results_received());
2330 EXPECT_EQ(captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL
,
2331 portal_observer
.captive_portal_result());
2332 EXPECT_EQ(0, NumLoadingTabs());
2333 EXPECT_FALSE(CheckPending(browser()));
2334 EXPECT_EQ(CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL
,
2335 GetStateOfTabReloaderAt(browser(), 0));
2336 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
,
2337 GetStateOfTabReloaderAt(browser(), 1));
2338 EXPECT_TRUE(IsLoginTab(tab_strip_model
->GetWebContentsAt(1)));
2341 // A cert error triggers a captive portal check and results in opening a login
2342 // tab. The user then logs in and the page with the error is reloaded.
2343 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest
, SSLCertErrorLogin
) {
2344 // Need an HTTP TestServer to handle a dynamically created server redirect.
2345 ASSERT_TRUE(test_server()->Start());
2347 net::SpawnedTestServer::SSLOptions https_options
;
2348 https_options
.server_certificate
=
2349 net::SpawnedTestServer::SSLOptions::CERT_MISMATCHED_NAME
;
2350 net::SpawnedTestServer
https_server(
2351 net::SpawnedTestServer::TYPE_HTTPS
, https_options
,
2352 base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
2353 ASSERT_TRUE(https_server
.Start());
2355 // Set SSL interstitial delay to zero so that a captive portal result can not
2356 // arrive during this window, so an SSL interstitial is displayed instead
2357 // of a captive portal error page.
2358 SSLErrorHandler::SetInterstitialDelayTypeForTest(SSLErrorHandler::NONE
);
2359 TabStripModel
* tab_strip_model
= browser()->tab_strip_model();
2360 WebContents
* broken_tab_contents
= tab_strip_model
->GetActiveWebContents();
2362 // Setting the delay to zero above has a race condition: A captive portal
2363 // result triggered by a cert error can arrive before the SSL interstitial
2364 // display timer is fired, even though it's set to zero.
2365 // To avoid this, disable captive portal checks until the SSL interstitial is
2366 // displayed. Once it's displayed, enable portal checks and fire one.
2367 bool delay_portal_response_until_interstital
= true;
2369 // The path does not matter.
2370 GURL cert_error_url
= https_server
.GetURL(kTestServerLoginPath
);
2371 // A captive portal check is triggered in FastErrorBehindCaptivePortal.
2372 FastErrorBehindCaptivePortal(
2376 delay_portal_response_until_interstital
);
2378 EXPECT_EQ(SSLBlockingPage::kTypeForTesting
,
2379 GetInterstitialType(broken_tab_contents
));
2381 LoginCertError(browser());
2384 // Tries navigating both the tab that encounters an SSL timeout and the
2385 // login tab twice, only logging in the second time.
2386 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest
, LoginExtraNavigations
) {
2387 FastTimeoutBehindCaptivePortal(browser(), true);
2389 // Activate the timed out tab and navigate it to a timeout again.
2390 TabStripModel
* tab_strip_model
= browser()->tab_strip_model();
2391 tab_strip_model
->ActivateTabAt(0, true);
2392 FastTimeoutBehindCaptivePortal(browser(), false);
2394 // Activate and navigate the captive portal tab. This should not trigger a
2395 // reload of the tab with the error.
2396 tab_strip_model
->ActivateTabAt(1, true);
2397 NavigateLoginTab(browser(), 0, 1);
2399 // Simulate logging in.
2400 Login(browser(), 0, 1);
2403 // After the first SSL timeout, closes the login tab and makes sure it's opened
2404 // it again on a second timeout.
2405 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest
, CloseLoginTab
) {
2406 // First load starts, opens a login tab, and then times out.
2407 SlowLoadBehindCaptivePortal(browser(), true);
2408 FailLoadsWithoutLogin(browser(), 1);
2411 chrome::CloseTab(browser());
2413 // Go through the standard slow load login, and make sure it still works.
2414 SlowLoadBehindCaptivePortal(browser(), true);
2415 Login(browser(), 1, 0);
2416 FailLoadsAfterLogin(browser(), 1);
2419 // Checks that two tabs with SSL timeouts in the same window work. Both
2420 // tabs only timeout after logging in.
2421 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest
, TwoBrokenTabs
) {
2422 SlowLoadBehindCaptivePortal(browser(), true);
2424 // Can't set the TabReloader HTTPS timeout on a new tab without doing some
2425 // acrobatics, so open a new tab at a normal page, and then navigate it to a
2427 MultiNavigationObserver navigation_observer
;
2428 CaptivePortalObserver
portal_observer(browser()->profile());
2429 ui_test_utils::NavigateToURLWithDisposition(
2431 URLRequestMockHTTPJob::GetMockUrl(
2432 base::FilePath(FILE_PATH_LITERAL("title2.html"))),
2434 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION
);
2436 TabStripModel
* tab_strip_model
= browser()->tab_strip_model();
2437 ASSERT_EQ(3, tab_strip_model
->count());
2438 EXPECT_FALSE(CheckPending(browser()));
2439 EXPECT_EQ(0, portal_observer
.num_results_received());
2440 EXPECT_EQ(1, NumLoadingTabs());
2441 EXPECT_EQ(1, navigation_observer
.num_navigations());
2442 EXPECT_EQ(1, navigation_observer
.NumNavigationsForTab(
2443 tab_strip_model
->GetWebContentsAt(2)));
2444 ASSERT_EQ(CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL
,
2445 GetStateOfTabReloaderAt(browser(), 0));
2446 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
,
2447 GetStateOfTabReloaderAt(browser(), 1));
2448 ASSERT_TRUE(IsLoginTab(tab_strip_model
->GetWebContentsAt(1)));
2449 ASSERT_EQ(CaptivePortalTabReloader::STATE_NONE
,
2450 GetStateOfTabReloaderAt(browser(), 2));
2451 ASSERT_EQ(2, tab_strip_model
->active_index());
2453 SlowLoadBehindCaptivePortal(browser(), false);
2455 tab_strip_model
->ActivateTabAt(1, true);
2456 Login(browser(), 2, 0);
2457 FailLoadsAfterLogin(browser(), 2);
2460 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest
, AbortLoad
) {
2461 SlowLoadBehindCaptivePortal(browser(), true);
2463 // Abandon the request.
2464 URLRequestTimeoutOnDemandJob::WaitForJobs(1);
2465 URLRequestTimeoutOnDemandJob::AbandonJobs(1);
2467 CaptivePortalObserver
portal_observer(browser()->profile());
2468 MultiNavigationObserver navigation_observer
;
2470 // Switch back to the hung tab from the login tab, and abort the navigation.
2471 TabStripModel
* tab_strip_model
= browser()->tab_strip_model();
2472 tab_strip_model
->ActivateTabAt(0, true);
2473 chrome::Stop(browser());
2474 navigation_observer
.WaitForNavigations(1);
2476 EXPECT_EQ(0, NumBrokenTabs());
2477 EXPECT_EQ(0, portal_observer
.num_results_received());
2478 EXPECT_FALSE(CheckPending(browser()));
2479 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
,
2480 GetStateOfTabReloaderAt(browser(), 0));
2482 tab_strip_model
->ActivateTabAt(1, true);
2483 Login(browser(), 0, 0);
2486 // Checks the case where the timed out tab is successfully navigated before
2488 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest
, NavigateBrokenTab
) {
2489 // Go to the error page.
2490 SlowLoadBehindCaptivePortal(browser(), true);
2491 FailLoadsWithoutLogin(browser(), 1);
2493 // Navigate the error tab to a non-error page.
2494 TabStripModel
* tab_strip_model
= browser()->tab_strip_model();
2495 tab_strip_model
->ActivateTabAt(0, true);
2496 ui_test_utils::NavigateToURL(
2497 browser(), URLRequestMockHTTPJob::GetMockUrl(
2498 base::FilePath(FILE_PATH_LITERAL("title2.html"))));
2499 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
,
2500 GetStateOfTabReloaderAt(browser(), 0));
2502 // Simulate logging in.
2503 tab_strip_model
->ActivateTabAt(1, true);
2504 Login(browser(), 0, 0);
2507 // Checks that captive portal detection triggers correctly when a same-site
2508 // navigation is cancelled by a navigation to the same site.
2509 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest
,
2510 NavigateLoadingTabToTimeoutSingleSite
) {
2511 RunNavigateLoadingTabToTimeoutTest(
2513 GURL(kMockHttpsUrl
),
2514 GURL(kMockHttpsUrl
),
2515 GURL(kMockHttpsUrl
));
2518 // Fails on Windows only, mostly on Win7. http://crbug.com/170033
2520 #define MAYBE_NavigateLoadingTabToTimeoutTwoSites \
2521 DISABLED_NavigateLoadingTabToTimeoutTwoSites
2523 #define MAYBE_NavigateLoadingTabToTimeoutTwoSites \
2524 NavigateLoadingTabToTimeoutTwoSites
2527 // Checks that captive portal detection triggers correctly when a same-site
2528 // navigation is cancelled by a navigation to another site.
2529 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest
,
2530 MAYBE_NavigateLoadingTabToTimeoutTwoSites
) {
2531 RunNavigateLoadingTabToTimeoutTest(
2533 GURL(kMockHttpsUrl
),
2534 GURL(kMockHttpsUrl
),
2535 GURL(kMockHttpsUrl2
));
2538 // Checks that captive portal detection triggers correctly when a cross-site
2539 // navigation is cancelled by a navigation to yet another site.
2540 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest
,
2541 NavigateLoadingTabToTimeoutThreeSites
) {
2542 RunNavigateLoadingTabToTimeoutTest(
2544 URLRequestMockHTTPJob::GetMockUrl(
2545 base::FilePath(FILE_PATH_LITERAL("title.html"))),
2546 GURL(kMockHttpsUrl
),
2547 GURL(kMockHttpsUrl2
));
2550 // Checks that navigating a timed out tab back clears its state.
2551 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest
, GoBack
) {
2552 // Navigate to a working page.
2553 ui_test_utils::NavigateToURL(
2555 URLRequestMockHTTPJob::GetMockUrl(
2556 base::FilePath(FILE_PATH_LITERAL("title2.html"))));
2558 // Go to the error page.
2559 SlowLoadBehindCaptivePortal(browser(), true);
2560 FailLoadsWithoutLogin(browser(), 1);
2562 CaptivePortalObserver
portal_observer(browser()->profile());
2563 MultiNavigationObserver navigation_observer
;
2565 // Activate the error page tab again and go back.
2566 TabStripModel
* tab_strip_model
= browser()->tab_strip_model();
2567 tab_strip_model
->ActivateTabAt(0, true);
2568 chrome::GoBack(browser(), CURRENT_TAB
);
2569 navigation_observer
.WaitForNavigations(1);
2571 EXPECT_EQ(1, navigation_observer
.NumNavigationsForTab(
2572 tab_strip_model
->GetWebContentsAt(0)));
2573 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
,
2574 GetStateOfTabReloaderAt(browser(), 0));
2575 EXPECT_EQ(0, portal_observer
.num_results_received());
2578 // Checks that navigating back to a timeout triggers captive portal detection.
2579 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest
, GoBackToTimeout
) {
2580 // Disable captive portal detection so the first navigation doesn't open a
2582 EnableCaptivePortalDetection(browser()->profile(), false);
2584 SlowLoadNoCaptivePortal(browser(), captive_portal::RESULT_INTERNET_CONNECTED
);
2586 // Navigate to a working page.
2587 ui_test_utils::NavigateToURL(
2588 browser(), URLRequestMockHTTPJob::GetMockUrl(
2589 base::FilePath(FILE_PATH_LITERAL("title2.html"))));
2590 ASSERT_EQ(CaptivePortalTabReloader::STATE_NONE
,
2591 GetStateOfTabReloaderAt(browser(), 0));
2593 EnableCaptivePortalDetection(browser()->profile(), true);
2595 TabStripModel
* tab_strip_model
= browser()->tab_strip_model();
2596 CaptivePortalTabReloader
* tab_reloader
=
2597 GetTabReloader(tab_strip_model
->GetActiveWebContents());
2598 ASSERT_TRUE(tab_reloader
);
2599 SetSlowSSLLoadTime(tab_reloader
, base::TimeDelta());
2601 // Go to the error page.
2602 MultiNavigationObserver navigation_observer
;
2603 CaptivePortalObserver
portal_observer(browser()->profile());
2604 chrome::GoBack(browser(), CURRENT_TAB
);
2606 // Wait for the check triggered by the broken tab and for the login tab to
2608 portal_observer
.WaitForResults(1);
2609 navigation_observer
.WaitForNavigations(1);
2610 // Make sure the request has been issued.
2611 URLRequestTimeoutOnDemandJob::WaitForJobs(1);
2613 EXPECT_EQ(1, portal_observer
.num_results_received());
2614 ASSERT_FALSE(CheckPending(browser()));
2615 ASSERT_EQ(captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL
,
2616 portal_observer
.captive_portal_result());
2618 ASSERT_EQ(CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL
,
2619 GetStateOfTabReloaderAt(browser(), 0));
2620 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
,
2621 GetStateOfTabReloaderAt(browser(), 1));
2622 ASSERT_TRUE(IsLoginTab(browser()->tab_strip_model()->GetWebContentsAt(1)));
2624 ASSERT_EQ(2, tab_strip_model
->count());
2625 EXPECT_EQ(1, tab_strip_model
->active_index());
2626 EXPECT_EQ(1, navigation_observer
.NumNavigationsForTab(
2627 tab_strip_model
->GetWebContentsAt(1)));
2628 EXPECT_EQ(1, NumLoadingTabs());
2630 SetSlowSSLLoadTime(tab_reloader
, base::TimeDelta::FromDays(1));
2631 Login(browser(), 1, 0);
2632 FailLoadsAfterLogin(browser(), 1);
2635 // Checks that reloading a timeout triggers captive portal detection.
2636 // Much like the last test, though the captive portal is disabled before
2637 // the inital navigation, rather than captive portal detection.
2638 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest
, ReloadTimeout
) {
2639 factory_
.SetBehindCaptivePortal(false);
2641 // Do the first navigation while not behind a captive portal.
2642 TabStripModel
* tab_strip_model
= browser()->tab_strip_model();
2643 CaptivePortalObserver
portal_observer(browser()->profile());
2644 ui_test_utils::NavigateToURL(browser(), GURL(kMockHttpsUrl
));
2645 ASSERT_EQ(0, portal_observer
.num_results_received());
2646 ASSERT_EQ(1, tab_strip_model
->count());
2648 // A captive portal spontaneously appears.
2649 factory_
.SetBehindCaptivePortal(true);
2651 CaptivePortalTabReloader
* tab_reloader
=
2652 GetTabReloader(tab_strip_model
->GetActiveWebContents());
2653 ASSERT_TRUE(tab_reloader
);
2654 SetSlowSSLLoadTime(tab_reloader
, base::TimeDelta());
2656 MultiNavigationObserver navigation_observer
;
2657 tab_strip_model
->GetActiveWebContents()->GetController().Reload(true);
2659 // Wait for the check triggered by the broken tab and for the login tab to
2661 portal_observer
.WaitForResults(1);
2662 navigation_observer
.WaitForNavigations(1);
2663 // Make sure the request has been issued.
2664 URLRequestTimeoutOnDemandJob::WaitForJobs(1);
2666 ASSERT_EQ(1, portal_observer
.num_results_received());
2667 ASSERT_FALSE(CheckPending(browser()));
2668 ASSERT_EQ(captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL
,
2669 portal_observer
.captive_portal_result());
2671 ASSERT_EQ(CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL
,
2672 GetStateOfTabReloaderAt(browser(), 0));
2673 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
,
2674 GetStateOfTabReloaderAt(browser(), 1));
2675 ASSERT_TRUE(IsLoginTab(tab_strip_model
->GetWebContentsAt(1)));
2677 ASSERT_EQ(2, tab_strip_model
->count());
2678 EXPECT_EQ(1, tab_strip_model
->active_index());
2679 EXPECT_EQ(1, navigation_observer
.NumNavigationsForTab(
2680 tab_strip_model
->GetWebContentsAt(1)));
2681 EXPECT_EQ(1, NumLoadingTabs());
2683 SetSlowSSLLoadTime(tab_reloader
, base::TimeDelta::FromDays(1));
2684 Login(browser(), 1, 0);
2685 FailLoadsAfterLogin(browser(), 1);
2688 // Checks the case where there are two windows, and there's an SSL timeout in
2689 // the background one.
2690 // Disabled: http://crbug.com/134357
2691 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest
, DISABLED_TwoWindows
) {
2693 new Browser(Browser::CreateParams(browser()->profile(),
2694 browser()->host_desktop_type()));
2695 // Navigate the new browser window so it'll be shown and we can pick the
2697 ui_test_utils::NavigateToURL(browser2
, GURL(url::kAboutBlankURL
));
2699 // Generally, |browser2| will be the active window. However, if the
2700 // original browser window lost focus before creating the new one, such as
2701 // when running multiple tests at once, the original browser window may
2702 // remain the profile's active window.
2703 Browser
* active_browser
=
2704 chrome::FindTabbedBrowser(browser()->profile(), true,
2705 browser()->host_desktop_type());
2706 Browser
* inactive_browser
;
2707 if (active_browser
== browser2
) {
2708 // When only one test is running at a time, the new browser will probably be
2709 // on top, but when multiple tests are running at once, this is not
2711 inactive_browser
= browser();
2713 ASSERT_EQ(active_browser
, browser());
2714 inactive_browser
= browser2
;
2717 CaptivePortalObserver
portal_observer(browser()->profile());
2718 MultiNavigationObserver navigation_observer
;
2720 // Navigate the tab in the inactive browser to an SSL timeout. Have to use
2721 // chrome::NavigateParams and NEW_BACKGROUND_TAB to avoid activating the
2723 chrome::NavigateParams
params(inactive_browser
,
2724 GURL(kMockHttpsQuickTimeoutUrl
),
2725 ui::PAGE_TRANSITION_TYPED
);
2726 params
.disposition
= NEW_BACKGROUND_TAB
;
2727 params
.window_action
= chrome::NavigateParams::NO_ACTION
;
2728 ui_test_utils::NavigateToURL(¶ms
);
2729 navigation_observer
.WaitForNavigations(2);
2731 // Make sure the active window hasn't changed, and its new tab is
2733 ASSERT_EQ(active_browser
,
2734 chrome::FindTabbedBrowser(browser()->profile(), true,
2735 browser()->host_desktop_type()));
2736 ASSERT_EQ(1, active_browser
->tab_strip_model()->active_index());
2738 // Check that the only two navigated tabs were the new error tab in the
2739 // backround windows, and the login tab in the active window.
2740 EXPECT_EQ(1, navigation_observer
.NumNavigationsForTab(
2741 inactive_browser
->tab_strip_model()->GetWebContentsAt(1)));
2742 EXPECT_EQ(1, navigation_observer
.NumNavigationsForTab(
2743 active_browser
->tab_strip_model()->GetWebContentsAt(1)));
2744 EXPECT_EQ(0, NumLoadingTabs());
2746 // Check captive portal test results.
2747 portal_observer
.WaitForResults(1);
2748 ASSERT_EQ(captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL
,
2749 portal_observer
.captive_portal_result());
2750 EXPECT_EQ(1, portal_observer
.num_results_received());
2752 // Check the inactive browser.
2753 EXPECT_EQ(2, inactive_browser
->tab_strip_model()->count());
2754 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
,
2755 GetStateOfTabReloaderAt(inactive_browser
, 0));
2756 EXPECT_EQ(CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL
,
2757 GetStateOfTabReloaderAt(inactive_browser
, 1));
2759 // Check the active browser.
2760 ASSERT_EQ(2, active_browser
->tab_strip_model()->count());
2761 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
,
2762 GetStateOfTabReloaderAt(active_browser
, 0));
2763 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
,
2764 GetStateOfTabReloaderAt(active_browser
, 1));
2766 IsLoginTab(active_browser
->tab_strip_model()->GetWebContentsAt(1)));
2768 // Simulate logging in.
2769 Login(active_browser
, 0, 1);
2772 // An HTTP page redirects to an HTTPS page loads slowly before timing out. A
2773 // captive portal is found, and then the user logs in before the original page
2775 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest
, HttpToHttpsRedirectLogin
) {
2776 ASSERT_TRUE(test_server()->Start());
2777 SlowLoadBehindCaptivePortal(
2780 test_server()->GetURL(CreateServerRedirect(kMockHttpsUrl
)),
2783 Login(browser(), 1, 0);
2784 FailLoadsAfterLogin(browser(), 1);
2787 // An HTTPS page redirects to an HTTP page.
2788 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest
, HttpsToHttpRedirect
) {
2789 // Use an HTTPS server for the top level page.
2790 net::SpawnedTestServer
https_server(
2791 net::SpawnedTestServer::TYPE_HTTPS
, net::SpawnedTestServer::kLocalhost
,
2792 base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
2793 ASSERT_TRUE(https_server
.Start());
2795 GURL http_timeout_url
=
2796 URLRequestFailedJob::GetMockHttpUrl(net::ERR_CONNECTION_TIMED_OUT
);
2798 // 2 navigations due to the Link Doctor.
2799 NavigateToPageExpectNoTest(
2801 https_server
.GetURL(CreateServerRedirect(http_timeout_url
.spec())),
2805 // Tests the 511 response code, along with an HTML redirect to a login page.
2806 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest
, Status511
) {
2807 SetUpCaptivePortalService(browser()->profile(),
2808 GURL(kMockCaptivePortal511Url
));
2809 SlowLoadBehindCaptivePortal(browser(), true, GURL(kMockHttpsUrl
), 2, 2);
2810 Login(browser(), 1, 0);
2811 FailLoadsAfterLogin(browser(), 1);
2814 // HSTS redirects an HTTP request to HTTPS, and the request then times out.
2815 // A captive portal is then detected, and a login tab opened, before logging
2817 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest
, HstsLogin
) {
2818 GURL::Replacements replacements
;
2819 replacements
.SetSchemeStr("http");
2820 GURL http_timeout_url
= GURL(kMockHttpsUrl
).ReplaceComponents(replacements
);
2822 URLRequestFailedJob::GetMockHttpUrl(net::ERR_CONNECTION_TIMED_OUT
);
2823 content::BrowserThread::PostTask(
2824 content::BrowserThread::IO
, FROM_HERE
,
2825 base::Bind(&AddHstsHost
,
2826 make_scoped_refptr(browser()->profile()->GetRequestContext()),
2827 http_timeout_url
.host()));
2829 SlowLoadBehindCaptivePortal(browser(), true, http_timeout_url
, 1, 1);
2830 Login(browser(), 1, 0);
2831 FailLoadsAfterLogin(browser(), 1);
2834 // A slow SSL load starts. The reloader triggers a captive portal check, finds a
2835 // captive portal. The SSL commits with a cert error, triggering another captive
2837 // The second check finds no captive portal. The reloader triggers a reload at
2838 // the same time SSL error handler tries to show an interstitial. Should result
2839 // in an SSL interstitial.
2840 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest
,
2841 InterstitialTimerCertErrorAfterSlowLoad
) {
2842 // Use a url that triggers a slow load, instead of creating an https server.
2843 GURL cert_error_url
= GURL(kMockHttpsUrl
);
2845 TabStripModel
* tab_strip_model
= browser()->tab_strip_model();
2846 int broken_tab_index
= tab_strip_model
->active_index();
2847 WebContents
* broken_tab_contents
= tab_strip_model
->GetActiveWebContents();
2848 SlowLoadBehindCaptivePortal(browser(), true, cert_error_url
, 1, 1);
2850 // No longer behind a captive portal. Committing the SSL page should trigger
2851 // an SSL interstitial which triggers a new captive portal check. Since there
2852 // is no captive portal anymore, should end up with an SSL interstitial.
2853 factory_
.SetBehindCaptivePortal(false);
2855 CaptivePortalObserver
portal_observer(browser()->profile());
2856 MultiNavigationObserver navigation_observer
;
2857 URLRequestTimeoutOnDemandJob::FailJobsWithCertError(1);
2858 navigation_observer
.WaitForNavigations(1);
2860 EXPECT_EQ(CaptivePortalTabReloader::STATE_NEEDS_RELOAD
,
2861 GetStateOfTabReloaderAt(browser(), broken_tab_index
));
2863 WaitForInterstitialAttach(broken_tab_contents
);
2864 portal_observer
.WaitForResults(1);
2866 EXPECT_EQ(SSLBlockingPage::kTypeForTesting
,
2867 GetInterstitialType(broken_tab_contents
));