• 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 #include "components/network_time/network_time_tracker.h"
6 
7 #include <stdint.h>
8 
9 #include <memory>
10 #include <optional>
11 #include <string>
12 #include <string_view>
13 #include <utility>
14 
15 #include "base/check.h"
16 #include "base/check_op.h"
17 #include "base/functional/bind.h"
18 #include "base/i18n/time_formatting.h"
19 #include "base/json/json_reader.h"
20 #include "base/logging.h"
21 #include "base/metrics/field_trial_params.h"
22 #include "base/rand_util.h"
23 #include "base/run_loop.h"
24 #include "base/strings/string_number_conversions.h"
25 #include "base/strings/utf_string_conversions.h"
26 #include "base/time/tick_clock.h"
27 #include "base/time/time.h"
28 #include "build/build_config.h"
29 #include "build/chromeos_buildflags.h"
30 #include "components/client_update_protocol/ecdsa.h"
31 #include "components/network_time/network_time_pref_names.h"
32 #include "components/network_time/time_tracker/time_tracker.h"
33 #include "components/prefs/pref_registry_simple.h"
34 #include "components/prefs/pref_service.h"
35 #include "net/base/load_flags.h"
36 #include "net/base/net_errors.h"
37 #include "net/http/http_response_headers.h"
38 #include "net/traffic_annotation/network_traffic_annotation.h"
39 #include "services/network/public/cpp/resource_request.h"
40 #include "services/network/public/cpp/shared_url_loader_factory.h"
41 #include "services/network/public/cpp/simple_url_loader.h"
42 #include "services/network/public/mojom/url_response_head.mojom.h"
43 
44 // Time updates happen in two ways. First, other components may call
45 // UpdateNetworkTime() if they happen to obtain the time securely. This will
46 // likely be deprecated in favor of the second way, which is scheduled time
47 // queries issued by NetworkTimeTracker itself.
48 //
49 // On startup, the clock state may be read from a pref. (This, too, may be
50 // deprecated.) After that, the time is checked every |kCheckTimeInterval|. A
51 // "check" means the possibility, but not the certainty, of a time query. A time
52 // query may be issued at random, or if the network time is believed to have
53 // become inaccurate.
54 //
55 // After issuing a query, the next check will not happen until
56 // |kBackoffInterval|. This delay is doubled in the event of an error.
57 
58 namespace network_time {
59 
60 // Network time queries are enabled on all desktop platforms except ChromeOS,
61 // which uses tlsdated to set the system time.
62 #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_IOS)
63 BASE_FEATURE(kNetworkTimeServiceQuerying,
64              "NetworkTimeServiceQuerying",
65              base::FEATURE_DISABLED_BY_DEFAULT);
66 #else
67 BASE_FEATURE(kNetworkTimeServiceQuerying,
68              "NetworkTimeServiceQuerying",
69              base::FEATURE_ENABLED_BY_DEFAULT);
70 #endif
71 
72 namespace {
73 
74 // Duration between time checks. The value should be greater than zero. Note
75 // that a "check" is not necessarily a network time query!
76 constexpr base::FeatureParam<base::TimeDelta> kCheckTimeInterval{
77     &kNetworkTimeServiceQuerying, "CheckTimeInterval", base::Seconds(360)};
78 
79 // Minimum number of minutes between time queries.
80 constexpr base::FeatureParam<base::TimeDelta> kBackoffInterval{
81     &kNetworkTimeServiceQuerying, "BackoffInterval", base::Hours(1)};
82 
83 // Probability that a check will randomly result in a query. Checks are made
84 // every |kCheckTimeInterval|. The default values are chosen with the goal of a
85 // high probability that a query will be issued every 24 hours. The value should
86 // fall between 0.0 and 1.0 (inclusive).
87 constexpr base::FeatureParam<double> kRandomQueryProbability{
88     &kNetworkTimeServiceQuerying, "RandomQueryProbability", .012};
89 
90 // The |kFetchBehavior| parameter can have three values:
91 //
92 // - "background-only": Time queries will be issued in the background as
93 //   needed (when the clock loses sync), but on-demand time queries will
94 //   not be issued (i.e. StartTimeFetch() will not start time queries.)
95 //
96 // - "on-demand-only": Time queries will not be issued except when
97 //   StartTimeFetch() is called. This is the default value.
98 //
99 // - "background-and-on-demand": Time queries will be issued both in the
100 //   background as needed and also on-demand.
101 constexpr base::FeatureParam<NetworkTimeTracker::FetchBehavior>::Option
102     kFetchBehaviorOptions[] = {
103         {NetworkTimeTracker::FETCHES_IN_BACKGROUND_ONLY, "background-only"},
104         {NetworkTimeTracker::FETCHES_ON_DEMAND_ONLY, "on-demand-only"},
105         {NetworkTimeTracker::FETCHES_IN_BACKGROUND_AND_ON_DEMAND,
106          "background-and-on-demand"},
107 };
108 constexpr base::FeatureParam<NetworkTimeTracker::FetchBehavior> kFetchBehavior{
109     &kNetworkTimeServiceQuerying, "FetchBehavior",
110     NetworkTimeTracker::FETCHES_ON_DEMAND_ONLY, &kFetchBehaviorOptions};
111 
112 // Number of time measurements performed in a given network time calculation.
113 const uint32_t kNumTimeMeasurements = 7;
114 
115 // Maximum time lapse before deserialized data are considered stale.
116 const uint32_t kSerializedDataMaxAgeDays = 7;
117 
118 // Name of a pref that stores the wall clock time, via
119 // |InMillisecondsFSinceUnixEpoch|.
120 const char kPrefTime[] = "local";
121 
122 // Name of a pref that stores the tick clock time, via |ToInternalValue|.
123 const char kPrefTicks[] = "ticks";
124 
125 // Name of a pref that stores the time uncertainty, via |ToInternalValue|.
126 const char kPrefUncertainty[] = "uncertainty";
127 
128 // Name of a pref that stores the network time via
129 // |InMillisecondsFSinceUnixEpoch|.
130 const char kPrefNetworkTime[] = "network";
131 
132 // Time server's maximum allowable clock skew, in seconds.  (This is a property
133 // of the time server that we happen to know.  It's unlikely that it would ever
134 // be that badly wrong, but all the same it's included here to document the very
135 // rough nature of the time service provided by this class.)
136 const uint32_t kTimeServerMaxSkewSeconds = 10;
137 
138 const char kTimeServiceURL[] = "http://clients2.google.com/time/1/current";
139 
140 // This is an ECDSA prime256v1 named-curve key.
141 const int kKeyVersion = 8;
142 const uint8_t kKeyPubBytes[] = {
143     0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02,
144     0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03,
145     0x42, 0x00, 0x04, 0x62, 0x54, 0x7B, 0x74, 0x30, 0xD7, 0x1A, 0x9C, 0x73,
146     0x88, 0xC8, 0xEE, 0x9B, 0x27, 0x57, 0xCA, 0x2C, 0xCA, 0x93, 0xBF, 0xEA,
147     0x1B, 0xD1, 0x07, 0x58, 0xBB, 0xFF, 0x83, 0x70, 0x30, 0xD0, 0x3C, 0xC7,
148     0x7B, 0x40, 0x60, 0x8D, 0x3E, 0x11, 0x4E, 0x0C, 0x97, 0x16, 0xBF, 0xA7,
149     0x31, 0xAC, 0x29, 0xBC, 0x27, 0x13, 0x69, 0xB8, 0x4D, 0x2B, 0x67, 0x1C,
150     0x90, 0x4C, 0x44, 0x50, 0x6E, 0xD1, 0xE1};
151 
GetServerProof(scoped_refptr<net::HttpResponseHeaders> response_headers)152 std::string GetServerProof(
153     scoped_refptr<net::HttpResponseHeaders> response_headers) {
154   std::string proof;
155   return response_headers->EnumerateHeader(nullptr, "x-cup-server-proof",
156                                            &proof)
157              ? proof
158              : std::string();
159 }
160 
161 }  // namespace
162 
163 // static
RegisterPrefs(PrefRegistrySimple * registry)164 void NetworkTimeTracker::RegisterPrefs(PrefRegistrySimple* registry) {
165   registry->RegisterDictionaryPref(prefs::kNetworkTimeMapping);
166   registry->RegisterBooleanPref(prefs::kNetworkTimeQueriesEnabled, true);
167 }
168 
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)169 NetworkTimeTracker::NetworkTimeTracker(
170     std::unique_ptr<base::Clock> clock,
171     std::unique_ptr<const base::TickClock> tick_clock,
172     PrefService* pref_service,
173     scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
174     std::optional<FetchBehavior> fetch_behavior)
175     : server_url_(kTimeServiceURL),
176       max_response_size_(1024),
177       backoff_(kBackoffInterval.Get()),
178       url_loader_factory_(std::move(url_loader_factory)),
179       clock_(std::move(clock)),
180       tick_clock_(std::move(tick_clock)),
181       pref_service_(pref_service),
182       time_query_completed_(false),
183       fetch_behavior_(fetch_behavior) {
184   const base::Value::Dict& time_mapping =
185       pref_service_->GetDict(prefs::kNetworkTimeMapping);
186   std::optional<double> time_js = time_mapping.FindDouble(kPrefTime);
187   std::optional<double> ticks_js = time_mapping.FindDouble(kPrefTicks);
188   std::optional<double> uncertainty_js =
189       time_mapping.FindDouble(kPrefUncertainty);
190   std::optional<double> network_time_js =
191       time_mapping.FindDouble(kPrefNetworkTime);
192   if (time_js && ticks_js && uncertainty_js && network_time_js) {
193     base::Time time_at_last_measurement =
194         base::Time::FromMillisecondsSinceUnixEpoch(*time_js);
195     base::TimeTicks ticks_at_last_measurement =
196         base::TimeTicks::FromInternalValue(static_cast<int64_t>(*ticks_js));
197     base::TimeDelta network_time_uncertainty =
198         base::TimeDelta::FromInternalValue(
199             static_cast<int64_t>(*uncertainty_js));
200     base::Time network_time_at_last_measurement =
201         base::Time::FromMillisecondsSinceUnixEpoch(*network_time_js);
202     base::Time now = clock_->Now();
203     if (ticks_at_last_measurement > tick_clock_->NowTicks() ||
204         time_at_last_measurement > now ||
205         now - time_at_last_measurement >
206             base::Days(kSerializedDataMaxAgeDays)) {
207       // Drop saved mapping if either clock has run backward, or the data are
208       // too old.
209       pref_service_->ClearPref(prefs::kNetworkTimeMapping);
210     } else {
211       tracker_.emplace(time_at_last_measurement, ticks_at_last_measurement,
212                        network_time_at_last_measurement,
213                        network_time_uncertainty);
214     }
215   }
216 
217   std::string_view public_key = {reinterpret_cast<const char*>(kKeyPubBytes),
218                                  sizeof(kKeyPubBytes)};
219   query_signer_ =
220       client_update_protocol::Ecdsa::Create(kKeyVersion, public_key);
221 
222   QueueCheckTime(base::Seconds(0));
223 }
224 
~NetworkTimeTracker()225 NetworkTimeTracker::~NetworkTimeTracker() {
226   DCHECK(thread_checker_.CalledOnValidThread());
227 }
228 
UpdateNetworkTime(base::Time network_time,base::TimeDelta resolution,base::TimeDelta latency,base::TimeTicks post_time)229 void NetworkTimeTracker::UpdateNetworkTime(base::Time network_time,
230                                            base::TimeDelta resolution,
231                                            base::TimeDelta latency,
232                                            base::TimeTicks post_time) {
233   DCHECK(thread_checker_.CalledOnValidThread());
234   DVLOG(1) << "Network time updating to "
235            << base::UTF16ToUTF8(
236                   base::TimeFormatFriendlyDateAndTime(network_time));
237   // Update network time on every request to limit dependency on ticks lag.
238   // TODO(mad): Find a heuristic to avoid augmenting the
239   // network_time_uncertainty_ too much by a particularly long latency.
240   // Maybe only update when the the new time either improves in accuracy or
241   // drifts too far from |network_time_at_last_measurement_|.
242   base::Time network_time_at_last_measurement = network_time;
243 
244   // Calculate the delay since the network time was received.
245   base::TimeTicks now_ticks = tick_clock_->NowTicks();
246   base::TimeDelta task_delay = now_ticks - post_time;
247   DCHECK_GE(task_delay.InMilliseconds(), 0);
248   DCHECK_GE(latency.InMilliseconds(), 0);
249   // Estimate that the time was set midway through the latency time.
250   base::TimeDelta offset = task_delay + latency / 2;
251   base::TimeTicks ticks_at_last_measurement = now_ticks - offset;
252   base::Time time_at_last_measurement = clock_->Now() - offset;
253 
254   // Can't assume a better time than the resolution of the given time and the
255   // ticks measurements involved, each with their own uncertainty.  1 & 2 are
256   // the ones used to compute the latency, 3 is the Now() from when this task
257   // was posted, 4 and 5 are the Now() and NowTicks() above, and 6 and 7 will be
258   // the Now() and NowTicks() in GetNetworkTime().
259   base::TimeDelta network_time_uncertainty =
260       resolution + latency +
261       kNumTimeMeasurements * base::Milliseconds(kTicksResolutionMs);
262 
263   tracker_.emplace(time_at_last_measurement, ticks_at_last_measurement,
264                    network_time_at_last_measurement, network_time_uncertainty);
265 
266   base::Value::Dict time_mapping;
267   time_mapping.Set(kPrefTime,
268                    time_at_last_measurement.InMillisecondsFSinceUnixEpoch());
269   time_mapping.Set(
270       kPrefTicks,
271       static_cast<double>(ticks_at_last_measurement.ToInternalValue()));
272   time_mapping.Set(
273       kPrefUncertainty,
274       static_cast<double>(network_time_uncertainty.ToInternalValue()));
275   time_mapping.Set(
276       kPrefNetworkTime,
277       network_time_at_last_measurement.InMillisecondsFSinceUnixEpoch());
278   pref_service_->Set(prefs::kNetworkTimeMapping,
279                      base::Value(std::move(time_mapping)));
280 
281   NotifyObservers();
282 }
283 
AreTimeFetchesEnabled() const284 bool NetworkTimeTracker::AreTimeFetchesEnabled() const {
285   return base::FeatureList::IsEnabled(kNetworkTimeServiceQuerying);
286 }
287 
GetFetchBehavior() const288 NetworkTimeTracker::FetchBehavior NetworkTimeTracker::GetFetchBehavior() const {
289   return fetch_behavior_.value_or(kFetchBehavior.Get());
290 }
291 
SetTimeServerURLForTesting(const GURL & url)292 void NetworkTimeTracker::SetTimeServerURLForTesting(const GURL& url) {
293   server_url_ = url;
294 }
295 
GetTimeServerURLForTesting() const296 GURL NetworkTimeTracker::GetTimeServerURLForTesting() const {
297   return server_url_;
298 }
299 
SetMaxResponseSizeForTesting(size_t limit)300 void NetworkTimeTracker::SetMaxResponseSizeForTesting(size_t limit) {
301   max_response_size_ = limit;
302 }
303 
SetPublicKeyForTesting(std::string_view key)304 void NetworkTimeTracker::SetPublicKeyForTesting(std::string_view key) {
305   query_signer_ = client_update_protocol::Ecdsa::Create(kKeyVersion, key);
306 }
307 
QueryTimeServiceForTesting()308 bool NetworkTimeTracker::QueryTimeServiceForTesting() {
309   CheckTime();
310   return time_fetcher_ != nullptr;
311 }
312 
WaitForFetch()313 void NetworkTimeTracker::WaitForFetch() {
314   base::RunLoop run_loop;
315   fetch_completion_callbacks_.push_back(run_loop.QuitClosure());
316   run_loop.Run();
317 }
318 
AddObserver(NetworkTimeObserver * obs)319 void NetworkTimeTracker::AddObserver(NetworkTimeObserver* obs) {
320   observers_.AddObserver(obs);
321 }
322 
RemoveObserver(NetworkTimeObserver * obs)323 void NetworkTimeTracker::RemoveObserver(NetworkTimeObserver* obs) {
324   observers_.RemoveObserver(obs);
325 }
326 
GetTrackerState(TimeTracker::TimeTrackerState * state) const327 bool NetworkTimeTracker::GetTrackerState(
328     TimeTracker::TimeTrackerState* state) const {
329   base::Time unused;
330   auto res = GetNetworkTime(&unused, nullptr);
331   if (res != NETWORK_TIME_AVAILABLE) {
332     return false;
333   }
334   *state = tracker_->GetStateAtCreation();
335   return true;
336 }
337 
WaitForFetchForTesting(uint32_t nonce)338 void NetworkTimeTracker::WaitForFetchForTesting(uint32_t nonce) {
339   query_signer_->OverrideNonceForTesting(kKeyVersion, nonce);  // IN-TEST
340   WaitForFetch();
341 }
342 
OverrideNonceForTesting(uint32_t nonce)343 void NetworkTimeTracker::OverrideNonceForTesting(uint32_t nonce) {
344   query_signer_->OverrideNonceForTesting(kKeyVersion, nonce);
345 }
346 
GetTimerDelayForTesting() const347 base::TimeDelta NetworkTimeTracker::GetTimerDelayForTesting() const {
348   DCHECK(timer_.IsRunning());
349   return timer_.GetCurrentDelay();
350 }
351 
ClearNetworkTimeForTesting()352 void NetworkTimeTracker::ClearNetworkTimeForTesting() {
353   tracker_ = std::nullopt;
354 }
355 
GetNetworkTime(base::Time * network_time,base::TimeDelta * uncertainty) const356 NetworkTimeTracker::NetworkTimeResult NetworkTimeTracker::GetNetworkTime(
357     base::Time* network_time,
358     base::TimeDelta* uncertainty) const {
359   DCHECK(thread_checker_.CalledOnValidThread());
360   DCHECK(network_time);
361   if (!tracker_.has_value()) {
362     if (time_query_completed_) {
363       // Time query attempts have been made in the past and failed.
364       if (time_fetcher_) {
365         // A fetch (not the first attempt) is in progress.
366         return NETWORK_TIME_SUBSEQUENT_SYNC_PENDING;
367       }
368       return NETWORK_TIME_NO_SUCCESSFUL_SYNC;
369     }
370     // No time queries have happened yet.
371     if (time_fetcher_) {
372       return NETWORK_TIME_FIRST_SYNC_PENDING;
373     }
374     return NETWORK_TIME_NO_SYNC_ATTEMPT;
375   }
376 
377   if (!tracker_->GetTime(clock_->Now(), tick_clock_->NowTicks(), network_time,
378                          uncertainty)) {
379     return NETWORK_TIME_SYNC_LOST;
380   }
381   return NETWORK_TIME_AVAILABLE;
382 }
383 
StartTimeFetch(base::OnceClosure closure)384 bool NetworkTimeTracker::StartTimeFetch(base::OnceClosure closure) {
385   DCHECK(thread_checker_.CalledOnValidThread());
386   FetchBehavior behavior = GetFetchBehavior();
387   if (behavior != FETCHES_ON_DEMAND_ONLY &&
388       behavior != FETCHES_IN_BACKGROUND_AND_ON_DEMAND) {
389     return false;
390   }
391 
392   // Enqueue the callback before calling CheckTime(), so that if
393   // CheckTime() completes synchronously, the callback gets called.
394   fetch_completion_callbacks_.push_back(std::move(closure));
395 
396   // If a time query is already in progress, do not start another one.
397   if (time_fetcher_) {
398     return true;
399   }
400 
401   // Cancel any fetches that are scheduled for the future, and try to
402   // start one now.
403   timer_.Stop();
404   CheckTime();
405 
406   // CheckTime() does not necessarily start a fetch; for example, time
407   // queries might be disabled or network time might already be
408   // available.
409   if (!time_fetcher_) {
410     // If no query is in progress, no callbacks need to be called.
411     fetch_completion_callbacks_.clear();
412     return false;
413   }
414   return true;
415 }
416 
CheckTime()417 void NetworkTimeTracker::CheckTime() {
418   DCHECK(thread_checker_.CalledOnValidThread());
419 
420   base::TimeDelta interval = kCheckTimeInterval.Get();
421   if (interval.is_negative()) {
422     interval = kCheckTimeInterval.default_value;
423   }
424 
425   // If NetworkTimeTracker is waking up after a backoff, this will reset the
426   // timer to its default faster frequency.
427   QueueCheckTime(interval);
428 
429   if (!ShouldIssueTimeQuery()) {
430     return;
431   }
432 
433   std::string query_string;
434   query_signer_->SignRequest("", &query_string);
435   GURL::Replacements replacements;
436   replacements.SetQueryStr(query_string);
437   GURL url = server_url_.ReplaceComponents(replacements);
438 
439   net::NetworkTrafficAnnotationTag traffic_annotation =
440       net::DefineNetworkTrafficAnnotation("network_time_component", R"(
441         semantics {
442           sender: "Network Time Component"
443           description:
444             "Sends a request to a Google server to retrieve the current "
445             "timestamp."
446           trigger:
447             "A request can be sent to retrieve the current time when the user "
448             "encounters an SSL date error, or in the background if Chromium "
449             "determines that it doesn't have an accurate timestamp."
450           data: "None"
451           destination: GOOGLE_OWNED_SERVICE
452         }
453         policy {
454           cookies_allowed: NO
455           setting: "This feature cannot be disabled by settings."
456           chrome_policy {
457             BrowserNetworkTimeQueriesEnabled {
458                 BrowserNetworkTimeQueriesEnabled: false
459             }
460           }
461         })");
462   auto resource_request = std::make_unique<network::ResourceRequest>();
463   resource_request->url = std::move(url);
464   // Not expecting any cookies, but just in case.
465   resource_request->load_flags =
466       net::LOAD_BYPASS_CACHE | net::LOAD_DISABLE_CACHE;
467   resource_request->credentials_mode = network::mojom::CredentialsMode::kOmit;
468   resource_request->enable_load_timing = true;
469   // This cancels any outstanding fetch.
470   time_fetcher_ = network::SimpleURLLoader::Create(std::move(resource_request),
471                                                    traffic_annotation);
472   time_fetcher_->SetAllowHttpErrorResults(true);
473   time_fetcher_->DownloadToString(
474       url_loader_factory_.get(),
475       base::BindOnce(&NetworkTimeTracker::OnURLLoaderComplete,
476                      base::Unretained(this)),
477       max_response_size_);
478 
479   timer_.Stop();  // Restarted in OnURLLoaderComplete().
480 }
481 
482 bool NetworkTimeTracker::UpdateTimeFromResponse(
483     std::unique_ptr<std::string> response_body) {
484   int response_code = 0;
485   if (time_fetcher_->ResponseInfo() && time_fetcher_->ResponseInfo()->headers) {
486     response_code = time_fetcher_->ResponseInfo()->headers->response_code();
487   }
488   if (response_code != 200 || !response_body) {
489     time_query_completed_ = true;
490     DVLOG(1) << "fetch failed code=" << response_code;
491     return false;
492   }
493 
494   std::string_view response(*response_body);
495 
496   DCHECK(query_signer_);
497   if (!query_signer_->ValidateResponse(
498           response, GetServerProof(time_fetcher_->ResponseInfo()->headers))) {
499     DVLOG(1) << "invalid signature";
500     return false;
501   }
502   response.remove_prefix(5);  // Skips leading )]}'\n
503   std::optional<base::Value> value = base::JSONReader::Read(response);
504   if (!value) {
505     DVLOG(1) << "bad JSON";
506     return false;
507   }
508   if (!value->is_dict()) {
509     DVLOG(1) << "not a dictionary";
510     return false;
511   }
512   std::optional<double> current_time_millis =
513       value->GetDict().FindDouble("current_time_millis");
514   if (!current_time_millis) {
515     DVLOG(1) << "no current_time_millis";
516     return false;
517   }
518 
519   // There is a "server_nonce" key here too, but it serves no purpose other than
520   // to make the server's response unpredictable.
521   base::Time current_time =
522       base::Time::FromMillisecondsSinceUnixEpoch(*current_time_millis);
523   base::TimeDelta resolution =
524       base::Milliseconds(1) + base::Seconds(kTimeServerMaxSkewSeconds);
525 
526   // Record histograms for the latency of the time query and the time delta
527   // between time fetches.
528   base::TimeDelta latency =
529       time_fetcher_->ResponseInfo()->load_timing.receive_headers_start -
530       time_fetcher_->ResponseInfo()->load_timing.send_end;
531 
532   last_fetched_time_ = current_time;
533 
534   UpdateNetworkTime(current_time, resolution, latency, tick_clock_->NowTicks());
535   return true;
536 }
537 
OnURLLoaderComplete(std::unique_ptr<std::string> response_body)538 void NetworkTimeTracker::OnURLLoaderComplete(
539     std::unique_ptr<std::string> response_body) {
540   DCHECK(thread_checker_.CalledOnValidThread());
541   DCHECK(time_fetcher_);
542 
543   time_query_completed_ = true;
544 
545   // After completion of a query, whether succeeded or failed, go to sleep
546   // for a long time.
547   if (!UpdateTimeFromResponse(
548           std::move(response_body))) {  // On error, back off.
549     if (backoff_ < base::Days(2)) {
550       backoff_ *= 2;
551     }
552   } else {
553     backoff_ = kBackoffInterval.Get();
554   }
555   QueueCheckTime(backoff_);
556   time_fetcher_.reset();
557 
558   // Clear |fetch_completion_callbacks_| before running any of them,
559   // because a callback could call StartTimeFetch() to enqueue another
560   // callback.
561   std::vector<base::OnceClosure> callbacks =
562       std::move(fetch_completion_callbacks_);
563   fetch_completion_callbacks_.clear();
564   for (auto& callback : callbacks) {
565     std::move(callback).Run();
566   }
567 }
568 
QueueCheckTime(base::TimeDelta delay)569 void NetworkTimeTracker::QueueCheckTime(base::TimeDelta delay) {
570   DCHECK_GE(delay, base::TimeDelta()) << "delay must be non-negative";
571   // Check if the user is opted in to background time fetches.
572   FetchBehavior behavior = GetFetchBehavior();
573   if (behavior == FETCHES_IN_BACKGROUND_ONLY ||
574       behavior == FETCHES_IN_BACKGROUND_AND_ON_DEMAND) {
575     timer_.Start(FROM_HERE, delay,
576                  base::BindRepeating(&NetworkTimeTracker::CheckTime,
577                                      base::Unretained(this)));
578   }
579 }
580 
ShouldIssueTimeQuery()581 bool NetworkTimeTracker::ShouldIssueTimeQuery() {
582   // Do not query the time service if the feature is not enabled.
583   if (!AreTimeFetchesEnabled()) {
584     return false;
585   }
586 
587   // Do not query the time service if queries are disabled by policy.
588   if (!pref_service_->GetBoolean(prefs::kNetworkTimeQueriesEnabled)) {
589     return false;
590   }
591 
592   // If GetNetworkTime() does not return NETWORK_TIME_AVAILABLE,
593   // synchronization has been lost and a query is needed.
594   base::Time network_time;
595   if (GetNetworkTime(&network_time, nullptr) != NETWORK_TIME_AVAILABLE) {
596     return true;
597   }
598 
599   // Otherwise, make the decision at random.
600   double probability = kRandomQueryProbability.Get();
601   if (probability < 0.0 || probability > 1.0) {
602     probability = kRandomQueryProbability.default_value;
603   }
604 
605   return base::RandDouble() < probability;
606 }
607 
NotifyObservers()608 void NetworkTimeTracker::NotifyObservers() {
609   // Don't notify if the current state is not NETWORK_TIME_AVAILABLE.
610   base::Time unused;
611   auto res = GetNetworkTime(&unused, nullptr);
612   if (res != NETWORK_TIME_AVAILABLE) {
613     return;
614   }
615   TimeTracker::TimeTrackerState state = tracker_->GetStateAtCreation();
616   for (NetworkTimeObserver& obs : observers_) {
617     obs.OnNetworkTimeChanged(state);
618   }
619 }
620 
621 }  // namespace network_time
622