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_wrapper.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(TabContentsWrapper* 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 TabContentsWrapper* 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( |
| 655 TabContentsWrapper* tab_contents) const; |
| 656 |
| 657 private: |
| 658 DISALLOW_COPY_AND_ASSIGN(CaptivePortalBrowserTest); |
| 659 }; |
| 660 |
| 661 CaptivePortalBrowserTest::CaptivePortalBrowserTest() { |
| 662 } |
| 663 |
| 664 void CaptivePortalBrowserTest::SetUpOnMainThread() { |
| 665 // Enable mock requests. |
| 666 content::BrowserThread::PostTask( |
| 667 content::BrowserThread::IO, FROM_HERE, |
| 668 base::Bind(&chrome_browser_net::SetUrlRequestMocksEnabled, true)); |
| 669 URLRequestMockCaptivePortalJobFactory::AddUrlHandlers(); |
| 670 |
| 671 EnableCaptivePortalDetection(browser()->profile(), true); |
| 672 |
| 673 // Set the captive portal service to use URLRequestMockCaptivePortalJob's |
| 674 // mock URL, by default. |
| 675 SetUpCaptivePortalService(browser()->profile(), |
| 676 GURL(kMockCaptivePortalTestUrl)); |
| 677 } |
| 678 |
| 679 void CaptivePortalBrowserTest::CleanUpOnMainThread() { |
| 680 // No test should have a captive portal check pending on quit. |
| 681 EXPECT_FALSE(CheckPending(browser())); |
| 682 } |
| 683 |
| 684 void CaptivePortalBrowserTest::SetUpCommandLine( |
| 685 CommandLine* command_line) { |
| 686 command_line->AppendSwitch(switches::kCaptivePortalDetection); |
| 687 } |
| 688 |
| 689 void CaptivePortalBrowserTest::EnableCaptivePortalDetection( |
| 690 Profile* profile, bool enabled) { |
| 691 profile->GetPrefs()->SetBoolean(prefs::kAlternateErrorPagesEnabled, enabled); |
| 692 } |
| 693 |
| 694 void CaptivePortalBrowserTest::SetUpCaptivePortalService(Profile* profile, |
| 695 const GURL& test_url) { |
| 696 CaptivePortalService* captive_portal_service = |
| 697 CaptivePortalServiceFactory::GetForProfile(profile); |
| 698 captive_portal_service->set_test_url(test_url); |
| 699 |
| 700 // Don't use any non-zero timers. Timers are checked in unit tests. |
| 701 CaptivePortalService::RecheckPolicy* recheck_policy = |
| 702 &captive_portal_service->recheck_policy(); |
| 703 recheck_policy->initial_backoff_no_portal_ms = 0; |
| 704 recheck_policy->initial_backoff_portal_ms = 0; |
| 705 recheck_policy->backoff_policy.maximum_backoff_ms = 0; |
| 706 } |
| 707 |
| 708 bool CaptivePortalBrowserTest::CheckPending(Browser* browser) { |
| 709 CaptivePortalService* captive_portal_service = |
| 710 CaptivePortalServiceFactory::GetForProfile(browser->profile()); |
| 711 |
| 712 return captive_portal_service->FetchingURL() || |
| 713 captive_portal_service->TimerRunning(); |
| 714 } |
| 715 |
| 716 CaptivePortalTabReloader::State |
| 717 CaptivePortalBrowserTest::GetStateOfTabReloader( |
| 718 TabContentsWrapper* tab_contents) const { |
| 719 return GetTabReloader(tab_contents)->state(); |
| 720 } |
| 721 |
| 722 CaptivePortalTabReloader::State |
| 723 CaptivePortalBrowserTest::GetStateOfTabReloaderAt( |
| 724 Browser* browser, |
| 725 int index) const { |
| 726 return GetStateOfTabReloader(browser->GetTabContentsWrapperAt(index)); |
| 727 } |
| 728 |
| 729 int CaptivePortalBrowserTest::NumTabsWithState( |
| 730 CaptivePortalTabReloader::State state) const { |
| 731 int num_tabs = 0; |
| 732 for (TabContentsIterator tab_contents_it; |
| 733 !tab_contents_it.done(); |
| 734 ++tab_contents_it) { |
| 735 if (GetStateOfTabReloader(*tab_contents_it) == state) |
| 736 ++num_tabs; |
| 737 } |
| 738 return num_tabs; |
| 739 } |
| 740 |
| 741 int CaptivePortalBrowserTest::NumBrokenTabs() const { |
| 742 return NumTabsWithState(CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL); |
| 743 } |
| 744 |
| 745 int CaptivePortalBrowserTest::NumNeedReloadTabs() const { |
| 746 return NumTabsWithState(CaptivePortalTabReloader::STATE_NEEDS_RELOAD); |
| 747 } |
| 748 |
| 749 void CaptivePortalBrowserTest::NavigateToPageExpectNoTest( |
| 750 Browser* browser, |
| 751 const GURL& url, |
| 752 int expected_navigations) { |
| 753 MultiNavigationObserver navigation_observer; |
| 754 CaptivePortalObserver portal_observer(browser->profile()); |
| 755 |
| 756 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete( |
| 757 browser, url, expected_navigations); |
| 758 |
| 759 // No captive portal checks should have ocurred or be pending, and there |
| 760 // should be no new tabs. |
| 761 EXPECT_EQ(0, portal_observer.num_results_received()); |
| 762 EXPECT_FALSE(CheckPending(browser)); |
| 763 EXPECT_EQ(1, browser->tab_count()); |
| 764 EXPECT_EQ(expected_navigations, navigation_observer.num_navigations()); |
| 765 EXPECT_EQ(0, NumLoadingTabs()); |
| 766 } |
| 767 |
| 768 void CaptivePortalBrowserTest::SlowLoadNoCaptivePortal( |
| 769 Browser* browser, Result expected_result) { |
| 770 CaptivePortalTabReloader* tab_reloader = |
| 771 GetTabReloader(browser->GetSelectedTabContentsWrapper()); |
| 772 ASSERT_TRUE(tab_reloader); |
| 773 SetSlowSSLLoadTime(tab_reloader, base::TimeDelta()); |
| 774 |
| 775 MultiNavigationObserver navigation_observer; |
| 776 CaptivePortalObserver portal_observer(browser->profile()); |
| 777 ui_test_utils::NavigateToURLWithDisposition(browser, |
| 778 GURL(kMockHttpsUrl), |
| 779 CURRENT_TAB, |
| 780 ui_test_utils::BROWSER_TEST_NONE); |
| 781 |
| 782 portal_observer.WaitForResults(1); |
| 783 |
| 784 ASSERT_EQ(1, browser->tab_count()); |
| 785 EXPECT_EQ(expected_result, portal_observer.captive_portal_result()); |
| 786 EXPECT_EQ(1, portal_observer.num_results_received()); |
| 787 EXPECT_EQ(0, navigation_observer.num_navigations()); |
| 788 EXPECT_FALSE(CheckPending(browser)); |
| 789 |
| 790 // First tab should still be loading. |
| 791 EXPECT_EQ(1, NumLoadingTabs()); |
| 792 |
| 793 // Original request times out. |
| 794 URLRequestTimeoutOnDemandJob::FailRequests(); |
| 795 navigation_observer.WaitForNavigations(1); |
| 796 |
| 797 ASSERT_EQ(1, browser->tab_count()); |
| 798 EXPECT_EQ(1, portal_observer.num_results_received()); |
| 799 EXPECT_FALSE(CheckPending(browser)); |
| 800 EXPECT_EQ(0, NumLoadingTabs()); |
| 801 |
| 802 // Set a slow SSL load time to prevent the timer from triggering. |
| 803 SetSlowSSLLoadTime(tab_reloader, base::TimeDelta::FromDays(1)); |
| 804 } |
| 805 |
| 806 void CaptivePortalBrowserTest::FastTimeoutNoCaptivePortal( |
| 807 Browser* browser, Result expected_result) { |
| 808 ASSERT_NE(expected_result, RESULT_BEHIND_CAPTIVE_PORTAL); |
| 809 |
| 810 // Set the load time to be large, so the timer won't trigger. The value is |
| 811 // not restored at the end of the function. |
| 812 CaptivePortalTabReloader* tab_reloader = |
| 813 GetTabReloader(browser->GetSelectedTabContentsWrapper()); |
| 814 ASSERT_TRUE(tab_reloader); |
| 815 SetSlowSSLLoadTime(tab_reloader, base::TimeDelta::FromHours(1)); |
| 816 |
| 817 MultiNavigationObserver navigation_observer; |
| 818 CaptivePortalObserver portal_observer(browser->profile()); |
| 819 |
| 820 // Neither of these should be changed by the navigation. |
| 821 int active_index = browser->active_index(); |
| 822 int expected_tab_count = browser->tab_count(); |
| 823 |
| 824 ui_test_utils::NavigateToURL( |
| 825 browser, |
| 826 URLRequestFailedJob::GetMockHttpsUrl(net::ERR_CONNECTION_TIMED_OUT)); |
| 827 |
| 828 // An attempt to detect a captive portal should have started by now. If not, |
| 829 // abort early to prevent hanging. |
| 830 ASSERT_TRUE(portal_observer.num_results_received() > 0 || |
| 831 CheckPending(browser)); |
| 832 |
| 833 portal_observer.WaitForResults(1); |
| 834 navigation_observer.WaitForNavigations(1); |
| 835 |
| 836 // Check the result. |
| 837 EXPECT_EQ(1, portal_observer.num_results_received()); |
| 838 EXPECT_EQ(expected_result, portal_observer.captive_portal_result()); |
| 839 |
| 840 // Check that the right tab was navigated, and there were no extra |
| 841 // navigations. |
| 842 EXPECT_EQ(1, navigation_observer.NumNavigationsForTab( |
| 843 browser->GetWebContentsAt(active_index))); |
| 844 EXPECT_EQ(0, NumLoadingTabs()); |
| 845 |
| 846 // Check the tab's state, and verify no captive portal check is pending. |
| 847 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, |
| 848 GetStateOfTabReloaderAt(browser, 0)); |
| 849 EXPECT_FALSE(CheckPending(browser)); |
| 850 |
| 851 // Make sure no login tab was opened. |
| 852 EXPECT_EQ(expected_tab_count, browser->tab_count()); |
| 853 } |
| 854 |
| 855 void CaptivePortalBrowserTest::SlowLoadBehindCaptivePortal( |
| 856 Browser* browser, |
| 857 bool expect_open_login_tab) { |
| 858 // Calling this on a tab that's waiting for a load to manually be timed out |
| 859 // will result in a hang. |
| 860 ASSERT_FALSE(browser->GetSelectedWebContents()->IsLoading()); |
| 861 |
| 862 // Trigger a captive portal check quickly. |
| 863 CaptivePortalTabReloader* tab_reloader = |
| 864 GetTabReloader(browser->GetSelectedTabContentsWrapper()); |
| 865 ASSERT_TRUE(tab_reloader); |
| 866 SetSlowSSLLoadTime(tab_reloader, base::TimeDelta()); |
| 867 |
| 868 // Number of tabs expected to be open after the captive portal checks |
| 869 // have completed. |
| 870 int initial_tab_count = browser->tab_count(); |
| 871 int initial_active_index = browser->active_index(); |
| 872 int initial_loading_tabs = NumLoadingTabs(); |
| 873 int expected_broken_tabs = NumBrokenTabs(); |
| 874 if (CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL != |
| 875 GetStateOfTabReloader(browser->GetSelectedTabContentsWrapper())) { |
| 876 ++expected_broken_tabs; |
| 877 } |
| 878 |
| 879 MultiNavigationObserver navigation_observer; |
| 880 CaptivePortalObserver portal_observer(browser->profile()); |
| 881 ui_test_utils::NavigateToURLWithDisposition(browser, |
| 882 GURL(kMockHttpsUrl), |
| 883 CURRENT_TAB, |
| 884 ui_test_utils::BROWSER_TEST_NONE); |
| 885 |
| 886 if (expect_open_login_tab) { |
| 887 portal_observer.WaitForResults(2); |
| 888 navigation_observer.WaitForNavigations(1); |
| 889 EXPECT_EQ(2, portal_observer.num_results_received()); |
| 890 |
| 891 ASSERT_EQ(initial_tab_count + 1, browser->tab_count()); |
| 892 EXPECT_EQ(initial_tab_count, browser->active_index()); |
| 893 |
| 894 EXPECT_EQ(1, navigation_observer.NumNavigationsForTab( |
| 895 browser->GetWebContentsAt(initial_tab_count))); |
| 896 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, |
| 897 GetStateOfTabReloader(browser->GetTabContentsWrapperAt(1))); |
| 898 EXPECT_TRUE(IsLoginTab(browser->GetTabContentsWrapperAt(1))); |
| 899 } else { |
| 900 portal_observer.WaitForResults(1); |
| 901 EXPECT_EQ(0, navigation_observer.num_navigations()); |
| 902 EXPECT_EQ(initial_active_index, browser->active_index()); |
| 903 ASSERT_EQ(initial_tab_count, browser->tab_count()); |
| 904 EXPECT_EQ(initial_active_index, browser->active_index()); |
| 905 } |
| 906 |
| 907 EXPECT_EQ(initial_loading_tabs + 1, NumLoadingTabs()); |
| 908 EXPECT_EQ(expected_broken_tabs, NumBrokenTabs()); |
| 909 EXPECT_EQ(RESULT_BEHIND_CAPTIVE_PORTAL, |
| 910 portal_observer.captive_portal_result()); |
| 911 EXPECT_FALSE(CheckPending(browser)); |
| 912 |
| 913 EXPECT_EQ(CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL, |
| 914 GetStateOfTabReloader( |
| 915 browser->GetTabContentsWrapperAt(initial_active_index))); |
| 916 |
| 917 // Reset the load time to be large, so the timer won't trigger on a reload. |
| 918 SetSlowSSLLoadTime(tab_reloader, base::TimeDelta::FromHours(1)); |
| 919 } |
| 920 |
| 921 void CaptivePortalBrowserTest::FastTimeoutBehindCaptivePortal( |
| 922 Browser* browser, |
| 923 bool expect_open_login_tab) { |
| 924 // Calling this on a tab that's waiting for a load to manually be timed out |
| 925 // will result in a hang. |
| 926 ASSERT_FALSE(browser->GetSelectedWebContents()->IsLoading()); |
| 927 |
| 928 // Set the load time to be large, so the timer won't trigger. The value is |
| 929 // not restored at the end of the function. |
| 930 CaptivePortalTabReloader* tab_reloader = |
| 931 GetTabReloader(browser->GetSelectedTabContentsWrapper()); |
| 932 ASSERT_TRUE(tab_reloader); |
| 933 SetSlowSSLLoadTime(tab_reloader, base::TimeDelta::FromHours(1)); |
| 934 |
| 935 // Number of tabs expected to be open after the captive portal checks |
| 936 // have completed. |
| 937 int initial_tab_count = browser->tab_count(); |
| 938 int initial_active_index = browser->active_index(); |
| 939 int initial_loading_tabs = NumLoadingTabs(); |
| 940 int expected_broken_tabs = NumBrokenTabs(); |
| 941 if (CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL != |
| 942 GetStateOfTabReloader(browser->GetSelectedTabContentsWrapper())) { |
| 943 ++expected_broken_tabs; |
| 944 } |
| 945 |
| 946 MultiNavigationObserver navigation_observer; |
| 947 CaptivePortalObserver portal_observer(browser->profile()); |
| 948 ui_test_utils::NavigateToURLWithDisposition(browser, |
| 949 GURL(kMockHttpsQuickTimeoutUrl), |
| 950 CURRENT_TAB, |
| 951 ui_test_utils::BROWSER_TEST_NONE); |
| 952 |
| 953 if (expect_open_login_tab) { |
| 954 portal_observer.WaitForResults(2); |
| 955 navigation_observer.WaitForNavigations(2); |
| 956 EXPECT_EQ(2, portal_observer.num_results_received()); |
| 957 |
| 958 ASSERT_EQ(initial_tab_count + 1, browser->tab_count()); |
| 959 EXPECT_EQ(initial_tab_count, browser->active_index()); |
| 960 // Make sure that the originally active tab and the captive portal tab have |
| 961 // each loaded once. |
| 962 EXPECT_EQ(1, navigation_observer.NumNavigationsForTab( |
| 963 browser->GetWebContentsAt(initial_active_index))); |
| 964 EXPECT_EQ(1, navigation_observer.NumNavigationsForTab( |
| 965 browser->GetWebContentsAt(initial_tab_count))); |
| 966 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, |
| 967 GetStateOfTabReloader(browser->GetTabContentsWrapperAt(1))); |
| 968 EXPECT_TRUE(IsLoginTab(browser->GetTabContentsWrapperAt(1))); |
| 969 } else { |
| 970 portal_observer.WaitForResults(1); |
| 971 navigation_observer.WaitForNavigations(1); |
| 972 EXPECT_EQ(1, portal_observer.num_results_received()); |
| 973 |
| 974 EXPECT_EQ(initial_active_index, browser->active_index()); |
| 975 EXPECT_EQ(1, navigation_observer.NumNavigationsForTab( |
| 976 browser->GetWebContentsAt(initial_active_index))); |
| 977 ASSERT_EQ(initial_tab_count, browser->tab_count()); |
| 978 EXPECT_EQ(initial_active_index, browser->active_index()); |
| 979 } |
| 980 |
| 981 EXPECT_EQ(initial_loading_tabs, NumLoadingTabs()); |
| 982 EXPECT_EQ(expected_broken_tabs, NumBrokenTabs()); |
| 983 EXPECT_EQ(RESULT_BEHIND_CAPTIVE_PORTAL, |
| 984 portal_observer.captive_portal_result()); |
| 985 EXPECT_FALSE(CheckPending(browser)); |
| 986 |
| 987 EXPECT_EQ(CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL, |
| 988 GetStateOfTabReloader( |
| 989 browser->GetTabContentsWrapperAt(initial_active_index))); |
| 990 } |
| 991 |
| 992 void CaptivePortalBrowserTest::NavigateLoginTab(Browser* browser, |
| 993 int num_loading_tabs, |
| 994 int num_timed_out_tabs) { |
| 995 MultiNavigationObserver navigation_observer; |
| 996 CaptivePortalObserver portal_observer(browser->profile()); |
| 997 |
| 998 int initial_tab_count = browser->tab_count(); |
| 999 EXPECT_EQ(num_loading_tabs, NumLoadingTabs()); |
| 1000 EXPECT_EQ(num_timed_out_tabs, NumBrokenTabs() - NumLoadingTabs()); |
| 1001 |
| 1002 int login_tab_index = browser->active_index(); |
| 1003 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, |
| 1004 GetStateOfTabReloader(browser->GetSelectedTabContentsWrapper())); |
| 1005 ASSERT_TRUE(IsLoginTab(browser->GetSelectedTabContentsWrapper())); |
| 1006 |
| 1007 // Do the navigation. |
| 1008 content::RenderViewHost* render_view_host = |
| 1009 browser->GetSelectedWebContents()->GetRenderViewHost(); |
| 1010 render_view_host->ExecuteJavascriptInWebFrame( |
| 1011 string16(), |
| 1012 ASCIIToUTF16("submitForm()")); |
| 1013 |
| 1014 portal_observer.WaitForResults(1); |
| 1015 navigation_observer.WaitForNavigations(1); |
| 1016 |
| 1017 // Check the captive portal result. |
| 1018 EXPECT_EQ(RESULT_BEHIND_CAPTIVE_PORTAL, |
| 1019 portal_observer.captive_portal_result()); |
| 1020 EXPECT_EQ(1, portal_observer.num_results_received()); |
| 1021 EXPECT_FALSE(CheckPending(browser)); |
| 1022 |
| 1023 // Make sure not much has changed. |
| 1024 EXPECT_EQ(initial_tab_count, browser->tab_count()); |
| 1025 EXPECT_EQ(num_loading_tabs, NumLoadingTabs()); |
| 1026 EXPECT_EQ(num_loading_tabs + num_timed_out_tabs, NumBrokenTabs()); |
| 1027 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, |
| 1028 GetStateOfTabReloader(browser->GetTabContentsWrapperAt( |
| 1029 login_tab_index))); |
| 1030 EXPECT_TRUE(IsLoginTab(browser->GetTabContentsWrapperAt(login_tab_index))); |
| 1031 |
| 1032 // Make sure there were no unexpected navigations. |
| 1033 EXPECT_EQ(1, navigation_observer.NumNavigationsForTab( |
| 1034 browser->GetWebContentsAt(login_tab_index))); |
| 1035 } |
| 1036 |
| 1037 void CaptivePortalBrowserTest::Login(Browser* browser, |
| 1038 int num_loading_tabs, |
| 1039 int num_timed_out_tabs) { |
| 1040 // Simulate logging in. |
| 1041 URLRequestMockCaptivePortalJobFactory::SetBehindCaptivePortal(false); |
| 1042 |
| 1043 MultiNavigationObserver navigation_observer; |
| 1044 CaptivePortalObserver portal_observer(browser->profile()); |
| 1045 |
| 1046 int initial_tab_count = browser->tab_count(); |
| 1047 ASSERT_EQ(num_loading_tabs, NumLoadingTabs()); |
| 1048 EXPECT_EQ(num_timed_out_tabs, NumBrokenTabs() - NumLoadingTabs()); |
| 1049 |
| 1050 // Verify that the login page is on top. |
| 1051 int login_tab_index = browser->active_index(); |
| 1052 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, |
| 1053 GetStateOfTabReloader(browser->GetTabContentsWrapperAt( |
| 1054 login_tab_index))); |
| 1055 ASSERT_TRUE(IsLoginTab(browser->GetTabContentsWrapperAt(login_tab_index))); |
| 1056 |
| 1057 // Trigger a navigation. |
| 1058 content::RenderViewHost* render_view_host = |
| 1059 browser->GetSelectedWebContents()->GetRenderViewHost(); |
| 1060 render_view_host->ExecuteJavascriptInWebFrame( |
| 1061 string16(), |
| 1062 ASCIIToUTF16("submitForm()")); |
| 1063 |
| 1064 portal_observer.WaitForResults(1); |
| 1065 |
| 1066 // Wait for all the timed out tabs to reload. |
| 1067 navigation_observer.WaitForNavigations(1 + num_timed_out_tabs); |
| 1068 EXPECT_EQ(1, portal_observer.num_results_received()); |
| 1069 |
| 1070 // The tabs that were loading before should still be loading, and now be in |
| 1071 // STATE_NEEDS_RELOAD. |
| 1072 EXPECT_EQ(0, NumBrokenTabs()); |
| 1073 EXPECT_EQ(num_loading_tabs, NumLoadingTabs()); |
| 1074 EXPECT_EQ(num_loading_tabs, NumNeedReloadTabs()); |
| 1075 |
| 1076 // Make sure that the broken tabs have reloaded, and there's no more |
| 1077 // captive portal tab. |
| 1078 EXPECT_EQ(initial_tab_count, browser->tab_count()); |
| 1079 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, |
| 1080 GetStateOfTabReloaderAt(browser, login_tab_index)); |
| 1081 EXPECT_FALSE(IsLoginTab(browser->GetTabContentsWrapperAt(login_tab_index))); |
| 1082 |
| 1083 // Make sure there were no unexpected navigations of the login tab. |
| 1084 EXPECT_EQ(1, navigation_observer.NumNavigationsForTab( |
| 1085 browser->GetWebContentsAt(login_tab_index))); |
| 1086 } |
| 1087 |
| 1088 void CaptivePortalBrowserTest::FailLoadsAfterLogin(Browser* browser, |
| 1089 int num_loading_tabs) { |
| 1090 ASSERT_EQ(num_loading_tabs, NumLoadingTabs()); |
| 1091 ASSERT_EQ(num_loading_tabs, NumNeedReloadTabs()); |
| 1092 EXPECT_EQ(0, NumBrokenTabs()); |
| 1093 |
| 1094 int initial_num_tabs = browser->tab_count(); |
| 1095 int initial_active_tab = browser->active_index(); |
| 1096 |
| 1097 CaptivePortalObserver portal_observer(browser->profile()); |
| 1098 MultiNavigationObserver navigation_observer; |
| 1099 // Connection finally times out. |
| 1100 URLRequestTimeoutOnDemandJob::FailRequests(); |
| 1101 |
| 1102 navigation_observer.WaitForNavigations(2 * num_loading_tabs); |
| 1103 |
| 1104 // No captive portal checks should have ocurred or be pending, and there |
| 1105 // should be no new tabs. |
| 1106 EXPECT_EQ(0, portal_observer.num_results_received()); |
| 1107 EXPECT_FALSE(CheckPending(browser)); |
| 1108 EXPECT_EQ(initial_num_tabs, browser->tab_count()); |
| 1109 |
| 1110 EXPECT_EQ(initial_active_tab, browser->active_index()); |
| 1111 |
| 1112 EXPECT_EQ(0, NumNeedReloadTabs()); |
| 1113 EXPECT_EQ(0, NumLoadingTabs()); |
| 1114 EXPECT_EQ(0, navigation_observer.NumNavigationsForTab( |
| 1115 browser->GetSelectedWebContents())); |
| 1116 } |
| 1117 |
| 1118 void CaptivePortalBrowserTest::FailLoadsWithoutLogin(Browser* browser, |
| 1119 int num_loading_tabs) { |
| 1120 ASSERT_EQ(num_loading_tabs, NumLoadingTabs()); |
| 1121 ASSERT_EQ(0, NumNeedReloadTabs()); |
| 1122 EXPECT_EQ(num_loading_tabs, NumBrokenTabs()); |
| 1123 |
| 1124 int initial_num_tabs = browser->tab_count(); |
| 1125 int login_tab = browser->active_index(); |
| 1126 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, |
| 1127 GetStateOfTabReloader(browser->GetSelectedTabContentsWrapper())); |
| 1128 ASSERT_TRUE(IsLoginTab(browser->GetSelectedTabContentsWrapper())); |
| 1129 |
| 1130 CaptivePortalObserver portal_observer(browser->profile()); |
| 1131 MultiNavigationObserver navigation_observer; |
| 1132 // Connection finally times out. |
| 1133 URLRequestTimeoutOnDemandJob::FailRequests(); |
| 1134 |
| 1135 navigation_observer.WaitForNavigations(num_loading_tabs); |
| 1136 |
| 1137 // No captive portal checks should have ocurred or be pending, and there |
| 1138 // should be no new tabs. |
| 1139 EXPECT_EQ(0, portal_observer.num_results_received()); |
| 1140 EXPECT_FALSE(CheckPending(browser)); |
| 1141 EXPECT_EQ(initial_num_tabs, browser->tab_count()); |
| 1142 |
| 1143 EXPECT_EQ(0, NumNeedReloadTabs()); |
| 1144 EXPECT_EQ(0, NumLoadingTabs()); |
| 1145 EXPECT_EQ(num_loading_tabs, NumBrokenTabs()); |
| 1146 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, |
| 1147 GetStateOfTabReloader(browser->GetSelectedTabContentsWrapper())); |
| 1148 EXPECT_TRUE(IsLoginTab(browser->GetSelectedTabContentsWrapper())); |
| 1149 EXPECT_EQ(login_tab, browser->active_index()); |
| 1150 |
| 1151 EXPECT_EQ(0, navigation_observer.NumNavigationsForTab( |
| 1152 browser->GetWebContentsAt(login_tab))); |
| 1153 } |
| 1154 |
| 1155 void CaptivePortalBrowserTest::SetSlowSSLLoadTime( |
| 1156 CaptivePortalTabReloader* tab_reloader, |
| 1157 base::TimeDelta slow_ssl_load_time) { |
| 1158 tab_reloader->set_slow_ssl_load_time(slow_ssl_load_time); |
| 1159 } |
| 1160 |
| 1161 CaptivePortalTabReloader* CaptivePortalBrowserTest::GetTabReloader( |
| 1162 TabContentsWrapper* tab_contents) const { |
| 1163 return tab_contents->captive_portal_tab_helper()->GetTabReloaderForTest(); |
| 1164 } |
| 1165 |
| 1166 // Make sure there's no test for a captive portal on HTTP timeouts. This will |
| 1167 // also trigger the link doctor page, which results in the load of a second |
| 1168 // error page. |
| 1169 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, HttpTimeout) { |
| 1170 GURL url = URLRequestFailedJob::GetMockHttpUrl(net::ERR_CONNECTION_TIMED_OUT); |
| 1171 NavigateToPageExpectNoTest(browser(), url, 2); |
| 1172 } |
| 1173 |
| 1174 // Make sure there's no check for a captive portal on HTTPS errors other than |
| 1175 // timeouts, when they preempt the slow load timer. |
| 1176 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, HttpsNonTimeoutError) { |
| 1177 GURL url = URLRequestFailedJob::GetMockHttpsUrl(net::ERR_UNEXPECTED); |
| 1178 NavigateToPageExpectNoTest(browser(), url, 1); |
| 1179 } |
| 1180 |
| 1181 // Make sure no captive portal test triggers on HTTPS timeouts of iframes. |
| 1182 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, HttpsIframeTimeout) { |
| 1183 CaptivePortalObserver portal_observer(browser()->profile()); |
| 1184 |
| 1185 // Use an HTTPS server for the top level page. |
| 1186 net::TestServer https_server(net::TestServer::TYPE_HTTPS, |
| 1187 net::TestServer::kLocalhost, |
| 1188 FilePath(FILE_PATH_LITERAL("chrome/test/data"))); |
| 1189 ASSERT_TRUE(https_server.Start()); |
| 1190 |
| 1191 GURL url = https_server.GetURL(kTestServerIframeTimeoutPath); |
| 1192 NavigateToPageExpectNoTest(browser(), url, 1); |
| 1193 } |
| 1194 |
| 1195 // Check the captive portal result when the test request reports a network |
| 1196 // error. The check is triggered by a slow loading page, and the page |
| 1197 // errors out only after getting a captive portal result. |
| 1198 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, RequestFails) { |
| 1199 SetUpCaptivePortalService( |
| 1200 browser()->profile(), |
| 1201 URLRequestFailedJob::GetMockHttpUrl(net::ERR_CONNECTION_CLOSED)); |
| 1202 SlowLoadNoCaptivePortal(browser(), RESULT_NO_RESPONSE); |
| 1203 } |
| 1204 |
| 1205 // Same as above, but for the rather unlikely case that the connection times out |
| 1206 // before the timer triggers. |
| 1207 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, RequestFailsFastTimout) { |
| 1208 SetUpCaptivePortalService( |
| 1209 browser()->profile(), |
| 1210 URLRequestFailedJob::GetMockHttpUrl(net::ERR_CONNECTION_CLOSED)); |
| 1211 FastTimeoutNoCaptivePortal(browser(), RESULT_NO_RESPONSE); |
| 1212 } |
| 1213 |
| 1214 // Checks the case that captive portal detection is disabled. |
| 1215 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, Disabled) { |
| 1216 EnableCaptivePortalDetection(browser()->profile(), false); |
| 1217 SlowLoadNoCaptivePortal(browser(), RESULT_INTERNET_CONNECTED); |
| 1218 } |
| 1219 |
| 1220 // Checks that we look for a captive portal on HTTPS timeouts and don't reload |
| 1221 // the error tab when the captive portal probe gets a 204 response, indicating |
| 1222 // there is no captive portal. |
| 1223 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, InternetConnected) { |
| 1224 // Can't just use SetBehindCaptivePortal(false), since then there wouldn't |
| 1225 // be a timeout. |
| 1226 ASSERT_TRUE(test_server()->Start()); |
| 1227 SetUpCaptivePortalService(browser()->profile(), |
| 1228 test_server()->GetURL("nocontent")); |
| 1229 SlowLoadNoCaptivePortal(browser(), RESULT_INTERNET_CONNECTED); |
| 1230 } |
| 1231 |
| 1232 // Checks that no login page is opened when the HTTP test URL redirects to an |
| 1233 // SSL certificate error. |
| 1234 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, RedirectSSLCertError) { |
| 1235 // Need an HTTP TestServer to handle a dynamically created server redirect. |
| 1236 ASSERT_TRUE(test_server()->Start()); |
| 1237 |
| 1238 net::TestServer::HTTPSOptions https_options; |
| 1239 https_options.server_certificate = |
| 1240 net::TestServer::HTTPSOptions::CERT_MISMATCHED_NAME; |
| 1241 net::TestServer https_server(https_options, |
| 1242 FilePath(FILE_PATH_LITERAL("chrome/test/data"))); |
| 1243 ASSERT_TRUE(https_server.Start()); |
| 1244 |
| 1245 GURL ssl_login_url = https_server.GetURL(kTestServerLoginPath); |
| 1246 |
| 1247 CaptivePortalService* captive_portal_service = |
| 1248 CaptivePortalServiceFactory::GetForProfile(browser()->profile()); |
| 1249 ASSERT_TRUE(captive_portal_service); |
| 1250 SetUpCaptivePortalService( |
| 1251 browser()->profile(), |
| 1252 test_server()->GetURL(CreateServerRedirect(ssl_login_url.spec()))); |
| 1253 |
| 1254 SlowLoadNoCaptivePortal(browser(), RESULT_NO_RESPONSE); |
| 1255 } |
| 1256 |
| 1257 // A slow SSL load triggers a captive portal check. The user logs on before |
| 1258 // the SSL page times out. We wait for the timeout and subsequent reload. |
| 1259 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, Login) { |
| 1260 // Load starts, detect captive portal and open up a login tab. |
| 1261 SlowLoadBehindCaptivePortal(browser(), true); |
| 1262 |
| 1263 // Log in. One loading tab, no timed out ones. |
| 1264 Login(browser(), 1, 0); |
| 1265 |
| 1266 string16 expected_title = ASCIIToUTF16(kInternetConnectedTitle); |
| 1267 ui_test_utils::TitleWatcher title_watcher( |
| 1268 browser()->GetWebContentsAt(0), |
| 1269 expected_title); |
| 1270 |
| 1271 // Timeout occurs, and page is automatically reloaded. |
| 1272 FailLoadsAfterLogin(browser(), 1); |
| 1273 |
| 1274 // Double check the tab's title. |
| 1275 EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle()); |
| 1276 } |
| 1277 |
| 1278 // Same as above, except we make sure everything works with an incognito |
| 1279 // profile. Main issues it tests for are that the incognito has its own |
| 1280 // non-NULL captive portal service, and we open the tab in the correct |
| 1281 // window. |
| 1282 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, LoginIncognito) { |
| 1283 // This will watch tabs for both profiles, but only used to make sure no |
| 1284 // navigations occur for the non-incognito profile. |
| 1285 MultiNavigationObserver navigation_observer; |
| 1286 CaptivePortalObserver non_incognito_portal_observer(browser()->profile()); |
| 1287 |
| 1288 Browser* incognito_browser = CreateIncognitoBrowser(); |
| 1289 EnableCaptivePortalDetection(incognito_browser->profile(), true); |
| 1290 SetUpCaptivePortalService(incognito_browser->profile(), |
| 1291 GURL(kMockCaptivePortalTestUrl)); |
| 1292 |
| 1293 SlowLoadBehindCaptivePortal(incognito_browser, true); |
| 1294 |
| 1295 EXPECT_EQ(1, browser()->tab_count()); |
| 1296 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, |
| 1297 GetStateOfTabReloaderAt(browser(), 0)); |
| 1298 |
| 1299 Login(incognito_browser, 1, 0); |
| 1300 FailLoadsAfterLogin(incognito_browser, 1); |
| 1301 |
| 1302 EXPECT_EQ(1, browser()->tab_count()); |
| 1303 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, |
| 1304 GetStateOfTabReloaderAt(browser(), 0)); |
| 1305 |
| 1306 EXPECT_EQ(0, navigation_observer.NumNavigationsForTab( |
| 1307 browser()->GetWebContentsAt(0))); |
| 1308 EXPECT_EQ(0, non_incognito_portal_observer.num_results_received()); |
| 1309 } |
| 1310 |
| 1311 // The captive portal page is opened before the SSL page times out, |
| 1312 // but the user logs in only after the page times out. |
| 1313 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, LoginSlow) { |
| 1314 SlowLoadBehindCaptivePortal(browser(), true); |
| 1315 FailLoadsWithoutLogin(browser(), 1); |
| 1316 Login(browser(), 0, 1); |
| 1317 } |
| 1318 |
| 1319 // Checks the unlikely case that the tab times out before the timer triggers. |
| 1320 // This most likely won't happen, but should still work: |
| 1321 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, LoginFastTimeout) { |
| 1322 FastTimeoutBehindCaptivePortal(browser(), true); |
| 1323 Login(browser(), 0, 1); |
| 1324 } |
| 1325 |
| 1326 // Tries navigating both the tab that encounters an SSL timeout and the |
| 1327 // login tab twice, only logging in the second time. |
| 1328 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, LoginExtraNavigations) { |
| 1329 FastTimeoutBehindCaptivePortal(browser(), true); |
| 1330 |
| 1331 // Activate the timed out tab and navigate it to a timeout again. |
| 1332 browser()->ActivateTabAt(0, true); |
| 1333 FastTimeoutBehindCaptivePortal(browser(), false); |
| 1334 |
| 1335 // Activate and navigate the captive portal tab. This should not trigger a |
| 1336 // reload of the tab with the error. |
| 1337 browser()->ActivateTabAt(1, true); |
| 1338 NavigateLoginTab(browser(), 0, 1); |
| 1339 |
| 1340 // Simulate logging in. |
| 1341 Login(browser(), 0, 1); |
| 1342 } |
| 1343 |
| 1344 // After the first SSL timeout, closes the login tab and makes sure it's opened |
| 1345 // it again on a second timeout. |
| 1346 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, CloseLoginTab) { |
| 1347 // First load starts, opens a login tab, and then times out. |
| 1348 SlowLoadBehindCaptivePortal(browser(), true); |
| 1349 FailLoadsWithoutLogin(browser(), 1); |
| 1350 |
| 1351 // Close login tab. |
| 1352 browser()->CloseTab(); |
| 1353 |
| 1354 // Go through the standard slow load login, and make sure it still works. |
| 1355 SlowLoadBehindCaptivePortal(browser(), true); |
| 1356 Login(browser(), 1, 0); |
| 1357 FailLoadsAfterLogin(browser(), 1); |
| 1358 } |
| 1359 |
| 1360 // Checks that two tabs with SSL timeouts in the same window work. Both |
| 1361 // tabs only timeout after logging in. |
| 1362 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, TwoBrokenTabs) { |
| 1363 SlowLoadBehindCaptivePortal(browser(), true); |
| 1364 |
| 1365 // Can't set the TabReloader HTTPS timeout on a new tab without doing some |
| 1366 // acrobatics, so open a new tab at a normal page, and then navigate it to a |
| 1367 // timeout. |
| 1368 MultiNavigationObserver navigation_observer; |
| 1369 CaptivePortalObserver portal_observer(browser()->profile()); |
| 1370 ui_test_utils::NavigateToURLWithDisposition( |
| 1371 browser(), |
| 1372 URLRequestMockHTTPJob::GetMockUrl( |
| 1373 FilePath(FILE_PATH_LITERAL("title2.html"))), |
| 1374 NEW_FOREGROUND_TAB, |
| 1375 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); |
| 1376 |
| 1377 ASSERT_EQ(3, browser()->tab_count()); |
| 1378 EXPECT_FALSE(CheckPending(browser())); |
| 1379 EXPECT_EQ(0, portal_observer.num_results_received()); |
| 1380 EXPECT_EQ(1, NumLoadingTabs()); |
| 1381 EXPECT_EQ(1, navigation_observer.num_navigations()); |
| 1382 EXPECT_EQ(1, navigation_observer.NumNavigationsForTab( |
| 1383 browser()->GetWebContentsAt(2))); |
| 1384 ASSERT_EQ(CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL, |
| 1385 GetStateOfTabReloaderAt(browser(), 0)); |
| 1386 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, |
| 1387 GetStateOfTabReloader(browser()->GetTabContentsWrapperAt(1))); |
| 1388 ASSERT_TRUE(IsLoginTab(browser()->GetTabContentsWrapperAt(1))); |
| 1389 ASSERT_EQ(CaptivePortalTabReloader::STATE_NONE, |
| 1390 GetStateOfTabReloaderAt(browser(), 2)); |
| 1391 ASSERT_EQ(2, browser()->active_index()); |
| 1392 |
| 1393 SlowLoadBehindCaptivePortal(browser(), false); |
| 1394 |
| 1395 browser()->ActivateTabAt(1, true); |
| 1396 Login(browser(), 2, 0); |
| 1397 FailLoadsAfterLogin(browser(), 2); |
| 1398 } |
| 1399 |
| 1400 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, AbortLoad) { |
| 1401 // Go to the error page. |
| 1402 SlowLoadBehindCaptivePortal(browser(), true); |
| 1403 // The load will be destroyed without returning any result, so remove it from |
| 1404 // the list of jobs that will timeout. |
| 1405 URLRequestTimeoutOnDemandJob::AbandonRequests(); |
| 1406 |
| 1407 CaptivePortalObserver portal_observer(browser()->profile()); |
| 1408 MultiNavigationObserver navigation_observer; |
| 1409 |
| 1410 // Switch back to the hung tab from the login tab, and abort the navigation. |
| 1411 browser()->ActivateTabAt(0, true); |
| 1412 browser()->Stop(); |
| 1413 navigation_observer.WaitForNavigations(1); |
| 1414 |
| 1415 EXPECT_EQ(0, NumBrokenTabs()); |
| 1416 EXPECT_EQ(0, portal_observer.num_results_received()); |
| 1417 EXPECT_FALSE(CheckPending(browser())); |
| 1418 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, |
| 1419 GetStateOfTabReloaderAt(browser(), 0)); |
| 1420 |
| 1421 browser()->ActivateTabAt(1, true); |
| 1422 Login(browser(), 0, 0); |
| 1423 } |
| 1424 |
| 1425 // Checks the case where the timed out tab is successfully navigated before |
| 1426 // logging in. |
| 1427 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, NavigateBrokenTab) { |
| 1428 // Go to the error page. |
| 1429 SlowLoadBehindCaptivePortal(browser(), true); |
| 1430 FailLoadsWithoutLogin(browser(), 1); |
| 1431 |
| 1432 // Navigate the error tab to a non-error page. |
| 1433 browser()->ActivateTabAt(0, true); |
| 1434 ui_test_utils::NavigateToURL(browser(), |
| 1435 URLRequestMockHTTPJob::GetMockUrl( |
| 1436 FilePath(FILE_PATH_LITERAL("title2.html")))); |
| 1437 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, |
| 1438 GetStateOfTabReloaderAt(browser(), 0)); |
| 1439 |
| 1440 // Simulate logging in. |
| 1441 browser()->ActivateTabAt(1, true); |
| 1442 Login(browser(), 0, 0); |
| 1443 } |
| 1444 |
| 1445 // Navigates a broken, but still loading, tab to another timeout before logging |
| 1446 // in. |
| 1447 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, |
| 1448 NavigateBrokenToTimeoutTabWhileLoading) { |
| 1449 // Go to the error page. |
| 1450 SlowLoadBehindCaptivePortal(browser(), true); |
| 1451 URLRequestTimeoutOnDemandJob::AbandonRequests(); |
| 1452 |
| 1453 CaptivePortalTabReloader* tab_reloader = |
| 1454 GetTabReloader(browser()->GetTabContentsWrapperAt(0)); |
| 1455 ASSERT_TRUE(tab_reloader); |
| 1456 SetSlowSSLLoadTime(tab_reloader, base::TimeDelta()); |
| 1457 |
| 1458 CaptivePortalObserver portal_observer(browser()->profile()); |
| 1459 MultiNavigationObserver navigation_observer; |
| 1460 |
| 1461 // Navigate the error tab to a non-error page. Can't have ui_test_utils |
| 1462 // do the navigation because it will wait for loading tabs to stop loading |
| 1463 // before navigating. |
| 1464 browser()->ActivateTabAt(0, true); |
| 1465 browser()->OpenURL(content::OpenURLParams(GURL(kMockHttpsUrl), |
| 1466 content::Referrer(), |
| 1467 CURRENT_TAB, |
| 1468 content::PAGE_TRANSITION_TYPED, |
| 1469 false)); |
| 1470 navigation_observer.WaitForNavigations(1); |
| 1471 portal_observer.WaitForResults(1); |
| 1472 EXPECT_FALSE(CheckPending(browser())); |
| 1473 EXPECT_EQ(1, NumLoadingTabs()); |
| 1474 EXPECT_EQ(CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL, |
| 1475 GetStateOfTabReloaderAt(browser(), 0)); |
| 1476 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, |
| 1477 GetStateOfTabReloader(browser()->GetTabContentsWrapperAt(1))); |
| 1478 ASSERT_TRUE(IsLoginTab(browser()->GetTabContentsWrapperAt(1))); |
| 1479 |
| 1480 // Simulate logging in. |
| 1481 browser()->ActivateTabAt(1, true); |
| 1482 SetSlowSSLLoadTime(tab_reloader, base::TimeDelta::FromDays(1)); |
| 1483 Login(browser(), 1, 0); |
| 1484 |
| 1485 // Timeout occurs, and page is automatically reloaded. |
| 1486 FailLoadsAfterLogin(browser(), 1); |
| 1487 } |
| 1488 |
| 1489 // Checks that navigating a timed out tab back clears its state. |
| 1490 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, GoBack) { |
| 1491 // Navigate to a working page. |
| 1492 ui_test_utils::NavigateToURL( |
| 1493 browser(), |
| 1494 URLRequestMockHTTPJob::GetMockUrl( |
| 1495 FilePath(FILE_PATH_LITERAL("title2.html")))); |
| 1496 |
| 1497 // Go to the error page. |
| 1498 SlowLoadBehindCaptivePortal(browser(), true); |
| 1499 FailLoadsWithoutLogin(browser(), 1); |
| 1500 |
| 1501 CaptivePortalObserver portal_observer(browser()->profile()); |
| 1502 MultiNavigationObserver navigation_observer; |
| 1503 |
| 1504 // Activate the error page tab again and go back. |
| 1505 browser()->ActivateTabAt(0, true); |
| 1506 browser()->GoBack(CURRENT_TAB); |
| 1507 navigation_observer.WaitForNavigations(1); |
| 1508 |
| 1509 EXPECT_EQ(1, navigation_observer.NumNavigationsForTab( |
| 1510 browser()->GetWebContentsAt(0))); |
| 1511 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, |
| 1512 GetStateOfTabReloaderAt(browser(), 0)); |
| 1513 EXPECT_EQ(0, portal_observer.num_results_received()); |
| 1514 } |
| 1515 |
| 1516 // Checks that navigating back to a timeout triggers captive portal detection. |
| 1517 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, GoBackToTimeout) { |
| 1518 // Disable captive portal detection so the first navigation doesn't open a |
| 1519 // login tab. |
| 1520 EnableCaptivePortalDetection(browser()->profile(), false); |
| 1521 |
| 1522 SlowLoadNoCaptivePortal(browser(), RESULT_INTERNET_CONNECTED); |
| 1523 |
| 1524 // Navigate to a working page. |
| 1525 ui_test_utils::NavigateToURL(browser(), |
| 1526 URLRequestMockHTTPJob::GetMockUrl( |
| 1527 FilePath(FILE_PATH_LITERAL("title2.html")))); |
| 1528 ASSERT_EQ(CaptivePortalTabReloader::STATE_NONE, |
| 1529 GetStateOfTabReloaderAt(browser(), 0)); |
| 1530 |
| 1531 EnableCaptivePortalDetection(browser()->profile(), true); |
| 1532 |
| 1533 CaptivePortalTabReloader* tab_reloader = |
| 1534 GetTabReloader(browser()->GetSelectedTabContentsWrapper()); |
| 1535 ASSERT_TRUE(tab_reloader); |
| 1536 SetSlowSSLLoadTime(tab_reloader, base::TimeDelta()); |
| 1537 |
| 1538 // Go to the error page. |
| 1539 MultiNavigationObserver navigation_observer; |
| 1540 CaptivePortalObserver portal_observer(browser()->profile()); |
| 1541 browser()->GoBack(CURRENT_TAB); |
| 1542 |
| 1543 // Wait for both the check triggered by the broken tab and the first load |
| 1544 // of the login tab, and for the login tab to stop loading. |
| 1545 portal_observer.WaitForResults(2); |
| 1546 navigation_observer.WaitForNavigations(1); |
| 1547 |
| 1548 EXPECT_EQ(2, portal_observer.num_results_received()); |
| 1549 ASSERT_FALSE(CheckPending(browser())); |
| 1550 ASSERT_EQ(RESULT_BEHIND_CAPTIVE_PORTAL, |
| 1551 portal_observer.captive_portal_result()); |
| 1552 |
| 1553 ASSERT_EQ(CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL, |
| 1554 GetStateOfTabReloader(browser()->GetTabContentsWrapperAt(0))); |
| 1555 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, |
| 1556 GetStateOfTabReloader(browser()->GetTabContentsWrapperAt(1))); |
| 1557 ASSERT_TRUE(IsLoginTab(browser()->GetTabContentsWrapperAt(1))); |
| 1558 |
| 1559 ASSERT_EQ(2, browser()->tab_count()); |
| 1560 EXPECT_EQ(1, browser()->active_index()); |
| 1561 EXPECT_EQ(1, navigation_observer.NumNavigationsForTab( |
| 1562 browser()->GetWebContentsAt(1))); |
| 1563 EXPECT_EQ(1, NumLoadingTabs()); |
| 1564 |
| 1565 SetSlowSSLLoadTime(tab_reloader, base::TimeDelta::FromDays(1)); |
| 1566 Login(browser(), 1, 0); |
| 1567 FailLoadsAfterLogin(browser(), 1); |
| 1568 } |
| 1569 |
| 1570 // Checks that reloading a timeout triggers captive portal detection. |
| 1571 // Much like the last test, though the captive portal is disabled before |
| 1572 // the inital navigation, rather than captive portal detection. |
| 1573 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, ReloadTimeout) { |
| 1574 URLRequestMockCaptivePortalJobFactory::SetBehindCaptivePortal(false); |
| 1575 |
| 1576 // Do the first navigation while not behind a captive portal. |
| 1577 CaptivePortalObserver portal_observer(browser()->profile()); |
| 1578 ui_test_utils::NavigateToURL(browser(), GURL(kMockHttpsUrl)); |
| 1579 ASSERT_EQ(0, portal_observer.num_results_received()); |
| 1580 ASSERT_EQ(1, browser()->tab_count()); |
| 1581 |
| 1582 // A captive portal spontaneously appears. |
| 1583 URLRequestMockCaptivePortalJobFactory::SetBehindCaptivePortal(true); |
| 1584 |
| 1585 CaptivePortalTabReloader* tab_reloader = |
| 1586 GetTabReloader(browser()->GetSelectedTabContentsWrapper()); |
| 1587 ASSERT_TRUE(tab_reloader); |
| 1588 SetSlowSSLLoadTime(tab_reloader, base::TimeDelta()); |
| 1589 |
| 1590 MultiNavigationObserver navigation_observer; |
| 1591 browser()->GetSelectedWebContents()->GetController().Reload(true); |
| 1592 |
| 1593 // Wait for the login tab to open, and the two captive portal results from |
| 1594 // opening an it. |
| 1595 portal_observer.WaitForResults(2); |
| 1596 navigation_observer.WaitForNavigations(1); |
| 1597 |
| 1598 ASSERT_EQ(2, portal_observer.num_results_received()); |
| 1599 ASSERT_FALSE(CheckPending(browser())); |
| 1600 ASSERT_EQ(RESULT_BEHIND_CAPTIVE_PORTAL, |
| 1601 portal_observer.captive_portal_result()); |
| 1602 |
| 1603 ASSERT_EQ(CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL, |
| 1604 GetStateOfTabReloader(browser()->GetTabContentsWrapperAt(0))); |
| 1605 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, |
| 1606 GetStateOfTabReloader(browser()->GetTabContentsWrapperAt(1))); |
| 1607 ASSERT_TRUE(IsLoginTab(browser()->GetTabContentsWrapperAt(1))); |
| 1608 |
| 1609 ASSERT_EQ(2, browser()->tab_count()); |
| 1610 EXPECT_EQ(1, browser()->active_index()); |
| 1611 EXPECT_EQ(1, navigation_observer.NumNavigationsForTab( |
| 1612 browser()->GetWebContentsAt(1))); |
| 1613 EXPECT_EQ(1, NumLoadingTabs()); |
| 1614 |
| 1615 SetSlowSSLLoadTime(tab_reloader, base::TimeDelta::FromDays(1)); |
| 1616 Login(browser(), 1, 0); |
| 1617 FailLoadsAfterLogin(browser(), 1); |
| 1618 } |
| 1619 |
| 1620 // Checks the case where there are two windows, and there's an SSL timeout in |
| 1621 // the background one. |
| 1622 IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, TwoWindows) { |
| 1623 Browser* browser2 = Browser::Create(browser()->profile()); |
| 1624 // Navigate the new browser window so it'll be shown and we can pick the |
| 1625 // active window. |
| 1626 ui_test_utils::NavigateToURL(browser2, GURL(chrome::kAboutBlankURL)); |
| 1627 |
| 1628 // Generally, |browser2| will be the active window. However, if the |
| 1629 // original browser window lost focus before creating the new one, such as |
| 1630 // when running multiple tests at once, the original browser window may |
| 1631 // remain the profile's active window. |
| 1632 Browser* active_browser = |
| 1633 browser::FindTabbedBrowser(browser()->profile(), true); |
| 1634 Browser* inactive_browser; |
| 1635 if (active_browser == browser2) { |
| 1636 // When only one test is running at a time, the new browser will probably be |
| 1637 // on top, but when multiple tests are running at once, this is not |
| 1638 // guaranteed. |
| 1639 inactive_browser = browser(); |
| 1640 } else { |
| 1641 ASSERT_EQ(active_browser, browser()); |
| 1642 inactive_browser = browser2; |
| 1643 } |
| 1644 |
| 1645 CaptivePortalObserver portal_observer(browser()->profile()); |
| 1646 MultiNavigationObserver navigation_observer; |
| 1647 |
| 1648 // Navigate the tab in the inactive browser to an SSL timeout. Have to use |
| 1649 // browser::NavigateParams and NEW_BACKGROUND_TAB to avoid activating the |
| 1650 // window. |
| 1651 browser::NavigateParams params(inactive_browser, |
| 1652 GURL(kMockHttpsQuickTimeoutUrl), |
| 1653 content::PAGE_TRANSITION_TYPED); |
| 1654 params.disposition = NEW_BACKGROUND_TAB; |
| 1655 params.window_action = browser::NavigateParams::NO_ACTION; |
| 1656 ui_test_utils::NavigateToURL(¶ms); |
| 1657 navigation_observer.WaitForNavigations(2); |
| 1658 |
| 1659 // Make sure the active window hasn't changed, and its new tab is |
| 1660 // active. |
| 1661 ASSERT_EQ(active_browser, |
| 1662 browser::FindTabbedBrowser(browser()->profile(), true)); |
| 1663 ASSERT_EQ(1, active_browser->active_index()); |
| 1664 |
| 1665 // Check that the only two navigated tabs were the new error tab in the |
| 1666 // backround windows, and the login tab in the active window. |
| 1667 EXPECT_EQ(1, navigation_observer.NumNavigationsForTab( |
| 1668 inactive_browser->GetWebContentsAt(1))); |
| 1669 EXPECT_EQ(1, navigation_observer.NumNavigationsForTab( |
| 1670 active_browser->GetWebContentsAt(1))); |
| 1671 EXPECT_EQ(0, NumLoadingTabs()); |
| 1672 |
| 1673 // Check captive portal test results. |
| 1674 portal_observer.WaitForResults(2); |
| 1675 ASSERT_EQ(RESULT_BEHIND_CAPTIVE_PORTAL, |
| 1676 portal_observer.captive_portal_result()); |
| 1677 EXPECT_EQ(2, portal_observer.num_results_received()); |
| 1678 |
| 1679 // Check the inactive browser. |
| 1680 EXPECT_EQ(2, inactive_browser->tab_count()); |
| 1681 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, |
| 1682 GetStateOfTabReloaderAt(inactive_browser, 0)); |
| 1683 EXPECT_EQ(CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL, |
| 1684 GetStateOfTabReloaderAt(inactive_browser, 1)); |
| 1685 |
| 1686 // Check the active browser. |
| 1687 ASSERT_EQ(2, active_browser->tab_count()); |
| 1688 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, |
| 1689 GetStateOfTabReloaderAt(active_browser, 0)); |
| 1690 EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, |
| 1691 GetStateOfTabReloaderAt(active_browser, 1)); |
| 1692 EXPECT_TRUE(IsLoginTab(active_browser->GetTabContentsWrapperAt(1))); |
| 1693 |
| 1694 // Simulate logging in. |
| 1695 Login(active_browser, 0, 1); |
| 1696 } |
| 1697 |
| 1698 } // namespace captive_portal |
OLD | NEW |