• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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