• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_SERVICE_H_
6 #define CHROME_BROWSER_CAPTIVE_PORTAL_CAPTIVE_PORTAL_SERVICE_H_
7 
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"
17 #include "url/gurl.h"
18 
19 class Profile;
20 
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.
24 //
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 {
29  public:
30   enum TestingState {
31     NOT_TESTING,
32     DISABLED_FOR_TESTING,  // The service is always disabled.
33     SKIP_OS_CHECK_FOR_TESTING  // The service can be enabled even if the OS has
34                                // native captive portal detection.
35   };
36 
37   // The details sent via a NOTIFICATION_CAPTIVE_PORTAL_CHECK_RESULT.
38   struct Results {
39     // The result of the second most recent captive portal check.
40     captive_portal::CaptivePortalResult previous_result;
41     // The result of the most recent captive portal check.
42     captive_portal::CaptivePortalResult result;
43   };
44 
45   explicit CaptivePortalService(Profile* profile);
46   virtual ~CaptivePortalService();
47 
48   // Triggers a check for a captive portal.  If there's already a check in
49   // progress, does nothing.  Throttles the rate at which requests are sent.
50   // Always sends the result notification asynchronously.
51   void DetectCaptivePortal();
52 
53   // Returns the URL used for captive portal testing.  When a captive portal is
54   // detected, this URL will take us to the captive portal landing page.
test_url()55   const GURL& test_url() const { return test_url_; }
56 
57   // Result of the most recent captive portal check.
last_detection_result()58   captive_portal::CaptivePortalResult last_detection_result() const {
59     return last_detection_result_;
60   }
61 
62   // Whether or not the CaptivePortalService is enabled.  When disabled, all
63   // checks return INTERNET_CONNECTED.
enabled()64   bool enabled() const { return enabled_; }
65 
66   // Used to disable captive portal detection so it doesn't interfere with
67   // tests.  Should be called before the service is created.
set_state_for_testing(TestingState testing_state)68   static void set_state_for_testing(TestingState testing_state) {
69     testing_state_ = testing_state;
70   }
get_state_for_testing()71   static TestingState get_state_for_testing() { return testing_state_; }
72 
73  private:
74   friend class CaptivePortalServiceTest;
75   friend class CaptivePortalBrowserTest;
76 
77   // Subclass of BackoffEntry that uses the CaptivePortalService's
78   // GetCurrentTime function, for unit testing.
79   class RecheckBackoffEntry;
80 
81   enum State {
82     // No check is running or pending.
83     STATE_IDLE,
84     // The timer to check for a captive portal is running.
85     STATE_TIMER_RUNNING,
86     // There's an outstanding HTTP request to check for a captive portal.
87     STATE_CHECKING_FOR_PORTAL,
88   };
89 
90   // Contains all the information about the minimum time allowed between two
91   // consecutive captive portal checks.
92   struct RecheckPolicy {
93     // Constructor initializes all values to defaults.
94     RecheckPolicy();
95 
96     // The minimum amount of time between two captive portal checks, when the
97     // last check found no captive portal.
98     int initial_backoff_no_portal_ms;
99 
100     // The minimum amount of time between two captive portal checks, when the
101     // last check found a captive portal.  This is expected to be less than
102     // |initial_backoff_no_portal_ms|.  Also used when the service is disabled.
103     int initial_backoff_portal_ms;
104 
105     net::BackoffEntry::Policy backoff_policy;
106   };
107 
108   // Initiates a captive portal check, without any throttling.  If the service
109   // is disabled, just acts like there's an Internet connection.
110   void DetectCaptivePortalInternal();
111 
112   // Called by CaptivePortalDetector when detection completes.
113   void OnPortalDetectionCompleted(
114       const captive_portal::CaptivePortalDetector::Results& results);
115 
116   // KeyedService:
117   virtual void Shutdown() OVERRIDE;
118 
119   // Called when a captive portal check completes.  Passes the result to all
120   // observers.
121   void OnResult(captive_portal::CaptivePortalResult result);
122 
123   // Updates BackoffEntry::Policy and creates a new BackoffEntry, which
124   // resets the count used for throttling.
125   void ResetBackoffEntry(captive_portal::CaptivePortalResult result);
126 
127   // Updates |enabled_| based on command line flags and Profile preferences,
128   // and sets |state_| to STATE_NONE if it's false.
129   // TODO(mmenke): Figure out on which platforms, if any, should not use
130   //               automatic captive portal detection.  Currently it's enabled
131   //               on all platforms, though this code is not compiled on
132   //               Android, since it lacks the Browser class.
133   void UpdateEnabledState();
134 
135   // Returns the current TimeTicks.
136   base::TimeTicks GetCurrentTimeTicks() const;
137 
138   bool DetectionInProgress() const;
139 
140   // Returns true if the timer to try and detect a captive portal is running.
141   bool TimerRunning() const;
142 
state()143   State state() const { return state_; }
144 
recheck_policy()145   RecheckPolicy& recheck_policy() { return recheck_policy_; }
146 
set_test_url(const GURL & test_url)147   void set_test_url(const GURL& test_url) { test_url_ = test_url; }
148 
149   // Sets current test time ticks. Used by unit tests.
set_time_ticks_for_testing(const base::TimeTicks & time_ticks)150   void set_time_ticks_for_testing(const base::TimeTicks& time_ticks) {
151     time_ticks_for_testing_ = time_ticks;
152   }
153 
154   // Advances current test time ticks. Used by unit tests.
advance_time_ticks_for_testing(const base::TimeDelta & delta)155   void advance_time_ticks_for_testing(const base::TimeDelta& delta) {
156     time_ticks_for_testing_ += delta;
157   }
158 
159   // The profile that owns this CaptivePortalService.
160   Profile* profile_;
161 
162   State state_;
163 
164   // Detector for checking active network for a portal state.
165   captive_portal::CaptivePortalDetector captive_portal_detector_;
166 
167   // True if the service is enabled.  When not enabled, all checks will return
168   // RESULT_INTERNET_CONNECTED.
169   bool enabled_;
170 
171   // The result of the most recent captive portal check.
172   captive_portal::CaptivePortalResult last_detection_result_;
173 
174   // Number of sequential checks with the same captive portal result.
175   int num_checks_with_same_result_;
176 
177   // Time when |last_detection_result_| was first received.
178   base::TimeTicks first_check_time_with_same_result_;
179 
180   // Time the last captive portal check completed.
181   base::TimeTicks last_check_time_;
182 
183   // Policy for throttling portal checks.
184   RecheckPolicy recheck_policy_;
185 
186   // Implements behavior needed by |recheck_policy_|.  Whenever there's a new
187   // captive_portal::CaptivePortalResult, BackoffEntry::Policy is updated and
188   // |backoff_entry_| is recreated.  Each check that returns the same result
189   // is considered a "failure", to trigger throttling.
190   scoped_ptr<net::BackoffEntry> backoff_entry_;
191 
192   // URL that returns a 204 response code when connected to the Internet.
193   GURL test_url_;
194 
195   // The pref member for whether navigation errors should be resolved with a web
196   // service.  Actually called "alternate_error_pages", since it's also used for
197   // the Link Doctor.
198   BooleanPrefMember resolve_errors_with_web_service_;
199 
200   base::OneShotTimer<CaptivePortalService> check_captive_portal_timer_;
201 
202   static TestingState testing_state_;
203 
204   // Test time ticks used by unit tests.
205   base::TimeTicks time_ticks_for_testing_;
206 
207   DISALLOW_COPY_AND_ASSIGN(CaptivePortalService);
208 };
209 
210 #endif  // CHROME_BROWSER_CAPTIVE_PORTAL_CAPTIVE_PORTAL_SERVICE_H_
211