OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include <map> |
| 6 #include <set> |
| 7 |
| 8 #include "base/basictypes.h" |
| 9 #include "base/bind.h" |
| 10 #include "base/command_line.h" |
| 11 #include "base/compiler_specific.h" |
| 12 #include "base/file_path.h" |
| 13 #include "base/message_loop.h" |
| 14 #include "base/path_service.h" |
| 15 #include "base/utf_string_conversions.h" |
| 16 #include "chrome/browser/captive_portal/captive_portal_service.h" |
| 17 #include "chrome/browser/captive_portal/captive_portal_service_factory.h" |
| 18 #include "chrome/browser/captive_portal/captive_portal_tab_helper.h" |
| 19 #include "chrome/browser/captive_portal/captive_portal_tab_reloader.h" |
| 20 #include "chrome/browser/net/url_request_mock_util.h" |
| 21 #include "chrome/browser/prefs/pref_service.h" |
| 22 #include "chrome/browser/profiles/profile.h" |
| 23 #include "chrome/browser/ui/browser.h" |
| 24 #include "chrome/browser/ui/browser_finder.h" |
| 25 #include "chrome/browser/ui/browser_navigator.h" |
| 26 #include "chrome/browser/ui/tab_contents/tab_contents_iterator.h" |
| 27 #include "chrome/browser/ui/tab_contents/tab_contents.h" |
| 28 #include "chrome/common/chrome_notification_types.h" |
| 29 #include "chrome/common/chrome_paths.h" |
| 30 #include "chrome/common/chrome_switches.h" |
| 31 #include "chrome/common/pref_names.h" |
| 32 #include "chrome/test/base/in_process_browser_test.h" |
| 33 #include "chrome/test/base/ui_test_utils.h" |
| 34 #include "content/public/browser/browser_thread.h" |
| 35 #include "content/public/browser/navigation_controller.h" |
| 36 #include "content/public/browser/notification_observer.h" |
| 37 #include "content/public/browser/notification_registrar.h" |
| 38 #include "content/public/browser/notification_service.h" |
| 39 #include "content/public/browser/notification_types.h" |
| 40 #include "content/public/browser/render_view_host.h" |
| 41 #include "content/public/browser/web_contents.h" |
| 42 #include "content/public/common/url_constants.h" |
| 43 #include "content/test/net/url_request_failed_job.h" |
| 44 #include "content/test/net/url_request_mock_http_job.h" |
| 45 #include "net/base/net_errors.h" |
| 46 #include "net/url_request/url_request_filter.h" |
| 47 #include "net/url_request/url_request_job.h" |
| 48 #include "net/url_request/url_request_status.h" |
| 49 #include "testing/gtest/include/gtest/gtest.h" |
| 50 |
| 51 using content::BrowserThread; |
| 52 |
| 53 namespace captive_portal { |
| 54 |
| 55 namespace { |
| 56 |
| 57 // Path of the fake login page, when using the TestServer. |
| 58 const char* const kTestServerLoginPath = "files/captive_portal/login.html"; |
| 59 |
| 60 // Path of a page with an iframe that has a mock SSL timeout, when using the |
| 61 // TestServer. |
| 62 const char* const kTestServerIframeTimeoutPath = |
| 63 "files/captive_portal/iframe_timeout.html"; |
| 64 |
| 65 // The following URLs each have two different behaviors, depending on whether |
| 66 // URLRequestMockCaptivePortalJobFactory is currently simulating the presence |
| 67 // of a captive portal or not. |
| 68 |
| 69 // A mock URL for the CaptivePortalService's |test_url|. When behind a captive |
| 70 // portal, this URL return a mock login page. When connected to the Internet, |
| 71 // it returns a 204 response. |
| 72 const char* const kMockCaptivePortalTestUrl = |
| 73 "http://mock.captive.portal/captive_portal_test/"; |
| 74 |
| 75 // When behind a captive portal, this URL hangs without committing until a call |
| 76 // to URLRequestTimeoutOnDemandJob::FailRequests. When that function is called, |
| 77 // the request will time out. |
| 78 // |
| 79 // When connected to the Internet, this URL returns a non-error page. |
| 80 const char* const kMockHttpsUrl = "https://mock.captive.portal/long_timeout/"; |
| 81 |
| 82 // Same as kMockHttpsUrl, except the timeout happens instantly. |
| 83 const char* const kMockHttpsQuickTimeoutUrl = |
| 84 "https://mock.captive.portal/quick_timeout/"; |
| 85 |
| 86 // Expected title of a tab once an HTTPS load completes, when not behind a |
| 87 // captive portal. |
| 88 const char* const kInternetConnectedTitle = "Title Of Awesomeness"; |
| 89 |
| 90 // A URL request job that hangs until FailRequests() is called. Started jobs |
| 91 // are stored in a static class variable containing a linked list so that |
| 92 // FailRequests() can locate them. |
| 93 class URLRequestTimeoutOnDemandJob : public net::URLRequestJob, |
| 94 public base::NonThreadSafe { |
| 95 public: |
| 96 // net::URLRequestJob: |
| 97 virtual void Start() OVERRIDE; |
| 98 |
| 99 // All the public static methods below can be called on any thread. |
| 100 |
| 101 // Fails all active URLRequestFailOnDemandJobs with connection timeouts. |
| 102 // Must only be called when there are requests that have been started but not |
| 103 // yet timed out. |
| 104 static void FailRequests(); |
| 105 |
| 106 // Clears the |waiting_jobs_list_| without having the jobs return anything. |
| 107 // Used to allow an assertion that jobs are not in the |waiting_jobs_list_| |
| 108 // when destroyed. Must only be called when there are requests that have |
| 109 // been started but not yet timed out. |
| 110 static void AbandonRequests(); |
| 111 |
| 112 private: |
| 113 friend class URLRequestMockCaptivePortalJobFactory; |
| 114 |
| 115 explicit URLRequestTimeoutOnDemandJob(net::URLRequest* request); |
| 116 virtual ~URLRequestTimeoutOnDemandJob(); |
| 117 |
| 118 // Attempts to removes |this| from |jobs_|. Returns true if it was removed |
| 119 // from the list. |
| 120 bool RemoveFromList(); |
| 121 |
| 122 // These do all the work of the corresponding public functions, with the only |
| 123 // difference being that they must be called on the IO thread. |
| 124 static void FailRequestsOnIOThread(); |
| 125 static void AbandonRequestsOnIOThread(); |
| 126 |
| 127 // Head of linked list of jobs that have been started and are now waiting to |
| 128 // be timed out. |
| 129 static URLRequestTimeoutOnDemandJob* job_list_; |
| 130 |
| 131 // The next job that had been started but not yet timed out. |
| 132 URLRequestTimeoutOnDemandJob* next_job_; |
| 133 |
| 134 DISALLOW_COPY_AND_ASSIGN(URLRequestTimeoutOnDemandJob); |
| 135 }; |
| 136 |
| 137 URLRequestTimeoutOnDemandJob* URLRequestTimeoutOnDemandJob::job_list_ = NULL; |
| 138 |
| 139 void URLRequestTimeoutOnDemandJob::Start() { |
| 140 EXPECT_TRUE(CalledOnValidThread()); |
| 141 |
| 142 // Insert at start of the list. |
| 143 next_job_ = job_list_; |
| 144 job_list_ = this; |
| 145 } |
| 146 |
| 147 // static |
| 148 void URLRequestTimeoutOnDemandJob::FailRequests() { |
| 149 content::BrowserThread::PostTask( |
| 150 content::BrowserThread::IO, FROM_HERE, |
| 151 base::Bind(&URLRequestTimeoutOnDemandJob::FailRequestsOnIOThread)); |
| 152 } |
| 153 |
| 154 // static |
| 155 void URLRequestTimeoutOnDemandJob::AbandonRequests() { |
| 156 content::BrowserThread::PostTask( |
| 157 content::BrowserThread::IO, FROM_HERE, |
| 158 base::Bind(&URLRequestTimeoutOnDemandJob::AbandonRequestsOnIOThread)); |
| 159 } |
| 160 |
| 161 URLRequestTimeoutOnDemandJob::URLRequestTimeoutOnDemandJob( |
| 162 net::URLRequest* request) |
| 163 : net::URLRequestJob(request), |
| 164 next_job_(NULL) { |
| 165 } |
| 166 |
| 167 URLRequestTimeoutOnDemandJob::~URLRequestTimeoutOnDemandJob() { |
| 168 // |this| shouldn't be in the list. |
| 169 EXPECT_FALSE(RemoveFromList()); |
| 170 } |
| 171 |
| 172 bool URLRequestTimeoutOnDemandJob::RemoveFromList() { |
| 173 URLRequestTimeoutOnDemandJob** job = &job_list_; |
| 174 while (*job) { |
| 175 if (*job == this) { |
| 176 *job = next_job_; |
| 177 next_job_ = NULL; |
| 178 return true; |
| 179 } |
| 180 job = &next_job_; |
| 181 } |
| 182 |
| 183 // If the job wasn't in this list, |next_job_| should be NULL. |
| 184 EXPECT_FALSE(next_job_); |
| 185 return false; |
| 186 } |
| 187 |
| 188 // static |
| 189 void URLRequestTimeoutOnDemandJob::FailRequestsOnIOThread() { |
| 190 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 191 EXPECT_TRUE(job_list_); |
| 192 while (job_list_) { |
| 193 URLRequestTimeoutOnDemandJob* job = job_list_; |
| 194 // Since the error notification may result in the job's destruction, remove |
| 195 // it from the job list before the error. |
| 196 EXPECT_TRUE(job->RemoveFromList()); |
| 197 job->NotifyStartError(net::URLRequestStatus( |
| 198 net::URLRequestStatus::FAILED, |
| 199 net::ERR_CONNECTION_TIMED_OUT)); |
| 200 } |
| 201 } |
| 202 |
| 203 // static |
| 204 void URLRequestTimeoutOnDemandJob::AbandonRequestsOnIOThread() { |
| 205 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 206 EXPECT_TRUE(job_list_); |
| 207 while (job_list_) |
| 208 EXPECT_TRUE(job_list_->RemoveFromList()); |
| 209 } |
| 210 |
| 211 // URLRequestCaptivePortalJobFactory emulates captive portal behavior. |
| 212 // Initially, it emulates being behind a captive portal. When |
| 213 // SetBehindCaptivePortal(false) is called, it emulates behavior when not behind |
| 214 // a captive portal. The class itself is never instantiated. |
| 215 // |
| 216 // It handles requests for kMockCaptivePortalTestUrl, kMockHttpsUrl, and |
| 217 // kMockHttpsQuickTimeoutUrl. |
| 218 class URLRequestMockCaptivePortalJobFactory { |
| 219 public: |
| 220 // The public static methods below can be called on any thread. |
| 221 |
| 222 // Adds the testing URLs to the net::URLRequestFilter. Should only be called |
| 223 // once. |
| 224 static void AddUrlHandlers(); |
| 225 |
| 226 // Sets whether or not there is a captive portal. Outstanding requests are |
| 227 // not affected. |
| 228 static void SetBehindCaptivePortal(bool behind_captive_portal); |
| 229 |
| 230 private: |
| 231 // These do all the work of the corresponding public functions, with the only |
| 232 // difference being that they must be called on the IO thread. |
| 233 static void AddUrlHandlersOnIOThread(); |
| 234 static void SetBehindCaptivePortalOnIOThread(bool behind_captive_portal); |
| 235 |
| 236 // Returns a URLRequestJob that reflects the current captive portal state |
| 237 // for the URLs: kMockCaptivePortalTestUrl, kMockHttpsUrl, and |
| 238 // kMockHttpsQuickTimeoutUrl. See documentation of individual URLs for |
| 239 // actual behavior. |
| 240 static net::URLRequestJob* Factory(net::URLRequest* request, |
| 241 const std::string& scheme); |
| 242 |
| 243 static bool behind_captive_portal_; |
| 244 |
| 245 DISALLOW_IMPLICIT_CONSTRUCTORS(URLRequestMockCaptivePortalJobFactory); |
| 246 }; |
| 247 |
| 248 bool URLRequestMockCaptivePortalJobFactory::behind_captive_portal_ = true; |
| 249 |
| 250 // static |
| 251 void URLRequestMockCaptivePortalJobFactory::AddUrlHandlers() { |
| 252 content::BrowserThread::PostTask( |
| 253 content::BrowserThread::IO, FROM_HERE, |
| 254 base::Bind( |
| 255 &URLRequestMockCaptivePortalJobFactory::AddUrlHandlersOnIOThread)); |
| 256 } |
| 257 |
| 258 // static |
| 259 void URLRequestMockCaptivePortalJobFactory::SetBehindCaptivePortal( |
| 260 bool behind_captive_portal) { |
| 261 content::BrowserThread::PostTask( |
| 262 content::BrowserThread::IO, FROM_HERE, |
| 263 base::Bind( |
| 264 &URLRequestMockCaptivePortalJobFactory:: |
| 265 SetBehindCaptivePortalOnIOThread, |
| 266 behind_captive_portal)); |
| 267 } |
| 268 |
| 269 // static |
| 270 void URLRequestMockCaptivePortalJobFactory::AddUrlHandlersOnIOThread() { |
| 271 EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 272 net::URLRequestFilter* filter = net::URLRequestFilter::GetInstance(); |
| 273 filter->AddHostnameHandler("http", "mock.captive.portal", |
| 274 URLRequestMockCaptivePortalJobFactory::Factory); |
| 275 filter->AddHostnameHandler("https", "mock.captive.portal", |
| 276 URLRequestMockCaptivePortalJobFactory::Factory); |
| 277 } |
| 278 |
| 279 // static |
| 280 void URLRequestMockCaptivePortalJobFactory::SetBehindCaptivePortalOnIOThread( |
| 281 bool behind_captive_portal) { |
| 282 EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 283 behind_captive_portal_ = behind_captive_portal; |
| 284 } |
| 285 |
| 286 // static |
| 287 net::URLRequestJob* URLRequestMockCaptivePortalJobFactory::Factory( |
| 288 net::URLRequest* request, |
| 289 const std::string& scheme) { |
| 290 EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 291 |
| 292 // The PathService is threadsafe. |
| 293 FilePath root_http; |
| 294 PathService::Get(chrome::DIR_TEST_DATA, &root_http); |
| 295 |
| 296 if (scheme == "https") { |
| 297 if (behind_captive_portal_) { |
| 298 // If not logged in to the captive portal, HTTPS requests will time out, |
| 299 // either immediately on on demand. |
| 300 if (request->url() == GURL(kMockHttpsQuickTimeoutUrl)) |
| 301 return new URLRequestFailedJob(request, net::ERR_CONNECTION_TIMED_OUT); |
| 302 return new URLRequestTimeoutOnDemandJob(request); |
| 303 } |
| 304 // Once logged in to the portal, HTTPS requests return the page that was |
| 305 // actually requested. |
| 306 return new URLRequestMockHTTPJob( |
| 307 request, |
| 308 root_http.Append(FILE_PATH_LITERAL("title2.html"))); |
| 309 } |
| 310 |
| 311 // The URL is the captive portal test URL. |
| 312 |
| 313 if (behind_captive_portal_) { |
| 314 // Prior to logging in to the portal, HTTP requests go to the login page. |
| 315 return new URLRequestMockHTTPJob( |
| 316 request, |
| 317 root_http.Append( |
| 318 FILE_PATH_LITERAL("captive_portal/login.html"))); |
| 319 } |
| 320 // After logging in to the portal, the test URL returns a 204 response. |
| 321 return new URLRequestMockHTTPJob( |
| 322 request, |
| 323 root_http.Append( |
| 324 FILE_PATH_LITERAL("captive_portal/page204.html"))); |
| 325 } |
| 326 |
| 327 // Creates a server-side redirect for use with the TestServer. |
| 328 std::string CreateServerRedirect(const std::string& dest_url) { |
| 329 const char* const kServerRedirectBase = "server-redirect?"; |
| 330 return kServerRedirectBase + dest_url; |
| 331 } |
| 332 |
| 333 // Returns the total number of loading tabs across all Browsers, for all |
| 334 // Profiles. |
| 335 int NumLoadingTabs() { |
| 336 int num_loading_tabs = 0; |
| 337 for (TabContentsIterator tab_contents_it; |
| 338 !tab_contents_it.done(); |
| 339 ++tab_contents_it) { |
| 340 if (tab_contents_it->web_contents()->IsLoading()) |
| 341 ++num_loading_tabs; |
| 342 } |
| 343 return num_loading_tabs; |
| 344 } |
| 345 |
| 346 bool IsLoginTab(TabContents* tab_contents) { |
| 347 return tab_contents->captive_portal_tab_helper()->IsLoginTab(); |
| 348 } |
| 349 |
| 350 // Tracks how many times each tab has been navigated since the Observer was |
| 351 // created. The standard TestNavigationObserver can only watch specific |
| 352 // pre-existing tabs or loads in serial for all tabs. |
| 353 class MultiNavigationObserver : public content::NotificationObserver { |
| 354 public: |
| 355 MultiNavigationObserver(); |
| 356 virtual ~MultiNavigationObserver(); |
| 357 |
| 358 // Waits for exactly |num_navigations_to_wait_for| LOAD_STOP |
| 359 // notifications to have occurred since the construction of |this|. More |
| 360 // navigations than expected occuring will trigger a expect failure. |
| 361 void WaitForNavigations(int num_navigations_to_wait_for); |
| 362 |
| 363 // Returns the number of LOAD_STOP events that have occurred for |
| 364 // |web_contents| since this was constructed. |
| 365 int NumNavigationsForTab(content::WebContents* web_contents) const; |
| 366 |
| 367 // The number of LOAD_STOP events since |this| was created. |
| 368 int num_navigations() const { return num_navigations_; } |
| 369 |
| 370 private: |
| 371 typedef std::map<content::WebContents*, int> TabNavigationMap; |
| 372 |
| 373 // content::NotificationObserver: |
| 374 virtual void Observe(int type, const content::NotificationSource& source, |
| 375 const content::NotificationDetails& details) OVERRIDE; |
| 376 |
| 377 int num_navigations_; |
| 378 |
| 379 // Map of how many times each tab has navigated since |this| was created. |
| 380 TabNavigationMap tab_navigation_map_; |
| 381 |
| 382 // Total number of navigations to wait for. Value only matters when |
| 383 // |waiting_for_navigation_| is true. |
| 384 int num_navigations_to_wait_for_; |
| 385 |
| 386 // True if WaitForNavigations has been called, until |
| 387 // |num_navigations_to_wait_for_| have been observed. |
| 388 bool waiting_for_navigation_; |
| 389 |
| 390 content::NotificationRegistrar registrar_; |
| 391 |
| 392 DISALLOW_COPY_AND_ASSIGN(MultiNavigationObserver); |
| 393 }; |
| 394 |
| 395 MultiNavigationObserver::MultiNavigationObserver() |
| 396 : num_navigations_(0), |
| 397 num_navigations_to_wait_for_(0), |
| 398 waiting_for_navigation_(false) { |
| 399 registrar_.Add(this, content::NOTIFICATION_LOAD_STOP, |
| 400 content::NotificationService::AllSources()); |
| 401 } |
| 402 |
| 403 MultiNavigationObserver::~MultiNavigationObserver() { |
| 404 } |
| 405 |
| 406 void MultiNavigationObserver::WaitForNavigations( |
| 407 int num_navigations_to_wait_for) { |
| 408 // Shouldn't already be waiting for navigations. |
| 409 EXPECT_FALSE(waiting_for_navigation_); |
| 410 EXPECT_LT(0, num_navigations_to_wait_for); |
| 411 if (num_navigations_ < num_navigations_to_wait_for) { |
| 412 num_navigations_to_wait_for_ = num_navigations_to_wait_for; |
| 413 waiting_for_navigation_ = true; |
| 414 ui_test_utils::RunMessageLoop(); |
| 415 EXPECT_FALSE(waiting_for_navigation_); |
| 416 } |
| 417 EXPECT_EQ(num_navigations_, num_navigations_to_wait_for); |
| 418 } |
| 419 |
| 420 int MultiNavigationObserver::NumNavigationsForTab( |
| 421 content::WebContents* web_contents) const { |
| 422 TabNavigationMap::const_iterator tab_navigations = |
| 423 tab_navigation_map_.find(web_contents); |
| 424 if (tab_navigations == tab_navigation_map_.end()) |
| 425 return 0; |
| 426 return tab_navigations->second; |
| 427 } |
| 428 |
| 429 void MultiNavigationObserver::Observe( |
| 430 int type, |
| 431 const content::NotificationSource& source, |
| 432 const content::NotificationDetails& details) { |
| 433 ASSERT_EQ(type, content::NOTIFICATION_LOAD_STOP); |
| 434 content::NavigationController* controller = |
| 435 content::Source<content::NavigationController>(source).ptr(); |
| 436 ++num_navigations_; |
| 437 ++tab_navigation_map_[controller->GetWebContents()]; |
| 438 if (waiting_for_navigation_ && |
| 439 num_navigations_to_wait_for_ == num_navigations_) { |
| 440 waiting_for_navigation_ = false; |
| 441 MessageLoopForUI::current()->Quit(); |
| 442 } |
| 443 } |
| 444 |
| 445 // An observer for watching the CaptivePortalService. It tracks the last |
| 446 // received result and the total number of received results. |
| 447 class CaptivePortalObserver : public content::NotificationObserver { |
| 448 public: |
| 449 explicit CaptivePortalObserver(Profile* profile); |
| 450 |
| 451 // Runs the message loop until until at exactly |update_count| capitive portal |
| 452 // results have been received, since this creation of |this|. Expects no |
| 453 // additional captive portal results. |
| 454 void WaitForResults(int num_results_to_wait_for); |
| 455 |
| 456 int num_results_received() const { return num_results_received_; } |
| 457 |
| 458 Result captive_portal_result() const { |
| 459 return captive_portal_result_; |
| 460 } |
| 461 |
| 462 private: |
| 463 // Records results and exits the message loop, if needed. |
| 464 void Observe(int type, |
| 465 const content::NotificationSource& source, |
| 466 const content::NotificationDetails& details); |
| 467 |
| 468 // Number of times OnPortalResult has been called since construction. |
| 469 int num_results_received_; |
| 470 |
| 471 // If WaitForResults was called, the total number of updates for which to |
| 472 // wait. Value doesn't matter when |waiting_for_result_| is false. |
| 473 int num_results_to_wait_for_; |
| 474 |
| 475 bool waiting_for_result_; |
| 476 |
| 477 Profile* profile_; |
| 478 |
| 479 CaptivePortalService* captive_portal_service_; |
| 480 |
| 481 // Last result received. |
| 482 Result captive_portal_result_; |
| 483 |
| 484 content::NotificationRegistrar registrar_; |
| 485 |
| 486 DISALLOW_COPY_AND_ASSIGN(CaptivePortalObserver); |
| 487 }; |
| 488 |
| 489 CaptivePortalObserver::CaptivePortalObserver(Profile* profile) |
| 490 : num_results_received_(0), |
| 491 num_results_to_wait_for_(0), |
| 492 waiting_for_result_(false), |
| 493 profile_(profile), |
| 494 captive_portal_service_( |
| 495 CaptivePortalServiceFactory::GetForProfile(profile)), |
| 496 captive_portal_result_( |
| 497 captive_portal_service_->last_detection_result()) { |
| 498 registrar_.Add(this, |
| 499 chrome::NOTIFICATION_CAPTIVE_PORTAL_CHECK_RESULT, |
| 500 content::Source<Profile>(profile_)); |
| 501 } |
| 502 |
| 503 void CaptivePortalObserver::WaitForResults(int num_results_to_wait_for) { |
| 504 EXPECT_LT(0, num_results_to_wait_for); |
| 505 EXPECT_FALSE(waiting_for_result_); |
| 506 if (num_results_received_ < num_results_to_wait_for) { |
| 507 num_results_to_wait_for_ = num_results_to_wait_for; |
| 508 waiting_for_result_ = true; |
| 509 ui_test_utils::RunMessageLoop(); |
| 510 EXPECT_FALSE(waiting_for_result_); |
| 511 } |
| 512 EXPECT_EQ(num_results_received_, num_results_to_wait_for); |
| 513 } |
| 514 |
| 515 void CaptivePortalObserver::Observe( |
| 516 int type, |
| 517 const content::NotificationSource& source, |
| 518 const content::NotificationDetails& details) { |
| 519 ASSERT_EQ(type, chrome::NOTIFICATION_CAPTIVE_PORTAL_CHECK_RESULT); |
| 520 ASSERT_EQ(profile_, content::Source<Profile>(source).ptr()); |
| 521 |
| 522 CaptivePortalService::Results* results = |
| 523 content::Details<CaptivePortalService::Results>(details).ptr(); |
| 524 |
| 525 EXPECT_EQ(captive_portal_result_, results->previous_result); |
| 526 EXPECT_EQ(captive_portal_service_->last_detection_result(), |
| 527 results->result); |
| 528 |
| 529 captive_portal_result_ = results->result; |
| 530 ++num_results_received_; |
| 531 |
| 532 if (waiting_for_result_ && |
| 533 num_results_to_wait_for_ == num_results_received_) { |
| 534 waiting_for_result_ = false; |
| 535 MessageLoop::current()->Quit(); |
| 536 } |
| 537 } |
| 538 |
| 539 } // namespace |
| 540 |
| 541 class CaptivePortalBrowserTest : public InProcessBrowserTest { |
| 542 public: |
| 543 CaptivePortalBrowserTest(); |
| 544 |
| 545 // InProcessBrowserTest: |
| 546 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE; |
| 547 virtual void SetUpOnMainThread() OVERRIDE; |
| 548 virtual void CleanUpOnMainThread() OVERRIDE; |
| 549 |
| 550 // Sets the captive portal checking preference. Does not affect the command |
| 551 // line flag, which is set in SetUpCommandLine. |
| 552 void EnableCaptivePortalDetection(Profile* profile, bool enabled); |
| 553 |
| 554 // Sets up the captive portal service for the given profile so that |
| 555 // all checks go to |test_url|. Also disables all timers. |
| 556 void SetUpCaptivePortalService(Profile* profile, const GURL& test_url); |
| 557 |
| 558 // Returns true if |browser|'s profile is currently running a captive portal |
| 559 // check. |
| 560 bool CheckPending(Browser* browser); |
| 561 |
| 562 // Returns the CaptivePortalTabReloader::State of |tab_contents|. |
| 563 CaptivePortalTabReloader::State GetStateOfTabReloader( |
| 564 TabContents* tab_contents) const; |
| 565 |
| 566 // Returns the CaptivePortalTabReloader::State of the indicated tab. |
| 567 CaptivePortalTabReloader::State GetStateOfTabReloaderAt(Browser* browser, |
| 568 int index) const; |
| 569 |
| 570 // Returns the number of tabs with the given state, across all profiles. |
| 571 int NumTabsWithState(CaptivePortalTabReloader::State state) const; |
| 572 |
| 573 // Returns the number of tabs broken by captive portals, across all profiles. |
| 574 int NumBrokenTabs() const; |
| 575 |
| 576 // Returns the number of tabs that need to be reloaded due to having logged |
| 577 // in to a captive portal, across all profiles. |
| 578 int NumNeedReloadTabs() const; |
| 579 |
| 580 // Navigates |browser|'s active tab to |url| and expects no captive portal |
| 581 // test to be triggered. |expected_navigations| is the number of times the |
| 582 // active tab will end up being navigated. It should be 1, except for the |
| 583 // Link Doctor page, which acts like two navigations. |
| 584 void NavigateToPageExpectNoTest(Browser* browser, |
| 585 const GURL& url, |
| 586 int expected_navigations); |
| 587 |
| 588 // Navigates |browser|'s active tab to an SSL tab that takes a while to load, |
| 589 // triggering a captive portal check, which is expected to give the result |
| 590 // |expected_result|. The page finishes loading, with a timeout, after the |
| 591 // captive portal check. |
| 592 void SlowLoadNoCaptivePortal(Browser* browser, Result expected_result); |
| 593 |
| 594 // Navigates |browser|'s active tab to an SSL timeout, expecting a captive |
| 595 // portal check to be triggered and return a result which will indicates |
| 596 // there's no detected captive portal. |
| 597 void FastTimeoutNoCaptivePortal(Browser* browser, Result expected_result); |
| 598 |
| 599 // Navigates the active tab to a slow loading SSL page, which will then |
| 600 // trigger a captive portal test. The test is expected to find a captive |
| 601 // portal. The slow loading page will continue to load after the function |
| 602 // returns, until URLRequestTimeoutOnDemandJob::FailRequests() is called, |
| 603 // at which point it will timeout. |
| 604 // |
| 605 // When |expect_login_tab| is false, no login tab is expected to be opened, |
| 606 // because one already exists, and the function returns once the captive |
| 607 // portal test is complete. |
| 608 // |
| 609 // If |expect_login_tab| is true, a login tab is then expected to be opened. |
| 610 // It waits until both the login tab has finished loading, and two captive |
| 611 // portal tests complete. The second test is triggered by the load of the |
| 612 // captive portal tab completing. |
| 613 // |
| 614 // This function must not be called when the active tab is currently loading. |
| 615 void SlowLoadBehindCaptivePortal(Browser* browser, bool expect_login_tab); |
| 616 |
| 617 // Just like SlowLoadBehindCaptivePortal, except the navigated tab has |
| 618 // a connection timeout rather having its time trigger, and the function |
| 619 // waits until that timeout occurs. |
| 620 void FastTimeoutBehindCaptivePortal(Browser* browser, |
| 621 bool expect_open_login_tab); |
| 622 |
| 623 // Navigates the login tab without logging in. The login tab must be the |
| 624 // specified browser's active tab. Expects no other tab to change state. |
| 625 // |num_loading_tabs| and |num_timed_out_tabs| are used as extra checks |
| 626 // that nothing has gone wrong prior to the function call. |
| 627 void NavigateLoginTab(Browser* browser, |
| 628 int num_loading_tabs, |
| 629 int num_timed_out_tabs); |
| 630 |
| 631 // Simulates a login by updating the URLRequestMockCaptivePortalJob's |
| 632 // behind captive portal state, and navigating the login tab. Waits for |
| 633 // all broken but not loading tabs to be reloaded. |
| 634 // |num_loading_tabs| and |num_timed_out_tabs| are used as extra checks |
| 635 // that nothing has gone wrong prior to the function call. |
| 636 void Login(Browser* browser, int num_loading_tabs, int num_timed_out_tabs); |
| 637 |
| 638 // Makes the slow SSL loads of all active tabs time out at once, and waits for |
| 639 // them to finish both that load and the automatic reload it should trigger. |
| 640 // There should be no timed out tabs when this is called. The former login |
| 641 // tab should be the active tab. |
| 642 void FailLoadsAfterLogin(Browser* browser, int num_loading_tabs); |
| 643 |
| 644 // Makes the slow SSL loads of all active tabs time out at once, and waits for |
| 645 // them to finish displaying their error pages. The login tab should be the |
| 646 // active tab. There should be no timed out tabs when this is called. |
| 647 void FailLoadsWithoutLogin(Browser* browser, int num_loading_tabs); |
| 648 |
| 649 // Sets the timeout used by a CaptivePortalTabReloader on slow SSL loads |
| 650 // before a captive portal check. |
| 651 void SetSlowSSLLoadTime(CaptivePortalTabReloader* tab_reloader, |
| 652 base::TimeDelta slow_ssl_load_time); |
| 653 |
| 654 CaptivePortalTabReloader* GetTabReloader(TabContents* tab_contents) const; |
| 655 |
| 656 private: |
| 657 DISALLOW_COPY_AND_ASSIGN(CaptivePortalBrowserTest); |
| 658 }; |
| 659 |
| 660 CaptivePortalBrowserTest::CaptivePortalBrowserTest() { |
| 661 } |
| 662 |
| 663 void CaptivePortalBrowserTest::SetUpOnMainThread() { |
| 664 // Enable mock requests. |
| 665 content::BrowserThread::PostTask( |
| 666 content::BrowserThread::IO, FROM_HERE, |
| 667 base::Bind(&chrome_browser_net::SetUrlRequestMocksEnabled, true)); |
| 668 URLRequestMockCaptivePortalJobFactory::AddUrlHandlers(); |
| 669 |
| 670 EnableCaptivePortalDetection(browser()->profile(), true); |
| 671 |
| 672 // Set the captive portal service to use URLRequestMockCaptivePortalJob's |
| 673 // mock URL, by default. |
| 674 SetUpCaptivePortalService(browser()->profile(), |
| 675 GURL(kMockCaptivePortalTestUrl)); |
| 676 } |
| 677 |
| 678 void CaptivePortalBrowserTest::CleanUpOnMainThread() { |
| 679 // No test should have a captive portal check pending on quit. |
| 680 EXPECT_FALSE(CheckPending(browser())); |
| 681 } |
| 682 |
| 683 void CaptivePortalBrowserTest::SetUpCommandLine( |
| 684 CommandLine* command_line) { |
| 685 command_line->AppendSwitch(switches::kCaptivePortalDetection); |
| 686 } |
| 687 |
| 688 void CaptivePortalBrowserTest::EnableCaptivePortalDetection( |
| 689 Profile* profile, bool enabled) { |
| 690 profile->GetPrefs()->SetBoolean(prefs::kAlternateErrorPagesEnabled, enabled); |
| 691 } |
| 692 |
| 693 void CaptivePortalBrowserTest::SetUpCaptivePortalService(Profile* profile, |
| 694 const GURL& test_url) { |
| 695 CaptivePortalService* captive_portal_service = |
| 696 CaptivePortalServiceFactory::GetForProfile(profile); |
| 697 captive_portal_service->set_test_url(test_url); |
| 698 |
| 699 // Don't use any non-zero timers. Timers are checked in unit tests. |
| 700 CaptivePortalService::RecheckPolicy* recheck_policy = |
| 701 &captive_portal_service->recheck_policy(); |
| 702 recheck_policy->initial_backoff_no_portal_ms = 0; |
| 703 recheck_policy->initial_backoff_portal_ms = 0; |
| 704 recheck_policy->backoff_policy.maximum_backoff_ms = 0; |
| 705 } |
| 706 |
| 707 bool CaptivePortalBrowserTest::CheckPending(Browser* browser) { |
| 708 CaptivePortalService* captive_portal_service = |
| 709 CaptivePortalServiceFactory::GetForProfile(browser->profile()); |
| 710 |
| 711 return captive_portal_service->FetchingURL() || |
| 712 captive_portal_service->TimerRunning(); |
| 713 } |
| 714 |
| 715 CaptivePortalTabReloader::State CaptivePortalBrowserTest::GetStateOfTabReloader( |
| 716 TabContents* tab_contents) const { |
| 717 return GetTabReloader(tab_contents)->state(); |
| 718 } |
| 719 |
| 720 CaptivePortalTabReloader::State |
| 721 CaptivePortalBrowserTest::GetStateOfTabReloaderAt(Browser* browser, |
| 722 int index) const { |
| 723 return GetStateOfTabReloader(browser->GetTabContentsAt(index)); |
| 724 } |
| 725 |
| 726 int CaptivePortalBrowserTest::NumTabsWithState( |
| 727 CaptivePortalTabReloader::State state) const { |
| 728 int num_tabs = 0; |
| 729 for (TabContentsIterator tab_contents_it; |
| 730 !tab_contents_it.done(); |
| 731 ++tab_contents_it) { |
| 732 if (GetStateOfTabReloader(*tab_contents_it) == state) |
| 733 ++num_tabs; |
| 734 } |
| 735 return num_tabs; |
| 736 } |
| 737 |
| 738 int CaptivePortalBrowserTest::NumBrokenTabs() const { |
| 739 return NumTabsWithState(CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL); |
| 740 } |
| 741 |
| 742 int CaptivePortalBrowserTest::NumNeedReloadTabs() const { |
| 743 return NumTabsWithState(CaptivePortalTabReloader::STATE_NEEDS_RELOAD); |
| 744 } |
| 745 |
| 746 void CaptivePortalBrowserTest::NavigateToPageExpectNoTest( |
| 747 Browser* browser, |
| 748 const GURL& url, |
| 749 int expected_navigations) { |
| 750 MultiNavigationObserver navigation_observer; |
| 751 CaptivePortalObserver portal_observer(browser->profile()); |
| 752 |
| 753 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete( |
| 754 browser, url, expected_navigations); |
| 755 |
| 756 // No captive portal checks should have ocurred or be pending, and there |
| 757 // should be no new tabs. |
| 758 EXPECT_EQ(0, portal_observer.num_results_received()); |
| 759 EXPECT_FALSE(CheckPending(browser)); |
| 760 EXPECT_EQ(1, browser->tab_count()); |
| 761 EXPECT_EQ(expected_navigations, navigation_observer.num_navigations()); |
| 762 EXPECT_EQ(0, NumLoadingTabs()); |
| 763 } |
| 764 |
| 765 void CaptivePortalBrowserTest::SlowLoadNoCaptivePortal( |
| 766 Browser* browser, Result expected_result) { |
| 767 CaptivePortalTabReloader* tab_reloader = |
| 768 GetTabReloader(browser->GetActiveTabContents()); |
| 769 ASSERT_TRUE(tab_reloader); |
| 770 SetSlowSSLLoadTime(tab_reloader, base::TimeDelta()); |
| 771 |
| 772 MultiNavigationObserver navigation_observer; |
| 773 CaptivePortalObserver portal_observer(browser->profile()); |
| 774 ui_test_utils::NavigateToURLWithDisposition(browser, |
| 775 GURL(kMockHttpsUrl), |
| 776 CURRENT_TAB, |
| 777 ui_test_utils::BROWSER_TEST_NONE); |
| 778 |
| 779 portal_observer.WaitForResults(1); |
| 780 |
| 781 ASSERT_EQ(1, browser->tab_count()); |
| 782 EXPECT_EQ(expected_result, portal_observer.captive_portal_result()); |
| 783 EXPECT_EQ(1, portal_observer.num_results_received()); |
| 784 EXPECT_EQ(0, navigation_observer.num_navigations()); |
| 785 EXPECT_FALSE(CheckPending(browser)); |
| 786 |
| 787 // First tab should still be loading. |
| 788 EXPECT_EQ(1, NumLoadingTabs()); |
| 789 |
| 790 // Original request times out. |
| 791 URLRequestTimeoutOnDemandJob::FailRequests(); |
| 792 navigation_observer.WaitForNavigations(1); |
| 793 |
| 794 ASSERT_EQ(1, browser->tab_count()); |
| 795 EXPECT_EQ(1, portal_observer.num_results_received()); |
| 796 EXPECT_FALSE(CheckPending(browser)); |
| 797 EXPECT_EQ(0, NumLoadingTabs()); |
| 798 |
| 799 // Set a slow SSL load time to prevent the timer from triggering. |
| 800 SetSlowSSLLoadTime(tab_reloader, base::TimeDelta::FromDays(1)); |
| 801 } |
| 802 |
| 803 void CaptivePortalBrowserTest::FastTimeoutNoCaptivePortal( |
| 804 Browser* browser, Result expected_result) { |
| 805 ASSERT_NE(expected_result, RESULT_BEHIND_CAPTIVE_PORTAL); |
| 806 |
| 807 // Set the load time to be large, so the timer won't trigger. The value is |
| 808 // not restored at the end of the function. |
| 809 CaptivePortalTabReloader* tab_reloader = |
| 810 GetTabReloader(browser->GetActiveTabContents()); |
| 811 ASSERT_TRUE(tab_reloader); |
| 812 SetSlowSSLLoadTime(tab_reloader, base::TimeDelta::FromHours(1)); |
| 813 |
| 814 MultiNavigationObserver navigation_observer; |
| 815 CaptivePortalObserver portal_observer(browser->profile()); |
| 816 |
| 817 // Neither of these should be changed by the navigation. |
| 818 int active_index = browser->active_index(); |
| 819 int expected_tab_count = browser->tab_count(); |
| 820 |
| 821 ui_test_utils::NavigateToURL( |
| 822 browser, |
| 823 URLRequestFailedJob::GetMockHttpsUrl(net::ERR_CONNECTION_TIMED_OUT)); |
| 824 |
| 825 // An attempt to detect a captive portal should have started by now. If not, |
| 826 // abort early to prevent hanging. |
| 827 ASSERT_TRUE(portal_observer.num_results_received() > 0 || |
| 828 CheckPending(browser)); |
| 829 |
| 830 portal_observer.WaitForResults(1); |
| 831 navigation_observer.WaitForNavigations(1); |
| 832 |
| 833 // Check the result. |
| 834 EXPECT_EQ(1, portal_observer.num_results_received()); |
| 835 EXPECT_EQ(expected_result, portal_observer.captive_portal_result()); |
| 836 |
| 837 // Check that the right tab was navigated, and there were no extra |
| 838 // navigations. |
| 839 EXPECT_EQ(1, navigation_observer.NumNavigationsForTab( |
| 840 browser->GetWebContentsAt(active_index))); |
| 841 EXPECT_EQ(0, NumLoadingTabs()); |
| 842 |
| 843 // Check the tab's state, and verify no captive portal check is pending. |
| 844 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, |
| 845 GetStateOfTabReloaderAt(browser, 0)); |
| 846 EXPECT_FALSE(CheckPending(browser)); |
| 847 |
| 848 // Make sure no login tab was opened. |
| 849 EXPECT_EQ(expected_tab_count, browser->tab_count()); |
| 850 } |
| 851 |
| 852 void CaptivePortalBrowserTest::SlowLoadBehindCaptivePortal( |
| 853 Browser* browser, |
| 854 bool expect_open_login_tab) { |
| 855 // Calling this on a tab that's waiting for a load to manually be timed out |
| 856 // will result in a hang. |
| 857 ASSERT_FALSE(browser->GetActiveWebContents()->IsLoading()); |
| 858 |
| 859 // Trigger a captive portal check quickly. |
| 860 CaptivePortalTabReloader* tab_reloader = |
| 861 GetTabReloader(browser->GetActiveTabContents()); |
| 862 ASSERT_TRUE(tab_reloader); |
| 863 SetSlowSSLLoadTime(tab_reloader, base::TimeDelta()); |
| 864 |
| 865 // Number of tabs expected to be open after the captive portal checks |
| 866 // have completed. |
| 867 int initial_tab_count = browser->tab_count(); |
| 868 int initial_active_index = browser->active_index(); |
| 869 int initial_loading_tabs = NumLoadingTabs(); |
| 870 int expected_broken_tabs = NumBrokenTabs(); |
| 871 if (CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL != |
| 872 GetStateOfTabReloader(browser->GetActiveTabContents())) { |
| 873 ++expected_broken_tabs; |
| 874 } |
| 875 |
| 876 MultiNavigationObserver navigation_observer; |
| 877 CaptivePortalObserver portal_observer(browser->profile()); |
| 878 ui_test_utils::NavigateToURLWithDisposition(browser, |
| 879 GURL(kMockHttpsUrl), |
| 880 CURRENT_TAB, |
| 881 ui_test_utils::BROWSER_TEST_NONE); |
| 882 |
| 883 if (expect_open_login_tab) { |
| 884 portal_observer.WaitForResults(2); |
| 885 navigation_observer.WaitForNavigations(1); |
| 886 EXPECT_EQ(2, portal_observer.num_results_received()); |
| 887 |
| 888 ASSERT_EQ(initial_tab_count + 1, browser->tab_count()); |
| 889 EXPECT_EQ(initial_tab_count, browser->active_index()); |
| 890 |
| 891 EXPECT_EQ(1, navigation_observer.NumNavigationsForTab( |
| 892 browser->GetWebContentsAt(initial_tab_count))); |
| 893 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, |
| 894 GetStateOfTabReloader(browser->GetTabContentsAt(1))); |
| 895 EXPECT_TRUE(IsLoginTab(browser->GetTabContentsAt(1))); |
| 896 } else { |
| 897 portal_observer.WaitForResults(1); |
| 898 EXPECT_EQ(0, navigation_observer.num_navigations()); |
| 899 EXPECT_EQ(initial_active_index, browser->active_index()); |
| 900 ASSERT_EQ(initial_tab_count, browser->tab_count()); |
| 901 EXPECT_EQ(initial_active_index, browser->active_index()); |
| 902 } |
| 903 |
| 904 EXPECT_EQ(initial_loading_tabs + 1, NumLoadingTabs()); |
| 905 EXPECT_EQ(expected_broken_tabs, NumBrokenTabs()); |
| 906 EXPECT_EQ(RESULT_BEHIND_CAPTIVE_PORTAL, |
| 907 portal_observer.captive_portal_result()); |
| 908 EXPECT_FALSE(CheckPending(browser)); |
| 909 |
| 910 EXPECT_EQ(CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL, |
| 911 GetStateOfTabReloader( |
| 912 browser->GetTabContentsAt(initial_active_index))); |
| 913 |
| 914 // Reset the load time to be large, so the timer won't trigger on a reload. |
| 915 SetSlowSSLLoadTime(tab_reloader, base::TimeDelta::FromHours(1)); |
| 916 } |
| 917 |
| 918 void CaptivePortalBrowserTest::FastTimeoutBehindCaptivePortal( |
| 919 Browser* browser, |
| 920 bool expect_open_login_tab) { |
| 921 // Calling this on a tab that's waiting for a load to manually be timed out |
| 922 // will result in a hang. |
| 923 ASSERT_FALSE(browser->GetActiveWebContents()->IsLoading()); |
| 924 |
| 925 // Set the load time to be large, so the timer won't trigger. The value is |
| 926 // not restored at the end of the function. |
| 927 CaptivePortalTabReloader* tab_reloader = |
| 928 GetTabReloader(browser->GetActiveTabContents()); |
| 929 ASSERT_TRUE(tab_reloader); |
| 930 SetSlowSSLLoadTime(tab_reloader, base::TimeDelta::FromHours(1)); |
| 931 |
| 932 // Number of tabs expected to be open after the captive portal checks |
| 933 // have completed. |
| 934 int initial_tab_count = browser->tab_count(); |
| 935 int initial_active_index = browser->active_index(); |
| 936 int initial_loading_tabs = NumLoadingTabs(); |
| 937 int expected_broken_tabs = NumBrokenTabs(); |
| 938 if (CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL != |
| 939 GetStateOfTabReloader(browser->GetActiveTabContents())) { |
| 940 ++expected_broken_tabs; |
| 941 } |
| 942 |
| 943 MultiNavigationObserver navigation_observer; |
| 944 CaptivePortalObserver portal_observer(browser->profile()); |
| 945 ui_test_utils::NavigateToURLWithDisposition(browser, |
| 946 GURL(kMockHttpsQuickTimeoutUrl), |
| 947 CURRENT_TAB, |
| 948 ui_test_utils::BROWSER_TEST_NONE); |
| 949 |
| 950 if (expect_open_login_tab) { |
| 951 portal_observer.WaitForResults(2); |
| 952 navigation_observer.WaitForNavigations(2); |
| 953 EXPECT_EQ(2, portal_observer.num_results_received()); |
| 954 |
| 955 ASSERT_EQ(initial_tab_count + 1, browser->tab_count()); |
| 956 EXPECT_EQ(initial_tab_count, browser->active_index()); |
| 957 // Make sure that the originally active tab and the captive portal tab have |
| 958 // each loaded once. |
| 959 EXPECT_EQ(1, navigation_observer.NumNavigationsForTab( |
| 960 browser->GetWebContentsAt(initial_active_index))); |
| 961 EXPECT_EQ(1, navigation_observer.NumNavigationsForTab( |
| 962 browser->GetWebContentsAt(initial_tab_count))); |
| 963 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, |
| 964 GetStateOfTabReloader(browser->GetTabContentsAt(1))); |
| 965 EXPECT_TRUE(IsLoginTab(browser->GetTabContentsAt(1))); |
| 966 } else { |
| 967 portal_observer.WaitForResults(1); |
| 968 navigation_observer.WaitForNavigations(1); |
| 969 EXPECT_EQ(1, portal_observer.num_results_received()); |
| 970 |
| 971 EXPECT_EQ(initial_active_index, browser->active_index()); |
| 972 EXPECT_EQ(1, navigation_observer.NumNavigationsForTab( |
| 973 browser->GetWebContentsAt(initial_active_index))); |
| 974 ASSERT_EQ(initial_tab_count, browser->tab_count()); |
| 975 EXPECT_EQ(initial_active_index, browser->active_index()); |
| 976 } |
| 977 |
| 978 EXPECT_EQ(initial_loading_tabs, NumLoadingTabs()); |
| 979 EXPECT_EQ(expected_broken_tabs, NumBrokenTabs()); |
| 980 EXPECT_EQ(RESULT_BEHIND_CAPTIVE_PORTAL, |
| 981 portal_observer.captive_portal_result()); |
| 982 EXPECT_FALSE(CheckPending(browser)); |
| 983 |
| 984 EXPECT_EQ(CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL, |
| 985 GetStateOfTabReloader( |
| 986 browser->GetTabContentsAt(initial_active_index))); |
| 987 } |
| 988 |
| 989 void CaptivePortalBrowserTest::NavigateLoginTab(Browser* browser, |
| 990 int num_loading_tabs, |
| 991 int num_timed_out_tabs) { |
| 992 MultiNavigationObserver navigation_observer; |
| 993 CaptivePortalObserver portal_observer(browser->profile()); |
| 994 |
| 995 int initial_tab_count = browser->tab_count(); |
| 996 EXPECT_EQ(num_loading_tabs, NumLoadingTabs()); |
| 997 EXPECT_EQ(num_timed_out_tabs, NumBrokenTabs() - NumLoadingTabs()); |
| 998 |
| 999 int login_tab_index = browser->active_index(); |
| 1000 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, |
| 1001 GetStateOfTabReloader(browser->GetActiveTabContents())); |
| 1002 ASSERT_TRUE(IsLoginTab(browser->GetActiveTabContents())); |
| 1003 |
| 1004 // Do the navigation. |
| 1005 content::RenderViewHost* render_view_host = |
| 1006 browser->GetActiveWebContents()->GetRenderViewHost(); |
| 1007 render_view_host->ExecuteJavascriptInWebFrame( |
| 1008 string16(), |
| 1009 ASCIIToUTF16("submitForm()")); |
| 1010 |
| 1011 portal_observer.WaitForResults(1); |
| 1012 navigation_observer.WaitForNavigations(1); |
| 1013 |
| 1014 // Check the captive portal result. |
| 1015 EXPECT_EQ(RESULT_BEHIND_CAPTIVE_PORTAL, |
| 1016 portal_observer.captive_portal_result()); |
| 1017 EXPECT_EQ(1, portal_observer.num_results_received()); |
| 1018 EXPECT_FALSE(CheckPending(browser)); |
| 1019 |
| 1020 // Make sure not much has changed. |
| 1021 EXPECT_EQ(initial_tab_count, browser->tab_count()); |
| 1022 EXPECT_EQ(num_loading_tabs, NumLoadingTabs()); |
| 1023 EXPECT_EQ(num_loading_tabs + num_timed_out_tabs, NumBrokenTabs()); |
| 1024 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, |
| 1025 GetStateOfTabReloader(browser->GetTabContentsAt(login_tab_index))); |
| 1026 EXPECT_TRUE(IsLoginTab(browser->GetTabContentsAt(login_tab_index))); |
| 1027 |
| 1028 // Make sure there were no unexpected navigations. |
| 1029 EXPECT_EQ(1, navigation_observer.NumNavigationsForTab( |
| 1030 browser->GetWebContentsAt(login_tab_index))); |
| 1031 } |
| 1032 |
| 1033 void CaptivePortalBrowserTest::Login(Browser* browser, |
| 1034 int num_loading_tabs, |
| 1035 int num_timed_out_tabs) { |
| 1036 // Simulate logging in. |
| 1037 URLRequestMockCaptivePortalJobFactory::SetBehindCaptivePortal(false); |
| 1038 |
| 1039 MultiNavigationObserver navigation_observer; |
| 1040 CaptivePortalObserver portal_observer(browser->profile()); |
| 1041 |
| 1042 int initial_tab_count = browser->tab_count(); |
| 1043 ASSERT_EQ(num_loading_tabs, NumLoadingTabs()); |
| 1044 EXPECT_EQ(num_timed_out_tabs, NumBrokenTabs() - NumLoadingTabs()); |
| 1045 |
| 1046 // Verify that the login page is on top. |
| 1047 int login_tab_index = browser->active_index(); |
| 1048 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, |
| 1049 GetStateOfTabReloader(browser->GetTabContentsAt(login_tab_index))); |
| 1050 ASSERT_TRUE(IsLoginTab(browser->GetTabContentsAt(login_tab_index))); |
| 1051 |
| 1052 // Trigger a navigation. |
| 1053 content::RenderViewHost* render_view_host = |
| 1054 browser->GetActiveWebContents()->GetRenderViewHost(); |
| 1055 render_view_host->ExecuteJavascriptInWebFrame( |
| 1056 string16(), |
| 1057 ASCIIToUTF16("submitForm()")); |
| 1058 |
| 1059 portal_observer.WaitForResults(1); |
| 1060 |
| 1061 // Wait for all the timed out tabs to reload. |
| 1062 navigation_observer.WaitForNavigations(1 + num_timed_out_tabs); |
| 1063 EXPECT_EQ(1, portal_observer.num_results_received()); |
| 1064 |
| 1065 // The tabs that were loading before should still be loading, and now be in |
| 1066 // STATE_NEEDS_RELOAD. |
| 1067 EXPECT_EQ(0, NumBrokenTabs()); |
| 1068 EXPECT_EQ(num_loading_tabs, NumLoadingTabs()); |
| 1069 EXPECT_EQ(num_loading_tabs, NumNeedReloadTabs()); |
| 1070 |
| 1071 // Make sure that the broken tabs have reloaded, and there's no more |
| 1072 // captive portal tab. |
| 1073 EXPECT_EQ(initial_tab_count, browser->tab_count()); |
| 1074 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, |
| 1075 GetStateOfTabReloaderAt(browser, login_tab_index)); |
| 1076 EXPECT_FALSE(IsLoginTab(browser->GetTabContentsAt(login_tab_index))); |
| 1077 |
| 1078 // Make sure there were no unexpected navigations of the login tab. |
| 1079 EXPECT_EQ(1, navigation_observer.NumNavigationsForTab( |
| 1080 browser->GetWebContentsAt(login_tab_index))); |
| 1081 } |
| 1082 |
| 1083 void CaptivePortalBrowserTest::FailLoadsAfterLogin(Browser* browser, |
| 1084 int num_loading_tabs) { |
| 1085 ASSERT_EQ(num_loading_tabs, NumLoadingTabs()); |
| 1086 ASSERT_EQ(num_loading_tabs, NumNeedReloadTabs()); |
| 1087 EXPECT_EQ(0, NumBrokenTabs()); |
| 1088 |
| 1089 int initial_num_tabs = browser->tab_count(); |
| 1090 int initial_active_tab = browser->active_index(); |
| 1091 |
| 1092 CaptivePortalObserver portal_observer(browser->profile()); |
| 1093 MultiNavigationObserver navigation_observer; |
| 1094 // Connection finally times out. |
| 1095 URLRequestTimeoutOnDemandJob::FailRequests(); |
| 1096 |
| 1097 navigation_observer.WaitForNavigations(2 * num_loading_tabs); |
| 1098 |
| 1099 // No captive portal checks should have ocurred or be pending, and there |
| 1100 // should be no new tabs. |
| 1101 EXPECT_EQ(0, portal_observer.num_results_received()); |
| 1102 EXPECT_FALSE(CheckPending(browser)); |
| 1103 EXPECT_EQ(initial_num_tabs, browser->tab_count()); |
| 1104 |
| 1105 EXPECT_EQ(initial_active_tab, browser->active_index()); |
| 1106 |
| 1107 EXPECT_EQ(0, NumNeedReloadTabs()); |
| 1108 EXPECT_EQ(0, NumLoadingTabs()); |
| 1109 EXPECT_EQ(0, navigation_observer.NumNavigationsForTab( |
| 1110 browser->GetActiveWebContents())); |
| 1111 } |
| 1112 |
| 1113 void CaptivePortalBrowserTest::FailLoadsWithoutLogin(Browser* browser, |
| 1114 int num_loading_tabs) { |
| 1115 ASSERT_EQ(num_loading_tabs, NumLoadingTabs()); |
| 1116 ASSERT_EQ(0, NumNeedReloadTabs()); |
| 1117 EXPECT_EQ(num_loading_tabs, NumBrokenTabs()); |
| 1118 |
| 1119 int initial_num_tabs = browser->tab_count(); |
| 1120 int login_tab = browser->active_index(); |
| 1121 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, |
| 1122 GetStateOfTabReloader(browser->GetActiveTabContents())); |
| 1123 ASSERT_TRUE(IsLoginTab(browser->GetActiveTabContents())); |
| 1124 |
| 1125 CaptivePortalObserver portal_observer(browser->profile()); |
| 1126 MultiNavigationObserver navigation_observer; |
| 1127 // Connection finally times out. |
| 1128 URLRequestTimeoutOnDemandJob::FailRequests(); |
| 1129 |
| 1130 navigation_observer.WaitForNavigations(num_loading_tabs); |
| 1131 |
| 1132 // No captive portal checks should have ocurred or be pending, and there |
| 1133 // should be no new tabs. |
| 1134 EXPECT_EQ(0, portal_observer.num_results_received()); |
| 1135 EXPECT_FALSE(CheckPending(browser)); |
| 1136 EXPECT_EQ(initial_num_tabs, browser->tab_count()); |
| 1137 |
| 1138 EXPECT_EQ(0, NumNeedReloadTabs()); |
| 1139 EXPECT_EQ(0, NumLoadingTabs()); |
| 1140 EXPECT_EQ(num_loading_tabs, NumBrokenTabs()); |
| 1141 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, |
| 1142 GetStateOfTabReloader(browser->GetActiveTabContents())); |
| 1143 EXPECT_TRUE(IsLoginTab(browser->GetActiveTabContents())); |
| 1144 EXPECT_EQ(login_tab, browser->active_index()); |
| 1145 |
| 1146 EXPECT_EQ(0, navigation_observer.NumNavigationsForTab( |
| 1147 browser->GetWebContentsAt(login_tab))); |
| 1148 } |
| 1149 |
| 1150 void CaptivePortalBrowserTest::SetSlowSSLLoadTime( |
| 1151 CaptivePortalTabReloader* tab_reloader, |
| 1152 base::TimeDelta slow_ssl_load_time) { |
| 1153 tab_reloader->set_slow_ssl_load_time(slow_ssl_load_time); |
| 1154 } |
| 1155 |
| 1156 CaptivePortalTabReloader* CaptivePortalBrowserTest::GetTabReloader( |
| 1157 TabContents* tab_contents) const { |
| 1158 return tab_contents->captive_portal_tab_helper()->GetTabReloaderForTest(); |
| 1159 } |
| 1160 |
| 1161 // Make sure there's no test for a captive portal on HTTP timeouts. This will |
| 1162 // also trigger the link doctor page, which results in the load of a second |
| 1163 // error page. |
| 1164 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, HttpTimeout) { |
| 1165 GURL url = URLRequestFailedJob::GetMockHttpUrl(net::ERR_CONNECTION_TIMED_OUT); |
| 1166 NavigateToPageExpectNoTest(browser(), url, 2); |
| 1167 } |
| 1168 |
| 1169 // Make sure there's no check for a captive portal on HTTPS errors other than |
| 1170 // timeouts, when they preempt the slow load timer. |
| 1171 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, HttpsNonTimeoutError) { |
| 1172 GURL url = URLRequestFailedJob::GetMockHttpsUrl(net::ERR_UNEXPECTED); |
| 1173 NavigateToPageExpectNoTest(browser(), url, 1); |
| 1174 } |
| 1175 |
| 1176 // Make sure no captive portal test triggers on HTTPS timeouts of iframes. |
| 1177 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, HttpsIframeTimeout) { |
| 1178 CaptivePortalObserver portal_observer(browser()->profile()); |
| 1179 |
| 1180 // Use an HTTPS server for the top level page. |
| 1181 net::TestServer https_server(net::TestServer::TYPE_HTTPS, |
| 1182 net::TestServer::kLocalhost, |
| 1183 FilePath(FILE_PATH_LITERAL("chrome/test/data"))); |
| 1184 ASSERT_TRUE(https_server.Start()); |
| 1185 |
| 1186 GURL url = https_server.GetURL(kTestServerIframeTimeoutPath); |
| 1187 NavigateToPageExpectNoTest(browser(), url, 1); |
| 1188 } |
| 1189 |
| 1190 // Check the captive portal result when the test request reports a network |
| 1191 // error. The check is triggered by a slow loading page, and the page |
| 1192 // errors out only after getting a captive portal result. |
| 1193 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, RequestFails) { |
| 1194 SetUpCaptivePortalService( |
| 1195 browser()->profile(), |
| 1196 URLRequestFailedJob::GetMockHttpUrl(net::ERR_CONNECTION_CLOSED)); |
| 1197 SlowLoadNoCaptivePortal(browser(), RESULT_NO_RESPONSE); |
| 1198 } |
| 1199 |
| 1200 // Same as above, but for the rather unlikely case that the connection times out |
| 1201 // before the timer triggers. |
| 1202 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, RequestFailsFastTimout) { |
| 1203 SetUpCaptivePortalService( |
| 1204 browser()->profile(), |
| 1205 URLRequestFailedJob::GetMockHttpUrl(net::ERR_CONNECTION_CLOSED)); |
| 1206 FastTimeoutNoCaptivePortal(browser(), RESULT_NO_RESPONSE); |
| 1207 } |
| 1208 |
| 1209 // Checks the case that captive portal detection is disabled. |
| 1210 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, Disabled) { |
| 1211 EnableCaptivePortalDetection(browser()->profile(), false); |
| 1212 SlowLoadNoCaptivePortal(browser(), RESULT_INTERNET_CONNECTED); |
| 1213 } |
| 1214 |
| 1215 // Checks that we look for a captive portal on HTTPS timeouts and don't reload |
| 1216 // the error tab when the captive portal probe gets a 204 response, indicating |
| 1217 // there is no captive portal. |
| 1218 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, InternetConnected) { |
| 1219 // Can't just use SetBehindCaptivePortal(false), since then there wouldn't |
| 1220 // be a timeout. |
| 1221 ASSERT_TRUE(test_server()->Start()); |
| 1222 SetUpCaptivePortalService(browser()->profile(), |
| 1223 test_server()->GetURL("nocontent")); |
| 1224 SlowLoadNoCaptivePortal(browser(), RESULT_INTERNET_CONNECTED); |
| 1225 } |
| 1226 |
| 1227 // Checks that no login page is opened when the HTTP test URL redirects to an |
| 1228 // SSL certificate error. |
| 1229 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, RedirectSSLCertError) { |
| 1230 // Need an HTTP TestServer to handle a dynamically created server redirect. |
| 1231 ASSERT_TRUE(test_server()->Start()); |
| 1232 |
| 1233 net::TestServer::HTTPSOptions https_options; |
| 1234 https_options.server_certificate = |
| 1235 net::TestServer::HTTPSOptions::CERT_MISMATCHED_NAME; |
| 1236 net::TestServer https_server(https_options, |
| 1237 FilePath(FILE_PATH_LITERAL("chrome/test/data"))); |
| 1238 ASSERT_TRUE(https_server.Start()); |
| 1239 |
| 1240 GURL ssl_login_url = https_server.GetURL(kTestServerLoginPath); |
| 1241 |
| 1242 CaptivePortalService* captive_portal_service = |
| 1243 CaptivePortalServiceFactory::GetForProfile(browser()->profile()); |
| 1244 ASSERT_TRUE(captive_portal_service); |
| 1245 SetUpCaptivePortalService( |
| 1246 browser()->profile(), |
| 1247 test_server()->GetURL(CreateServerRedirect(ssl_login_url.spec()))); |
| 1248 |
| 1249 SlowLoadNoCaptivePortal(browser(), RESULT_NO_RESPONSE); |
| 1250 } |
| 1251 |
| 1252 // A slow SSL load triggers a captive portal check. The user logs on before |
| 1253 // the SSL page times out. We wait for the timeout and subsequent reload. |
| 1254 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, Login) { |
| 1255 // Load starts, detect captive portal and open up a login tab. |
| 1256 SlowLoadBehindCaptivePortal(browser(), true); |
| 1257 |
| 1258 // Log in. One loading tab, no timed out ones. |
| 1259 Login(browser(), 1, 0); |
| 1260 |
| 1261 string16 expected_title = ASCIIToUTF16(kInternetConnectedTitle); |
| 1262 ui_test_utils::TitleWatcher title_watcher( |
| 1263 browser()->GetWebContentsAt(0), |
| 1264 expected_title); |
| 1265 |
| 1266 // Timeout occurs, and page is automatically reloaded. |
| 1267 FailLoadsAfterLogin(browser(), 1); |
| 1268 |
| 1269 // Double check the tab's title. |
| 1270 EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle()); |
| 1271 } |
| 1272 |
| 1273 // Same as above, except we make sure everything works with an incognito |
| 1274 // profile. Main issues it tests for are that the incognito has its own |
| 1275 // non-NULL captive portal service, and we open the tab in the correct |
| 1276 // window. |
| 1277 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, LoginIncognito) { |
| 1278 // This will watch tabs for both profiles, but only used to make sure no |
| 1279 // navigations occur for the non-incognito profile. |
| 1280 MultiNavigationObserver navigation_observer; |
| 1281 CaptivePortalObserver non_incognito_portal_observer(browser()->profile()); |
| 1282 |
| 1283 Browser* incognito_browser = CreateIncognitoBrowser(); |
| 1284 EnableCaptivePortalDetection(incognito_browser->profile(), true); |
| 1285 SetUpCaptivePortalService(incognito_browser->profile(), |
| 1286 GURL(kMockCaptivePortalTestUrl)); |
| 1287 |
| 1288 SlowLoadBehindCaptivePortal(incognito_browser, true); |
| 1289 |
| 1290 EXPECT_EQ(1, browser()->tab_count()); |
| 1291 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, |
| 1292 GetStateOfTabReloaderAt(browser(), 0)); |
| 1293 |
| 1294 Login(incognito_browser, 1, 0); |
| 1295 FailLoadsAfterLogin(incognito_browser, 1); |
| 1296 |
| 1297 EXPECT_EQ(1, browser()->tab_count()); |
| 1298 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, |
| 1299 GetStateOfTabReloaderAt(browser(), 0)); |
| 1300 |
| 1301 EXPECT_EQ(0, navigation_observer.NumNavigationsForTab( |
| 1302 browser()->GetWebContentsAt(0))); |
| 1303 EXPECT_EQ(0, non_incognito_portal_observer.num_results_received()); |
| 1304 } |
| 1305 |
| 1306 // The captive portal page is opened before the SSL page times out, |
| 1307 // but the user logs in only after the page times out. |
| 1308 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, LoginSlow) { |
| 1309 SlowLoadBehindCaptivePortal(browser(), true); |
| 1310 FailLoadsWithoutLogin(browser(), 1); |
| 1311 Login(browser(), 0, 1); |
| 1312 } |
| 1313 |
| 1314 // Checks the unlikely case that the tab times out before the timer triggers. |
| 1315 // This most likely won't happen, but should still work: |
| 1316 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, LoginFastTimeout) { |
| 1317 FastTimeoutBehindCaptivePortal(browser(), true); |
| 1318 Login(browser(), 0, 1); |
| 1319 } |
| 1320 |
| 1321 // Tries navigating both the tab that encounters an SSL timeout and the |
| 1322 // login tab twice, only logging in the second time. |
| 1323 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, LoginExtraNavigations) { |
| 1324 FastTimeoutBehindCaptivePortal(browser(), true); |
| 1325 |
| 1326 // Activate the timed out tab and navigate it to a timeout again. |
| 1327 browser()->ActivateTabAt(0, true); |
| 1328 FastTimeoutBehindCaptivePortal(browser(), false); |
| 1329 |
| 1330 // Activate and navigate the captive portal tab. This should not trigger a |
| 1331 // reload of the tab with the error. |
| 1332 browser()->ActivateTabAt(1, true); |
| 1333 NavigateLoginTab(browser(), 0, 1); |
| 1334 |
| 1335 // Simulate logging in. |
| 1336 Login(browser(), 0, 1); |
| 1337 } |
| 1338 |
| 1339 // After the first SSL timeout, closes the login tab and makes sure it's opened |
| 1340 // it again on a second timeout. |
| 1341 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, CloseLoginTab) { |
| 1342 // First load starts, opens a login tab, and then times out. |
| 1343 SlowLoadBehindCaptivePortal(browser(), true); |
| 1344 FailLoadsWithoutLogin(browser(), 1); |
| 1345 |
| 1346 // Close login tab. |
| 1347 browser()->CloseTab(); |
| 1348 |
| 1349 // Go through the standard slow load login, and make sure it still works. |
| 1350 SlowLoadBehindCaptivePortal(browser(), true); |
| 1351 Login(browser(), 1, 0); |
| 1352 FailLoadsAfterLogin(browser(), 1); |
| 1353 } |
| 1354 |
| 1355 // Checks that two tabs with SSL timeouts in the same window work. Both |
| 1356 // tabs only timeout after logging in. |
| 1357 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, TwoBrokenTabs) { |
| 1358 SlowLoadBehindCaptivePortal(browser(), true); |
| 1359 |
| 1360 // Can't set the TabReloader HTTPS timeout on a new tab without doing some |
| 1361 // acrobatics, so open a new tab at a normal page, and then navigate it to a |
| 1362 // timeout. |
| 1363 MultiNavigationObserver navigation_observer; |
| 1364 CaptivePortalObserver portal_observer(browser()->profile()); |
| 1365 ui_test_utils::NavigateToURLWithDisposition( |
| 1366 browser(), |
| 1367 URLRequestMockHTTPJob::GetMockUrl( |
| 1368 FilePath(FILE_PATH_LITERAL("title2.html"))), |
| 1369 NEW_FOREGROUND_TAB, |
| 1370 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); |
| 1371 |
| 1372 ASSERT_EQ(3, browser()->tab_count()); |
| 1373 EXPECT_FALSE(CheckPending(browser())); |
| 1374 EXPECT_EQ(0, portal_observer.num_results_received()); |
| 1375 EXPECT_EQ(1, NumLoadingTabs()); |
| 1376 EXPECT_EQ(1, navigation_observer.num_navigations()); |
| 1377 EXPECT_EQ(1, navigation_observer.NumNavigationsForTab( |
| 1378 browser()->GetWebContentsAt(2))); |
| 1379 ASSERT_EQ(CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL, |
| 1380 GetStateOfTabReloaderAt(browser(), 0)); |
| 1381 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, |
| 1382 GetStateOfTabReloader(browser()->GetTabContentsAt(1))); |
| 1383 ASSERT_TRUE(IsLoginTab(browser()->GetTabContentsAt(1))); |
| 1384 ASSERT_EQ(CaptivePortalTabReloader::STATE_NONE, |
| 1385 GetStateOfTabReloaderAt(browser(), 2)); |
| 1386 ASSERT_EQ(2, browser()->active_index()); |
| 1387 |
| 1388 SlowLoadBehindCaptivePortal(browser(), false); |
| 1389 |
| 1390 browser()->ActivateTabAt(1, true); |
| 1391 Login(browser(), 2, 0); |
| 1392 FailLoadsAfterLogin(browser(), 2); |
| 1393 } |
| 1394 |
| 1395 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, AbortLoad) { |
| 1396 // Go to the error page. |
| 1397 SlowLoadBehindCaptivePortal(browser(), true); |
| 1398 // The load will be destroyed without returning any result, so remove it from |
| 1399 // the list of jobs that will timeout. |
| 1400 URLRequestTimeoutOnDemandJob::AbandonRequests(); |
| 1401 |
| 1402 CaptivePortalObserver portal_observer(browser()->profile()); |
| 1403 MultiNavigationObserver navigation_observer; |
| 1404 |
| 1405 // Switch back to the hung tab from the login tab, and abort the navigation. |
| 1406 browser()->ActivateTabAt(0, true); |
| 1407 browser()->Stop(); |
| 1408 navigation_observer.WaitForNavigations(1); |
| 1409 |
| 1410 EXPECT_EQ(0, NumBrokenTabs()); |
| 1411 EXPECT_EQ(0, portal_observer.num_results_received()); |
| 1412 EXPECT_FALSE(CheckPending(browser())); |
| 1413 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, |
| 1414 GetStateOfTabReloaderAt(browser(), 0)); |
| 1415 |
| 1416 browser()->ActivateTabAt(1, true); |
| 1417 Login(browser(), 0, 0); |
| 1418 } |
| 1419 |
| 1420 // Checks the case where the timed out tab is successfully navigated before |
| 1421 // logging in. |
| 1422 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, NavigateBrokenTab) { |
| 1423 // Go to the error page. |
| 1424 SlowLoadBehindCaptivePortal(browser(), true); |
| 1425 FailLoadsWithoutLogin(browser(), 1); |
| 1426 |
| 1427 // Navigate the error tab to a non-error page. |
| 1428 browser()->ActivateTabAt(0, true); |
| 1429 ui_test_utils::NavigateToURL(browser(), |
| 1430 URLRequestMockHTTPJob::GetMockUrl( |
| 1431 FilePath(FILE_PATH_LITERAL("title2.html")))); |
| 1432 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, |
| 1433 GetStateOfTabReloaderAt(browser(), 0)); |
| 1434 |
| 1435 // Simulate logging in. |
| 1436 browser()->ActivateTabAt(1, true); |
| 1437 Login(browser(), 0, 0); |
| 1438 } |
| 1439 |
| 1440 // Navigates a broken, but still loading, tab to another timeout before logging |
| 1441 // in. |
| 1442 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, |
| 1443 NavigateBrokenToTimeoutTabWhileLoading) { |
| 1444 // Go to the error page. |
| 1445 SlowLoadBehindCaptivePortal(browser(), true); |
| 1446 URLRequestTimeoutOnDemandJob::AbandonRequests(); |
| 1447 |
| 1448 CaptivePortalTabReloader* tab_reloader = |
| 1449 GetTabReloader(browser()->GetTabContentsAt(0)); |
| 1450 ASSERT_TRUE(tab_reloader); |
| 1451 SetSlowSSLLoadTime(tab_reloader, base::TimeDelta()); |
| 1452 |
| 1453 CaptivePortalObserver portal_observer(browser()->profile()); |
| 1454 MultiNavigationObserver navigation_observer; |
| 1455 |
| 1456 // Navigate the error tab to a non-error page. Can't have ui_test_utils |
| 1457 // do the navigation because it will wait for loading tabs to stop loading |
| 1458 // before navigating. |
| 1459 browser()->ActivateTabAt(0, true); |
| 1460 browser()->OpenURL(content::OpenURLParams(GURL(kMockHttpsUrl), |
| 1461 content::Referrer(), |
| 1462 CURRENT_TAB, |
| 1463 content::PAGE_TRANSITION_TYPED, |
| 1464 false)); |
| 1465 navigation_observer.WaitForNavigations(1); |
| 1466 portal_observer.WaitForResults(1); |
| 1467 EXPECT_FALSE(CheckPending(browser())); |
| 1468 EXPECT_EQ(1, NumLoadingTabs()); |
| 1469 EXPECT_EQ(CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL, |
| 1470 GetStateOfTabReloaderAt(browser(), 0)); |
| 1471 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, |
| 1472 GetStateOfTabReloader(browser()->GetTabContentsAt(1))); |
| 1473 ASSERT_TRUE(IsLoginTab(browser()->GetTabContentsAt(1))); |
| 1474 |
| 1475 // Simulate logging in. |
| 1476 browser()->ActivateTabAt(1, true); |
| 1477 SetSlowSSLLoadTime(tab_reloader, base::TimeDelta::FromDays(1)); |
| 1478 Login(browser(), 1, 0); |
| 1479 |
| 1480 // Timeout occurs, and page is automatically reloaded. |
| 1481 FailLoadsAfterLogin(browser(), 1); |
| 1482 } |
| 1483 |
| 1484 // Checks that navigating a timed out tab back clears its state. |
| 1485 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, GoBack) { |
| 1486 // Navigate to a working page. |
| 1487 ui_test_utils::NavigateToURL( |
| 1488 browser(), |
| 1489 URLRequestMockHTTPJob::GetMockUrl( |
| 1490 FilePath(FILE_PATH_LITERAL("title2.html")))); |
| 1491 |
| 1492 // Go to the error page. |
| 1493 SlowLoadBehindCaptivePortal(browser(), true); |
| 1494 FailLoadsWithoutLogin(browser(), 1); |
| 1495 |
| 1496 CaptivePortalObserver portal_observer(browser()->profile()); |
| 1497 MultiNavigationObserver navigation_observer; |
| 1498 |
| 1499 // Activate the error page tab again and go back. |
| 1500 browser()->ActivateTabAt(0, true); |
| 1501 browser()->GoBack(CURRENT_TAB); |
| 1502 navigation_observer.WaitForNavigations(1); |
| 1503 |
| 1504 EXPECT_EQ(1, navigation_observer.NumNavigationsForTab( |
| 1505 browser()->GetWebContentsAt(0))); |
| 1506 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, |
| 1507 GetStateOfTabReloaderAt(browser(), 0)); |
| 1508 EXPECT_EQ(0, portal_observer.num_results_received()); |
| 1509 } |
| 1510 |
| 1511 // Checks that navigating back to a timeout triggers captive portal detection. |
| 1512 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, GoBackToTimeout) { |
| 1513 // Disable captive portal detection so the first navigation doesn't open a |
| 1514 // login tab. |
| 1515 EnableCaptivePortalDetection(browser()->profile(), false); |
| 1516 |
| 1517 SlowLoadNoCaptivePortal(browser(), RESULT_INTERNET_CONNECTED); |
| 1518 |
| 1519 // Navigate to a working page. |
| 1520 ui_test_utils::NavigateToURL(browser(), |
| 1521 URLRequestMockHTTPJob::GetMockUrl( |
| 1522 FilePath(FILE_PATH_LITERAL("title2.html")))); |
| 1523 ASSERT_EQ(CaptivePortalTabReloader::STATE_NONE, |
| 1524 GetStateOfTabReloaderAt(browser(), 0)); |
| 1525 |
| 1526 EnableCaptivePortalDetection(browser()->profile(), true); |
| 1527 |
| 1528 CaptivePortalTabReloader* tab_reloader = |
| 1529 GetTabReloader(browser()->GetActiveTabContents()); |
| 1530 ASSERT_TRUE(tab_reloader); |
| 1531 SetSlowSSLLoadTime(tab_reloader, base::TimeDelta()); |
| 1532 |
| 1533 // Go to the error page. |
| 1534 MultiNavigationObserver navigation_observer; |
| 1535 CaptivePortalObserver portal_observer(browser()->profile()); |
| 1536 browser()->GoBack(CURRENT_TAB); |
| 1537 |
| 1538 // Wait for both the check triggered by the broken tab and the first load |
| 1539 // of the login tab, and for the login tab to stop loading. |
| 1540 portal_observer.WaitForResults(2); |
| 1541 navigation_observer.WaitForNavigations(1); |
| 1542 |
| 1543 EXPECT_EQ(2, portal_observer.num_results_received()); |
| 1544 ASSERT_FALSE(CheckPending(browser())); |
| 1545 ASSERT_EQ(RESULT_BEHIND_CAPTIVE_PORTAL, |
| 1546 portal_observer.captive_portal_result()); |
| 1547 |
| 1548 ASSERT_EQ(CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL, |
| 1549 GetStateOfTabReloader(browser()->GetTabContentsAt(0))); |
| 1550 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, |
| 1551 GetStateOfTabReloader(browser()->GetTabContentsAt(1))); |
| 1552 ASSERT_TRUE(IsLoginTab(browser()->GetTabContentsAt(1))); |
| 1553 |
| 1554 ASSERT_EQ(2, browser()->tab_count()); |
| 1555 EXPECT_EQ(1, browser()->active_index()); |
| 1556 EXPECT_EQ(1, navigation_observer.NumNavigationsForTab( |
| 1557 browser()->GetWebContentsAt(1))); |
| 1558 EXPECT_EQ(1, NumLoadingTabs()); |
| 1559 |
| 1560 SetSlowSSLLoadTime(tab_reloader, base::TimeDelta::FromDays(1)); |
| 1561 Login(browser(), 1, 0); |
| 1562 FailLoadsAfterLogin(browser(), 1); |
| 1563 } |
| 1564 |
| 1565 // Checks that reloading a timeout triggers captive portal detection. |
| 1566 // Much like the last test, though the captive portal is disabled before |
| 1567 // the inital navigation, rather than captive portal detection. |
| 1568 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, ReloadTimeout) { |
| 1569 URLRequestMockCaptivePortalJobFactory::SetBehindCaptivePortal(false); |
| 1570 |
| 1571 // Do the first navigation while not behind a captive portal. |
| 1572 CaptivePortalObserver portal_observer(browser()->profile()); |
| 1573 ui_test_utils::NavigateToURL(browser(), GURL(kMockHttpsUrl)); |
| 1574 ASSERT_EQ(0, portal_observer.num_results_received()); |
| 1575 ASSERT_EQ(1, browser()->tab_count()); |
| 1576 |
| 1577 // A captive portal spontaneously appears. |
| 1578 URLRequestMockCaptivePortalJobFactory::SetBehindCaptivePortal(true); |
| 1579 |
| 1580 CaptivePortalTabReloader* tab_reloader = |
| 1581 GetTabReloader(browser()->GetActiveTabContents()); |
| 1582 ASSERT_TRUE(tab_reloader); |
| 1583 SetSlowSSLLoadTime(tab_reloader, base::TimeDelta()); |
| 1584 |
| 1585 MultiNavigationObserver navigation_observer; |
| 1586 browser()->GetActiveWebContents()->GetController().Reload(true); |
| 1587 |
| 1588 // Wait for the login tab to open, and the two captive portal results from |
| 1589 // opening an it. |
| 1590 portal_observer.WaitForResults(2); |
| 1591 navigation_observer.WaitForNavigations(1); |
| 1592 |
| 1593 ASSERT_EQ(2, portal_observer.num_results_received()); |
| 1594 ASSERT_FALSE(CheckPending(browser())); |
| 1595 ASSERT_EQ(RESULT_BEHIND_CAPTIVE_PORTAL, |
| 1596 portal_observer.captive_portal_result()); |
| 1597 |
| 1598 ASSERT_EQ(CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL, |
| 1599 GetStateOfTabReloader(browser()->GetTabContentsAt(0))); |
| 1600 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, |
| 1601 GetStateOfTabReloader(browser()->GetTabContentsAt(1))); |
| 1602 ASSERT_TRUE(IsLoginTab(browser()->GetTabContentsAt(1))); |
| 1603 |
| 1604 ASSERT_EQ(2, browser()->tab_count()); |
| 1605 EXPECT_EQ(1, browser()->active_index()); |
| 1606 EXPECT_EQ(1, navigation_observer.NumNavigationsForTab( |
| 1607 browser()->GetWebContentsAt(1))); |
| 1608 EXPECT_EQ(1, NumLoadingTabs()); |
| 1609 |
| 1610 SetSlowSSLLoadTime(tab_reloader, base::TimeDelta::FromDays(1)); |
| 1611 Login(browser(), 1, 0); |
| 1612 FailLoadsAfterLogin(browser(), 1); |
| 1613 } |
| 1614 |
| 1615 // Checks the case where there are two windows, and there's an SSL timeout in |
| 1616 // the background one. |
| 1617 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, TwoWindows) { |
| 1618 Browser* browser2 = Browser::Create(browser()->profile()); |
| 1619 // Navigate the new browser window so it'll be shown and we can pick the |
| 1620 // active window. |
| 1621 ui_test_utils::NavigateToURL(browser2, GURL(chrome::kAboutBlankURL)); |
| 1622 |
| 1623 // Generally, |browser2| will be the active window. However, if the |
| 1624 // original browser window lost focus before creating the new one, such as |
| 1625 // when running multiple tests at once, the original browser window may |
| 1626 // remain the profile's active window. |
| 1627 Browser* active_browser = |
| 1628 browser::FindTabbedBrowser(browser()->profile(), true); |
| 1629 Browser* inactive_browser; |
| 1630 if (active_browser == browser2) { |
| 1631 // When only one test is running at a time, the new browser will probably be |
| 1632 // on top, but when multiple tests are running at once, this is not |
| 1633 // guaranteed. |
| 1634 inactive_browser = browser(); |
| 1635 } else { |
| 1636 ASSERT_EQ(active_browser, browser()); |
| 1637 inactive_browser = browser2; |
| 1638 } |
| 1639 |
| 1640 CaptivePortalObserver portal_observer(browser()->profile()); |
| 1641 MultiNavigationObserver navigation_observer; |
| 1642 |
| 1643 // Navigate the tab in the inactive browser to an SSL timeout. Have to use |
| 1644 // browser::NavigateParams and NEW_BACKGROUND_TAB to avoid activating the |
| 1645 // window. |
| 1646 browser::NavigateParams params(inactive_browser, |
| 1647 GURL(kMockHttpsQuickTimeoutUrl), |
| 1648 content::PAGE_TRANSITION_TYPED); |
| 1649 params.disposition = NEW_BACKGROUND_TAB; |
| 1650 params.window_action = browser::NavigateParams::NO_ACTION; |
| 1651 ui_test_utils::NavigateToURL(¶ms); |
| 1652 navigation_observer.WaitForNavigations(2); |
| 1653 |
| 1654 // Make sure the active window hasn't changed, and its new tab is |
| 1655 // active. |
| 1656 ASSERT_EQ(active_browser, |
| 1657 browser::FindTabbedBrowser(browser()->profile(), true)); |
| 1658 ASSERT_EQ(1, active_browser->active_index()); |
| 1659 |
| 1660 // Check that the only two navigated tabs were the new error tab in the |
| 1661 // backround windows, and the login tab in the active window. |
| 1662 EXPECT_EQ(1, navigation_observer.NumNavigationsForTab( |
| 1663 inactive_browser->GetWebContentsAt(1))); |
| 1664 EXPECT_EQ(1, navigation_observer.NumNavigationsForTab( |
| 1665 active_browser->GetWebContentsAt(1))); |
| 1666 EXPECT_EQ(0, NumLoadingTabs()); |
| 1667 |
| 1668 // Check captive portal test results. |
| 1669 portal_observer.WaitForResults(2); |
| 1670 ASSERT_EQ(RESULT_BEHIND_CAPTIVE_PORTAL, |
| 1671 portal_observer.captive_portal_result()); |
| 1672 EXPECT_EQ(2, portal_observer.num_results_received()); |
| 1673 |
| 1674 // Check the inactive browser. |
| 1675 EXPECT_EQ(2, inactive_browser->tab_count()); |
| 1676 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, |
| 1677 GetStateOfTabReloaderAt(inactive_browser, 0)); |
| 1678 EXPECT_EQ(CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL, |
| 1679 GetStateOfTabReloaderAt(inactive_browser, 1)); |
| 1680 |
| 1681 // Check the active browser. |
| 1682 ASSERT_EQ(2, active_browser->tab_count()); |
| 1683 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, |
| 1684 GetStateOfTabReloaderAt(active_browser, 0)); |
| 1685 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, |
| 1686 GetStateOfTabReloaderAt(active_browser, 1)); |
| 1687 EXPECT_TRUE(IsLoginTab(active_browser->GetTabContentsAt(1))); |
| 1688 |
| 1689 // Simulate logging in. |
| 1690 Login(active_browser, 0, 1); |
| 1691 } |
| 1692 |
| 1693 } // namespace captive_portal |
OLD | NEW |