Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(53)

Side by Side Diff: components/network_time/network_time_tracker.cc

Issue 2453523002: Add NetworkTimeTracker::StartTimeFetch() for on-demand time queries (Closed)
Patch Set: Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "components/network_time/network_time_tracker.h" 5 #include "components/network_time/network_time_tracker.h"
6 6
7 #include <stdint.h> 7 #include <stdint.h>
8 #include <string> 8 #include <string>
9 #include <utility> 9 #include <utility>
10 10
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
93 // be that badly wrong, but all the same it's included here to document the very 93 // be that badly wrong, but all the same it's included here to document the very
94 // rough nature of the time service provided by this class.) 94 // rough nature of the time service provided by this class.)
95 const uint32_t kTimeServerMaxSkewSeconds = 10; 95 const uint32_t kTimeServerMaxSkewSeconds = 10;
96 96
97 const char kTimeServiceURL[] = "http://clients2.google.com/time/1/current"; 97 const char kTimeServiceURL[] = "http://clients2.google.com/time/1/current";
98 98
99 const char kVariationsServiceCheckTimeIntervalSeconds[] = 99 const char kVariationsServiceCheckTimeIntervalSeconds[] =
100 "CheckTimeIntervalSeconds"; 100 "CheckTimeIntervalSeconds";
101 const char kVariationsServiceRandomQueryProbability[] = 101 const char kVariationsServiceRandomQueryProbability[] =
102 "RandomQueryProbability"; 102 "RandomQueryProbability";
103 // This parameter must have the value "true" in order for
104 // StartTimeFetch() to start time queries on demand.
105 const char kVariationsServiceEnableFetchesOnDemand[] = "EnableFetchesOnDemand";
103 106
104 // This is an ECDSA prime256v1 named-curve key. 107 // This is an ECDSA prime256v1 named-curve key.
105 const int kKeyVersion = 1; 108 const int kKeyVersion = 1;
106 const uint8_t kKeyPubBytes[] = { 109 const uint8_t kKeyPubBytes[] = {
107 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 110 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02,
108 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 111 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03,
109 0x42, 0x00, 0x04, 0xeb, 0xd8, 0xad, 0x0b, 0x8f, 0x75, 0xe8, 0x84, 0x36, 112 0x42, 0x00, 0x04, 0xeb, 0xd8, 0xad, 0x0b, 0x8f, 0x75, 0xe8, 0x84, 0x36,
110 0x23, 0x48, 0x14, 0x24, 0xd3, 0x93, 0x42, 0x25, 0x43, 0xc1, 0xde, 0x36, 113 0x23, 0x48, 0x14, 0x24, 0xd3, 0x93, 0x42, 0x25, 0x43, 0xc1, 0xde, 0x36,
111 0x29, 0xc6, 0x95, 0xca, 0xeb, 0x28, 0x85, 0xff, 0x09, 0xdc, 0x08, 0xec, 114 0x29, 0xc6, 0x95, 0xca, 0xeb, 0x28, 0x85, 0xff, 0x09, 0xdc, 0x08, 0xec,
112 0x45, 0x74, 0x6e, 0x4b, 0xc3, 0xa5, 0xfd, 0x8a, 0x2f, 0x02, 0xa0, 0x4b, 115 0x45, 0x74, 0x6e, 0x4b, 0xc3, 0xa5, 0xfd, 0x8a, 0x2f, 0x02, 0xa0, 0x4b,
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after
288 } 291 }
289 292
290 bool NetworkTimeTracker::QueryTimeServiceForTesting() { 293 bool NetworkTimeTracker::QueryTimeServiceForTesting() {
291 CheckTime(); 294 CheckTime();
292 return time_fetcher_ != nullptr; 295 return time_fetcher_ != nullptr;
293 } 296 }
294 297
295 void NetworkTimeTracker::WaitForFetchForTesting(uint32_t nonce) { 298 void NetworkTimeTracker::WaitForFetchForTesting(uint32_t nonce) {
296 query_signer_->OverrideNonceForTesting(kKeyVersion, nonce); 299 query_signer_->OverrideNonceForTesting(kKeyVersion, nonce);
297 base::RunLoop run_loop; 300 base::RunLoop run_loop;
298 run_loop_for_testing_ = &run_loop; 301 fetch_completion_callbacks_.push_back(run_loop.QuitClosure());
299 run_loop.Run(); 302 run_loop.Run();
300 run_loop_for_testing_ = nullptr;
301 } 303 }
302 304
303 base::TimeDelta NetworkTimeTracker::GetTimerDelayForTesting() const { 305 base::TimeDelta NetworkTimeTracker::GetTimerDelayForTesting() const {
304 DCHECK(timer_.IsRunning()); 306 DCHECK(timer_.IsRunning());
305 return timer_.GetCurrentDelay(); 307 return timer_.GetCurrentDelay();
306 } 308 }
307 309
308 NetworkTimeTracker::NetworkTimeResult NetworkTimeTracker::GetNetworkTime( 310 NetworkTimeTracker::NetworkTimeResult NetworkTimeTracker::GetNetworkTime(
309 base::Time* network_time, 311 base::Time* network_time,
310 base::TimeDelta* uncertainty) const { 312 base::TimeDelta* uncertainty) const {
311 DCHECK(thread_checker_.CalledOnValidThread()); 313 DCHECK(thread_checker_.CalledOnValidThread());
312 DCHECK(network_time); 314 DCHECK(network_time);
313 if (network_time_at_last_measurement_.is_null()) { 315 if (network_time_at_last_measurement_.is_null()) {
314 if (time_query_completed_) { 316 if (time_query_completed_) {
315 // Time query attempts have been made in the past and failed. 317 // Time query attempts have been made in the past and failed.
316 if (time_fetcher_) { 318 if (time_fetcher_) {
317 // A fetch (not the first attempt) is in progress. 319 // A fetch (not the first attempt) is in progress.
318 return NETWORK_TIME_SUBSEQUENT_SYNC_PENDING; 320 return NETWORK_TIME_SUBSEQUENT_SYNC_PENDING;
319 } else {
320 return NETWORK_TIME_NO_SUCCESSFUL_SYNC;
321 } 321 }
322 } else { 322 return NETWORK_TIME_NO_SUCCESSFUL_SYNC;
estark 2016/10/25 20:14:00 unrelated cleanup, sorry. there was too much inden
323 // No time queries have happened yet.
324 if (time_fetcher_) {
325 return NETWORK_TIME_FIRST_SYNC_PENDING;
326 } else {
327 return NETWORK_TIME_NO_SYNC_ATTEMPT;
328 }
329 } 323 }
324 // No time queries have happened yet.
325 if (time_fetcher_) {
326 return NETWORK_TIME_FIRST_SYNC_PENDING;
327 }
328 return NETWORK_TIME_NO_SYNC_ATTEMPT;
330 } 329 }
330
331 DCHECK(!ticks_at_last_measurement_.is_null()); 331 DCHECK(!ticks_at_last_measurement_.is_null());
332 DCHECK(!time_at_last_measurement_.is_null()); 332 DCHECK(!time_at_last_measurement_.is_null());
333 base::TimeDelta tick_delta = 333 base::TimeDelta tick_delta =
334 tick_clock_->NowTicks() - ticks_at_last_measurement_; 334 tick_clock_->NowTicks() - ticks_at_last_measurement_;
335 base::TimeDelta time_delta = clock_->Now() - time_at_last_measurement_; 335 base::TimeDelta time_delta = clock_->Now() - time_at_last_measurement_;
336 if (time_delta.InMilliseconds() < 0) { // Has wall clock run backward? 336 if (time_delta.InMilliseconds() < 0) { // Has wall clock run backward?
337 DVLOG(1) << "Discarding network time due to wall clock running backward"; 337 DVLOG(1) << "Discarding network time due to wall clock running backward";
338 UMA_HISTOGRAM_CUSTOM_TIMES( 338 UMA_HISTOGRAM_CUSTOM_TIMES(
339 "NetworkTimeTracker.WallClockRanBackwards", time_delta.magnitude(), 339 "NetworkTimeTracker.WallClockRanBackwards", time_delta.magnitude(),
340 base::TimeDelta::FromSeconds(1), base::TimeDelta::FromDays(7), 50); 340 base::TimeDelta::FromSeconds(1), base::TimeDelta::FromDays(7), 50);
(...skipping 24 matching lines...) Expand all
365 network_time_at_last_measurement_ = base::Time(); 365 network_time_at_last_measurement_ = base::Time();
366 return NETWORK_TIME_SYNC_LOST; 366 return NETWORK_TIME_SYNC_LOST;
367 } 367 }
368 *network_time = network_time_at_last_measurement_ + tick_delta; 368 *network_time = network_time_at_last_measurement_ + tick_delta;
369 if (uncertainty) { 369 if (uncertainty) {
370 *uncertainty = network_time_uncertainty_ + divergence; 370 *uncertainty = network_time_uncertainty_ + divergence;
371 } 371 }
372 return NETWORK_TIME_AVAILABLE; 372 return NETWORK_TIME_AVAILABLE;
373 } 373 }
374 374
375 bool NetworkTimeTracker::StartTimeFetch(const base::Closure& closure) {
meacer 2016/10/26 19:19:22 Could you add a DCHECK(thread_checker_.CalledOnVal
estark 2016/10/26 20:35:13 Done.
376 // Check if the user is opted in to on-demand time fetches.
377 const std::string param = variations::GetVariationParamValueByFeature(
378 kNetworkTimeServiceQuerying, kVariationsServiceEnableFetchesOnDemand);
379 if (param != "true") {
380 return false;
381 }
382
383 // Enqueue the callback before calling CheckTime(), so that if
384 // CheckTime() completes synchronously, the callback gets called.
385 fetch_completion_callbacks_.push_back(closure);
386
387 // If a time query is already in progress, do not start another one.
388 if (time_fetcher_) {
389 return true;
390 }
391
392 // Cancel any fetches that are scheduled for the future, and try to
393 // start one now.
meacer 2016/10/26 00:38:15 For my own education: If two clients call StartTim
meacer 2016/10/26 01:07:37 "If two clients call StartTimeFetch one of the oth
394 timer_.Stop();
395 CheckTime();
396
397 // CheckTime() does not necessarily start a fetch; for example, time
398 // queries might be disabled or network time might already be
399 // available.
400 if (!time_fetcher_) {
401 // If no query is in progress, there should be no callbacks waiting for it
402 // to complete.
meacer 2016/10/26 19:19:22 nit: I'm a bit confused by this comment, it sounds
estark 2016/10/26 20:35:13 Oh, yes, what I wrote was confusing. Done.
403 fetch_completion_callbacks_.clear();
404 return false;
405 }
406 return true;
407 }
408
375 void NetworkTimeTracker::CheckTime() { 409 void NetworkTimeTracker::CheckTime() {
376 DCHECK(thread_checker_.CalledOnValidThread()); 410 DCHECK(thread_checker_.CalledOnValidThread());
377 411
378 // If NetworkTimeTracker is waking up after a backoff, this will reset the 412 // If NetworkTimeTracker is waking up after a backoff, this will reset the
379 // timer to its default faster frequency. 413 // timer to its default faster frequency.
380 QueueCheckTime(CheckTimeInterval()); 414 QueueCheckTime(CheckTimeInterval());
381 415
382 if (!ShouldIssueTimeQuery()) { 416 if (!ShouldIssueTimeQuery()) {
383 return; 417 return;
384 } 418 }
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
483 // long time. 517 // long time.
484 if (!UpdateTimeFromResponse()) { // On error, back off. 518 if (!UpdateTimeFromResponse()) { // On error, back off.
485 if (backoff_ < base::TimeDelta::FromDays(2)) { 519 if (backoff_ < base::TimeDelta::FromDays(2)) {
486 backoff_ *= 2; 520 backoff_ *= 2;
487 } 521 }
488 } else { 522 } else {
489 backoff_ = base::TimeDelta::FromMinutes(kBackoffMinutes); 523 backoff_ = base::TimeDelta::FromMinutes(kBackoffMinutes);
490 } 524 }
491 QueueCheckTime(backoff_); 525 QueueCheckTime(backoff_);
492 time_fetcher_.reset(); 526 time_fetcher_.reset();
493 if (run_loop_for_testing_ != nullptr) 527
494 run_loop_for_testing_->QuitWhenIdle(); 528 // Clear |fetch_completion_callbacks_| before running any of them,
529 // because a callback could call StartTimeFetch() to enqueue another
530 // callback.
531 std::vector<base::Closure> callbacks = fetch_completion_callbacks_;
532 fetch_completion_callbacks_.clear();
533 for (const auto& callback : callbacks) {
534 callback.Run();
535 }
495 } 536 }
496 537
497 void NetworkTimeTracker::QueueCheckTime(base::TimeDelta delay) { 538 void NetworkTimeTracker::QueueCheckTime(base::TimeDelta delay) {
498 timer_.Start(FROM_HERE, delay, this, &NetworkTimeTracker::CheckTime); 539 timer_.Start(FROM_HERE, delay, this, &NetworkTimeTracker::CheckTime);
499 } 540 }
500 541
501 bool NetworkTimeTracker::ShouldIssueTimeQuery() { 542 bool NetworkTimeTracker::ShouldIssueTimeQuery() {
502 // Do not query the time service if not enabled via Variations Service. 543 // Do not query the time service if not enabled via Variations Service.
503 if (!base::FeatureList::IsEnabled(kNetworkTimeServiceQuerying)) { 544 if (!base::FeatureList::IsEnabled(kNetworkTimeServiceQuerying)) {
504 return false; 545 return false;
505 } 546 }
506 547
507 // If GetNetworkTime() does not return NETWORK_TIME_AVAILABLE, 548 // If GetNetworkTime() does not return NETWORK_TIME_AVAILABLE,
508 // synchronization has been lost and a query is needed. 549 // synchronization has been lost and a query is needed.
509 base::Time network_time; 550 base::Time network_time;
510 if (GetNetworkTime(&network_time, nullptr) != NETWORK_TIME_AVAILABLE) { 551 if (GetNetworkTime(&network_time, nullptr) != NETWORK_TIME_AVAILABLE) {
511 return true; 552 return true;
512 } 553 }
513 554
514 // Otherwise, make the decision at random. 555 // Otherwise, make the decision at random.
515 return base::RandDouble() < RandomQueryProbability(); 556 return base::RandDouble() < RandomQueryProbability();
516 } 557 }
517 558
518 } // namespace network_time 559 } // namespace network_time
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698