File: ip_protection_token_manager_impl.h

package info (click to toggle)
chromium 139.0.7258.127-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 6,122,156 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 (177 lines) | stat: -rw-r--r-- 6,796 bytes parent folder | download | duplicates (5)
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
// Copyright 2023 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_IP_PROTECTION_COMMON_IP_PROTECTION_TOKEN_MANAGER_IMPL_H_
#define COMPONENTS_IP_PROTECTION_COMMON_IP_PROTECTION_TOKEN_MANAGER_IMPL_H_

#include <cstddef>
#include <cstdint>
#include <deque>
#include <map>
#include <memory>
#include <optional>
#include <string>
#include <utility>
#include <vector>

#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "components/ip_protection/common/ip_protection_token_manager.h"

namespace ip_protection {

class IpProtectionTokenFetcher;
class IpProtectionCore;
enum class ProxyLayer;

// An implementation of IpProtectionTokenManager that populates itself
// using a passed in IpProtectionTokenFetcher pointer from the cache.
class IpProtectionTokenManagerImpl : public IpProtectionTokenManager {
 public:
  explicit IpProtectionTokenManagerImpl(
      IpProtectionCore* core,
      std::unique_ptr<IpProtectionTokenFetcher> fetcher,
      ProxyLayer proxy_layer,
      bool disable_cache_management_for_testing = false);
  ~IpProtectionTokenManagerImpl() override;

  // IpProtectionTokenManager implementation.
  bool IsAuthTokenAvailable() override;
  bool IsAuthTokenAvailable(const std::string& geo_id) override;
  bool WasTokenCacheEverFilled() override;
  std::optional<BlindSignedAuthToken> GetAuthToken() override;
  std::optional<BlindSignedAuthToken> GetAuthToken(
      const std::string& geo_id) override;
  std::string CurrentGeo() const override;
  void SetCurrentGeo(const std::string& geo_id) override;
  void InvalidateTryAgainAfterTime() override;

  // Set a callback that will be run after the next call to `TryGetAuthTokens()`
  // has completed.
  void SetOnTryGetAuthTokensCompletedForTesting(
      base::OnceClosure on_try_get_auth_tokens_completed) {
    on_try_get_auth_tokens_completed_for_testing_ =
        std::move(on_try_get_auth_tokens_completed);
  }

  // Enable active cache management in the background, if it was disabled
  // (either via the constructor or via a call to
  // `DisableCacheManagementForTesting()`).
  void EnableCacheManagementForTesting() {
    disable_cache_management_for_testing_ = false;
    ScheduleMaybeRefillCache();
  }

  bool IsCacheManagementEnabledForTesting() {
    return !disable_cache_management_for_testing_;
  }

  // Disable active cache management and reset the manager back to its base
  // state: no tokens, no backoff, no active token fetches, no pending timers.
  void DisableCacheManagementForTesting(
      base::OnceClosure on_cache_management_disabled);

  void EnableTokenExpirationFuzzingForTesting(bool enable);

  // Requests tokens from the browser process and executes the provided callback
  // after the response is received.
  void CallTryGetAuthTokensForTesting();

  base::Time try_get_auth_tokens_after_for_testing() {
    return try_get_auth_tokens_after_;
  }

  bool fetching_auth_tokens_for_testing() { return fetching_auth_tokens_; }

 private:
  void OnGotAuthTokens(base::TimeTicks attempt_start_time_for_metrics,
                       std::optional<std::vector<BlindSignedAuthToken>> tokens,
                       std::optional<base::Time> try_again_after);
  void RemoveExpiredTokens();
  void MeasureTokenRates();
  void MaybeRefillCache();
  void ScheduleMaybeRefillCache();
  bool NeedsRefill(const std::string& geo_id) const;
  bool IsTokenLimitExceeded(const std::string& geo_id) const;

  // Current geo of the client.
  // This value should only be set by the `IpProtectionCore` using the
  // `IpProtectionTokenManager::SetCurrentGeo()` function.
  std::string current_geo_id_ = "";

  // Batch size and cache low-water mark as determined from feature params at
  // construction time.
  const int batch_size_;
  const size_t cache_low_water_mark_;

  // The last time token rates were measured and the counts since then.
  base::TimeTicks last_token_rate_measurement_;
  int64_t tokens_spent_ = 0;
  int64_t tokens_expired_ = 0;

  // Map for caches of tokens keyed by geo id. For each geo entry, tokens are
  // sorted by their expiration time.
  std::map<std::string, std::deque<BlindSignedAuthToken>> cache_by_geo_;

  // Source of proxy list, when needed.
  std::unique_ptr<IpProtectionTokenFetcher> fetcher_;

  // The proxy layer which the cache of tokens will be used for.
  ProxyLayer proxy_layer_;

  // Pointer to the `IpProtectionCore` that holds the proxy list and
  // tokens. Required to observe geo changes from retrieved tokens.
  // The lifetime of the `IpProtectionCore` object WILL ALWAYS outlive
  // this class b/c `ip_protection_core_` owns this (at least outside of
  // testing).
  const raw_ptr<IpProtectionCore> ip_protection_core_;

  // True if an attempt to fetch tokens is outstanding.
  bool fetching_auth_tokens_ = false;

  // True if the cache has been filled at least once.
  bool cache_has_been_filled_ = false;

  // True if the "NetworkService.IpProtection.GeoChangeTokenPresence" metric
  // needs to be sampled. False if the presence has already been sampled. This
  // value should be reset to true after `SetCurrentGeo` is called after a token
  // refill.
  // A boolean flag is crucial to prevent duplicate or incorrect histogram
  // measurements. By tracking whether a histogram has already been logged for a
  // given geo change, we can avoid redundant or misleading data which could be
  // caused b/c a cache is filled with tokens before a call to `SetCurrentGeo`
  // is made.
  bool emitted_geo_presence_histogram_before_refill_ = true;

  // If not null, this is the `try_again_after` time from the last call to
  // `TryGetAuthTokens()`, and no calls should be made until this time.
  base::Time try_get_auth_tokens_after_;
  // A timer to run `MaybeRefillCache()` when necessary, such as when the next
  // token expires or the cache is able to fetch more tokens.
  base::OneShotTimer next_maybe_refill_cache_;

  // A callback triggered when the next call to `TryGetAuthTokens()` occurs, for
  // use in testing.
  base::OnceClosure on_try_get_auth_tokens_completed_for_testing_;

  // If true, do not try to automatically refill the cache.
  bool disable_cache_management_for_testing_ = false;

  // If false, token expiration is not fuzzed.
  bool enable_token_expiration_fuzzing_= true;

  base::RepeatingTimer measurement_timer_;

  SEQUENCE_CHECKER(sequence_checker_);

  base::WeakPtrFactory<IpProtectionTokenManagerImpl> weak_ptr_factory_{this};
};

}  // namespace ip_protection

#endif  // COMPONENTS_IP_PROTECTION_COMMON_IP_PROTECTION_TOKEN_MANAGER_IMPL_H_