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_
|