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 #ifndef CHROME_BROWSER_CAPTIVE_PORTAL_CAPTIVE_PORTAL_DETECTOR_H_ 6 #define CHROME_BROWSER_CAPTIVE_PORTAL_CAPTIVE_PORTAL_DETECTOR_H_ 7 8 #include "base/basictypes.h" 9 #include "base/callback.h" 10 #include "base/compiler_specific.h" 11 #include "base/memory/ref_counted.h" 12 #include "base/memory/scoped_ptr.h" 13 #include "base/threading/non_thread_safe.h" 14 #include "base/time/time.h" 15 #include "net/url_request/url_fetcher.h" 16 #include "net/url_request/url_fetcher_delegate.h" 17 #include "net/url_request/url_request_context_getter.h" 18 19 class GURL; 20 21 namespace captive_portal { 22 23 // Possible results of an attempt to detect a captive portal. 24 enum Result { 25 // There's a confirmed connection to the Internet. 26 RESULT_INTERNET_CONNECTED, 27 // The URL request received a network or HTTP error, or a non-HTTP response. 28 RESULT_NO_RESPONSE, 29 // The URL request apparently encountered a captive portal. It received a 30 // a valid HTTP response with a 2xx other than 204, 3xx, or 511 status code. 31 RESULT_BEHIND_CAPTIVE_PORTAL, 32 RESULT_COUNT 33 }; 34 35 class CaptivePortalDetector : public net::URLFetcherDelegate, 36 public base::NonThreadSafe { 37 public: 38 struct Results { 39 Results() 40 : result(RESULT_NO_RESPONSE), 41 response_code(net::URLFetcher::RESPONSE_CODE_INVALID) { 42 } 43 44 Result result; 45 int response_code; 46 base::TimeDelta retry_after_delta; 47 }; 48 49 typedef base::Callback<void(const Results& results)> DetectionCallback; 50 51 // The test URL. When connected to the Internet, it should return a 52 // blank page with a 204 status code. When behind a captive portal, 53 // requests for this URL should get an HTTP redirect or a login 54 // page. When neither is true, no server should respond to requests 55 // for this URL. 56 static const char kDefaultURL[]; 57 58 explicit CaptivePortalDetector( 59 const scoped_refptr<net::URLRequestContextGetter>& request_context); 60 virtual ~CaptivePortalDetector(); 61 62 static std::string CaptivePortalResultToString(Result result); 63 64 // Triggers a check for a captive portal. After completion, runs the 65 // |callback|. 66 void DetectCaptivePortal(const GURL& url, const DetectionCallback& callback); 67 68 // Cancels captive portal check. 69 void Cancel(); 70 71 private: 72 friend class CaptivePortalDetectorTestBase; 73 74 // net::URLFetcherDelegate: 75 virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE; 76 77 // Takes a net::URLFetcher that has finished trying to retrieve the 78 // test URL, and fills a Results struct based on its result. If the 79 // response is a 503 with a Retry-After header, |retry_after| field 80 // of |results| is populated accordingly. Otherwise, it's set to 81 // base::TimeDelta(). 82 void GetCaptivePortalResultFromResponse(const net::URLFetcher* url_fetcher, 83 Results* results) const; 84 85 // Returns the current time. Used only when determining time until a 86 // Retry-After date. 87 base::Time GetCurrentTime() const; 88 89 // Returns true if a captive portal check is currently running. 90 bool FetchingURL() const; 91 92 // Sets current test time. Used by unit tests. 93 void set_time_for_testing(const base::Time& time) { 94 time_for_testing_ = time; 95 } 96 97 // Advances current test time. Used by unit tests. 98 void advance_time_for_testing(const base::TimeDelta& delta) { 99 time_for_testing_ += delta; 100 } 101 102 // URL request context. 103 scoped_refptr<net::URLRequestContextGetter> request_context_; 104 105 DetectionCallback detection_callback_; 106 107 scoped_ptr<net::URLFetcher> url_fetcher_; 108 109 // Test time used by unit tests. 110 base::Time time_for_testing_; 111 112 DISALLOW_COPY_AND_ASSIGN(CaptivePortalDetector); 113 }; 114 115 } // namespace captive_portal 116 117 #endif // CHROME_BROWSER_CAPTIVE_PORTAL_CAPTIVE_PORTAL_DETECTOR_H_ 118