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