1 // Copyright 2014 The Chromium Authors 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 COMPONENTS_NETWORK_TIME_NETWORK_TIME_TRACKER_H_ 6 #define COMPONENTS_NETWORK_TIME_NETWORK_TIME_TRACKER_H_ 7 8 #include <stdint.h> 9 10 #include <memory> 11 #include <optional> 12 #include <string_view> 13 14 #include "base/feature_list.h" 15 #include "base/gtest_prod_util.h" 16 #include "base/memory/raw_ptr.h" 17 #include "base/memory/ref_counted.h" 18 #include "base/observer_list.h" 19 #include "base/observer_list_types.h" 20 #include "base/threading/thread_checker.h" 21 #include "base/time/clock.h" 22 #include "base/time/time.h" 23 #include "base/timer/timer.h" 24 #include "build/build_config.h" 25 #include "components/network_time/time_tracker/time_tracker.h" 26 #include "url/gurl.h" 27 28 class PrefRegistrySimple; 29 class PrefService; 30 31 namespace base { 32 class TickClock; 33 } // namespace base 34 35 namespace client_update_protocol { 36 class Ecdsa; 37 } // namespace client_update_protocol 38 39 namespace network { 40 class SimpleURLLoader; 41 class SharedURLLoaderFactory; 42 } // namespace network 43 44 namespace network_time { 45 46 // Clock resolution is platform dependent. 47 #if BUILDFLAG(IS_WIN) 48 const int64_t kTicksResolutionMs = base::Time::kMinLowResolutionThresholdMs; 49 #else 50 const int64_t kTicksResolutionMs = 1; // Assume 1ms for non-windows platforms. 51 #endif 52 53 // Feature that enables network time service querying. 54 BASE_DECLARE_FEATURE(kNetworkTimeServiceQuerying); 55 56 // A class that receives network time updates and can provide the network time 57 // for a corresponding local time. This class is not thread safe. 58 class NetworkTimeTracker { 59 public: 60 // Describes the result of a GetNetworkTime() call, describing whether 61 // network time was available and if not, why not. 62 enum NetworkTimeResult { 63 // Network time is available. 64 NETWORK_TIME_AVAILABLE, 65 // A time has been retrieved from the network in the past, but 66 // network time is no longer available because the tracker fell out 67 // of sync due to, for example, a suspend/resume. 68 NETWORK_TIME_SYNC_LOST, 69 // Network time is unavailable because the tracker has not yet 70 // attempted to retrieve a time from the network. 71 NETWORK_TIME_NO_SYNC_ATTEMPT, 72 // Network time is unavailable because the tracker has not yet 73 // successfully retrieved a time from the network (at least one 74 // attempt has been made but all have failed). 75 NETWORK_TIME_NO_SUCCESSFUL_SYNC, 76 // Network time is unavailable because the tracker has not yet 77 // attempted to retrieve a time from the network, but the first 78 // attempt is currently pending. 79 NETWORK_TIME_FIRST_SYNC_PENDING, 80 // Network time is unavailable because the tracker has made failed 81 // attempts to retrieve a time from the network, but an attempt is 82 // currently pending. 83 NETWORK_TIME_SUBSEQUENT_SYNC_PENDING, 84 }; 85 86 // Describes the behavior of fetches to the network time service. 87 enum FetchBehavior { 88 // Only used in case of an unrecognize Finch experiment parameter. 89 FETCH_BEHAVIOR_UNKNOWN, 90 // Time queries will be issued in the background as needed. 91 FETCHES_IN_BACKGROUND_ONLY, 92 // Time queries will not be issued except when StartTimeFetch() is called. 93 FETCHES_ON_DEMAND_ONLY, 94 // Time queries will be issued both in the background as needed and also 95 // on-demand. 96 FETCHES_IN_BACKGROUND_AND_ON_DEMAND, 97 }; 98 99 class NetworkTimeObserver : public base::CheckedObserver { 100 public: 101 virtual void OnNetworkTimeChanged( 102 const TimeTracker::TimeTrackerState state) = 0; 103 }; 104 105 static void RegisterPrefs(PrefRegistrySimple* registry); 106 107 // Constructor. Arguments may be stubbed out for tests. |url_loader_factory| 108 // must be non-null unless the kNetworkTimeServiceQuerying is disabled. 109 // Otherwise, time is available only if |UpdateNetworkTime| is called. 110 // If |fetch_behavior| is not nullopt, it will control the behavior of the 111 // NetworkTimeTracker, if it is nullopt, it will be controlled via a feature 112 // parameter. 113 NetworkTimeTracker( 114 std::unique_ptr<base::Clock> clock, 115 std::unique_ptr<const base::TickClock> tick_clock, 116 PrefService* pref_service, 117 scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, 118 std::optional<FetchBehavior> fetch_behavior); 119 120 NetworkTimeTracker(const NetworkTimeTracker&) = delete; 121 NetworkTimeTracker& operator=(const NetworkTimeTracker&) = delete; 122 123 ~NetworkTimeTracker(); 124 125 // Sets |network_time| to an estimate of the true time. Returns 126 // NETWORK_TIME_AVAILABLE if time is available. If |uncertainty| is 127 // non-NULL, it will be set to an estimate of the error range. 128 // 129 // If network time is unavailable, this method returns 130 // NETWORK_TIME_SYNC_LOST or NETWORK_TIME_NO_SYNC to indicate the 131 // reason. 132 // 133 // Network time may be available on startup if deserialized from a pref. 134 // Failing that, a call to |UpdateNetworkTime| is required to make time 135 // available to callers of |GetNetworkTime|. Subsequently, network time may 136 // become unavailable if |NetworkTimeTracker| has reason to believe it is no 137 // longer accurate. Consumers should even be prepared to handle the case 138 // where calls to |GetNetworkTime| never once succeeds. 139 NetworkTimeResult GetNetworkTime(base::Time* network_time, 140 base::TimeDelta* uncertainty) const; 141 142 // Starts a network time query if network time isn't already available 143 // and if there isn't already a time query in progress. If a new query 144 // is started or if there is one already in progress, |callback| will 145 // run when the query completes. 146 // 147 // Returns true if a time query is started or was already in progress, 148 // and false otherwise. For example, this method may return false if 149 // time queries are disabled or if network time is already available. 150 bool StartTimeFetch(base::OnceClosure callback); 151 152 // Calculates corresponding time ticks according to the given parameters. 153 // The provided |network_time| is precise at the given |resolution| and 154 // represent the time between now and up to |latency| + (now - |post_time|) 155 // ago. 156 void UpdateNetworkTime(base::Time network_time, 157 base::TimeDelta resolution, 158 base::TimeDelta latency, 159 base::TimeTicks post_time); 160 161 bool AreTimeFetchesEnabled() const; 162 FetchBehavior GetFetchBehavior() const; 163 164 // Blocks until the the next time query completes. 165 void WaitForFetch(); 166 167 void AddObserver(NetworkTimeObserver* obs); 168 169 void RemoveObserver(NetworkTimeObserver* obs); 170 171 bool GetTrackerState(TimeTracker::TimeTrackerState* state) const; 172 173 void SetMaxResponseSizeForTesting(size_t limit); 174 175 void SetPublicKeyForTesting(std::string_view key); 176 177 void SetTimeServerURLForTesting(const GURL& url); 178 179 GURL GetTimeServerURLForTesting() const; 180 181 bool QueryTimeServiceForTesting(); 182 183 void WaitForFetchForTesting(uint32_t nonce); 184 185 void OverrideNonceForTesting(uint32_t nonce); 186 187 base::TimeDelta GetTimerDelayForTesting() const; 188 189 void ClearNetworkTimeForTesting(); 190 191 private: 192 // Checks whether a network time query should be issued, and issues one if so. 193 // Upon response, execution resumes in |OnURLFetchComplete|. 194 void CheckTime(); 195 196 // Updates network time from a time server response, returning true 197 // if successful. 198 bool UpdateTimeFromResponse(std::unique_ptr<std::string> response_body); 199 200 // Called to process responses from the secure time service. 201 void OnURLLoaderComplete(std::unique_ptr<std::string> response_body); 202 203 // Sets the next time query to be run at the specified time. 204 void QueueCheckTime(base::TimeDelta delay); 205 206 // Returns true if there's sufficient reason to suspect that 207 // NetworkTimeTracker does not know what time it is. This returns true 208 // unconditionally every once in a long while, just to be on the safe side. 209 bool ShouldIssueTimeQuery(); 210 211 void NotifyObservers(); 212 213 // State variables for internally-managed secure time service queries. 214 GURL server_url_; 215 size_t max_response_size_; 216 base::TimeDelta backoff_; 217 // Timer that runs CheckTime(). All backoff and delay is implemented by 218 // changing the delay of this timer, with the result that CheckTime() may 219 // assume that if it runs, it is eligible to issue a time query. 220 base::RepeatingTimer timer_; 221 scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_; 222 std::unique_ptr<network::SimpleURLLoader> time_fetcher_; 223 std::unique_ptr<client_update_protocol::Ecdsa> query_signer_; 224 225 // The |Clock| and |TickClock| are used to sanity-check one another, allowing 226 // the NetworkTimeTracker to notice e.g. suspend/resume events and clock 227 // resets. 228 std::unique_ptr<base::Clock> clock_; 229 std::unique_ptr<const base::TickClock> tick_clock_; 230 231 raw_ptr<PrefService> pref_service_; 232 233 // True if any time query has completed (but not necessarily succeeded) in 234 // this NetworkTimeTracker's lifetime. 235 bool time_query_completed_; 236 237 // The time that was received from the last network time fetch made by 238 // CheckTime(). Unlike the time used inside |tracker_| this time is not 239 // updated when UpdateNetworkTime() is called. Used for UMA metrics. 240 base::Time last_fetched_time_; 241 242 // Callbacks to run when the in-progress time fetch completes. 243 std::vector<base::OnceClosure> fetch_completion_callbacks_; 244 245 base::ThreadChecker thread_checker_; 246 247 std::optional<FetchBehavior> fetch_behavior_; 248 249 std::optional<TimeTracker> tracker_; 250 251 base::ObserverList<NetworkTimeObserver> observers_; 252 }; 253 254 } // namespace network_time 255 256 #endif // COMPONENTS_NETWORK_TIME_NETWORK_TIME_TRACKER_H_ 257