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