File: captive_portal_service.h

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (229 lines) | stat: -rw-r--r-- 8,167 bytes parent folder | download | duplicates (9)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef COMPONENTS_CAPTIVE_PORTAL_CONTENT_CAPTIVE_PORTAL_SERVICE_H_
#define COMPONENTS_CAPTIVE_PORTAL_CONTENT_CAPTIVE_PORTAL_SERVICE_H_

#include <memory>

#include "base/callback_list.h"
#include "base/memory/raw_ptr.h"
#include "base/time/tick_clock.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "components/captive_portal/core/captive_portal_detector.h"
#include "components/captive_portal/core/captive_portal_types.h"
#include "components/keyed_service/core/keyed_service.h"
#include "components/prefs/pref_member.h"
#include "net/base/backoff_entry.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "url/gurl.h"

namespace content {
class BrowserContext;
}

namespace network {
namespace mojom {
class URLLoaderFactory;
}
}  // namespace network

class Browser;
class CaptivePortalBrowserTest;
class HttpsUpgradesBrowserTest;

namespace captive_portal {

class CaptivePortalServiceTest;

// Service that checks for captive portals when queried and sends updates to
// its registered consumers when results are obtained.
//
// Captive portal checks are rate-limited.  The CaptivePortalService may only
// be accessed on the UI thread.
// Design doc:
// https://docs.google.com/document/d/1k-gP2sswzYNvryu9NcgN7q5XrsMlUdlUdoW9WRaEmfM/edit
class CaptivePortalService : public KeyedService {
 public:
  enum TestingState {
    NOT_TESTING,
    DISABLED_FOR_TESTING,        // The service is always disabled.
    IGNORE_REQUESTS_FOR_TESTING  // Disables actual portal checks.
  };

  // The details sent to consumers on a query completing.
  struct Results {
    // The result of the second most recent captive portal check.
    CaptivePortalResult previous_result;
    // The result of the most recent captive portal check.
    CaptivePortalResult result;
    // Landing url of the captive portal check ping. If behind a captive portal,
    // this points to the login page.
    GURL landing_url;
  };

  CaptivePortalService(
      content::BrowserContext* browser_context,
      PrefService* pref_service,
      const base::TickClock* clock_for_testing = nullptr,
      network::mojom::URLLoaderFactory* loader_factory_for_testing = nullptr);

  CaptivePortalService(const CaptivePortalService&) = delete;
  CaptivePortalService& operator=(const CaptivePortalService&) = delete;

  ~CaptivePortalService() override;

  // Triggers a check for a captive portal.  If there's already a check in
  // progress, does nothing.  Throttles the rate at which requests are sent.
  // Always sends the result notification asynchronously.
  void DetectCaptivePortal();

  base::CallbackListSubscription RegisterCallback(
      const base::RepeatingCallback<void(const Results&)>& cb) {
    return callback_list_.Add(cb);
  }

  // Returns the URL used for captive portal testing.  When a captive portal is
  // detected, this URL will take us to the captive portal landing page.
  const GURL& test_url() const { return test_url_; }

  // Result of the most recent captive portal check.
  CaptivePortalResult last_detection_result() const {
    return last_detection_result_;
  }

  // Whether or not the CaptivePortalService is enabled.  When disabled, all
  // checks return INTERNET_CONNECTED.
  bool enabled() const { return enabled_; }

  // Used to disable captive portal detection so it doesn't interfere with
  // tests.  Should be called before the service is created.
  static void set_state_for_testing(TestingState testing_state) {
    testing_state_ = testing_state;
  }
  static TestingState get_state_for_testing() { return testing_state_; }

 private:
  friend class CaptivePortalServiceTest;
  friend class ::CaptivePortalBrowserTest;
  friend class ::HttpsUpgradesBrowserTest;

  enum State {
    // No check is running or pending.
    STATE_IDLE,
    // The timer to check for a captive portal is running.
    STATE_TIMER_RUNNING,
    // There's an outstanding HTTP request to check for a captive portal.
    STATE_CHECKING_FOR_PORTAL,
  };

  // Contains all the information about the minimum time allowed between two
  // consecutive captive portal checks.
  struct RecheckPolicy {
    // Constructor initializes all values to defaults.
    RecheckPolicy();

    // The minimum amount of time between two captive portal checks, when the
    // last check found no captive portal.
    int initial_backoff_no_portal_ms;

    // The minimum amount of time between two captive portal checks, when the
    // last check found a captive portal.  This is expected to be less than
    // |initial_backoff_no_portal_ms|.  Also used when the service is disabled.
    int initial_backoff_portal_ms;

    net::BackoffEntry::Policy backoff_policy;
  };

  // Initiates a captive portal check, without any throttling.  If the service
  // is disabled, just acts like there's an Internet connection.
  void DetectCaptivePortalInternal();

  // Called by CaptivePortalDetector when detection completes.
  void OnPortalDetectionCompleted(
      const CaptivePortalDetector::Results& results);

  // KeyedService:
  void Shutdown() override;

  // Called when a captive portal check completes.  Passes the result to all
  // observers.
  void OnResult(CaptivePortalResult result, const GURL& landing_url);

  // Updates BackoffEntry::Policy and creates a new BackoffEntry, which
  // resets the count used for throttling.
  void ResetBackoffEntry(CaptivePortalResult result);

  // Updates |enabled_| based on command line flags and Profile preferences,
  // and sets |state_| to STATE_NONE if it's false.
  // TODO(mmenke): Figure out on which platforms, if any, should not use
  //               automatic captive portal detection.  Currently it's enabled
  //               on all platforms, though this code is not compiled on
  //               Android, since it lacks the Browser class.
  void UpdateEnabledState();

  base::TimeTicks GetCurrentTimeTicks() const;

  bool DetectionInProgress() const;

  // Returns true if the timer to try and detect a captive portal is running.
  bool TimerRunning() const;

  State state() const { return state_; }

  RecheckPolicy& recheck_policy() { return recheck_policy_; }

  void set_test_url(const GURL& test_url) { test_url_ = test_url; }

  // The BrowserContext that owns this CaptivePortalService.
  const raw_ptr<content::BrowserContext> browser_context_;

  State state_;

  scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory_;

  // Detector for checking active network for a portal state.
  std::unique_ptr<CaptivePortalDetector> captive_portal_detector_;

  // True if the service is enabled.  When not enabled, all checks will return
  // RESULT_INTERNET_CONNECTED.
  bool enabled_;

  // The result of the most recent captive portal check.
  CaptivePortalResult last_detection_result_;

  base::RepeatingCallbackList<void(const Results&)> callback_list_;

  // Time the last captive portal check completed.
  base::TimeTicks last_check_time_;

  // Policy for throttling portal checks.
  RecheckPolicy recheck_policy_;

  // Implements behavior needed by |recheck_policy_|.  Whenever there's a new
  // CaptivePortalResult, BackoffEntry::Policy is updated and
  // |backoff_entry_| is recreated.  Each check that returns the same result
  // is considered a "failure", to trigger throttling.
  std::unique_ptr<net::BackoffEntry> backoff_entry_;

  // URL that returns a 204 response code when connected to the Internet.
  GURL test_url_;

  // The pref member for whether navigation errors should be resolved with a web
  // service.  Actually called "alternate_error_pages", since it's also used for
  // the Link Doctor.
  BooleanPrefMember resolve_errors_with_web_service_;

  base::OneShotTimer check_captive_portal_timer_;

  static TestingState testing_state_;

  // Test tick clock used by unit tests.
  const raw_ptr<const base::TickClock> tick_clock_for_testing_;  // Not owned.
};

}  // namespace captive_portal

#endif  // COMPONENTS_CAPTIVE_PORTAL_CONTENT_CAPTIVE_PORTAL_SERVICE_H_