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 #ifndef CHROME_BROWSER_CAPTIVE_PORTAL_CAPTIVE_PORTAL_SERVICE_H_
6 #define CHROME_BROWSER_CAPTIVE_PORTAL_CAPTIVE_PORTAL_SERVICE_H_
8 #include "base/basictypes.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "base/prefs/pref_member.h"
11 #include "base/threading/non_thread_safe.h"
12 #include "base/time/time.h"
13 #include "base/timer/timer.h"
14 #include "components/captive_portal/captive_portal_detector.h"
15 #include "components/keyed_service/core/keyed_service.h"
16 #include "net/base/backoff_entry.h"
21 // Service that checks for captive portals when queried, and sends a
22 // NOTIFICATION_CAPTIVE_PORTAL_CHECK_RESULT with the Profile as the source and
23 // a CaptivePortalService::Results as the details.
25 // Captive portal checks are rate-limited. The CaptivePortalService may only
26 // be accessed on the UI thread.
27 // Design doc: https://docs.google.com/document/d/1k-gP2sswzYNvryu9NcgN7q5XrsMlUdlUdoW9WRaEmfM/edit
28 class CaptivePortalService
: public KeyedService
, public base::NonThreadSafe
{
32 DISABLED_FOR_TESTING
, // The service is always disabled.
33 SKIP_OS_CHECK_FOR_TESTING
, // The service can be enabled even if the OS
34 // has native captive portal detection.
35 IGNORE_REQUESTS_FOR_TESTING
// Disables actual portal checks. This also
36 // implies SKIP_OS_CHECK_FOR_TESTING.
39 // The details sent via a NOTIFICATION_CAPTIVE_PORTAL_CHECK_RESULT.
41 // The result of the second most recent captive portal check.
42 captive_portal::CaptivePortalResult previous_result
;
43 // The result of the most recent captive portal check.
44 captive_portal::CaptivePortalResult result
;
45 // Landing url of the captive portal check ping. If behind a captive portal,
46 // this points to the login page.
50 explicit CaptivePortalService(Profile
* profile
);
51 ~CaptivePortalService() override
;
53 // Triggers a check for a captive portal. If there's already a check in
54 // progress, does nothing. Throttles the rate at which requests are sent.
55 // Always sends the result notification asynchronously.
56 void DetectCaptivePortal();
58 // Returns the URL used for captive portal testing. When a captive portal is
59 // detected, this URL will take us to the captive portal landing page.
60 const GURL
& test_url() const { return test_url_
; }
62 // Result of the most recent captive portal check.
63 captive_portal::CaptivePortalResult
last_detection_result() const {
64 return last_detection_result_
;
67 // Whether or not the CaptivePortalService is enabled. When disabled, all
68 // checks return INTERNET_CONNECTED.
69 bool enabled() const { return enabled_
; }
71 // Used to disable captive portal detection so it doesn't interfere with
72 // tests. Should be called before the service is created.
73 static void set_state_for_testing(TestingState testing_state
) {
74 testing_state_
= testing_state
;
76 static TestingState
get_state_for_testing() { return testing_state_
; }
79 friend class CaptivePortalServiceTest
;
80 friend class CaptivePortalBrowserTest
;
82 // Subclass of BackoffEntry that uses the CaptivePortalService's
83 // GetCurrentTime function, for unit testing.
84 class RecheckBackoffEntry
;
87 // No check is running or pending.
89 // The timer to check for a captive portal is running.
91 // There's an outstanding HTTP request to check for a captive portal.
92 STATE_CHECKING_FOR_PORTAL
,
95 // Contains all the information about the minimum time allowed between two
96 // consecutive captive portal checks.
97 struct RecheckPolicy
{
98 // Constructor initializes all values to defaults.
101 // The minimum amount of time between two captive portal checks, when the
102 // last check found no captive portal.
103 int initial_backoff_no_portal_ms
;
105 // The minimum amount of time between two captive portal checks, when the
106 // last check found a captive portal. This is expected to be less than
107 // |initial_backoff_no_portal_ms|. Also used when the service is disabled.
108 int initial_backoff_portal_ms
;
110 net::BackoffEntry::Policy backoff_policy
;
113 // Initiates a captive portal check, without any throttling. If the service
114 // is disabled, just acts like there's an Internet connection.
115 void DetectCaptivePortalInternal();
117 // Called by CaptivePortalDetector when detection completes.
118 void OnPortalDetectionCompleted(
119 const captive_portal::CaptivePortalDetector::Results
& results
);
122 void Shutdown() override
;
124 // Called when a captive portal check completes. Passes the result to all
126 void OnResult(captive_portal::CaptivePortalResult result
,
127 const GURL
& landing_url
);
129 // Updates BackoffEntry::Policy and creates a new BackoffEntry, which
130 // resets the count used for throttling.
131 void ResetBackoffEntry(captive_portal::CaptivePortalResult result
);
133 // Updates |enabled_| based on command line flags and Profile preferences,
134 // and sets |state_| to STATE_NONE if it's false.
135 // TODO(mmenke): Figure out on which platforms, if any, should not use
136 // automatic captive portal detection. Currently it's enabled
137 // on all platforms, though this code is not compiled on
138 // Android, since it lacks the Browser class.
139 void UpdateEnabledState();
141 // Returns the current TimeTicks.
142 base::TimeTicks
GetCurrentTimeTicks() const;
144 bool DetectionInProgress() const;
146 // Returns true if the timer to try and detect a captive portal is running.
147 bool TimerRunning() const;
149 State
state() const { return state_
; }
151 RecheckPolicy
& recheck_policy() { return recheck_policy_
; }
153 void set_test_url(const GURL
& test_url
) { test_url_
= test_url
; }
155 // Sets current test time ticks. Used by unit tests.
156 void set_time_ticks_for_testing(const base::TimeTicks
& time_ticks
) {
157 time_ticks_for_testing_
= time_ticks
;
160 // Advances current test time ticks. Used by unit tests.
161 void advance_time_ticks_for_testing(const base::TimeDelta
& delta
) {
162 time_ticks_for_testing_
+= delta
;
165 // The profile that owns this CaptivePortalService.
170 // Detector for checking active network for a portal state.
171 captive_portal::CaptivePortalDetector captive_portal_detector_
;
173 // True if the service is enabled. When not enabled, all checks will return
174 // RESULT_INTERNET_CONNECTED.
177 // The result of the most recent captive portal check.
178 captive_portal::CaptivePortalResult last_detection_result_
;
180 // Number of sequential checks with the same captive portal result.
181 int num_checks_with_same_result_
;
183 // Time when |last_detection_result_| was first received.
184 base::TimeTicks first_check_time_with_same_result_
;
186 // Time the last captive portal check completed.
187 base::TimeTicks last_check_time_
;
189 // Policy for throttling portal checks.
190 RecheckPolicy recheck_policy_
;
192 // Implements behavior needed by |recheck_policy_|. Whenever there's a new
193 // captive_portal::CaptivePortalResult, BackoffEntry::Policy is updated and
194 // |backoff_entry_| is recreated. Each check that returns the same result
195 // is considered a "failure", to trigger throttling.
196 scoped_ptr
<net::BackoffEntry
> backoff_entry_
;
198 // URL that returns a 204 response code when connected to the Internet.
201 // The pref member for whether navigation errors should be resolved with a web
202 // service. Actually called "alternate_error_pages", since it's also used for
204 BooleanPrefMember resolve_errors_with_web_service_
;
206 base::OneShotTimer
<CaptivePortalService
> check_captive_portal_timer_
;
208 static TestingState testing_state_
;
210 // Test time ticks used by unit tests.
211 base::TimeTicks time_ticks_for_testing_
;
213 DISALLOW_COPY_AND_ASSIGN(CaptivePortalService
);
216 #endif // CHROME_BROWSER_CAPTIVE_PORTAL_CAPTIVE_PORTAL_SERVICE_H_