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/base/test_data_directory.h"
58 #include "net/cert/x509_certificate.h"
59 #include "net/http/transport_security_state.h"
60 #include "net/test/cert_test_util.h"
61 #include "net/test/url_request/url_request_failed_job.h"
62 #include "net/test/url_request/url_request_mock_http_job.h"
63 #include "net/url_request/url_request.h"
64 #include "net/url_request/url_request_context.h"
65 #include "net/url_request/url_request_context_getter.h"
66 #include "net/url_request/url_request_filter.h"
67 #include "net/url_request/url_request_interceptor.h"
68 #include "net/url_request/url_request_job.h"
69 #include "net/url_request/url_request_status.h"
70 #include "testing/gtest/include/gtest/gtest.h"
72 using captive_portal::CaptivePortalResult
;
73 using content::BrowserThread
;
74 using content::WebContents
;
75 using net::URLRequestFailedJob
;
76 using net::URLRequestMockHTTPJob
;
80 // Path of the fake login page, when using the TestServer.
81 const char* const kTestServerLoginPath
= "files/captive_portal/login.html";
83 // Path of a page with an iframe that has a mock SSL timeout, when using the
85 const char* const kTestServerIframeTimeoutPath
=
86 "files/captive_portal/iframe_timeout.html";
88 // The following URLs each have two different behaviors, depending on whether
89 // URLRequestMockCaptivePortalJobFactory is currently simulating the presence
90 // of a captive portal or not. They use different domains so that HSTS can be
91 // applied to them independently.
93 // A mock URL for the CaptivePortalService's |test_url|. When behind a captive
94 // portal, this URL returns a mock login page. When connected to the Internet,
95 // it returns a 204 response. Uses the name of the login file so that reloading
96 // it will not request a different URL.
97 const char* const kMockCaptivePortalTestUrl
=
98 "http://mock.captive.portal.test/login.html";
100 // Another mock URL for the CaptivePortalService's |test_url|. When behind a
101 // captive portal, this URL returns a 511 status code and an HTML page that
102 // redirect to the above URL. When connected to the Internet, it returns a 204
104 const char* const kMockCaptivePortal511Url
=
105 "http://mock.captive.portal.511/page511.html";
107 // When behind a captive portal, this URL hangs without committing until a call
108 // to URLRequestTimeoutOnDemandJob::FailJobs. When that function is called,
109 // the request will time out.
111 // When connected to the Internet, this URL returns a non-error page.
112 const char* const kMockHttpsUrl
=
113 "https://mock.captive.portal.long.timeout/title2.html";
115 // Same as above, but different domain, so can be used to trigger cross-site
117 const char* const kMockHttpsUrl2
=
118 "https://mock.captive.portal.long.timeout2/title2.html";
120 // Same as kMockHttpsUrl, except the timeout happens instantly.
121 const char* const kMockHttpsQuickTimeoutUrl
=
122 "https://mock.captive.portal.quick.timeout/title2.html";
124 // Expected title of a tab once an HTTPS load completes, when not behind a
126 const char* const kInternetConnectedTitle
= "Title Of Awesomeness";
128 // A URL request job that hangs until FailJobs() is called. Started jobs
129 // are stored in a static class variable containing a linked list so that
130 // FailJobs() can locate them.
131 class URLRequestTimeoutOnDemandJob
: public net::URLRequestJob
,
132 public base::NonThreadSafe
{
134 // net::URLRequestJob:
135 void Start() override
;
137 // All the public static methods below can be called on any thread.
139 // Waits for exactly |num_jobs|.
140 static void WaitForJobs(int num_jobs
);
142 // Fails all active URLRequestTimeoutOnDemandJobs with connection timeouts.
143 // There are expected to be exactly |expected_num_jobs| waiting for
144 // failure. The only way to guarantee this is with an earlier call to
145 // WaitForJobs, so makes sure there has been a matching WaitForJobs call.
146 static void FailJobs(int expected_num_jobs
);
148 // Fails all active URLRequestTimeoutOnDemandJobs with SSL cert errors.
149 // |expected_num_jobs| behaves just as in FailJobs.
150 static void FailJobsWithCertError(int expected_num_jobs
,
151 const net::SSLInfo
& ssl_info
);
153 // Abandon all active URLRequestTimeoutOnDemandJobs. |expected_num_jobs|
154 // behaves just as in FailJobs.
155 static void AbandonJobs(int expected_num_jobs
);
158 friend class URLRequestMockCaptivePortalJobFactory
;
160 // Operation to perform on jobs when removing them from |job_list_|.
161 enum EndJobOperation
{
164 FAIL_JOBS_WITH_CERT_ERROR
167 URLRequestTimeoutOnDemandJob(net::URLRequest
* request
,
168 net::NetworkDelegate
* network_delegate
);
169 ~URLRequestTimeoutOnDemandJob() override
;
171 // Attempts to removes |this| from |jobs_|. Returns true if it was removed
173 bool RemoveFromList();
175 static void WaitForJobsOnIOThread(int num_jobs
);
176 static void FailOrAbandonJobsOnIOThread(int expected_num_jobs
,
177 EndJobOperation end_job_operation
,
178 const net::SSLInfo
& ssl_info
);
180 // Checks if there are at least |num_jobs_to_wait_for_| jobs in
181 // |job_list_|. If so, exits the message loop on the UI thread, which
182 // should be spinning in a call to WaitForJobs. Does nothing when
183 // |num_jobs_to_wait_for_| is 0.
184 static void MaybeStopWaitingForJobsOnIOThread();
186 // All class variables are only accessed on the IO thread.
188 // Number of jobs currently being waited for, or 0 if not currently
190 static int num_jobs_to_wait_for_
;
192 // The last number of jobs that were waited for. When FailJobs or
193 // AbandonJobs is called, this should match |expected_num_jobs|.
194 static int last_num_jobs_to_wait_for_
;
196 // Number of jobs that have been started, but not yet waited for. If jobs
197 // are deleted unexpectedly, they're still included in this count, even though
198 // they've been removed from |job_list_|. Intended to reduce chance of stalls
200 static int num_jobs_started_
;
202 // Head of linked list of jobs that have been started and are now waiting to
204 static URLRequestTimeoutOnDemandJob
* job_list_
;
206 // The next job that had been started but not yet timed out.
207 URLRequestTimeoutOnDemandJob
* next_job_
;
209 DISALLOW_COPY_AND_ASSIGN(URLRequestTimeoutOnDemandJob
);
212 int URLRequestTimeoutOnDemandJob::num_jobs_to_wait_for_
= 0;
213 int URLRequestTimeoutOnDemandJob::last_num_jobs_to_wait_for_
= 0;
214 int URLRequestTimeoutOnDemandJob::num_jobs_started_
= 0;
215 URLRequestTimeoutOnDemandJob
* URLRequestTimeoutOnDemandJob::job_list_
= NULL
;
217 void URLRequestTimeoutOnDemandJob::Start() {
218 EXPECT_TRUE(CalledOnValidThread());
220 // Insert at start of the list.
221 next_job_
= job_list_
;
225 // Checks if there are at least |num_jobs_to_wait_for_| jobs in
226 // |job_list_|. If so, exits the message loop on the UI thread, which
227 // should be spinning in a call to WaitForJobs. Does nothing if
228 // |num_jobs_to_wait_for_| is 0.
229 MaybeStopWaitingForJobsOnIOThread();
233 void URLRequestTimeoutOnDemandJob::WaitForJobs(int num_jobs
) {
234 content::BrowserThread::PostTask(
235 content::BrowserThread::IO
, FROM_HERE
,
236 base::Bind(&URLRequestTimeoutOnDemandJob::WaitForJobsOnIOThread
,
238 content::RunMessageLoop();
242 void URLRequestTimeoutOnDemandJob::FailJobs(int expected_num_jobs
) {
243 content::BrowserThread::PostTask(
244 content::BrowserThread::IO
, FROM_HERE
,
245 base::Bind(&URLRequestTimeoutOnDemandJob::FailOrAbandonJobsOnIOThread
,
246 expected_num_jobs
, FAIL_JOBS
, net::SSLInfo()));
250 void URLRequestTimeoutOnDemandJob::FailJobsWithCertError(
251 int expected_num_jobs
,
252 const net::SSLInfo
& ssl_info
) {
253 content::BrowserThread::PostTask(
254 content::BrowserThread::IO
, FROM_HERE
,
255 base::Bind(&URLRequestTimeoutOnDemandJob::FailOrAbandonJobsOnIOThread
,
256 expected_num_jobs
, FAIL_JOBS_WITH_CERT_ERROR
, ssl_info
));
260 void URLRequestTimeoutOnDemandJob::AbandonJobs(int expected_num_jobs
) {
261 content::BrowserThread::PostTask(
262 content::BrowserThread::IO
, FROM_HERE
,
263 base::Bind(&URLRequestTimeoutOnDemandJob::FailOrAbandonJobsOnIOThread
,
264 expected_num_jobs
, ABANDON_JOBS
, net::SSLInfo()));
267 URLRequestTimeoutOnDemandJob::URLRequestTimeoutOnDemandJob(
268 net::URLRequest
* request
, net::NetworkDelegate
* network_delegate
)
269 : net::URLRequestJob(request
, network_delegate
),
273 URLRequestTimeoutOnDemandJob::~URLRequestTimeoutOnDemandJob() {
274 // All hanging jobs should have failed or been abandoned before being
276 EXPECT_FALSE(RemoveFromList());
279 bool URLRequestTimeoutOnDemandJob::RemoveFromList() {
280 URLRequestTimeoutOnDemandJob
** job
= &job_list_
;
290 // If the job wasn't in this list, |next_job_| should be NULL.
291 EXPECT_FALSE(next_job_
);
296 void URLRequestTimeoutOnDemandJob::WaitForJobsOnIOThread(int num_jobs
) {
297 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO
));
298 ASSERT_EQ(0, num_jobs_to_wait_for_
);
299 ASSERT_LT(0, num_jobs
);
300 // Number of tabs being waited on should be strictly increasing.
301 ASSERT_LE(last_num_jobs_to_wait_for_
, num_jobs
);
303 num_jobs_to_wait_for_
= num_jobs
;
304 MaybeStopWaitingForJobsOnIOThread();
308 void URLRequestTimeoutOnDemandJob::MaybeStopWaitingForJobsOnIOThread() {
309 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO
));
310 if (num_jobs_to_wait_for_
== 0)
313 // There shouldn't be any extra jobs.
314 EXPECT_LE(num_jobs_started_
, num_jobs_to_wait_for_
);
316 // Should never be greater, but if it is, go ahead and exit the message loop
317 // to try and avoid hanging.
318 if (num_jobs_started_
>= num_jobs_to_wait_for_
) {
319 last_num_jobs_to_wait_for_
= num_jobs_to_wait_for_
;
320 num_jobs_to_wait_for_
= 0;
321 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
322 base::MessageLoop::QuitClosure());
327 void URLRequestTimeoutOnDemandJob::FailOrAbandonJobsOnIOThread(
328 int expected_num_jobs
,
329 EndJobOperation end_job_operation
,
330 const net::SSLInfo
& ssl_info
) {
331 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO
));
332 ASSERT_LT(0, expected_num_jobs
);
333 EXPECT_EQ(last_num_jobs_to_wait_for_
, expected_num_jobs
);
334 last_num_jobs_to_wait_for_
= 0;
339 URLRequestTimeoutOnDemandJob
* job
= job_list_
;
340 // Since the error notification may result in the job's destruction, remove
341 // it from the job list before the error.
342 EXPECT_TRUE(job
->RemoveFromList());
343 if (end_job_operation
== FAIL_JOBS
) {
344 job
->NotifyStartError(net::URLRequestStatus(
345 net::URLRequestStatus::FAILED
,
346 net::ERR_CONNECTION_TIMED_OUT
));
347 } else if (end_job_operation
== FAIL_JOBS_WITH_CERT_ERROR
) {
348 DCHECK(job
->request()->url().SchemeIsCryptographic());
349 job
->NotifySSLCertificateError(ssl_info
, true);
353 EXPECT_EQ(expected_num_jobs
, num_jobs_started_
);
354 EXPECT_EQ(expected_num_jobs
, num_jobs
);
356 num_jobs_started_
-= expected_num_jobs
;
359 // URLRequestCaptivePortalJobFactory emulates captive portal behavior.
360 // Initially, it emulates being behind a captive portal. When
361 // SetBehindCaptivePortal(false) is called, it emulates behavior when not behind
362 // a captive portal. The class itself is never instantiated.
364 // It handles requests for kMockCaptivePortalTestUrl, kMockHttpsUrl, and
365 // kMockHttpsQuickTimeoutUrl.
366 class URLRequestMockCaptivePortalJobFactory
{
368 URLRequestMockCaptivePortalJobFactory() : behind_captive_portal_(true) {}
369 virtual ~URLRequestMockCaptivePortalJobFactory() {}
371 // Adds the testing URLs to the net::URLRequestFilter. Should only be called
373 void AddUrlHandlers();
375 // Sets whether or not there is a captive portal. Outstanding requests are
377 void SetBehindCaptivePortal(bool behind_captive_portal
);
380 class Interceptor
: public net::URLRequestInterceptor
{
382 explicit Interceptor(bool behind_captive_portal
)
383 : behind_captive_portal_(behind_captive_portal
) {}
384 ~Interceptor() override
{}
386 // Returns a URLRequestJob that reflects the current captive portal state
387 // for the URLs: kMockCaptivePortalTestUrl, kMockHttpsUrl, and
388 // kMockHttpsQuickTimeoutUrl. See documentation of individual URLs for
390 net::URLRequestJob
* MaybeInterceptRequest(
391 net::URLRequest
* request
,
392 net::NetworkDelegate
* network_delegate
) const override
;
394 void SetBehindCaptivePortal(bool behind_captive_portal
) {
395 behind_captive_portal_
= behind_captive_portal
;
399 bool behind_captive_portal_
;
401 DISALLOW_COPY_AND_ASSIGN(Interceptor
);
404 // These do all the work of the corresponding public functions, with the only
405 // difference being that they must be called on the IO thread.
406 void AddUrlHandlersOnIOThread();
407 void SetBehindCaptivePortalOnIOThread(bool behind_captive_portal
);
409 // Create a new Interceptor and add it to |interceptors_|, though it returns
411 scoped_ptr
<net::URLRequestInterceptor
> CreateInterceptor();
413 // These variables are only accessed on IO thread, though
414 // URLRequestMockCaptivePortalJobFactory is created and
415 // destroyed on the UI thread.
416 // The Interceptors are owned by URLRequestFilter and live on the IO thread;
417 // these are just references.
418 std::vector
<Interceptor
*> interceptors_
;
419 bool behind_captive_portal_
;
421 DISALLOW_COPY_AND_ASSIGN(URLRequestMockCaptivePortalJobFactory
);
424 void URLRequestMockCaptivePortalJobFactory::AddUrlHandlers() {
425 content::BrowserThread::PostTask(
426 content::BrowserThread::IO
, FROM_HERE
,
428 &URLRequestMockCaptivePortalJobFactory::AddUrlHandlersOnIOThread
,
429 base::Unretained(this)));
432 void URLRequestMockCaptivePortalJobFactory::SetBehindCaptivePortal(
433 bool behind_captive_portal
) {
434 content::BrowserThread::PostTask(
435 content::BrowserThread::IO
, FROM_HERE
,
436 base::Bind(&URLRequestMockCaptivePortalJobFactory::
437 SetBehindCaptivePortalOnIOThread
,
438 base::Unretained(this), behind_captive_portal
));
441 scoped_ptr
<net::URLRequestInterceptor
>
442 URLRequestMockCaptivePortalJobFactory::CreateInterceptor() {
443 EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO
));
444 scoped_ptr
<Interceptor
> interceptor(new Interceptor(behind_captive_portal_
));
445 interceptors_
.push_back(interceptor
.get());
446 return interceptor
.Pass();
449 void URLRequestMockCaptivePortalJobFactory::AddUrlHandlersOnIOThread() {
450 EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO
));
452 // Handle only exact matches, so any related requests, such as those for
453 // favicons, are not handled by the factory.
454 net::URLRequestFilter
* filter
= net::URLRequestFilter::GetInstance();
455 filter
->AddUrlInterceptor(GURL(kMockCaptivePortalTestUrl
),
456 CreateInterceptor());
457 filter
->AddUrlInterceptor(GURL(kMockCaptivePortal511Url
),
458 CreateInterceptor());
459 filter
->AddUrlInterceptor(GURL(kMockHttpsUrl
), CreateInterceptor());
460 filter
->AddUrlInterceptor(GURL(kMockHttpsUrl2
), CreateInterceptor());
461 filter
->AddUrlInterceptor(GURL(kMockHttpsQuickTimeoutUrl
),
462 CreateInterceptor());
465 void URLRequestMockCaptivePortalJobFactory::SetBehindCaptivePortalOnIOThread(
466 bool behind_captive_portal
) {
467 EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO
));
468 behind_captive_portal_
= behind_captive_portal
;
469 for (auto* interceptor
: interceptors_
)
470 interceptor
->SetBehindCaptivePortal(behind_captive_portal
);
474 URLRequestMockCaptivePortalJobFactory::Interceptor::MaybeInterceptRequest(
475 net::URLRequest
* request
,
476 net::NetworkDelegate
* network_delegate
) const {
477 EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO
));
479 // The PathService is threadsafe.
480 base::FilePath root_http
;
481 PathService::Get(chrome::DIR_TEST_DATA
, &root_http
);
483 if (request
->url() == GURL(kMockHttpsUrl
) ||
484 request
->url() == GURL(kMockHttpsUrl2
)) {
485 if (behind_captive_portal_
)
486 return new URLRequestTimeoutOnDemandJob(request
, network_delegate
);
487 // Once logged in to the portal, HTTPS requests return the page that was
488 // actually requested.
489 return new URLRequestMockHTTPJob(
492 root_http
.Append(FILE_PATH_LITERAL("title2.html")),
493 BrowserThread::GetBlockingPool()->GetTaskRunnerWithShutdownBehavior(
494 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN
));
495 } else if (request
->url() == GURL(kMockHttpsQuickTimeoutUrl
)) {
496 if (behind_captive_portal_
)
497 return new URLRequestFailedJob(
498 request
, network_delegate
, net::ERR_CONNECTION_TIMED_OUT
);
499 // Once logged in to the portal, HTTPS requests return the page that was
500 // actually requested.
501 return new URLRequestMockHTTPJob(
504 root_http
.Append(FILE_PATH_LITERAL("title2.html")),
505 BrowserThread::GetBlockingPool()->GetTaskRunnerWithShutdownBehavior(
506 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN
));
508 // The URL should be the captive portal test URL.
509 EXPECT_TRUE(GURL(kMockCaptivePortalTestUrl
) == request
->url() ||
510 GURL(kMockCaptivePortal511Url
) == request
->url());
512 if (behind_captive_portal_
) {
513 // Prior to logging in to the portal, the HTTP test URLs are intercepted
514 // by the captive portal.
515 if (GURL(kMockCaptivePortal511Url
) == request
->url()) {
516 return new URLRequestMockHTTPJob(
519 root_http
.Append(FILE_PATH_LITERAL("captive_portal/page511.html")),
520 BrowserThread::GetBlockingPool()->GetTaskRunnerWithShutdownBehavior(
521 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN
));
523 return new URLRequestMockHTTPJob(
526 root_http
.Append(FILE_PATH_LITERAL("captive_portal/login.html")),
527 BrowserThread::GetBlockingPool()->GetTaskRunnerWithShutdownBehavior(
528 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN
));
531 // After logging in to the portal, the test URLs return a 204 response.
532 return new URLRequestMockHTTPJob(
535 root_http
.Append(FILE_PATH_LITERAL("captive_portal/page204.html")),
536 BrowserThread::GetBlockingPool()->GetTaskRunnerWithShutdownBehavior(
537 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN
));
541 // Creates a server-side redirect for use with the TestServer.
542 std::string
CreateServerRedirect(const std::string
& dest_url
) {
543 const char* const kServerRedirectBase
= "server-redirect?";
544 return kServerRedirectBase
+ dest_url
;
547 // Returns the total number of loading tabs across all Browsers, for all
549 int NumLoadingTabs() {
550 int num_loading_tabs
= 0;
551 for (TabContentsIterator it
; !it
.done(); it
.Next()) {
555 return num_loading_tabs
;
558 bool IsLoginTab(WebContents
* web_contents
) {
559 return CaptivePortalTabHelper::FromWebContents(web_contents
)->IsLoginTab();
562 // Tracks how many times each tab has been navigated since the Observer was
563 // created. The standard TestNavigationObserver can only watch specific
564 // pre-existing tabs or loads in serial for all tabs.
565 class MultiNavigationObserver
: public content::NotificationObserver
{
567 MultiNavigationObserver();
568 ~MultiNavigationObserver() override
;
570 // Waits for exactly |num_navigations_to_wait_for| LOAD_STOP
571 // notifications to have occurred since the construction of |this|. More
572 // navigations than expected occuring will trigger a expect failure.
573 void WaitForNavigations(int num_navigations_to_wait_for
);
575 // Returns the number of LOAD_STOP events that have occurred for
576 // |web_contents| since this was constructed.
577 int NumNavigationsForTab(WebContents
* web_contents
) const;
579 // The number of LOAD_STOP events since |this| was created.
580 int num_navigations() const { return num_navigations_
; }
583 typedef std::map
<const WebContents
*, int> TabNavigationMap
;
585 // content::NotificationObserver:
586 void Observe(int type
,
587 const content::NotificationSource
& source
,
588 const content::NotificationDetails
& details
) override
;
590 int num_navigations_
;
592 // Map of how many times each tab has navigated since |this| was created.
593 TabNavigationMap tab_navigation_map_
;
595 // Total number of navigations to wait for. Value only matters when
596 // |waiting_for_navigation_| is true.
597 int num_navigations_to_wait_for_
;
599 // True if WaitForNavigations has been called, until
600 // |num_navigations_to_wait_for_| have been observed.
601 bool waiting_for_navigation_
;
603 content::NotificationRegistrar registrar_
;
605 DISALLOW_COPY_AND_ASSIGN(MultiNavigationObserver
);
608 MultiNavigationObserver::MultiNavigationObserver()
609 : num_navigations_(0),
610 num_navigations_to_wait_for_(0),
611 waiting_for_navigation_(false) {
612 registrar_
.Add(this, content::NOTIFICATION_LOAD_STOP
,
613 content::NotificationService::AllSources());
616 MultiNavigationObserver::~MultiNavigationObserver() {
619 void MultiNavigationObserver::WaitForNavigations(
620 int num_navigations_to_wait_for
) {
621 // Shouldn't already be waiting for navigations.
622 EXPECT_FALSE(waiting_for_navigation_
);
623 EXPECT_LT(0, num_navigations_to_wait_for
);
624 if (num_navigations_
< num_navigations_to_wait_for
) {
625 num_navigations_to_wait_for_
= num_navigations_to_wait_for
;
626 waiting_for_navigation_
= true;
627 content::RunMessageLoop();
628 EXPECT_FALSE(waiting_for_navigation_
);
630 EXPECT_EQ(num_navigations_
, num_navigations_to_wait_for
);
633 int MultiNavigationObserver::NumNavigationsForTab(
634 WebContents
* web_contents
) const {
635 TabNavigationMap::const_iterator tab_navigations
=
636 tab_navigation_map_
.find(web_contents
);
637 if (tab_navigations
== tab_navigation_map_
.end())
639 return tab_navigations
->second
;
642 void MultiNavigationObserver::Observe(
644 const content::NotificationSource
& source
,
645 const content::NotificationDetails
& details
) {
646 ASSERT_EQ(type
, content::NOTIFICATION_LOAD_STOP
);
647 content::NavigationController
* controller
=
648 content::Source
<content::NavigationController
>(source
).ptr();
650 ++tab_navigation_map_
[controller
->GetWebContents()];
651 if (waiting_for_navigation_
&&
652 num_navigations_to_wait_for_
== num_navigations_
) {
653 waiting_for_navigation_
= false;
654 base::MessageLoopForUI::current()->Quit();
658 // This observer creates a list of loading tabs, and then waits for them all
659 // to stop loading and have the kInternetConnectedTitle.
661 // This is for the specific purpose of observing tabs time out after logging in
662 // to a captive portal, which will then cause them to reload.
663 // MultiNavigationObserver is insufficient for this because there may or may not
664 // be a LOAD_STOP event between the timeout and the reload.
665 // See bug http://crbug.com/133227
666 class FailLoadsAfterLoginObserver
: public content::NotificationObserver
{
668 FailLoadsAfterLoginObserver();
669 ~FailLoadsAfterLoginObserver() override
;
671 void WaitForNavigations();
674 typedef std::set
<const WebContents
*> TabSet
;
676 // content::NotificationObserver:
677 void Observe(int type
,
678 const content::NotificationSource
& source
,
679 const content::NotificationDetails
& details
) override
;
681 // The set of tabs that need to be navigated. This is the set of loading
682 // tabs when the observer is created.
683 TabSet tabs_needing_navigation_
;
685 // Number of tabs that have stopped navigating with the expected title. These
686 // are expected not to be navigated again.
687 TabSet tabs_navigated_to_final_destination_
;
689 // True if WaitForNavigations has been called, until
690 // |tabs_navigated_to_final_destination_| equals |tabs_needing_navigation_|.
691 bool waiting_for_navigation_
;
693 content::NotificationRegistrar registrar_
;
695 DISALLOW_COPY_AND_ASSIGN(FailLoadsAfterLoginObserver
);
698 FailLoadsAfterLoginObserver::FailLoadsAfterLoginObserver()
699 : waiting_for_navigation_(false) {
700 registrar_
.Add(this, content::NOTIFICATION_LOAD_STOP
,
701 content::NotificationService::AllSources());
702 for (TabContentsIterator it
; !it
.done(); it
.Next()) {
704 tabs_needing_navigation_
.insert(*it
);
708 FailLoadsAfterLoginObserver::~FailLoadsAfterLoginObserver() {
711 void FailLoadsAfterLoginObserver::WaitForNavigations() {
712 // Shouldn't already be waiting for navigations.
713 EXPECT_FALSE(waiting_for_navigation_
);
714 if (tabs_needing_navigation_
.size() !=
715 tabs_navigated_to_final_destination_
.size()) {
716 waiting_for_navigation_
= true;
717 content::RunMessageLoop();
718 EXPECT_FALSE(waiting_for_navigation_
);
720 EXPECT_EQ(tabs_needing_navigation_
.size(),
721 tabs_navigated_to_final_destination_
.size());
724 void FailLoadsAfterLoginObserver::Observe(
726 const content::NotificationSource
& source
,
727 const content::NotificationDetails
& details
) {
728 ASSERT_EQ(type
, content::NOTIFICATION_LOAD_STOP
);
729 content::NavigationController
* controller
=
730 content::Source
<content::NavigationController
>(source
).ptr();
731 WebContents
* contents
= controller
->GetWebContents();
733 ASSERT_EQ(1u, tabs_needing_navigation_
.count(contents
));
734 ASSERT_EQ(0u, tabs_navigated_to_final_destination_
.count(contents
));
736 if (contents
->GetTitle() != base::ASCIIToUTF16(kInternetConnectedTitle
))
738 tabs_navigated_to_final_destination_
.insert(contents
);
740 if (waiting_for_navigation_
&&
741 tabs_needing_navigation_
.size() ==
742 tabs_navigated_to_final_destination_
.size()) {
743 waiting_for_navigation_
= false;
744 base::MessageLoopForUI::current()->Quit();
748 // An observer for watching the CaptivePortalService. It tracks the last
749 // received result and the total number of received results.
750 class CaptivePortalObserver
: public content::NotificationObserver
{
752 explicit CaptivePortalObserver(Profile
* profile
);
754 // Runs the message loop until exactly |update_count| captive portal
755 // results have been received, since the creation of |this|. Expects no
756 // additional captive portal results.
757 void WaitForResults(int num_results_to_wait_for
);
759 int num_results_received() const { return num_results_received_
; }
761 CaptivePortalResult
captive_portal_result() const {
762 return captive_portal_result_
;
766 // Records results and exits the message loop, if needed.
767 void Observe(int type
,
768 const content::NotificationSource
& source
,
769 const content::NotificationDetails
& details
) override
;
771 // Number of times OnPortalResult has been called since construction.
772 int num_results_received_
;
774 // If WaitForResults was called, the total number of updates for which to
775 // wait. Value doesn't matter when |waiting_for_result_| is false.
776 int num_results_to_wait_for_
;
778 bool waiting_for_result_
;
782 CaptivePortalService
* captive_portal_service_
;
784 // Last result received.
785 CaptivePortalResult captive_portal_result_
;
787 content::NotificationRegistrar registrar_
;
789 DISALLOW_COPY_AND_ASSIGN(CaptivePortalObserver
);
792 CaptivePortalObserver::CaptivePortalObserver(Profile
* profile
)
793 : num_results_received_(0),
794 num_results_to_wait_for_(0),
795 waiting_for_result_(false),
797 captive_portal_service_(
798 CaptivePortalServiceFactory::GetForProfile(profile
)),
799 captive_portal_result_(
800 captive_portal_service_
->last_detection_result()) {
802 chrome::NOTIFICATION_CAPTIVE_PORTAL_CHECK_RESULT
,
803 content::Source
<Profile
>(profile_
));
806 void CaptivePortalObserver::WaitForResults(int num_results_to_wait_for
) {
807 EXPECT_LT(0, num_results_to_wait_for
);
808 EXPECT_FALSE(waiting_for_result_
);
809 if (num_results_received_
< num_results_to_wait_for
) {
810 num_results_to_wait_for_
= num_results_to_wait_for
;
811 waiting_for_result_
= true;
812 content::RunMessageLoop();
813 EXPECT_FALSE(waiting_for_result_
);
815 EXPECT_EQ(num_results_to_wait_for
, num_results_received_
);
818 void CaptivePortalObserver::Observe(
820 const content::NotificationSource
& source
,
821 const content::NotificationDetails
& details
) {
822 ASSERT_EQ(type
, chrome::NOTIFICATION_CAPTIVE_PORTAL_CHECK_RESULT
);
823 ASSERT_EQ(profile_
, content::Source
<Profile
>(source
).ptr());
825 CaptivePortalService::Results
* results
=
826 content::Details
<CaptivePortalService::Results
>(details
).ptr();
828 EXPECT_EQ(captive_portal_result_
, results
->previous_result
);
829 EXPECT_EQ(captive_portal_service_
->last_detection_result(),
832 captive_portal_result_
= results
->result
;
833 ++num_results_received_
;
835 if (waiting_for_result_
&&
836 num_results_to_wait_for_
== num_results_received_
) {
837 waiting_for_result_
= false;
838 base::MessageLoop::current()->Quit();
842 // This observer waits for the SSLErrorHandler to start an interstitial timer
843 // for the given web contents.
844 class SSLInterstitialTimerObserver
{
846 explicit SSLInterstitialTimerObserver(content::WebContents
* web_contents
);
847 ~SSLInterstitialTimerObserver();
849 // Waits until the interstitial delay timer in SSLErrorHandler is started.
850 void WaitForTimerStarted();
853 void OnTimerStarted(content::WebContents
* web_contents
);
855 const content::WebContents
* web_contents_
;
856 SSLErrorHandler::TimerStartedCallback callback_
;
858 scoped_refptr
<content::MessageLoopRunner
> message_loop_runner_
;
860 DISALLOW_COPY_AND_ASSIGN(SSLInterstitialTimerObserver
);
863 SSLInterstitialTimerObserver::SSLInterstitialTimerObserver(
864 content::WebContents
* web_contents
)
865 : web_contents_(web_contents
),
866 message_loop_runner_(new content::MessageLoopRunner
) {
867 callback_
= base::Bind(&SSLInterstitialTimerObserver::OnTimerStarted
,
868 base::Unretained(this));
869 SSLErrorHandler::SetInterstitialTimerStartedCallbackForTest(&callback_
);
872 SSLInterstitialTimerObserver::~SSLInterstitialTimerObserver() {
873 SSLErrorHandler::SetInterstitialTimerStartedCallbackForTest(nullptr);
876 void SSLInterstitialTimerObserver::WaitForTimerStarted() {
877 message_loop_runner_
->Run();
880 void SSLInterstitialTimerObserver::OnTimerStarted(
881 content::WebContents
* web_contents
) {
882 if (web_contents_
== web_contents
&& message_loop_runner_
.get())
883 message_loop_runner_
->Quit();
886 // Adds an HSTS rule for |host|, so that all HTTP requests sent to it will
887 // be switched to HTTPS requests.
888 void AddHstsHost(net::URLRequestContextGetter
* context_getter
,
889 const std::string
& host
) {
890 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO
));
891 net::TransportSecurityState
* transport_security_state
=
892 context_getter
->GetURLRequestContext()->transport_security_state();
893 if (!transport_security_state
) {
898 base::Time expiry
= base::Time::Now() + base::TimeDelta::FromDays(1000);
899 bool include_subdomains
= false;
900 transport_security_state
->AddHSTS(host
, expiry
, include_subdomains
);
905 class CaptivePortalBrowserTest
: public InProcessBrowserTest
{
907 CaptivePortalBrowserTest();
909 // InProcessBrowserTest:
910 void SetUpOnMainThread() override
;
911 void TearDownOnMainThread() override
;
912 void SetUpCommandLine(base::CommandLine
* command_line
) override
;
914 // Sets the captive portal checking preference. Does not affect the command
915 // line flag, which is set in SetUpCommandLine.
916 void EnableCaptivePortalDetection(Profile
* profile
, bool enabled
);
918 // Enables or disables actual captive portal probes. Should only be called
919 // after captive portal service setup is done. When disabled, probe requests
920 // are silently ignored, never receiving a response.
921 void RespondToProbeRequests(bool enabled
);
923 // Sets up the captive portal service for the given profile so that
924 // all checks go to |test_url|. Also disables all timers.
925 void SetUpCaptivePortalService(Profile
* profile
, const GURL
& test_url
);
927 // Returns true if |browser|'s profile is currently running a captive portal
929 bool CheckPending(Browser
* browser
);
931 // Returns the type of the interstitial being shown.
932 content::InterstitialPageDelegate::TypeID
GetInterstitialType(
933 WebContents
* contents
) const;
935 // Returns the CaptivePortalTabReloader::State of |web_contents|.
936 CaptivePortalTabReloader::State
GetStateOfTabReloader(
937 WebContents
* web_contents
) const;
939 // Returns the CaptivePortalTabReloader::State of the indicated tab.
940 CaptivePortalTabReloader::State
GetStateOfTabReloaderAt(Browser
* browser
,
943 // Returns the number of tabs with the given state, across all profiles.
944 int NumTabsWithState(CaptivePortalTabReloader::State state
) const;
946 // Returns the number of tabs broken by captive portals, across all profiles.
947 int NumBrokenTabs() const;
949 // Returns the number of tabs that need to be reloaded due to having logged
950 // in to a captive portal, across all profiles.
951 int NumNeedReloadTabs() const;
953 // Navigates |browser|'s active tab to |url| and expects no captive portal
954 // test to be triggered. |expected_navigations| is the number of times the
955 // active tab will end up being navigated. It should be 1, except for the
956 // Link Doctor page, which acts like two navigations.
957 void NavigateToPageExpectNoTest(Browser
* browser
,
959 int expected_navigations
);
961 // Navigates |browser|'s active tab to an SSL tab that takes a while to load,
962 // triggering a captive portal check, which is expected to give the result
963 // |expected_result|. The page finishes loading, with a timeout, after the
964 // captive portal check.
965 void SlowLoadNoCaptivePortal(Browser
* browser
,
966 CaptivePortalResult expected_result
);
968 // Navigates |browser|'s active tab to an SSL timeout, expecting a captive
969 // portal check to be triggered and return a result which will indicates
970 // there's no detected captive portal.
971 void FastTimeoutNoCaptivePortal(Browser
* browser
,
972 CaptivePortalResult expected_result
);
974 // Navigates the active tab to a slow loading SSL page, which will then
975 // trigger a captive portal test. The test is expected to find a captive
976 // portal. The slow loading page will continue to load after the function
977 // returns, until URLRequestTimeoutOnDemandJob::FailJobs() is called,
978 // at which point it will timeout.
980 // When |expect_open_login_tab| is false, no login tab is expected to be
981 // opened, because one already exists, and the function returns once the
982 // captive portal test is complete.
984 // If |expect_open_login_tab| is true, a login tab is then expected to be
985 // opened. It waits until both the login tab has finished loading, and two
986 // captive portal tests complete. The second test is triggered by the load of
987 // the captive portal tab completing.
989 // This function must not be called when the active tab is currently loading.
990 // Waits for the hanging request to be issued, so other functions can rely
991 // on URLRequestTimeoutOnDemandJob::WaitForJobs having been called.
992 void SlowLoadBehindCaptivePortal(Browser
* browser
,
993 bool expect_open_login_tab
);
995 // Same as above, but takes extra parameters.
997 // |hanging_url| should either be kMockHttpsUrl or redirect to kMockHttpsUrl.
999 // |expected_portal_checks| and |expected_login_tab_navigations| allow
1000 // client-side redirects to be tested. |expected_login_tab_navigations| is
1001 // ignored when |expect_open_login_tab| is false.
1002 void SlowLoadBehindCaptivePortal(Browser
* browser
,
1003 bool expect_open_login_tab
,
1004 const GURL
& hanging_url
,
1005 int expected_portal_checks
,
1006 int expected_login_tab_navigations
);
1008 // Just like SlowLoadBehindCaptivePortal, except the navigated tab has
1009 // a connection timeout rather having its time trigger, and the function
1010 // waits until that timeout occurs.
1011 void FastTimeoutBehindCaptivePortal(Browser
* browser
,
1012 bool expect_open_login_tab
);
1014 // Much as above, but accepts a URL parameter and can be used for errors that
1015 // trigger captive portal checks other than timeouts. |error_url| should
1016 // result in an error rather than hanging.
1017 // If |delay_portal_response_until_interstital| is true, captive portal probe
1018 // request are ignored until the interstitial is shown, at which point a
1019 // captive portal result is sent. This allows testing in conjunction with the
1020 // certificate error interstitial.
1021 void FastErrorBehindCaptivePortal(
1023 bool expect_open_login_tab
,
1024 const GURL
& error_url
,
1025 bool delay_portal_response_until_interstital
);
1027 // Navigates the active tab to an SSL error page which triggers an
1028 // interstitial timer. Also disables captive portal checks indefinitely, so
1029 // the page appears to be hanging.
1030 void FastErrorWithInterstitialTimer(Browser
* browser
,
1031 const GURL
& cert_error_url
);
1033 // Navigates the login tab without logging in. The login tab must be the
1034 // specified browser's active tab. Expects no other tab to change state.
1035 // |num_loading_tabs| and |num_timed_out_tabs| are used as extra checks
1036 // that nothing has gone wrong prior to the function call.
1037 void NavigateLoginTab(Browser
* browser
,
1038 int num_loading_tabs
,
1039 int num_timed_out_tabs
);
1041 // Simulates a login by updating the URLRequestMockCaptivePortalJob's
1042 // behind captive portal state, and navigating the login tab. Waits for
1043 // all broken but not loading tabs to be reloaded.
1044 // |num_loading_tabs| and |num_timed_out_tabs| are used as extra checks
1045 // that nothing has gone wrong prior to the function call.
1046 void Login(Browser
* browser
, int num_loading_tabs
, int num_timed_out_tabs
);
1048 // Simulates a login when the broken tab shows an SSL or captive portal
1049 // interstitial. Can't use Login() in those cases because the interstitial
1050 // tab looks like a cross between a hung tab (Load was never committed) and a
1051 // tab at an error page (The load was stopped).
1052 void LoginCertError(Browser
* browser
);
1054 // Makes the slow SSL loads of all active tabs time out at once, and waits for
1055 // them to finish both that load and the automatic reload it should trigger.
1056 // There should be no timed out tabs when this is called.
1057 void FailLoadsAfterLogin(Browser
* browser
, int num_loading_tabs
);
1059 // Makes the slow SSL loads of all active tabs time out at once, and waits for
1060 // them to finish displaying their error pages. The login tab should be the
1061 // active tab. There should be no timed out tabs when this is called.
1062 void FailLoadsWithoutLogin(Browser
* browser
, int num_loading_tabs
);
1064 // Navigates |browser|'s active tab to |starting_url| while not behind a
1065 // captive portal. Then navigates to |interrupted_url|, which should create
1066 // a URLRequestTimeoutOnDemandJob, which is then abandoned. The load should
1067 // trigger a captive portal check, which finds a captive portal and opens a
1070 // Then the navigation is interrupted by a navigation to |timeout_url|, which
1071 // should trigger a captive portal check, and finally the test simulates
1074 // The purpose of this test is to make sure the TabHelper triggers a captive
1075 // portal check when a load is interrupted by another load, particularly in
1076 // the case of cross-process navigations.
1077 void RunNavigateLoadingTabToTimeoutTest(Browser
* browser
,
1078 const GURL
& starting_url
,
1079 const GURL
& interrupted_url
,
1080 const GURL
& timeout_url
);
1082 // Sets the timeout used by a CaptivePortalTabReloader on slow SSL loads
1083 // before a captive portal check.
1084 void SetSlowSSLLoadTime(CaptivePortalTabReloader
* tab_reloader
,
1085 base::TimeDelta slow_ssl_load_time
);
1087 CaptivePortalTabReloader
* GetTabReloader(WebContents
* web_contents
) const;
1090 URLRequestMockCaptivePortalJobFactory factory_
;
1093 DISALLOW_COPY_AND_ASSIGN(CaptivePortalBrowserTest
);
1096 CaptivePortalBrowserTest::CaptivePortalBrowserTest() {
1099 void CaptivePortalBrowserTest::SetUpOnMainThread() {
1100 // Enable mock requests.
1101 content::BrowserThread::PostTask(
1102 content::BrowserThread::IO
, FROM_HERE
,
1103 base::Bind(&chrome_browser_net::SetUrlRequestMocksEnabled
, true));
1104 factory_
.AddUrlHandlers();
1106 // Double-check that the captive portal service isn't enabled by default for
1108 EXPECT_EQ(CaptivePortalService::DISABLED_FOR_TESTING
,
1109 CaptivePortalService::get_state_for_testing());
1111 CaptivePortalService::set_state_for_testing(
1112 CaptivePortalService::SKIP_OS_CHECK_FOR_TESTING
);
1113 EnableCaptivePortalDetection(browser()->profile(), true);
1115 // Set the captive portal service to use URLRequestMockCaptivePortalJob's
1116 // mock URL, by default.
1117 SetUpCaptivePortalService(browser()->profile(),
1118 GURL(kMockCaptivePortalTestUrl
));
1120 // Set SSL interstitial delay long enough so that a captive portal result
1121 // is guaranteed to arrive during this window, and a captive portal
1122 // error page is displayed instead of an SSL interstitial.
1123 SSLErrorHandler::SetInterstitialDelayForTest(base::TimeDelta::FromHours(1));
1126 void CaptivePortalBrowserTest::TearDownOnMainThread() {
1127 // No test should have a captive portal check pending on quit.
1128 EXPECT_FALSE(CheckPending(browser()));
1131 void CaptivePortalBrowserTest::SetUpCommandLine(
1132 base::CommandLine
* command_line
) {
1133 // Enable finch experiment for captive portal interstitials.
1134 command_line
->AppendSwitchASCII(
1135 switches::kForceFieldTrials
, "CaptivePortalInterstitial/Enabled/");
1138 void CaptivePortalBrowserTest::EnableCaptivePortalDetection(
1139 Profile
* profile
, bool enabled
) {
1140 profile
->GetPrefs()->SetBoolean(prefs::kAlternateErrorPagesEnabled
, enabled
);
1143 void CaptivePortalBrowserTest::RespondToProbeRequests(bool enabled
) {
1145 EXPECT_EQ(CaptivePortalService::IGNORE_REQUESTS_FOR_TESTING
,
1146 CaptivePortalService::get_state_for_testing());
1147 CaptivePortalService::set_state_for_testing(
1148 CaptivePortalService::SKIP_OS_CHECK_FOR_TESTING
);
1150 EXPECT_EQ(CaptivePortalService::SKIP_OS_CHECK_FOR_TESTING
,
1151 CaptivePortalService::get_state_for_testing());
1152 CaptivePortalService::set_state_for_testing(
1153 CaptivePortalService::IGNORE_REQUESTS_FOR_TESTING
);
1157 void CaptivePortalBrowserTest::SetUpCaptivePortalService(Profile
* profile
,
1158 const GURL
& test_url
) {
1159 CaptivePortalService
* captive_portal_service
=
1160 CaptivePortalServiceFactory::GetForProfile(profile
);
1161 captive_portal_service
->set_test_url(test_url
);
1163 // Don't use any non-zero timers. Timers are checked in unit tests.
1164 CaptivePortalService::RecheckPolicy
* recheck_policy
=
1165 &captive_portal_service
->recheck_policy();
1166 recheck_policy
->initial_backoff_no_portal_ms
= 0;
1167 recheck_policy
->initial_backoff_portal_ms
= 0;
1168 recheck_policy
->backoff_policy
.maximum_backoff_ms
= 0;
1171 bool CaptivePortalBrowserTest::CheckPending(Browser
* browser
) {
1172 CaptivePortalService
* captive_portal_service
=
1173 CaptivePortalServiceFactory::GetForProfile(browser
->profile());
1175 return captive_portal_service
->DetectionInProgress() ||
1176 captive_portal_service
->TimerRunning();
1179 content::InterstitialPageDelegate::TypeID
1180 CaptivePortalBrowserTest::GetInterstitialType(WebContents
* contents
) const {
1181 if (!contents
->ShowingInterstitialPage())
1183 return contents
->GetInterstitialPage()
1184 ->GetDelegateForTesting()
1185 ->GetTypeForTesting();
1188 CaptivePortalTabReloader::State
CaptivePortalBrowserTest::GetStateOfTabReloader(
1189 WebContents
* web_contents
) const {
1190 return GetTabReloader(web_contents
)->state();
1193 CaptivePortalTabReloader::State
1194 CaptivePortalBrowserTest::GetStateOfTabReloaderAt(Browser
* browser
,
1196 return GetStateOfTabReloader(
1197 browser
->tab_strip_model()->GetWebContentsAt(index
));
1200 int CaptivePortalBrowserTest::NumTabsWithState(
1201 CaptivePortalTabReloader::State state
) const {
1203 for (TabContentsIterator it
; !it
.done(); it
.Next()) {
1204 if (GetStateOfTabReloader(*it
) == state
)
1210 int CaptivePortalBrowserTest::NumBrokenTabs() const {
1211 return NumTabsWithState(CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL
);
1214 int CaptivePortalBrowserTest::NumNeedReloadTabs() const {
1215 return NumTabsWithState(CaptivePortalTabReloader::STATE_NEEDS_RELOAD
);
1218 void CaptivePortalBrowserTest::NavigateToPageExpectNoTest(
1221 int expected_navigations
) {
1222 MultiNavigationObserver navigation_observer
;
1223 CaptivePortalObserver
portal_observer(browser
->profile());
1225 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
1226 browser
, url
, expected_navigations
);
1228 // No captive portal checks should have ocurred or be pending, and there
1229 // should be no new tabs.
1230 EXPECT_EQ(0, portal_observer
.num_results_received());
1231 EXPECT_FALSE(CheckPending(browser
));
1232 EXPECT_EQ(1, browser
->tab_strip_model()->count());
1233 EXPECT_EQ(expected_navigations
, navigation_observer
.num_navigations());
1234 EXPECT_EQ(0, NumLoadingTabs());
1235 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
,
1236 GetStateOfTabReloaderAt(browser
, 0));
1239 void CaptivePortalBrowserTest::SlowLoadNoCaptivePortal(
1241 CaptivePortalResult expected_result
) {
1242 CaptivePortalTabReloader
* tab_reloader
=
1243 GetTabReloader(browser
->tab_strip_model()->GetActiveWebContents());
1244 ASSERT_TRUE(tab_reloader
);
1245 SetSlowSSLLoadTime(tab_reloader
, base::TimeDelta());
1247 MultiNavigationObserver navigation_observer
;
1248 CaptivePortalObserver
portal_observer(browser
->profile());
1249 ui_test_utils::NavigateToURLWithDisposition(browser
,
1250 GURL(kMockHttpsUrl
),
1252 ui_test_utils::BROWSER_TEST_NONE
);
1254 portal_observer
.WaitForResults(1);
1256 ASSERT_EQ(1, browser
->tab_strip_model()->count());
1257 EXPECT_EQ(expected_result
, portal_observer
.captive_portal_result());
1258 EXPECT_EQ(1, portal_observer
.num_results_received());
1259 EXPECT_EQ(0, navigation_observer
.num_navigations());
1260 EXPECT_FALSE(CheckPending(browser
));
1262 // First tab should still be loading.
1263 EXPECT_EQ(1, NumLoadingTabs());
1265 // Wait for the request to be issued, then time it out.
1266 URLRequestTimeoutOnDemandJob::WaitForJobs(1);
1267 URLRequestTimeoutOnDemandJob::FailJobs(1);
1268 navigation_observer
.WaitForNavigations(1);
1270 ASSERT_EQ(1, browser
->tab_strip_model()->count());
1271 EXPECT_EQ(1, portal_observer
.num_results_received());
1272 EXPECT_FALSE(CheckPending(browser
));
1273 EXPECT_EQ(0, NumLoadingTabs());
1275 // Set a slow SSL load time to prevent the timer from triggering.
1276 SetSlowSSLLoadTime(tab_reloader
, base::TimeDelta::FromDays(1));
1279 void CaptivePortalBrowserTest::FastTimeoutNoCaptivePortal(
1281 CaptivePortalResult expected_result
) {
1282 ASSERT_NE(expected_result
, captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL
);
1284 // Set the load time to be large, so the timer won't trigger. The value is
1285 // not restored at the end of the function.
1286 CaptivePortalTabReloader
* tab_reloader
=
1287 GetTabReloader(browser
->tab_strip_model()->GetActiveWebContents());
1288 ASSERT_TRUE(tab_reloader
);
1289 SetSlowSSLLoadTime(tab_reloader
, base::TimeDelta::FromHours(1));
1291 MultiNavigationObserver navigation_observer
;
1292 CaptivePortalObserver
portal_observer(browser
->profile());
1294 // Neither of these should be changed by the navigation.
1295 int active_index
= browser
->tab_strip_model()->active_index();
1296 int expected_tab_count
= browser
->tab_strip_model()->count();
1298 ui_test_utils::NavigateToURL(
1300 URLRequestFailedJob::GetMockHttpsUrl(net::ERR_CONNECTION_TIMED_OUT
));
1302 // An attempt to detect a captive portal should have started by now. If not,
1303 // abort early to prevent hanging.
1304 ASSERT_TRUE(portal_observer
.num_results_received() > 0 ||
1305 CheckPending(browser
));
1307 portal_observer
.WaitForResults(1);
1308 navigation_observer
.WaitForNavigations(1);
1310 // Check the result.
1311 EXPECT_EQ(1, portal_observer
.num_results_received());
1312 EXPECT_EQ(expected_result
, portal_observer
.captive_portal_result());
1314 // Check that the right tab was navigated, and there were no extra
1316 EXPECT_EQ(1, navigation_observer
.NumNavigationsForTab(
1317 browser
->tab_strip_model()->GetWebContentsAt(active_index
)));
1318 EXPECT_EQ(0, NumLoadingTabs());
1320 // Check the tab's state, and verify no captive portal check is pending.
1321 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
,
1322 GetStateOfTabReloaderAt(browser
, 0));
1323 EXPECT_FALSE(CheckPending(browser
));
1325 // Make sure no login tab was opened.
1326 EXPECT_EQ(expected_tab_count
, browser
->tab_strip_model()->count());
1329 void CaptivePortalBrowserTest::SlowLoadBehindCaptivePortal(
1331 bool expect_open_login_tab
) {
1332 SlowLoadBehindCaptivePortal(browser
,
1333 expect_open_login_tab
,
1334 GURL(kMockHttpsUrl
),
1339 void CaptivePortalBrowserTest::SlowLoadBehindCaptivePortal(
1341 bool expect_open_login_tab
,
1342 const GURL
& hanging_url
,
1343 int expected_portal_checks
,
1344 int expected_login_tab_navigations
) {
1345 ASSERT_GE(expected_portal_checks
, 1);
1346 TabStripModel
* tab_strip_model
= browser
->tab_strip_model();
1347 // Calling this on a tab that's waiting for a load to manually be timed out
1348 // will result in a hang.
1349 ASSERT_FALSE(tab_strip_model
->GetActiveWebContents()->IsLoading());
1351 // Trigger a captive portal check quickly.
1352 CaptivePortalTabReloader
* tab_reloader
=
1353 GetTabReloader(tab_strip_model
->GetActiveWebContents());
1354 ASSERT_TRUE(tab_reloader
);
1355 SetSlowSSLLoadTime(tab_reloader
, base::TimeDelta());
1357 // Number of tabs expected to be open after the captive portal checks
1359 int initial_tab_count
= tab_strip_model
->count();
1360 int initial_active_index
= tab_strip_model
->active_index();
1361 int initial_loading_tabs
= NumLoadingTabs();
1362 int expected_broken_tabs
= NumBrokenTabs();
1363 if (CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL
!=
1364 GetStateOfTabReloader(tab_strip_model
->GetActiveWebContents())) {
1365 ++expected_broken_tabs
;
1368 MultiNavigationObserver navigation_observer
;
1369 CaptivePortalObserver
portal_observer(browser
->profile());
1370 ui_test_utils::NavigateToURLWithDisposition(browser
,
1373 ui_test_utils::BROWSER_TEST_NONE
);
1374 portal_observer
.WaitForResults(expected_portal_checks
);
1376 if (expect_open_login_tab
) {
1377 ASSERT_GE(expected_login_tab_navigations
, 1);
1379 navigation_observer
.WaitForNavigations(expected_login_tab_navigations
);
1381 ASSERT_EQ(initial_tab_count
+ 1, tab_strip_model
->count());
1382 EXPECT_EQ(initial_tab_count
, tab_strip_model
->active_index());
1384 EXPECT_EQ(expected_login_tab_navigations
,
1385 navigation_observer
.NumNavigationsForTab(
1386 tab_strip_model
->GetWebContentsAt(initial_tab_count
)));
1387 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
,
1388 GetStateOfTabReloaderAt(browser
, 1));
1389 EXPECT_TRUE(IsLoginTab(tab_strip_model
->GetWebContentsAt(1)));
1391 EXPECT_EQ(0, navigation_observer
.num_navigations());
1392 EXPECT_EQ(initial_active_index
, tab_strip_model
->active_index());
1393 ASSERT_EQ(initial_tab_count
, tab_strip_model
->count());
1394 EXPECT_EQ(initial_active_index
, tab_strip_model
->active_index());
1397 // Wait for all the expect resource loads to actually start, so subsequent
1398 // functions can rely on them having started.
1399 URLRequestTimeoutOnDemandJob::WaitForJobs(initial_loading_tabs
+ 1);
1401 EXPECT_EQ(initial_loading_tabs
+ 1, NumLoadingTabs());
1402 EXPECT_EQ(expected_broken_tabs
, NumBrokenTabs());
1403 EXPECT_EQ(captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL
,
1404 portal_observer
.captive_portal_result());
1405 EXPECT_EQ(expected_portal_checks
, portal_observer
.num_results_received());
1406 EXPECT_FALSE(CheckPending(browser
));
1408 EXPECT_EQ(CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL
,
1409 GetStateOfTabReloaderAt(browser
, initial_active_index
));
1411 // Reset the load time to be large, so the timer won't trigger on a reload.
1412 SetSlowSSLLoadTime(tab_reloader
, base::TimeDelta::FromHours(1));
1415 void CaptivePortalBrowserTest::FastTimeoutBehindCaptivePortal(
1417 bool expect_open_login_tab
) {
1418 FastErrorBehindCaptivePortal(browser
,
1419 expect_open_login_tab
,
1420 GURL(kMockHttpsQuickTimeoutUrl
),
1424 void CaptivePortalBrowserTest::FastErrorBehindCaptivePortal(
1426 bool expect_open_login_tab
,
1427 const GURL
& error_url
,
1428 bool delay_portal_response_until_interstital
) {
1429 TabStripModel
* tab_strip_model
= browser
->tab_strip_model();
1430 // Calling this on a tab that's waiting for a load to manually be timed out
1431 // will result in a hang.
1432 ASSERT_FALSE(tab_strip_model
->GetActiveWebContents()->IsLoading());
1434 // Set the load time to be large, so the timer won't trigger. The value is
1435 // not restored at the end of the function.
1436 CaptivePortalTabReloader
* tab_reloader
=
1437 GetTabReloader(tab_strip_model
->GetActiveWebContents());
1438 ASSERT_TRUE(tab_reloader
);
1439 SetSlowSSLLoadTime(tab_reloader
, base::TimeDelta::FromHours(1));
1441 // Number of tabs expected to be open after the captive portal checks
1443 int initial_tab_count
= tab_strip_model
->count();
1444 int initial_active_index
= tab_strip_model
->active_index();
1445 int initial_loading_tabs
= NumLoadingTabs();
1446 int expected_broken_tabs
= NumBrokenTabs();
1447 if (CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL
!=
1448 GetStateOfTabReloader(tab_strip_model
->GetActiveWebContents())) {
1449 ++expected_broken_tabs
;
1452 CaptivePortalService
* captive_portal_service
=
1453 CaptivePortalServiceFactory::GetForProfile(browser
->profile());
1454 if (delay_portal_response_until_interstital
)
1455 RespondToProbeRequests(false);
1457 MultiNavigationObserver navigation_observer
;
1458 CaptivePortalObserver
portal_observer(browser
->profile());
1459 ui_test_utils::NavigateToURLWithDisposition(browser
,
1462 ui_test_utils::BROWSER_TEST_NONE
);
1464 if (delay_portal_response_until_interstital
) {
1465 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
,
1466 GetStateOfTabReloaderAt(browser
, initial_active_index
));
1467 // Once the interstitial is attached, probe for captive portal.
1468 WaitForInterstitialAttach(tab_strip_model
->GetActiveWebContents());
1469 RespondToProbeRequests(true);
1470 captive_portal_service
->DetectCaptivePortal();
1473 portal_observer
.WaitForResults(1);
1475 if (expect_open_login_tab
) {
1476 navigation_observer
.WaitForNavigations(2);
1477 ASSERT_EQ(initial_tab_count
+ 1, tab_strip_model
->count());
1478 EXPECT_EQ(initial_tab_count
, tab_strip_model
->active_index());
1479 // Make sure that the originally active tab and the captive portal tab have
1480 // each loaded once.
1481 EXPECT_EQ(1, navigation_observer
.NumNavigationsForTab(
1482 tab_strip_model
->GetWebContentsAt(initial_active_index
)));
1483 EXPECT_EQ(1, navigation_observer
.NumNavigationsForTab(
1484 tab_strip_model
->GetWebContentsAt(initial_tab_count
)));
1485 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
,
1486 GetStateOfTabReloaderAt(browser
, 1));
1487 EXPECT_TRUE(IsLoginTab(tab_strip_model
->GetWebContentsAt(1)));
1489 navigation_observer
.WaitForNavigations(1);
1490 EXPECT_EQ(initial_active_index
, tab_strip_model
->active_index());
1491 EXPECT_EQ(1, navigation_observer
.NumNavigationsForTab(
1492 tab_strip_model
->GetWebContentsAt(initial_active_index
)));
1493 ASSERT_EQ(initial_tab_count
, tab_strip_model
->count());
1494 EXPECT_EQ(initial_active_index
, tab_strip_model
->active_index());
1497 EXPECT_EQ(initial_loading_tabs
, NumLoadingTabs());
1498 EXPECT_EQ(expected_broken_tabs
, NumBrokenTabs());
1499 EXPECT_EQ(captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL
,
1500 portal_observer
.captive_portal_result());
1501 EXPECT_EQ(1, portal_observer
.num_results_received());
1502 EXPECT_FALSE(CheckPending(browser
));
1504 EXPECT_EQ(CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL
,
1505 GetStateOfTabReloaderAt(browser
, initial_active_index
));
1508 void CaptivePortalBrowserTest::FastErrorWithInterstitialTimer(
1510 const GURL
& cert_error_url
) {
1511 TabStripModel
* tab_strip_model
= browser
->tab_strip_model();
1512 WebContents
* broken_tab_contents
= tab_strip_model
->GetActiveWebContents();
1514 // Disable captive portal checks indefinitely.
1515 RespondToProbeRequests(false);
1517 SSLInterstitialTimerObserver
interstitial_timer_observer(broken_tab_contents
);
1518 ui_test_utils::NavigateToURLWithDisposition(browser
,
1521 ui_test_utils::BROWSER_TEST_NONE
);
1522 interstitial_timer_observer
.WaitForTimerStarted();
1524 // The tab should be in loading state, waiting for the interstitial timer to
1525 // expire or a captive portal result to arrive. Since captive portal checks
1526 // are disabled and timer set to expire after a very long time, the tab should
1527 // hang indefinitely.
1528 EXPECT_TRUE(broken_tab_contents
->IsLoading());
1529 EXPECT_EQ(1, NumLoadingTabs());
1532 void CaptivePortalBrowserTest::NavigateLoginTab(Browser
* browser
,
1533 int num_loading_tabs
,
1534 int num_timed_out_tabs
) {
1535 MultiNavigationObserver navigation_observer
;
1536 CaptivePortalObserver
portal_observer(browser
->profile());
1538 TabStripModel
* tab_strip_model
= browser
->tab_strip_model();
1539 int initial_tab_count
= tab_strip_model
->count();
1540 EXPECT_EQ(num_loading_tabs
, NumLoadingTabs());
1541 EXPECT_EQ(num_timed_out_tabs
, NumBrokenTabs() - NumLoadingTabs());
1543 int login_tab_index
= tab_strip_model
->active_index();
1544 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
,
1545 GetStateOfTabReloader(tab_strip_model
->GetActiveWebContents()));
1546 ASSERT_TRUE(IsLoginTab(browser
->tab_strip_model()->GetActiveWebContents()));
1548 // Do the navigation.
1549 EXPECT_TRUE(content::ExecuteScript(tab_strip_model
->GetActiveWebContents(),
1552 portal_observer
.WaitForResults(1);
1553 navigation_observer
.WaitForNavigations(1);
1555 // Check the captive portal result.
1556 EXPECT_EQ(captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL
,
1557 portal_observer
.captive_portal_result());
1558 EXPECT_EQ(1, portal_observer
.num_results_received());
1559 EXPECT_FALSE(CheckPending(browser
));
1561 // Make sure not much has changed.
1562 EXPECT_EQ(initial_tab_count
, tab_strip_model
->count());
1563 EXPECT_EQ(num_loading_tabs
, NumLoadingTabs());
1564 EXPECT_EQ(num_loading_tabs
+ num_timed_out_tabs
, NumBrokenTabs());
1565 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
,
1566 GetStateOfTabReloaderAt(browser
, login_tab_index
));
1567 EXPECT_TRUE(IsLoginTab(tab_strip_model
->GetWebContentsAt(login_tab_index
)));
1569 // Make sure there were no unexpected navigations.
1570 EXPECT_EQ(1, navigation_observer
.NumNavigationsForTab(
1571 tab_strip_model
->GetWebContentsAt(login_tab_index
)));
1574 void CaptivePortalBrowserTest::Login(Browser
* browser
,
1575 int num_loading_tabs
,
1576 int num_timed_out_tabs
) {
1577 // Simulate logging in.
1578 factory_
.SetBehindCaptivePortal(false);
1580 MultiNavigationObserver navigation_observer
;
1581 CaptivePortalObserver
portal_observer(browser
->profile());
1583 TabStripModel
* tab_strip_model
= browser
->tab_strip_model();
1584 int initial_tab_count
= tab_strip_model
->count();
1585 ASSERT_EQ(num_loading_tabs
, NumLoadingTabs());
1586 EXPECT_EQ(num_timed_out_tabs
, NumBrokenTabs() - NumLoadingTabs());
1588 // Verify that the login page is on top.
1589 int login_tab_index
= tab_strip_model
->active_index();
1590 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
,
1591 GetStateOfTabReloaderAt(browser
, login_tab_index
));
1592 ASSERT_TRUE(IsLoginTab(tab_strip_model
->GetWebContentsAt(login_tab_index
)));
1594 // Trigger a navigation.
1595 EXPECT_TRUE(content::ExecuteScript(tab_strip_model
->GetActiveWebContents(),
1598 portal_observer
.WaitForResults(1);
1600 // Wait for all the timed out tabs to reload.
1601 navigation_observer
.WaitForNavigations(1 + num_timed_out_tabs
);
1602 EXPECT_EQ(1, portal_observer
.num_results_received());
1604 // The tabs that were loading before should still be loading, and now be in
1605 // STATE_NEEDS_RELOAD.
1606 EXPECT_EQ(0, NumBrokenTabs());
1607 EXPECT_EQ(num_loading_tabs
, NumLoadingTabs());
1608 EXPECT_EQ(num_loading_tabs
, NumNeedReloadTabs());
1610 // Make sure that the broken tabs have reloaded, and there's no more
1611 // captive portal tab.
1612 EXPECT_EQ(initial_tab_count
, tab_strip_model
->count());
1613 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
,
1614 GetStateOfTabReloaderAt(browser
, login_tab_index
));
1615 EXPECT_FALSE(IsLoginTab(tab_strip_model
->GetWebContentsAt(login_tab_index
)));
1617 // Make sure there were no unexpected navigations of the login tab.
1618 EXPECT_EQ(1, navigation_observer
.NumNavigationsForTab(
1619 tab_strip_model
->GetWebContentsAt(login_tab_index
)));
1622 void CaptivePortalBrowserTest::LoginCertError(Browser
* browser
) {
1623 factory_
.SetBehindCaptivePortal(false);
1625 MultiNavigationObserver navigation_observer
;
1626 CaptivePortalObserver
portal_observer(browser
->profile());
1628 TabStripModel
* tab_strip_model
= browser
->tab_strip_model();
1630 // Verify that the login page is on top.
1631 int login_tab_index
= tab_strip_model
->active_index();
1632 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
,
1633 GetStateOfTabReloaderAt(browser
, login_tab_index
));
1634 ASSERT_TRUE(IsLoginTab(tab_strip_model
->GetWebContentsAt(login_tab_index
)));
1636 // Trigger a navigation.
1637 EXPECT_TRUE(content::ExecuteScript(tab_strip_model
->GetActiveWebContents(),
1640 // The captive portal tab navigation will trigger a captive portal check,
1641 // and reloading the original tab will bring up the interstitial page again,
1642 // triggering a second captive portal check.
1643 portal_observer
.WaitForResults(2);
1645 // Wait for both tabs to finish loading.
1646 navigation_observer
.WaitForNavigations(2);
1647 EXPECT_EQ(2, portal_observer
.num_results_received());
1648 EXPECT_FALSE(CheckPending(browser
));
1649 EXPECT_EQ(captive_portal::RESULT_INTERNET_CONNECTED
,
1650 portal_observer
.captive_portal_result());
1652 // Check state of tabs. While the first tab is still displaying an
1653 // interstitial page, since no portal was found, it should be in STATE_NONE,
1654 // as should the login tab.
1655 ASSERT_EQ(2, tab_strip_model
->count());
1656 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
,
1657 GetStateOfTabReloaderAt(browser
, 0));
1658 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
,
1659 GetStateOfTabReloaderAt(browser
, login_tab_index
));
1660 EXPECT_FALSE(IsLoginTab(tab_strip_model
->GetWebContentsAt(login_tab_index
)));
1662 // Make sure only one navigation was for the login tab.
1663 EXPECT_EQ(1, navigation_observer
.NumNavigationsForTab(
1664 tab_strip_model
->GetWebContentsAt(login_tab_index
)));
1667 void CaptivePortalBrowserTest::FailLoadsAfterLogin(Browser
* browser
,
1668 int num_loading_tabs
) {
1669 ASSERT_EQ(num_loading_tabs
, NumLoadingTabs());
1670 ASSERT_EQ(num_loading_tabs
, NumNeedReloadTabs());
1671 EXPECT_EQ(0, NumBrokenTabs());
1673 TabStripModel
* tab_strip_model
= browser
->tab_strip_model();
1674 int initial_num_tabs
= tab_strip_model
->count();
1675 int initial_active_tab
= tab_strip_model
->active_index();
1677 CaptivePortalObserver
portal_observer(browser
->profile());
1678 FailLoadsAfterLoginObserver fail_loads_observer
;
1679 // Connection(s) finally time out. There should have already been a call
1680 // to wait for the requests to be issued before logging on.
1681 URLRequestTimeoutOnDemandJob::WaitForJobs(num_loading_tabs
);
1682 URLRequestTimeoutOnDemandJob::FailJobs(num_loading_tabs
);
1684 fail_loads_observer
.WaitForNavigations();
1686 // No captive portal checks should have ocurred or be pending, and there
1687 // should be no new tabs.
1688 EXPECT_EQ(0, portal_observer
.num_results_received());
1689 EXPECT_FALSE(CheckPending(browser
));
1690 EXPECT_EQ(initial_num_tabs
, tab_strip_model
->count());
1692 EXPECT_EQ(initial_active_tab
, tab_strip_model
->active_index());
1694 EXPECT_EQ(0, NumNeedReloadTabs());
1695 EXPECT_EQ(0, NumLoadingTabs());
1698 void CaptivePortalBrowserTest::FailLoadsWithoutLogin(Browser
* browser
,
1699 int num_loading_tabs
) {
1700 ASSERT_EQ(num_loading_tabs
, NumLoadingTabs());
1701 ASSERT_EQ(0, NumNeedReloadTabs());
1702 EXPECT_EQ(num_loading_tabs
, NumBrokenTabs());
1704 TabStripModel
* tab_strip_model
= browser
->tab_strip_model();
1705 int initial_num_tabs
= tab_strip_model
->count();
1706 int login_tab
= tab_strip_model
->active_index();
1707 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
,
1708 GetStateOfTabReloader(tab_strip_model
->GetActiveWebContents()));
1709 ASSERT_TRUE(IsLoginTab(tab_strip_model
->GetActiveWebContents()));
1711 CaptivePortalObserver
portal_observer(browser
->profile());
1712 MultiNavigationObserver navigation_observer
;
1713 // Connection(s) finally time out. There should have already been a call
1714 // to wait for the requests to be issued.
1715 URLRequestTimeoutOnDemandJob::FailJobs(num_loading_tabs
);
1717 navigation_observer
.WaitForNavigations(num_loading_tabs
);
1719 // No captive portal checks should have ocurred or be pending, and there
1720 // should be no new tabs.
1721 EXPECT_EQ(0, portal_observer
.num_results_received());
1722 EXPECT_FALSE(CheckPending(browser
));
1723 EXPECT_EQ(initial_num_tabs
, tab_strip_model
->count());
1725 EXPECT_EQ(0, NumNeedReloadTabs());
1726 EXPECT_EQ(0, NumLoadingTabs());
1727 EXPECT_EQ(num_loading_tabs
, NumBrokenTabs());
1728 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
,
1729 GetStateOfTabReloader(tab_strip_model
->GetActiveWebContents()));
1730 EXPECT_TRUE(IsLoginTab(tab_strip_model
->GetActiveWebContents()));
1731 EXPECT_EQ(login_tab
, tab_strip_model
->active_index());
1733 EXPECT_EQ(0, navigation_observer
.NumNavigationsForTab(
1734 tab_strip_model
->GetWebContentsAt(login_tab
)));
1737 void CaptivePortalBrowserTest::RunNavigateLoadingTabToTimeoutTest(
1739 const GURL
& starting_url
,
1740 const GURL
& hanging_url
,
1741 const GURL
& timeout_url
) {
1742 // Temporarily disable the captive portal and navigate to the starting
1743 // URL, which may be a URL that will hang when behind a captive portal.
1744 factory_
.SetBehindCaptivePortal(false);
1745 NavigateToPageExpectNoTest(browser
, starting_url
, 1);
1746 factory_
.SetBehindCaptivePortal(true);
1748 // Go to the first hanging url.
1749 SlowLoadBehindCaptivePortal(browser
, true, hanging_url
, 1, 1);
1751 // Abandon the request.
1752 URLRequestTimeoutOnDemandJob::WaitForJobs(1);
1753 URLRequestTimeoutOnDemandJob::AbandonJobs(1);
1755 TabStripModel
* tab_strip_model
= browser
->tab_strip_model();
1756 CaptivePortalTabReloader
* tab_reloader
=
1757 GetTabReloader(tab_strip_model
->GetWebContentsAt(0));
1758 ASSERT_TRUE(tab_reloader
);
1760 // A non-zero delay makes it more likely that CaptivePortalTabHelper will
1761 // be confused by events relating to canceling the old navigation.
1762 SetSlowSSLLoadTime(tab_reloader
, base::TimeDelta::FromSeconds(2));
1763 CaptivePortalObserver
portal_observer(browser
->profile());
1765 // Navigate the error tab to another slow loading page. Can't have
1766 // ui_test_utils do the navigation because it will wait for loading tabs to
1767 // stop loading before navigating.
1769 // This may result in either 0 or 1 DidStopLoading events. If there is one,
1770 // it must happen before the CaptivePortalService sends out its test request,
1771 // so waiting for PortalObserver to see that request prevents it from
1772 // confusing the MultiNavigationObservers used later.
1773 tab_strip_model
->ActivateTabAt(0, true);
1774 browser
->OpenURL(content::OpenURLParams(timeout_url
,
1775 content::Referrer(),
1777 ui::PAGE_TRANSITION_TYPED
,
1779 portal_observer
.WaitForResults(1);
1780 EXPECT_FALSE(CheckPending(browser
));
1781 EXPECT_EQ(1, NumLoadingTabs());
1782 EXPECT_EQ(CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL
,
1783 GetStateOfTabReloaderAt(browser
, 0));
1784 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
,
1785 GetStateOfTabReloaderAt(browser
, 1));
1786 ASSERT_TRUE(IsLoginTab(tab_strip_model
->GetWebContentsAt(1)));
1788 // Need to make sure the request has been issued before logging in.
1789 URLRequestTimeoutOnDemandJob::WaitForJobs(1);
1791 // Simulate logging in.
1792 tab_strip_model
->ActivateTabAt(1, true);
1793 SetSlowSSLLoadTime(tab_reloader
, base::TimeDelta::FromDays(1));
1794 Login(browser
, 1, 0);
1796 // Timeout occurs, and page is automatically reloaded.
1797 FailLoadsAfterLogin(browser
, 1);
1800 void CaptivePortalBrowserTest::SetSlowSSLLoadTime(
1801 CaptivePortalTabReloader
* tab_reloader
,
1802 base::TimeDelta slow_ssl_load_time
) {
1803 tab_reloader
->set_slow_ssl_load_time(slow_ssl_load_time
);
1806 CaptivePortalTabReloader
* CaptivePortalBrowserTest::GetTabReloader(
1807 WebContents
* web_contents
) const {
1808 return CaptivePortalTabHelper::FromWebContents(web_contents
)->
1809 GetTabReloaderForTest();
1812 // Make sure there's no test for a captive portal on HTTP timeouts. This will
1813 // also trigger the link doctor page, which results in the load of a second
1815 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest
, HttpTimeout
) {
1816 GURL url
= URLRequestFailedJob::GetMockHttpUrl(net::ERR_CONNECTION_TIMED_OUT
);
1817 NavigateToPageExpectNoTest(browser(), url
, 2);
1820 // Make sure there's no check for a captive portal on HTTPS errors other than
1821 // timeouts, when they preempt the slow load timer.
1822 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest
, HttpsNonTimeoutError
) {
1823 GURL url
= URLRequestFailedJob::GetMockHttpsUrl(net::ERR_UNEXPECTED
);
1824 NavigateToPageExpectNoTest(browser(), url
, 1);
1827 // Make sure no captive portal test triggers on HTTPS timeouts of iframes.
1828 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest
, HttpsIframeTimeout
) {
1829 // Use an HTTPS server for the top level page.
1830 net::SpawnedTestServer
https_server(
1831 net::SpawnedTestServer::TYPE_HTTPS
, net::SpawnedTestServer::kLocalhost
,
1832 base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
1833 ASSERT_TRUE(https_server
.Start());
1835 GURL url
= https_server
.GetURL(kTestServerIframeTimeoutPath
);
1836 NavigateToPageExpectNoTest(browser(), url
, 1);
1839 // Check the captive portal result when the test request reports a network
1840 // error. The check is triggered by a slow loading page, and the page
1841 // errors out only after getting a captive portal result.
1842 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest
, RequestFails
) {
1843 SetUpCaptivePortalService(
1844 browser()->profile(),
1845 URLRequestFailedJob::GetMockHttpUrl(net::ERR_CONNECTION_CLOSED
));
1846 SlowLoadNoCaptivePortal(browser(), captive_portal::RESULT_NO_RESPONSE
);
1849 // Same as above, but for the rather unlikely case that the connection times out
1850 // before the timer triggers.
1851 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest
, RequestFailsFastTimout
) {
1852 SetUpCaptivePortalService(
1853 browser()->profile(),
1854 URLRequestFailedJob::GetMockHttpUrl(net::ERR_CONNECTION_CLOSED
));
1855 FastTimeoutNoCaptivePortal(browser(), captive_portal::RESULT_NO_RESPONSE
);
1858 // Checks the case that captive portal detection is disabled.
1859 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest
, Disabled
) {
1860 EnableCaptivePortalDetection(browser()->profile(), false);
1861 SlowLoadNoCaptivePortal(browser(), captive_portal::RESULT_INTERNET_CONNECTED
);
1864 // Checks that we look for a captive portal on HTTPS timeouts and don't reload
1865 // the error tab when the captive portal probe gets a 204 response, indicating
1866 // there is no captive portal.
1867 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest
, InternetConnected
) {
1868 // Can't just use SetBehindCaptivePortal(false), since then there wouldn't
1870 ASSERT_TRUE(test_server()->Start());
1871 SetUpCaptivePortalService(browser()->profile(),
1872 test_server()->GetURL("nocontent"));
1873 SlowLoadNoCaptivePortal(browser(), captive_portal::RESULT_INTERNET_CONNECTED
);
1876 // Checks that no login page is opened when the HTTP test URL redirects to an
1877 // SSL certificate error.
1878 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest
, RedirectSSLCertError
) {
1879 // Need an HTTP TestServer to handle a dynamically created server redirect.
1880 ASSERT_TRUE(test_server()->Start());
1882 net::SpawnedTestServer::SSLOptions ssl_options
;
1883 ssl_options
.server_certificate
=
1884 net::SpawnedTestServer::SSLOptions::CERT_MISMATCHED_NAME
;
1885 net::SpawnedTestServer
https_server(
1886 net::SpawnedTestServer::TYPE_HTTPS
, ssl_options
,
1887 base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
1888 ASSERT_TRUE(https_server
.Start());
1890 GURL ssl_login_url
= https_server
.GetURL(kTestServerLoginPath
);
1892 CaptivePortalService
* captive_portal_service
=
1893 CaptivePortalServiceFactory::GetForProfile(browser()->profile());
1894 ASSERT_TRUE(captive_portal_service
);
1895 SetUpCaptivePortalService(
1896 browser()->profile(),
1897 test_server()->GetURL(CreateServerRedirect(ssl_login_url
.spec())));
1899 SlowLoadNoCaptivePortal(browser(), captive_portal::RESULT_NO_RESPONSE
);
1902 // A slow SSL load triggers a captive portal check. The user logs on before
1903 // the SSL page times out. We wait for the timeout and subsequent reload.
1904 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest
, Login
) {
1905 // Load starts, detect captive portal and open up a login tab.
1906 SlowLoadBehindCaptivePortal(browser(), true);
1908 // Log in. One loading tab, no timed out ones.
1909 Login(browser(), 1, 0);
1911 // Timeout occurs, and page is automatically reloaded.
1912 FailLoadsAfterLogin(browser(), 1);
1915 // Same as above, except we make sure everything works with an incognito
1916 // profile. Main issues it tests for are that the incognito has its own
1917 // non-NULL captive portal service, and we open the tab in the correct
1919 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest
, LoginIncognito
) {
1920 // This will watch tabs for both profiles, but only used to make sure no
1921 // navigations occur for the non-incognito profile.
1922 MultiNavigationObserver navigation_observer
;
1923 CaptivePortalObserver
non_incognito_portal_observer(browser()->profile());
1925 Browser
* incognito_browser
= CreateIncognitoBrowser();
1926 EnableCaptivePortalDetection(incognito_browser
->profile(), true);
1927 SetUpCaptivePortalService(incognito_browser
->profile(),
1928 GURL(kMockCaptivePortalTestUrl
));
1930 SlowLoadBehindCaptivePortal(incognito_browser
, true);
1932 TabStripModel
* tab_strip_model
= browser()->tab_strip_model();
1933 EXPECT_EQ(1, tab_strip_model
->count());
1934 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
,
1935 GetStateOfTabReloaderAt(browser(), 0));
1937 Login(incognito_browser
, 1, 0);
1938 FailLoadsAfterLogin(incognito_browser
, 1);
1940 EXPECT_EQ(1, tab_strip_model
->count());
1941 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
,
1942 GetStateOfTabReloaderAt(browser(), 0));
1944 EXPECT_EQ(0, navigation_observer
.NumNavigationsForTab(
1945 tab_strip_model
->GetWebContentsAt(0)));
1946 EXPECT_EQ(0, non_incognito_portal_observer
.num_results_received());
1949 // The captive portal page is opened before the SSL page times out,
1950 // but the user logs in only after the page times out.
1951 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest
, LoginSlow
) {
1952 SlowLoadBehindCaptivePortal(browser(), true);
1953 FailLoadsWithoutLogin(browser(), 1);
1954 Login(browser(), 0, 1);
1957 // Checks the unlikely case that the tab times out before the timer triggers.
1958 // This most likely won't happen, but should still work:
1959 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest
, LoginFastTimeout
) {
1960 FastTimeoutBehindCaptivePortal(browser(), true);
1961 Login(browser(), 0, 1);
1964 // A cert error triggers a captive portal check and results in opening a login
1966 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest
,
1967 ShowCaptivePortalInterstitialOnCertError
) {
1968 net::SpawnedTestServer::SSLOptions https_options
;
1969 https_options
.server_certificate
=
1970 net::SpawnedTestServer::SSLOptions::CERT_MISMATCHED_NAME
;
1971 net::SpawnedTestServer
https_server(
1972 net::SpawnedTestServer::TYPE_HTTPS
, https_options
,
1973 base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
1974 ASSERT_TRUE(https_server
.Start());
1976 TabStripModel
* tab_strip_model
= browser()->tab_strip_model();
1977 WebContents
* broken_tab_contents
= tab_strip_model
->GetActiveWebContents();
1979 // The path does not matter.
1980 GURL cert_error_url
= https_server
.GetURL(kTestServerLoginPath
);
1981 int cert_error_tab_index
= tab_strip_model
->active_index();
1982 // The interstitial should trigger a captive portal check when it opens, just
1983 // like navigating to kMockHttpsQuickTimeoutUrl.
1984 FastErrorBehindCaptivePortal(browser(), true, cert_error_url
, false);
1985 EXPECT_EQ(CaptivePortalBlockingPage::kTypeForTesting
,
1986 GetInterstitialType(broken_tab_contents
));
1988 // Switch to the interstitial and click the |Connect| button. Should switch
1989 // active tab to the captive portal landing page.
1990 int login_tab_index
= tab_strip_model
->active_index();
1991 tab_strip_model
->ActivateTabAt(cert_error_tab_index
, false);
1992 // Wait for the interstitial to load all the JavaScript code. Otherwise,
1993 // trying to click on a button will fail.
1994 content::RenderFrameHost
* rfh
=
1995 broken_tab_contents
->GetInterstitialPage()->GetMainFrame();
1996 EXPECT_TRUE(WaitForRenderFrameReady(rfh
));
1997 const char kClickConnectButtonJS
[] =
1998 "document.getElementById('primary-button').click();";
2000 content::ExecuteScript(rfh
, kClickConnectButtonJS
));
2001 EXPECT_EQ(login_tab_index
, tab_strip_model
->active_index());
2003 // For completeness, close the login tab and try clicking |Connect| again.
2004 // A new login tab should open.
2005 EXPECT_EQ(1, login_tab_index
);
2006 content::WebContentsDestroyedWatcher
destroyed_watcher(
2007 tab_strip_model
->GetActiveWebContents());
2009 tab_strip_model
->CloseWebContentsAt(tab_strip_model
->active_index(), 0));
2010 destroyed_watcher
.Wait();
2011 MultiNavigationObserver navigation_observer
;
2013 content::ExecuteScript(rfh
, kClickConnectButtonJS
));
2014 navigation_observer
.WaitForNavigations(1);
2015 EXPECT_EQ(login_tab_index
, tab_strip_model
->active_index());
2017 LoginCertError(browser());
2019 // Once logged in, broken tab should reload and display the SSL interstitial.
2020 WaitForInterstitialAttach(broken_tab_contents
);
2021 tab_strip_model
->ActivateTabAt(cert_error_tab_index
, false);
2023 EXPECT_EQ(SSLBlockingPage::kTypeForTesting
,
2024 GetInterstitialType(tab_strip_model
->GetActiveWebContents()));
2026 // Trigger another captive portal check while the SSL interstitial is showing.
2027 // At this point the user is logged in to the captive portal, so the captive
2028 // portal interstitial shouldn't get recreated.
2029 CaptivePortalObserver
portal_observer(browser()->profile());
2030 CaptivePortalService
* captive_portal_service
=
2031 CaptivePortalServiceFactory::GetForProfile(browser()->profile());
2032 captive_portal_service
->DetectCaptivePortal();
2033 portal_observer
.WaitForResults(1);
2034 EXPECT_EQ(SSLBlockingPage::kTypeForTesting
,
2035 GetInterstitialType(broken_tab_contents
));
2037 // A captive portal appears. Trigger a final captive portal check. The
2038 // captive portal interstitial should still not get recreated.
2039 factory_
.SetBehindCaptivePortal(true);
2040 CaptivePortalObserver
final_portal_observer(browser()->profile());
2041 captive_portal_service
->DetectCaptivePortal();
2042 final_portal_observer
.WaitForResults(1);
2043 EXPECT_EQ(SSLBlockingPage::kTypeForTesting
,
2044 GetInterstitialType(broken_tab_contents
));
2047 // Tests this scenario:
2048 // - Portal probe requests are ignored, so that no captive portal result can
2050 // - A cert error triggers an interstitial timer with a very long timeout.
2051 // - No captive portal results arrive, causing the tab to appear as loading
2052 // indefinitely (because probe requests are ignored).
2053 // - Stopping the page load shouldn't result in any interstitials.
2054 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest
,
2055 InterstitialTimerStopNavigationWhileLoading
) {
2056 net::SpawnedTestServer::SSLOptions https_options
;
2057 https_options
.server_certificate
=
2058 net::SpawnedTestServer::SSLOptions::CERT_MISMATCHED_NAME
;
2059 net::SpawnedTestServer
https_server(
2060 net::SpawnedTestServer::TYPE_HTTPS
, https_options
,
2061 base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
2062 ASSERT_TRUE(https_server
.Start());
2063 // The path does not matter.
2064 GURL cert_error_url
= https_server
.GetURL(kTestServerLoginPath
);
2066 TabStripModel
* tab_strip_model
= browser()->tab_strip_model();
2067 WebContents
* broken_tab_contents
= tab_strip_model
->GetActiveWebContents();
2069 CaptivePortalObserver
portal_observer1(browser()->profile());
2070 FastErrorWithInterstitialTimer(browser(), cert_error_url
);
2072 // Page appears loading. Stop the navigation. There should be no interstitial.
2073 MultiNavigationObserver test_navigation_observer
;
2074 broken_tab_contents
->Stop();
2075 test_navigation_observer
.WaitForNavigations(1);
2077 // Make sure that the |ssl_error_handler| is deleted if page load is stopped.
2078 EXPECT_TRUE(nullptr == SSLErrorHandler::FromWebContents(broken_tab_contents
));
2080 EXPECT_FALSE(broken_tab_contents
->ShowingInterstitialPage());
2081 EXPECT_FALSE(broken_tab_contents
->IsLoading());
2082 EXPECT_EQ(0, portal_observer1
.num_results_received());
2083 EXPECT_EQ(0, NumLoadingTabs());
2084 EXPECT_FALSE(CheckPending(browser()));
2085 EXPECT_EQ(1, browser()->tab_strip_model()->count());
2086 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
,
2087 GetStateOfTabReloaderAt(browser(), 0));
2089 // Re-enable captive portal checks and fire one. The result should be ignored.
2090 RespondToProbeRequests(true);
2091 CaptivePortalObserver
portal_observer2(browser()->profile());
2092 CaptivePortalService
* captive_portal_service
=
2093 CaptivePortalServiceFactory::GetForProfile(browser()->profile());
2094 captive_portal_service
->DetectCaptivePortal();
2095 portal_observer2
.WaitForResults(1);
2097 EXPECT_FALSE(broken_tab_contents
->ShowingInterstitialPage());
2098 EXPECT_FALSE(broken_tab_contents
->IsLoading());
2099 EXPECT_EQ(1, portal_observer2
.num_results_received());
2100 EXPECT_EQ(captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL
,
2101 portal_observer2
.captive_portal_result());
2102 EXPECT_EQ(0, NumLoadingTabs());
2103 EXPECT_FALSE(CheckPending(browser()));
2104 EXPECT_EQ(1, browser()->tab_strip_model()->count());
2105 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
,
2106 GetStateOfTabReloaderAt(browser(), 0));
2109 // Same as above, but instead of stopping, the loading page is reloaded. The end
2110 // result is the same. (i.e. page load stops, no interstitials shown)
2111 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest
,
2112 InterstitialTimerReloadWhileLoading
) {
2113 net::SpawnedTestServer::SSLOptions https_options
;
2114 https_options
.server_certificate
=
2115 net::SpawnedTestServer::SSLOptions::CERT_MISMATCHED_NAME
;
2116 net::SpawnedTestServer
https_server(
2117 net::SpawnedTestServer::TYPE_HTTPS
, https_options
,
2118 base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
2119 ASSERT_TRUE(https_server
.Start());
2120 // The path does not matter.
2121 GURL cert_error_url
= https_server
.GetURL(kTestServerLoginPath
);
2123 TabStripModel
* tab_strip_model
= browser()->tab_strip_model();
2124 WebContents
* broken_tab_contents
= tab_strip_model
->GetActiveWebContents();
2126 CaptivePortalObserver
portal_observer(browser()->profile());
2127 FastErrorWithInterstitialTimer(browser(), cert_error_url
);
2129 // Page appears loading. Reloading it cancels the page load. Since the load is
2130 // stopped, no cert error occurs and SSLErrorHandler isn't instantiated.
2131 MultiNavigationObserver test_navigation_observer
;
2132 chrome::Reload(browser(), CURRENT_TAB
);
2133 test_navigation_observer
.WaitForNavigations(2);
2135 // Make sure that the |ssl_error_handler| is deleted.
2136 EXPECT_TRUE(nullptr == SSLErrorHandler::FromWebContents(broken_tab_contents
));
2138 EXPECT_FALSE(broken_tab_contents
->ShowingInterstitialPage());
2139 EXPECT_FALSE(broken_tab_contents
->IsLoading());
2140 EXPECT_EQ(0, portal_observer
.num_results_received());
2141 EXPECT_EQ(2, test_navigation_observer
.num_navigations());
2142 EXPECT_EQ(0, NumLoadingTabs());
2143 EXPECT_FALSE(CheckPending(browser()));
2144 EXPECT_EQ(1, browser()->tab_strip_model()->count());
2145 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
,
2146 GetStateOfTabReloaderAt(browser(), 0));
2148 // Re-enable captive portal checks and fire one. The result should be ignored.
2149 RespondToProbeRequests(true);
2150 CaptivePortalObserver
portal_observer2(browser()->profile());
2151 CaptivePortalService
* captive_portal_service
=
2152 CaptivePortalServiceFactory::GetForProfile(browser()->profile());
2153 captive_portal_service
->DetectCaptivePortal();
2154 portal_observer2
.WaitForResults(1);
2156 EXPECT_FALSE(broken_tab_contents
->ShowingInterstitialPage());
2157 EXPECT_FALSE(broken_tab_contents
->IsLoading());
2158 EXPECT_EQ(1, portal_observer2
.num_results_received());
2159 EXPECT_EQ(captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL
,
2160 portal_observer2
.captive_portal_result());
2161 EXPECT_EQ(0, NumLoadingTabs());
2162 EXPECT_FALSE(CheckPending(browser()));
2163 EXPECT_EQ(1, browser()->tab_strip_model()->count());
2164 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
,
2165 GetStateOfTabReloaderAt(browser(), 0));
2168 // Same as |InterstitialTimerReloadWhileLoading_NoSSLError|, but instead of
2169 // reloading, the page is navigated away. The new page should load, and no
2170 // interstitials should be shown.
2171 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest
,
2172 InterstitialTimerNavigateAwayWhileLoading
) {
2173 net::SpawnedTestServer::SSLOptions https_options
;
2174 https_options
.server_certificate
=
2175 net::SpawnedTestServer::SSLOptions::CERT_MISMATCHED_NAME
;
2176 net::SpawnedTestServer
https_server(
2177 net::SpawnedTestServer::TYPE_HTTPS
, https_options
,
2178 base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
2179 ASSERT_TRUE(https_server
.Start());
2180 // The path does not matter.
2181 GURL cert_error_url
= https_server
.GetURL(kTestServerLoginPath
);
2183 TabStripModel
* tab_strip_model
= browser()->tab_strip_model();
2184 WebContents
* broken_tab_contents
= tab_strip_model
->GetActiveWebContents();
2186 CaptivePortalObserver
portal_observer(browser()->profile());
2187 FastErrorWithInterstitialTimer(browser(), cert_error_url
);
2189 // Page appears loading. Navigating away shouldn't result in any interstitial.
2190 // Can't use ui_test_utils::NavigateToURLWithDisposition because it waits for
2191 // a load stop notification before starting a new navigation.
2192 MultiNavigationObserver test_navigation_observer
;
2193 browser()->OpenURL(content::OpenURLParams(
2194 URLRequestMockHTTPJob::GetMockUrl(
2195 base::FilePath(FILE_PATH_LITERAL("title2.html"))),
2196 content::Referrer(),
2198 ui::PAGE_TRANSITION_TYPED
, false));
2199 // Expect two navigations: First one for stopping the hanging page, second one
2200 // for completing the load of the above navigation.
2201 test_navigation_observer
.WaitForNavigations(2);
2203 // Make sure that the |ssl_error_handler| is deleted.
2204 EXPECT_TRUE(nullptr == SSLErrorHandler::FromWebContents(broken_tab_contents
));
2206 EXPECT_FALSE(broken_tab_contents
->ShowingInterstitialPage());
2207 EXPECT_FALSE(broken_tab_contents
->IsLoading());
2208 EXPECT_EQ(0, portal_observer
.num_results_received());
2209 EXPECT_EQ(2, test_navigation_observer
.num_navigations());
2210 EXPECT_EQ(0, NumLoadingTabs());
2211 EXPECT_FALSE(CheckPending(browser()));
2212 EXPECT_EQ(1, browser()->tab_strip_model()->count());
2213 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
,
2214 GetStateOfTabReloaderAt(browser(), 0));
2216 // Re-enable captive portal checks and fire one. The result should be ignored.
2217 RespondToProbeRequests(true);
2218 CaptivePortalObserver
portal_observer2(browser()->profile());
2219 CaptivePortalService
* captive_portal_service
=
2220 CaptivePortalServiceFactory::GetForProfile(browser()->profile());
2221 captive_portal_service
->DetectCaptivePortal();
2222 portal_observer2
.WaitForResults(1);
2224 EXPECT_FALSE(broken_tab_contents
->ShowingInterstitialPage());
2225 EXPECT_FALSE(broken_tab_contents
->IsLoading());
2226 EXPECT_EQ(1, portal_observer2
.num_results_received());
2227 EXPECT_EQ(captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL
,
2228 portal_observer2
.captive_portal_result());
2229 EXPECT_EQ(0, NumLoadingTabs());
2230 EXPECT_FALSE(CheckPending(browser()));
2231 EXPECT_EQ(1, browser()->tab_strip_model()->count());
2232 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
,
2233 GetStateOfTabReloaderAt(browser(), 0));
2236 // Same as above, but the hanging load is interrupted by a navigation to the
2237 // same page, this time committing the navigation. This should end up with an
2238 // SSL interstitial when not behind a captive portal. This ensures that a new
2239 // |SSLErrorHandler| is created on a new navigation, even though the tab's
2240 // WebContents doesn't change.
2241 IN_PROC_BROWSER_TEST_F(
2242 CaptivePortalBrowserTest
,
2243 InterstitialTimerNavigateWhileLoading_EndWithSSLInterstitial
) {
2244 net::SpawnedTestServer::SSLOptions https_options
;
2245 https_options
.server_certificate
=
2246 net::SpawnedTestServer::SSLOptions::CERT_MISMATCHED_NAME
;
2247 net::SpawnedTestServer
https_server(
2248 net::SpawnedTestServer::TYPE_HTTPS
, https_options
,
2249 base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
2250 ASSERT_TRUE(https_server
.Start());
2251 // The path does not matter.
2252 GURL cert_error_url
= https_server
.GetURL(kTestServerLoginPath
);
2253 factory_
.SetBehindCaptivePortal(false);
2255 TabStripModel
* tab_strip_model
= browser()->tab_strip_model();
2256 WebContents
* broken_tab_contents
= tab_strip_model
->GetActiveWebContents();
2258 FastErrorWithInterstitialTimer(browser(), cert_error_url
);
2259 // Page appears loading. Turn on response to probe request again, and navigate
2260 // to the same page. This should result in a cert error which should
2261 // instantiate an |SSLErrorHandler| and end up showing an SSL interstitial.
2262 RespondToProbeRequests(true);
2263 // Can't have ui_test_utils do the navigation because it will wait for loading
2264 // tabs to stop loading before navigating.
2265 CaptivePortalObserver
portal_observer(browser()->profile());
2266 MultiNavigationObserver test_navigation_observer
;
2267 browser()->OpenURL(content::OpenURLParams(cert_error_url
, content::Referrer(),
2269 ui::PAGE_TRANSITION_TYPED
, false));
2270 // Expect two navigations: First one for stopping the hanging page, second one
2271 // for completing the load of the above navigation.
2272 test_navigation_observer
.WaitForNavigations(2);
2273 // Should end up with an SSL interstitial.
2274 WaitForInterstitialAttach(broken_tab_contents
);
2275 ASSERT_TRUE(broken_tab_contents
->ShowingInterstitialPage());
2276 EXPECT_EQ(SSLBlockingPage::kTypeForTesting
,
2277 broken_tab_contents
->GetInterstitialPage()
2278 ->GetDelegateForTesting()
2279 ->GetTypeForTesting());
2280 EXPECT_FALSE(broken_tab_contents
->IsLoading());
2281 EXPECT_EQ(1, portal_observer
.num_results_received());
2282 EXPECT_EQ(captive_portal::RESULT_INTERNET_CONNECTED
,
2283 portal_observer
.captive_portal_result());
2284 EXPECT_EQ(0, NumLoadingTabs());
2285 EXPECT_FALSE(CheckPending(browser()));
2286 EXPECT_EQ(1, browser()->tab_strip_model()->count());
2287 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
,
2288 GetStateOfTabReloaderAt(browser(), 0));
2291 // Same as above, but this time behind a captive portal.
2292 IN_PROC_BROWSER_TEST_F(
2293 CaptivePortalBrowserTest
,
2294 InterstitialTimerNavigateWhileLoading_EndWithCaptivePortalInterstitial
) {
2295 net::SpawnedTestServer::SSLOptions https_options
;
2296 https_options
.server_certificate
=
2297 net::SpawnedTestServer::SSLOptions::CERT_MISMATCHED_NAME
;
2298 net::SpawnedTestServer
https_server(
2299 net::SpawnedTestServer::TYPE_HTTPS
, https_options
,
2300 base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
2301 ASSERT_TRUE(https_server
.Start());
2302 // The path does not matter.
2303 GURL cert_error_url
= https_server
.GetURL(kTestServerLoginPath
);
2304 factory_
.SetBehindCaptivePortal(true);
2306 TabStripModel
* tab_strip_model
= browser()->tab_strip_model();
2307 WebContents
* broken_tab_contents
= tab_strip_model
->GetActiveWebContents();
2308 int initial_tab_count
= tab_strip_model
->count();
2310 FastErrorWithInterstitialTimer(browser(), cert_error_url
);
2311 // Page appears loading. Turn on response to probe request again, and navigate
2312 // to the same page. This should result in a cert error which should
2313 // instantiate an |SSLErrorHandler| and end up showing an SSL.
2314 RespondToProbeRequests(true);
2315 // Can't have ui_test_utils do the navigation because it will wait for loading
2316 // tabs to stop loading before navigating.
2317 CaptivePortalObserver
portal_observer(browser()->profile());
2318 MultiNavigationObserver test_navigation_observer
;
2319 browser()->OpenURL(content::OpenURLParams(cert_error_url
, content::Referrer(),
2321 ui::PAGE_TRANSITION_TYPED
, false));
2322 // Expect three navigations:
2323 // 1- For stopping the hanging page.
2324 // 2- For completing the load of the above navigation.
2325 // 3- For completing the load of the login tab.
2326 test_navigation_observer
.WaitForNavigations(3);
2327 // Should end up with a captive portal interstitial and a new login tab.
2328 WaitForInterstitialAttach(broken_tab_contents
);
2329 ASSERT_TRUE(broken_tab_contents
->ShowingInterstitialPage());
2330 EXPECT_EQ(CaptivePortalBlockingPage::kTypeForTesting
,
2331 broken_tab_contents
->GetInterstitialPage()
2332 ->GetDelegateForTesting()
2333 ->GetTypeForTesting());
2334 ASSERT_EQ(initial_tab_count
+ 1, tab_strip_model
->count());
2335 EXPECT_EQ(initial_tab_count
, tab_strip_model
->active_index());
2336 EXPECT_FALSE(broken_tab_contents
->IsLoading());
2337 EXPECT_EQ(1, portal_observer
.num_results_received());
2338 EXPECT_EQ(captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL
,
2339 portal_observer
.captive_portal_result());
2340 EXPECT_EQ(0, NumLoadingTabs());
2341 EXPECT_FALSE(CheckPending(browser()));
2342 EXPECT_EQ(CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL
,
2343 GetStateOfTabReloaderAt(browser(), 0));
2344 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
,
2345 GetStateOfTabReloaderAt(browser(), 1));
2346 EXPECT_TRUE(IsLoginTab(tab_strip_model
->GetWebContentsAt(1)));
2349 // A cert error triggers a captive portal check and results in opening a login
2350 // tab. The user then logs in and the page with the error is reloaded.
2351 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest
, SSLCertErrorLogin
) {
2352 // Need an HTTP TestServer to handle a dynamically created server redirect.
2353 ASSERT_TRUE(test_server()->Start());
2355 net::SpawnedTestServer::SSLOptions https_options
;
2356 https_options
.server_certificate
=
2357 net::SpawnedTestServer::SSLOptions::CERT_MISMATCHED_NAME
;
2358 net::SpawnedTestServer
https_server(
2359 net::SpawnedTestServer::TYPE_HTTPS
, https_options
,
2360 base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
2361 ASSERT_TRUE(https_server
.Start());
2363 // Set SSL interstitial delay to zero so that a captive portal result can not
2364 // arrive during this window, so an SSL interstitial is displayed instead
2365 // of a captive portal error page.
2366 SSLErrorHandler::SetInterstitialDelayForTest(base::TimeDelta());
2367 TabStripModel
* tab_strip_model
= browser()->tab_strip_model();
2368 WebContents
* broken_tab_contents
= tab_strip_model
->GetActiveWebContents();
2370 // Setting the delay to zero above has a race condition: A captive portal
2371 // result triggered by a cert error can arrive before the SSL interstitial
2372 // display timer is fired, even though it's set to zero.
2373 // To avoid this, disable captive portal checks until the SSL interstitial is
2374 // displayed. Once it's displayed, enable portal checks and fire one.
2375 bool delay_portal_response_until_interstital
= true;
2377 // The path does not matter.
2378 GURL cert_error_url
= https_server
.GetURL(kTestServerLoginPath
);
2379 // A captive portal check is triggered in FastErrorBehindCaptivePortal.
2380 FastErrorBehindCaptivePortal(
2384 delay_portal_response_until_interstital
);
2386 EXPECT_EQ(SSLBlockingPage::kTypeForTesting
,
2387 GetInterstitialType(broken_tab_contents
));
2389 LoginCertError(browser());
2392 // Tries navigating both the tab that encounters an SSL timeout and the
2393 // login tab twice, only logging in the second time.
2394 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest
, LoginExtraNavigations
) {
2395 FastTimeoutBehindCaptivePortal(browser(), true);
2397 // Activate the timed out tab and navigate it to a timeout again.
2398 TabStripModel
* tab_strip_model
= browser()->tab_strip_model();
2399 tab_strip_model
->ActivateTabAt(0, true);
2400 FastTimeoutBehindCaptivePortal(browser(), false);
2402 // Activate and navigate the captive portal tab. This should not trigger a
2403 // reload of the tab with the error.
2404 tab_strip_model
->ActivateTabAt(1, true);
2405 NavigateLoginTab(browser(), 0, 1);
2407 // Simulate logging in.
2408 Login(browser(), 0, 1);
2411 // After the first SSL timeout, closes the login tab and makes sure it's opened
2412 // it again on a second timeout.
2413 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest
, CloseLoginTab
) {
2414 // First load starts, opens a login tab, and then times out.
2415 SlowLoadBehindCaptivePortal(browser(), true);
2416 FailLoadsWithoutLogin(browser(), 1);
2419 chrome::CloseTab(browser());
2421 // Go through the standard slow load login, and make sure it still works.
2422 SlowLoadBehindCaptivePortal(browser(), true);
2423 Login(browser(), 1, 0);
2424 FailLoadsAfterLogin(browser(), 1);
2427 // Checks that two tabs with SSL timeouts in the same window work. Both
2428 // tabs only timeout after logging in.
2429 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest
, TwoBrokenTabs
) {
2430 SlowLoadBehindCaptivePortal(browser(), true);
2432 // Can't set the TabReloader HTTPS timeout on a new tab without doing some
2433 // acrobatics, so open a new tab at a normal page, and then navigate it to a
2435 MultiNavigationObserver navigation_observer
;
2436 CaptivePortalObserver
portal_observer(browser()->profile());
2437 ui_test_utils::NavigateToURLWithDisposition(
2439 URLRequestMockHTTPJob::GetMockUrl(
2440 base::FilePath(FILE_PATH_LITERAL("title2.html"))),
2442 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION
);
2444 TabStripModel
* tab_strip_model
= browser()->tab_strip_model();
2445 ASSERT_EQ(3, tab_strip_model
->count());
2446 EXPECT_FALSE(CheckPending(browser()));
2447 EXPECT_EQ(0, portal_observer
.num_results_received());
2448 EXPECT_EQ(1, NumLoadingTabs());
2449 EXPECT_EQ(1, navigation_observer
.num_navigations());
2450 EXPECT_EQ(1, navigation_observer
.NumNavigationsForTab(
2451 tab_strip_model
->GetWebContentsAt(2)));
2452 ASSERT_EQ(CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL
,
2453 GetStateOfTabReloaderAt(browser(), 0));
2454 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
,
2455 GetStateOfTabReloaderAt(browser(), 1));
2456 ASSERT_TRUE(IsLoginTab(tab_strip_model
->GetWebContentsAt(1)));
2457 ASSERT_EQ(CaptivePortalTabReloader::STATE_NONE
,
2458 GetStateOfTabReloaderAt(browser(), 2));
2459 ASSERT_EQ(2, tab_strip_model
->active_index());
2461 SlowLoadBehindCaptivePortal(browser(), false);
2463 tab_strip_model
->ActivateTabAt(1, true);
2464 Login(browser(), 2, 0);
2465 FailLoadsAfterLogin(browser(), 2);
2468 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest
, AbortLoad
) {
2469 SlowLoadBehindCaptivePortal(browser(), true);
2471 // Abandon the request.
2472 URLRequestTimeoutOnDemandJob::WaitForJobs(1);
2473 URLRequestTimeoutOnDemandJob::AbandonJobs(1);
2475 CaptivePortalObserver
portal_observer(browser()->profile());
2476 MultiNavigationObserver navigation_observer
;
2478 // Switch back to the hung tab from the login tab, and abort the navigation.
2479 TabStripModel
* tab_strip_model
= browser()->tab_strip_model();
2480 tab_strip_model
->ActivateTabAt(0, true);
2481 chrome::Stop(browser());
2482 navigation_observer
.WaitForNavigations(1);
2484 EXPECT_EQ(0, NumBrokenTabs());
2485 EXPECT_EQ(0, portal_observer
.num_results_received());
2486 EXPECT_FALSE(CheckPending(browser()));
2487 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
,
2488 GetStateOfTabReloaderAt(browser(), 0));
2490 tab_strip_model
->ActivateTabAt(1, true);
2491 Login(browser(), 0, 0);
2494 // Checks the case where the timed out tab is successfully navigated before
2496 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest
, NavigateBrokenTab
) {
2497 // Go to the error page.
2498 SlowLoadBehindCaptivePortal(browser(), true);
2499 FailLoadsWithoutLogin(browser(), 1);
2501 // Navigate the error tab to a non-error page.
2502 TabStripModel
* tab_strip_model
= browser()->tab_strip_model();
2503 tab_strip_model
->ActivateTabAt(0, true);
2504 ui_test_utils::NavigateToURL(
2505 browser(), URLRequestMockHTTPJob::GetMockUrl(
2506 base::FilePath(FILE_PATH_LITERAL("title2.html"))));
2507 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
,
2508 GetStateOfTabReloaderAt(browser(), 0));
2510 // Simulate logging in.
2511 tab_strip_model
->ActivateTabAt(1, true);
2512 Login(browser(), 0, 0);
2515 // Checks that captive portal detection triggers correctly when a same-site
2516 // navigation is cancelled by a navigation to the same site.
2517 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest
,
2518 NavigateLoadingTabToTimeoutSingleSite
) {
2519 RunNavigateLoadingTabToTimeoutTest(
2521 GURL(kMockHttpsUrl
),
2522 GURL(kMockHttpsUrl
),
2523 GURL(kMockHttpsUrl
));
2526 // Fails on Windows only, mostly on Win7. http://crbug.com/170033
2528 #define MAYBE_NavigateLoadingTabToTimeoutTwoSites \
2529 DISABLED_NavigateLoadingTabToTimeoutTwoSites
2531 #define MAYBE_NavigateLoadingTabToTimeoutTwoSites \
2532 NavigateLoadingTabToTimeoutTwoSites
2535 // Checks that captive portal detection triggers correctly when a same-site
2536 // navigation is cancelled by a navigation to another site.
2537 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest
,
2538 MAYBE_NavigateLoadingTabToTimeoutTwoSites
) {
2539 RunNavigateLoadingTabToTimeoutTest(
2541 GURL(kMockHttpsUrl
),
2542 GURL(kMockHttpsUrl
),
2543 GURL(kMockHttpsUrl2
));
2546 // Checks that captive portal detection triggers correctly when a cross-site
2547 // navigation is cancelled by a navigation to yet another site.
2548 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest
,
2549 NavigateLoadingTabToTimeoutThreeSites
) {
2550 RunNavigateLoadingTabToTimeoutTest(
2552 URLRequestMockHTTPJob::GetMockUrl(
2553 base::FilePath(FILE_PATH_LITERAL("title.html"))),
2554 GURL(kMockHttpsUrl
),
2555 GURL(kMockHttpsUrl2
));
2558 // Checks that navigating a timed out tab back clears its state.
2559 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest
, GoBack
) {
2560 // Navigate to a working page.
2561 ui_test_utils::NavigateToURL(
2563 URLRequestMockHTTPJob::GetMockUrl(
2564 base::FilePath(FILE_PATH_LITERAL("title2.html"))));
2566 // Go to the error page.
2567 SlowLoadBehindCaptivePortal(browser(), true);
2568 FailLoadsWithoutLogin(browser(), 1);
2570 CaptivePortalObserver
portal_observer(browser()->profile());
2571 MultiNavigationObserver navigation_observer
;
2573 // Activate the error page tab again and go back.
2574 TabStripModel
* tab_strip_model
= browser()->tab_strip_model();
2575 tab_strip_model
->ActivateTabAt(0, true);
2576 chrome::GoBack(browser(), CURRENT_TAB
);
2577 navigation_observer
.WaitForNavigations(1);
2579 EXPECT_EQ(1, navigation_observer
.NumNavigationsForTab(
2580 tab_strip_model
->GetWebContentsAt(0)));
2581 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
,
2582 GetStateOfTabReloaderAt(browser(), 0));
2583 EXPECT_EQ(0, portal_observer
.num_results_received());
2586 // Checks that navigating back to a timeout triggers captive portal detection.
2587 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest
, GoBackToTimeout
) {
2588 // Disable captive portal detection so the first navigation doesn't open a
2590 EnableCaptivePortalDetection(browser()->profile(), false);
2592 SlowLoadNoCaptivePortal(browser(), captive_portal::RESULT_INTERNET_CONNECTED
);
2594 // Navigate to a working page.
2595 ui_test_utils::NavigateToURL(
2596 browser(), URLRequestMockHTTPJob::GetMockUrl(
2597 base::FilePath(FILE_PATH_LITERAL("title2.html"))));
2598 ASSERT_EQ(CaptivePortalTabReloader::STATE_NONE
,
2599 GetStateOfTabReloaderAt(browser(), 0));
2601 EnableCaptivePortalDetection(browser()->profile(), true);
2603 TabStripModel
* tab_strip_model
= browser()->tab_strip_model();
2604 CaptivePortalTabReloader
* tab_reloader
=
2605 GetTabReloader(tab_strip_model
->GetActiveWebContents());
2606 ASSERT_TRUE(tab_reloader
);
2607 SetSlowSSLLoadTime(tab_reloader
, base::TimeDelta());
2609 // Go to the error page.
2610 MultiNavigationObserver navigation_observer
;
2611 CaptivePortalObserver
portal_observer(browser()->profile());
2612 chrome::GoBack(browser(), CURRENT_TAB
);
2614 // Wait for the check triggered by the broken tab and for the login tab to
2616 portal_observer
.WaitForResults(1);
2617 navigation_observer
.WaitForNavigations(1);
2618 // Make sure the request has been issued.
2619 URLRequestTimeoutOnDemandJob::WaitForJobs(1);
2621 EXPECT_EQ(1, portal_observer
.num_results_received());
2622 ASSERT_FALSE(CheckPending(browser()));
2623 ASSERT_EQ(captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL
,
2624 portal_observer
.captive_portal_result());
2626 ASSERT_EQ(CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL
,
2627 GetStateOfTabReloaderAt(browser(), 0));
2628 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
,
2629 GetStateOfTabReloaderAt(browser(), 1));
2630 ASSERT_TRUE(IsLoginTab(browser()->tab_strip_model()->GetWebContentsAt(1)));
2632 ASSERT_EQ(2, tab_strip_model
->count());
2633 EXPECT_EQ(1, tab_strip_model
->active_index());
2634 EXPECT_EQ(1, navigation_observer
.NumNavigationsForTab(
2635 tab_strip_model
->GetWebContentsAt(1)));
2636 EXPECT_EQ(1, NumLoadingTabs());
2638 SetSlowSSLLoadTime(tab_reloader
, base::TimeDelta::FromDays(1));
2639 Login(browser(), 1, 0);
2640 FailLoadsAfterLogin(browser(), 1);
2643 // Checks that reloading a timeout triggers captive portal detection.
2644 // Much like the last test, though the captive portal is disabled before
2645 // the inital navigation, rather than captive portal detection.
2646 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest
, ReloadTimeout
) {
2647 factory_
.SetBehindCaptivePortal(false);
2649 // Do the first navigation while not behind a captive portal.
2650 TabStripModel
* tab_strip_model
= browser()->tab_strip_model();
2651 CaptivePortalObserver
portal_observer(browser()->profile());
2652 ui_test_utils::NavigateToURL(browser(), GURL(kMockHttpsUrl
));
2653 ASSERT_EQ(0, portal_observer
.num_results_received());
2654 ASSERT_EQ(1, tab_strip_model
->count());
2656 // A captive portal spontaneously appears.
2657 factory_
.SetBehindCaptivePortal(true);
2659 CaptivePortalTabReloader
* tab_reloader
=
2660 GetTabReloader(tab_strip_model
->GetActiveWebContents());
2661 ASSERT_TRUE(tab_reloader
);
2662 SetSlowSSLLoadTime(tab_reloader
, base::TimeDelta());
2664 MultiNavigationObserver navigation_observer
;
2665 tab_strip_model
->GetActiveWebContents()->GetController().Reload(true);
2667 // Wait for the check triggered by the broken tab and for the login tab to
2669 portal_observer
.WaitForResults(1);
2670 navigation_observer
.WaitForNavigations(1);
2671 // Make sure the request has been issued.
2672 URLRequestTimeoutOnDemandJob::WaitForJobs(1);
2674 ASSERT_EQ(1, portal_observer
.num_results_received());
2675 ASSERT_FALSE(CheckPending(browser()));
2676 ASSERT_EQ(captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL
,
2677 portal_observer
.captive_portal_result());
2679 ASSERT_EQ(CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL
,
2680 GetStateOfTabReloaderAt(browser(), 0));
2681 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
,
2682 GetStateOfTabReloaderAt(browser(), 1));
2683 ASSERT_TRUE(IsLoginTab(tab_strip_model
->GetWebContentsAt(1)));
2685 ASSERT_EQ(2, tab_strip_model
->count());
2686 EXPECT_EQ(1, tab_strip_model
->active_index());
2687 EXPECT_EQ(1, navigation_observer
.NumNavigationsForTab(
2688 tab_strip_model
->GetWebContentsAt(1)));
2689 EXPECT_EQ(1, NumLoadingTabs());
2691 SetSlowSSLLoadTime(tab_reloader
, base::TimeDelta::FromDays(1));
2692 Login(browser(), 1, 0);
2693 FailLoadsAfterLogin(browser(), 1);
2696 // Checks the case where there are two windows, and there's an SSL timeout in
2697 // the background one.
2698 // Disabled: http://crbug.com/134357
2699 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest
, DISABLED_TwoWindows
) {
2701 new Browser(Browser::CreateParams(browser()->profile(),
2702 browser()->host_desktop_type()));
2703 // Navigate the new browser window so it'll be shown and we can pick the
2705 ui_test_utils::NavigateToURL(browser2
, GURL(url::kAboutBlankURL
));
2707 // Generally, |browser2| will be the active window. However, if the
2708 // original browser window lost focus before creating the new one, such as
2709 // when running multiple tests at once, the original browser window may
2710 // remain the profile's active window.
2711 Browser
* active_browser
=
2712 chrome::FindTabbedBrowser(browser()->profile(), true,
2713 browser()->host_desktop_type());
2714 Browser
* inactive_browser
;
2715 if (active_browser
== browser2
) {
2716 // When only one test is running at a time, the new browser will probably be
2717 // on top, but when multiple tests are running at once, this is not
2719 inactive_browser
= browser();
2721 ASSERT_EQ(active_browser
, browser());
2722 inactive_browser
= browser2
;
2725 CaptivePortalObserver
portal_observer(browser()->profile());
2726 MultiNavigationObserver navigation_observer
;
2728 // Navigate the tab in the inactive browser to an SSL timeout. Have to use
2729 // chrome::NavigateParams and NEW_BACKGROUND_TAB to avoid activating the
2731 chrome::NavigateParams
params(inactive_browser
,
2732 GURL(kMockHttpsQuickTimeoutUrl
),
2733 ui::PAGE_TRANSITION_TYPED
);
2734 params
.disposition
= NEW_BACKGROUND_TAB
;
2735 params
.window_action
= chrome::NavigateParams::NO_ACTION
;
2736 ui_test_utils::NavigateToURL(¶ms
);
2737 navigation_observer
.WaitForNavigations(2);
2739 // Make sure the active window hasn't changed, and its new tab is
2741 ASSERT_EQ(active_browser
,
2742 chrome::FindTabbedBrowser(browser()->profile(), true,
2743 browser()->host_desktop_type()));
2744 ASSERT_EQ(1, active_browser
->tab_strip_model()->active_index());
2746 // Check that the only two navigated tabs were the new error tab in the
2747 // backround windows, and the login tab in the active window.
2748 EXPECT_EQ(1, navigation_observer
.NumNavigationsForTab(
2749 inactive_browser
->tab_strip_model()->GetWebContentsAt(1)));
2750 EXPECT_EQ(1, navigation_observer
.NumNavigationsForTab(
2751 active_browser
->tab_strip_model()->GetWebContentsAt(1)));
2752 EXPECT_EQ(0, NumLoadingTabs());
2754 // Check captive portal test results.
2755 portal_observer
.WaitForResults(1);
2756 ASSERT_EQ(captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL
,
2757 portal_observer
.captive_portal_result());
2758 EXPECT_EQ(1, portal_observer
.num_results_received());
2760 // Check the inactive browser.
2761 EXPECT_EQ(2, inactive_browser
->tab_strip_model()->count());
2762 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
,
2763 GetStateOfTabReloaderAt(inactive_browser
, 0));
2764 EXPECT_EQ(CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL
,
2765 GetStateOfTabReloaderAt(inactive_browser
, 1));
2767 // Check the active browser.
2768 ASSERT_EQ(2, active_browser
->tab_strip_model()->count());
2769 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
,
2770 GetStateOfTabReloaderAt(active_browser
, 0));
2771 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE
,
2772 GetStateOfTabReloaderAt(active_browser
, 1));
2774 IsLoginTab(active_browser
->tab_strip_model()->GetWebContentsAt(1)));
2776 // Simulate logging in.
2777 Login(active_browser
, 0, 1);
2780 // An HTTP page redirects to an HTTPS page loads slowly before timing out. A
2781 // captive portal is found, and then the user logs in before the original page
2783 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest
, HttpToHttpsRedirectLogin
) {
2784 ASSERT_TRUE(test_server()->Start());
2785 SlowLoadBehindCaptivePortal(
2788 test_server()->GetURL(CreateServerRedirect(kMockHttpsUrl
)),
2791 Login(browser(), 1, 0);
2792 FailLoadsAfterLogin(browser(), 1);
2795 // An HTTPS page redirects to an HTTP page.
2796 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest
, HttpsToHttpRedirect
) {
2797 // Use an HTTPS server for the top level page.
2798 net::SpawnedTestServer
https_server(
2799 net::SpawnedTestServer::TYPE_HTTPS
, net::SpawnedTestServer::kLocalhost
,
2800 base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
2801 ASSERT_TRUE(https_server
.Start());
2803 GURL http_timeout_url
=
2804 URLRequestFailedJob::GetMockHttpUrl(net::ERR_CONNECTION_TIMED_OUT
);
2806 // 2 navigations due to the Link Doctor.
2807 NavigateToPageExpectNoTest(
2809 https_server
.GetURL(CreateServerRedirect(http_timeout_url
.spec())),
2813 // Tests the 511 response code, along with an HTML redirect to a login page.
2814 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest
, Status511
) {
2815 SetUpCaptivePortalService(browser()->profile(),
2816 GURL(kMockCaptivePortal511Url
));
2817 SlowLoadBehindCaptivePortal(browser(), true, GURL(kMockHttpsUrl
), 2, 2);
2818 Login(browser(), 1, 0);
2819 FailLoadsAfterLogin(browser(), 1);
2822 // HSTS redirects an HTTP request to HTTPS, and the request then times out.
2823 // A captive portal is then detected, and a login tab opened, before logging
2825 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest
, HstsLogin
) {
2826 GURL::Replacements replacements
;
2827 replacements
.SetSchemeStr("http");
2828 GURL http_timeout_url
= GURL(kMockHttpsUrl
).ReplaceComponents(replacements
);
2830 URLRequestFailedJob::GetMockHttpUrl(net::ERR_CONNECTION_TIMED_OUT
);
2831 content::BrowserThread::PostTask(
2832 content::BrowserThread::IO
, FROM_HERE
,
2833 base::Bind(&AddHstsHost
,
2834 make_scoped_refptr(browser()->profile()->GetRequestContext()),
2835 http_timeout_url
.host()));
2837 SlowLoadBehindCaptivePortal(browser(), true, http_timeout_url
, 1, 1);
2838 Login(browser(), 1, 0);
2839 FailLoadsAfterLogin(browser(), 1);
2842 // A slow SSL load starts. The reloader triggers a captive portal check, finds a
2843 // captive portal. The SSL commits with a cert error, triggering another captive
2845 // The second check finds no captive portal. The reloader triggers a reload at
2846 // the same time SSL error handler tries to show an interstitial. Should result
2847 // in an SSL interstitial.
2848 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest
,
2849 InterstitialTimerCertErrorAfterSlowLoad
) {
2850 // Use a url that triggers a slow load, instead of creating an https server.
2851 GURL cert_error_url
= GURL(kMockHttpsUrl
);
2853 TabStripModel
* tab_strip_model
= browser()->tab_strip_model();
2854 int broken_tab_index
= tab_strip_model
->active_index();
2855 WebContents
* broken_tab_contents
= tab_strip_model
->GetActiveWebContents();
2856 SlowLoadBehindCaptivePortal(browser(), true, cert_error_url
, 1, 1);
2858 // No longer behind a captive portal. Committing the SSL page should trigger
2859 // an SSL interstitial which triggers a new captive portal check. Since there
2860 // is no captive portal anymore, should end up with an SSL interstitial.
2861 factory_
.SetBehindCaptivePortal(false);
2863 CaptivePortalObserver
portal_observer(browser()->profile());
2864 MultiNavigationObserver navigation_observer
;
2866 info
.cert_status
= net::CERT_STATUS_COMMON_NAME_INVALID
;
2868 net::ImportCertFromFile(net::GetTestCertsDirectory(), "ok_cert.pem");
2869 URLRequestTimeoutOnDemandJob::FailJobsWithCertError(1, info
);
2870 navigation_observer
.WaitForNavigations(1);
2872 EXPECT_EQ(CaptivePortalTabReloader::STATE_NEEDS_RELOAD
,
2873 GetStateOfTabReloaderAt(browser(), broken_tab_index
));
2875 WaitForInterstitialAttach(broken_tab_contents
);
2876 portal_observer
.WaitForResults(1);
2878 EXPECT_EQ(SSLBlockingPage::kTypeForTesting
,
2879 GetInterstitialType(broken_tab_contents
));