diff options
author | ygorshenin@chromium.org <ygorshenin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-10-24 18:57:23 +0000 |
---|---|---|
committer | ygorshenin@chromium.org <ygorshenin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-10-24 18:57:23 +0000 |
commit | 7d432e240fba393b53a65623df7e649eeb508653 (patch) | |
tree | 3f3461d9070de421b8ea60d57d1546d918bfc892 /chrome/browser/captive_portal/captive_portal_service.cc | |
parent | 812d4f7e14eedef990b9d0dd039276651a4d90fd (diff) | |
download | chromium_src-7d432e240fba393b53a65623df7e649eeb508653.zip chromium_src-7d432e240fba393b53a65623df7e649eeb508653.tar.gz chromium_src-7d432e240fba393b53a65623df7e649eeb508653.tar.bz2 |
Basic Captive Portal detection functionality is extracted into
individual service, so, it can be used without CaptivePortalService.
BUG=115487
TEST=browser_tests:CaptivePortalBrowserTest
Review URL: https://chromiumcodereview.appspot.com/11198066
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@163877 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/captive_portal/captive_portal_service.cc')
-rw-r--r-- | chrome/browser/captive_portal/captive_portal_service.cc | 139 |
1 files changed, 25 insertions, 114 deletions
diff --git a/chrome/browser/captive_portal/captive_portal_service.cc b/chrome/browser/captive_portal/captive_portal_service.cc index 8d8d59d..d6a013c 100644 --- a/chrome/browser/captive_portal/captive_portal_service.cc +++ b/chrome/browser/captive_portal/captive_portal_service.cc @@ -5,21 +5,15 @@ #include "chrome/browser/captive_portal/captive_portal_service.h" #include "base/bind.h" -#include "base/command_line.h" +#include "base/bind_helpers.h" #include "base/logging.h" #include "base/message_loop.h" #include "base/metrics/histogram.h" -#include "base/rand_util.h" -#include "base/string_number_conversions.h" #include "chrome/browser/prefs/pref_service.h" #include "chrome/browser/profiles/profile.h" #include "chrome/common/chrome_notification_types.h" #include "chrome/common/pref_names.h" #include "content/public/browser/notification_service.h" -#include "net/base/load_flags.h" -#include "net/http/http_response_headers.h" -#include "net/url_request/url_fetcher.h" -#include "net/url_request/url_request_status.h" #if defined(OS_MACOSX) #include "base/mac/mac_util.h" @@ -33,14 +27,6 @@ namespace captive_portal { namespace { -// The test URL. When connected to the Internet, it should return a blank page -// with a 204 status code. When behind a captive portal, requests for this -// URL should get an HTTP redirect or a login page. When neither is true, -// no server should respond to requests for this URL. -// TODO(mmenke): Look into getting another domain, for better load management. -// Need a cookieless domain, so can't use clients*.google.com. -const char* const kDefaultTestURL = "http://www.gstatic.com/generate_204"; - // Used for histograms. const char* const kCaptivePortalResultNames[] = { "InternetConnected", @@ -166,10 +152,11 @@ CaptivePortalService::RecheckPolicy::RecheckPolicy() CaptivePortalService::CaptivePortalService(Profile* profile) : profile_(profile), state_(STATE_IDLE), + captive_portal_detector_(profile->GetRequestContext()), enabled_(false), last_detection_result_(RESULT_INTERNET_CONNECTED), num_checks_with_same_result_(0), - test_url_(kDefaultTestURL) { + test_url_(CaptivePortalDetector::kDefaultURL) { // The order matters here: // |resolve_errors_with_web_service_| must be initialized and |backoff_entry_| // created before the call to UpdateEnabledState. @@ -206,7 +193,6 @@ void CaptivePortalService::DetectCaptivePortal() { void CaptivePortalService::DetectCaptivePortalInternal() { DCHECK(CalledOnValidThread()); DCHECK(state_ == STATE_TIMER_RUNNING || state_ == STATE_IDLE); - DCHECK(!FetchingURL()); DCHECK(!TimerRunning()); state_ = STATE_CHECKING_FOR_PORTAL; @@ -220,42 +206,26 @@ void CaptivePortalService::DetectCaptivePortalInternal() { return; } - // The first 0 means this can use a TestURLFetcherFactory in unit tests. - url_fetcher_.reset(net::URLFetcher::Create(0, - test_url_, - net::URLFetcher::GET, - this)); - url_fetcher_->SetAutomaticallyRetryOn5xx(false); - url_fetcher_->SetRequestContext(profile_->GetRequestContext()); - // Can't safely use net::LOAD_DISABLE_CERT_REVOCATION_CHECKING here, - // since then the connection may be reused without checking the cert. - url_fetcher_->SetLoadFlags( - net::LOAD_BYPASS_CACHE | - net::LOAD_DO_NOT_PROMPT_FOR_LOGIN | - net::LOAD_DO_NOT_SAVE_COOKIES | - net::LOAD_DO_NOT_SEND_COOKIES | - net::LOAD_DO_NOT_SEND_AUTH_DATA); - url_fetcher_->Start(); + captive_portal_detector_.DetectCaptivePortal( + test_url_, base::Bind( + &CaptivePortalService::OnPortalDetectionCompleted, + base::Unretained(this))); } -void CaptivePortalService::OnURLFetchComplete(const net::URLFetcher* source) { +void CaptivePortalService::OnPortalDetectionCompleted( + const CaptivePortalDetector::Results& results) { DCHECK(CalledOnValidThread()); DCHECK_EQ(STATE_CHECKING_FOR_PORTAL, state_); - DCHECK(FetchingURL()); DCHECK(!TimerRunning()); - DCHECK_EQ(url_fetcher_.get(), source); DCHECK(enabled_); + Result result = results.result; + const base::TimeDelta& retry_after_delta = results.retry_after_delta; base::TimeTicks now = GetCurrentTimeTicks(); - base::TimeDelta retry_after_delta; - Result new_result = GetCaptivePortalResultFromResponse(source, - &retry_after_delta); - url_fetcher_.reset(); - // Record histograms. UMA_HISTOGRAM_ENUMERATION("CaptivePortal.DetectResult", - new_result, + result, RESULT_COUNT); // If this isn't the first captive portal result, record stats. @@ -263,7 +233,7 @@ void CaptivePortalService::OnURLFetchComplete(const net::URLFetcher* source) { UMA_HISTOGRAM_LONG_TIMES("CaptivePortal.TimeBetweenChecks", now - last_check_time_); - if (last_detection_result_ != new_result) { + if (last_detection_result_ != result) { // If the last result was different from the result of the latest test, // record histograms about the previous period over which the result was // the same. @@ -273,13 +243,13 @@ void CaptivePortalService::OnURLFetchComplete(const net::URLFetcher* source) { } } - if (last_check_time_.is_null() || new_result != last_detection_result_) { + if (last_check_time_.is_null() || result != last_detection_result_) { first_check_time_with_same_result_ = now; num_checks_with_same_result_ = 1; // Reset the backoff entry both to update the default time and clear // previous failures. - ResetBackoffEntry(new_result); + ResetBackoffEntry(result); backoff_entry_->SetCustomReleaseTime(now + retry_after_delta); // The BackoffEntry is not informed of this request, so there's no delay @@ -298,7 +268,7 @@ void CaptivePortalService::OnURLFetchComplete(const net::URLFetcher* source) { last_check_time_ = now; - OnResult(new_result); + OnResult(result); } void CaptivePortalService::Observe( @@ -372,10 +342,10 @@ void CaptivePortalService::UpdateEnabledState() { ResetBackoffEntry(last_detection_result_); if (state_ == STATE_CHECKING_FOR_PORTAL || state_ == STATE_TIMER_RUNNING) { - // If a captive portal check was running or pending, stop the check or the - // timer. - url_fetcher_.reset(); + // If a captive portal check was running or pending, cancel check + // and the timer. check_captive_portal_timer_.Stop(); + captive_portal_detector_.Cancel(); state_ = STATE_IDLE; // Since a captive portal request was queued or running, something may be @@ -384,74 +354,15 @@ void CaptivePortalService::UpdateEnabledState() { } } -// Takes a net::URLFetcher that has finished trying to retrieve the test -// URL, and returns a CaptivePortalService::Result based on its result. -Result CaptivePortalService::GetCaptivePortalResultFromResponse( - const net::URLFetcher* url_fetcher, - base::TimeDelta* retry_after) const { - DCHECK(retry_after); - DCHECK(!url_fetcher->GetStatus().is_io_pending()); - - *retry_after = base::TimeDelta(); - - // If there's a network error of some sort when fetching a file via HTTP, - // there may be a networking problem, rather than a captive portal. - // TODO(mmenke): Consider special handling for redirects that end up at - // errors, especially SSL certificate errors. - if (url_fetcher->GetStatus().status() != net::URLRequestStatus::SUCCESS) - return RESULT_NO_RESPONSE; - - // In the case of 503 errors, look for the Retry-After header. - int response_code = url_fetcher->GetResponseCode(); - if (response_code == 503) { - net::HttpResponseHeaders* headers = url_fetcher->GetResponseHeaders(); - std::string retry_after_string; - - // If there's no Retry-After header, nothing else to do. - if (!headers->EnumerateHeader(NULL, "Retry-After", &retry_after_string)) - return RESULT_NO_RESPONSE; - - // Otherwise, try parsing it as an integer (seconds) or as an HTTP date. - int seconds; - base::Time full_date; - if (base::StringToInt(retry_after_string, &seconds)) { - *retry_after = base::TimeDelta::FromSeconds(seconds); - } else if (headers->GetTimeValuedHeader("Retry-After", &full_date)) { - base::Time now = GetCurrentTime(); - if (full_date > now) - *retry_after = full_date - now; - } - return RESULT_NO_RESPONSE; - } - - // A 511 response (Network Authentication Required) means that the user needs - // to login to whatever server issued the response. - // See: http://tools.ietf.org/html/rfc6585 - if (response_code == 511) - return RESULT_BEHIND_CAPTIVE_PORTAL; - - // Other non-2xx/3xx HTTP responses may indicate server errors. - if (response_code >= 400 || response_code < 200) - return RESULT_NO_RESPONSE; - - // A 204 response code indicates there's no captive portal. - if (response_code == 204) - return RESULT_INTERNET_CONNECTED; - - // Otherwise, assume it's a captive portal. - return RESULT_BEHIND_CAPTIVE_PORTAL; -} - -base::Time CaptivePortalService::GetCurrentTime() const { - return base::Time::Now(); -} - base::TimeTicks CaptivePortalService::GetCurrentTimeTicks() const { - return base::TimeTicks::Now(); + if (time_ticks_for_testing_.is_null()) + return base::TimeTicks::Now(); + else + return time_ticks_for_testing_; } -bool CaptivePortalService::FetchingURL() const { - return url_fetcher_.get() != NULL; +bool CaptivePortalService::DetectionInProgress() const { + return state_ == STATE_CHECKING_FOR_PORTAL; } bool CaptivePortalService::TimerRunning() const { |