File: network_time_tracker.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 (257 lines) | stat: -rw-r--r-- 9,745 bytes parent folder | download | duplicates (3)
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
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
// Copyright 2014 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_NETWORK_TIME_NETWORK_TIME_TRACKER_H_
#define COMPONENTS_NETWORK_TIME_NETWORK_TIME_TRACKER_H_

#include <stdint.h>

#include <memory>
#include <optional>
#include <string_view>
#include <vector>

#include "base/feature_list.h"
#include "base/gtest_prod_util.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/observer_list.h"
#include "base/observer_list_types.h"
#include "base/threading/thread_checker.h"
#include "base/time/clock.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "build/build_config.h"
#include "components/client_update_protocol/ecdsa.h"
#include "components/network_time/time_tracker/time_tracker.h"
#include "url/gurl.h"

class PrefRegistrySimple;
class PrefService;

namespace base {
class TickClock;
}  // namespace base

namespace client_update_protocol {
class Ecdsa;
}  // namespace client_update_protocol

namespace network {
class SimpleURLLoader;
class SharedURLLoaderFactory;
}  // namespace network

namespace network_time {

// Clock resolution is platform dependent.
#if BUILDFLAG(IS_WIN)
const int64_t kTicksResolutionMs = base::Time::kMinLowResolutionThresholdMs;
#else
const int64_t kTicksResolutionMs = 1;  // Assume 1ms for non-windows platforms.
#endif

// Feature that enables network time service querying.
BASE_DECLARE_FEATURE(kNetworkTimeServiceQuerying);

// A class that receives network time updates and can provide the network time
// for a corresponding local time. This class is not thread safe.
class NetworkTimeTracker {
 public:
  // Describes the result of a GetNetworkTime() call, describing whether
  // network time was available and if not, why not.
  enum NetworkTimeResult {
    // Network time is available.
    NETWORK_TIME_AVAILABLE,
    // A time has been retrieved from the network in the past, but
    // network time is no longer available because the tracker fell out
    // of sync due to, for example, a suspend/resume.
    NETWORK_TIME_SYNC_LOST,
    // Network time is unavailable because the tracker has not yet
    // attempted to retrieve a time from the network.
    NETWORK_TIME_NO_SYNC_ATTEMPT,
    // Network time is unavailable because the tracker has not yet
    // successfully retrieved a time from the network (at least one
    // attempt has been made but all have failed).
    NETWORK_TIME_NO_SUCCESSFUL_SYNC,
    // Network time is unavailable because the tracker has not yet
    // attempted to retrieve a time from the network, but the first
    // attempt is currently pending.
    NETWORK_TIME_FIRST_SYNC_PENDING,
    // Network time is unavailable because the tracker has made failed
    // attempts to retrieve a time from the network, but an attempt is
    // currently pending.
    NETWORK_TIME_SUBSEQUENT_SYNC_PENDING,
  };

  // Describes the behavior of fetches to the network time service.
  enum FetchBehavior {
    // Only used in case of an unrecognize Finch experiment parameter.
    FETCH_BEHAVIOR_UNKNOWN,
    // Time queries will be issued in the background as needed.
    FETCHES_IN_BACKGROUND_ONLY,
    // Time queries will not be issued except when StartTimeFetch() is called.
    FETCHES_ON_DEMAND_ONLY,
    // Time queries will be issued both in the background as needed and also
    // on-demand.
    FETCHES_IN_BACKGROUND_AND_ON_DEMAND,
  };

  class NetworkTimeObserver : public base::CheckedObserver {
   public:
    virtual void OnNetworkTimeChanged(
        const TimeTracker::TimeTrackerState state) = 0;
  };

  static void RegisterPrefs(PrefRegistrySimple* registry);

  // Constructor.  Arguments may be stubbed out for tests. |url_loader_factory|
  // must be non-null unless the kNetworkTimeServiceQuerying is disabled.
  // Otherwise, time is available only if |UpdateNetworkTime| is called.
  // If |fetch_behavior| is not nullopt, it will control the behavior of the
  // NetworkTimeTracker, if it is nullopt, it will be controlled via a feature
  // parameter.
  NetworkTimeTracker(
      std::unique_ptr<base::Clock> clock,
      std::unique_ptr<const base::TickClock> tick_clock,
      PrefService* pref_service,
      scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
      std::optional<FetchBehavior> fetch_behavior,
      base::span<const uint8_t> pubkey = base::span<const uint8_t>());

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

  ~NetworkTimeTracker();

  // Sets |network_time| to an estimate of the true time.  Returns
  // NETWORK_TIME_AVAILABLE if time is available. If |uncertainty| is
  // non-NULL, it will be set to an estimate of the error range.
  //
  // If network time is unavailable, this method returns
  // NETWORK_TIME_SYNC_LOST or NETWORK_TIME_NO_SYNC to indicate the
  // reason.
  //
  // Network time may be available on startup if deserialized from a pref.
  // Failing that, a call to |UpdateNetworkTime| is required to make time
  // available to callers of |GetNetworkTime|.  Subsequently, network time may
  // become unavailable if |NetworkTimeTracker| has reason to believe it is no
  // longer accurate.  Consumers should even be prepared to handle the case
  // where calls to |GetNetworkTime| never once succeeds.
  NetworkTimeResult GetNetworkTime(base::Time* network_time,
                                   base::TimeDelta* uncertainty) const;

  // Starts a network time query if network time isn't already available
  // and if there isn't already a time query in progress. If a new query
  // is started or if there is one already in progress, |callback| will
  // run when the query completes.
  //
  // Returns true if a time query is started or was already in progress,
  // and false otherwise. For example, this method may return false if
  // time queries are disabled or if network time is already available.
  bool StartTimeFetch(base::OnceClosure callback);

  // Calculates corresponding time ticks according to the given parameters.
  // The provided |network_time| is precise at the given |resolution| and
  // represent the time between now and up to |latency| + (now - |post_time|)
  // ago.
  void UpdateNetworkTime(base::Time network_time,
                         base::TimeDelta resolution,
                         base::TimeDelta latency,
                         base::TimeTicks post_time);

  bool AreTimeFetchesEnabled() const;
  FetchBehavior GetFetchBehavior() const;

  // Blocks until the the next time query completes.
  void WaitForFetch();

  void AddObserver(NetworkTimeObserver* obs);

  void RemoveObserver(NetworkTimeObserver* obs);

  bool GetTrackerState(TimeTracker::TimeTrackerState* state) const;

  void SetMaxResponseSizeForTesting(size_t limit);

  void SetTimeServerURLForTesting(const GURL& url);

  GURL GetTimeServerURLForTesting() const;

  bool QueryTimeServiceForTesting();

  void WaitForFetchForTesting(uint32_t nonce);

  void OverrideNonceForTesting(uint32_t nonce);

  base::TimeDelta GetTimerDelayForTesting() const;

  void ClearNetworkTimeForTesting();

 private:
  // Checks whether a network time query should be issued, and issues one if so.
  // Upon response, execution resumes in |OnURLFetchComplete|.
  void CheckTime();

  // Updates network time from a time server response, returning true
  // if successful.
  bool UpdateTimeFromResponse(std::optional<std::string> response_body);

  // Called to process responses from the secure time service.
  void OnURLLoaderComplete(std::optional<std::string> response_body);

  // Sets the next time query to be run at the specified time.
  void QueueCheckTime(base::TimeDelta delay);

  // Returns true if there's sufficient reason to suspect that
  // NetworkTimeTracker does not know what time it is.  This returns true
  // unconditionally every once in a long while, just to be on the safe side.
  bool ShouldIssueTimeQuery();

  void NotifyObservers();

  // State variables for internally-managed secure time service queries.
  GURL server_url_;
  size_t max_response_size_;
  base::TimeDelta backoff_;
  // Timer that runs CheckTime().  All backoff and delay is implemented by
  // changing the delay of this timer, with the result that CheckTime() may
  // assume that if it runs, it is eligible to issue a time query.
  base::RepeatingTimer timer_;
  scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
  std::unique_ptr<network::SimpleURLLoader> time_fetcher_;
  client_update_protocol::Ecdsa query_signer_;

  // The |Clock| and |TickClock| are used to sanity-check one another, allowing
  // the NetworkTimeTracker to notice e.g. suspend/resume events and clock
  // resets.
  std::unique_ptr<base::Clock> clock_;
  std::unique_ptr<const base::TickClock> tick_clock_;

  raw_ptr<PrefService> pref_service_;

  // True if any time query has completed (but not necessarily succeeded) in
  // this NetworkTimeTracker's lifetime.
  bool time_query_completed_;

  // The time that was received from the last network time fetch made by
  // CheckTime(). Unlike the time used inside |tracker_| this time is not
  // updated when UpdateNetworkTime() is called. Used for UMA metrics.
  base::Time last_fetched_time_;

  // Callbacks to run when the in-progress time fetch completes.
  std::vector<base::OnceClosure> fetch_completion_callbacks_;

  base::ThreadChecker thread_checker_;

  std::optional<FetchBehavior> fetch_behavior_;

  std::optional<TimeTracker> tracker_;

  base::ObserverList<NetworkTimeObserver> observers_;
};

}  // namespace network_time

#endif  // COMPONENTS_NETWORK_TIME_NETWORK_TIME_TRACKER_H_