Roll leveldb 3f7758:803d69 (v1.17 -> v1.18)
[chromium-blink-merge.git] / components / captive_portal / captive_portal_detector.cc
blobc9b84082ff58ed11fb07f311c5df531bc269b8a3
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "components/captive_portal/captive_portal_detector.h"
7 #include "base/logging.h"
8 #include "base/strings/string_number_conversions.h"
9 #include "net/base/load_flags.h"
10 #include "net/http/http_response_headers.h"
11 #include "net/http/http_util.h"
12 #include "net/url_request/url_request_status.h"
14 namespace captive_portal {
16 const char CaptivePortalDetector::kDefaultURL[] =
17 "http://www.gstatic.com/generate_204";
19 CaptivePortalDetector::CaptivePortalDetector(
20 const scoped_refptr<net::URLRequestContextGetter>& request_context)
21 : request_context_(request_context) {
24 CaptivePortalDetector::~CaptivePortalDetector() {
27 void CaptivePortalDetector::DetectCaptivePortal(
28 const GURL& url,
29 const DetectionCallback& detection_callback) {
30 DCHECK(CalledOnValidThread());
31 DCHECK(!FetchingURL());
32 DCHECK(detection_callback_.is_null());
34 detection_callback_ = detection_callback;
36 // The first 0 means this can use a TestURLFetcherFactory in unit tests.
37 url_fetcher_.reset(net::URLFetcher::Create(0,
38 url,
39 net::URLFetcher::GET,
40 this));
41 url_fetcher_->SetAutomaticallyRetryOn5xx(false);
42 url_fetcher_->SetRequestContext(request_context_.get());
44 // Can't safely use net::LOAD_DISABLE_CERT_REVOCATION_CHECKING here,
45 // since then the connection may be reused without checking the cert.
46 url_fetcher_->SetLoadFlags(
47 net::LOAD_BYPASS_CACHE |
48 net::LOAD_DO_NOT_PROMPT_FOR_LOGIN |
49 net::LOAD_DO_NOT_SAVE_COOKIES |
50 net::LOAD_DO_NOT_SEND_COOKIES |
51 net::LOAD_DO_NOT_SEND_AUTH_DATA);
52 url_fetcher_->Start();
55 void CaptivePortalDetector::Cancel() {
56 url_fetcher_.reset();
57 detection_callback_.Reset();
60 void CaptivePortalDetector::OnURLFetchComplete(const net::URLFetcher* source) {
61 DCHECK(CalledOnValidThread());
62 DCHECK(FetchingURL());
63 DCHECK_EQ(url_fetcher_.get(), source);
64 DCHECK(!detection_callback_.is_null());
66 Results results;
67 GetCaptivePortalResultFromResponse(url_fetcher_.get(), &results);
68 DetectionCallback callback = detection_callback_;
69 url_fetcher_.reset();
70 detection_callback_.Reset();
71 callback.Run(results);
74 // Takes a net::URLFetcher that has finished trying to retrieve the test
75 // URL, and returns a CaptivePortalService::Result based on its result.
76 void CaptivePortalDetector::GetCaptivePortalResultFromResponse(
77 const net::URLFetcher* url_fetcher,
78 Results* results) const {
79 DCHECK(results);
80 DCHECK(!url_fetcher->GetStatus().is_io_pending());
82 results->result = captive_portal::RESULT_NO_RESPONSE;
83 results->response_code = url_fetcher->GetResponseCode();
84 results->retry_after_delta = base::TimeDelta();
85 results->landing_url = url_fetcher->GetURL();
87 // If there's a network error of some sort when fetching a file via HTTP,
88 // there may be a networking problem, rather than a captive portal.
89 // TODO(mmenke): Consider special handling for redirects that end up at
90 // errors, especially SSL certificate errors.
91 if (url_fetcher->GetStatus().status() != net::URLRequestStatus::SUCCESS)
92 return;
94 // In the case of 503 errors, look for the Retry-After header.
95 if (results->response_code == 503) {
96 net::HttpResponseHeaders* headers = url_fetcher->GetResponseHeaders();
97 std::string retry_after_string;
99 // If there's no Retry-After header, nothing else to do.
100 if (!headers->EnumerateHeader(NULL, "Retry-After", &retry_after_string))
101 return;
103 base::TimeDelta retry_after_delta;
104 if (net::HttpUtil::ParseRetryAfterHeader(retry_after_string,
105 GetCurrentTime(),
106 &retry_after_delta)) {
107 results->retry_after_delta = retry_after_delta;
110 return;
113 // A 511 response (Network Authentication Required) means that the user needs
114 // to login to whatever server issued the response.
115 // See: http://tools.ietf.org/html/rfc6585
116 if (results->response_code == 511) {
117 results->result = captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL;
118 return;
121 // Other non-2xx/3xx HTTP responses may indicate server errors.
122 if (results->response_code >= 400 || results->response_code < 200)
123 return;
125 // A 204 response code indicates there's no captive portal.
126 if (results->response_code == 204) {
127 results->result = captive_portal::RESULT_INTERNET_CONNECTED;
128 return;
131 // Otherwise, assume it's a captive portal.
132 results->result = captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL;
135 base::Time CaptivePortalDetector::GetCurrentTime() const {
136 if (time_for_testing_.is_null())
137 return base::Time::Now();
138 else
139 return time_for_testing_;
142 bool CaptivePortalDetector::FetchingURL() const {
143 return url_fetcher_.get() != NULL;
146 } // namespace captive_portal