OLD | NEW |
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 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
181 std::unique_ptr<base::Clock> clock, | 181 std::unique_ptr<base::Clock> clock, |
182 std::unique_ptr<base::TickClock> tick_clock, | 182 std::unique_ptr<base::TickClock> tick_clock, |
183 PrefService* pref_service, | 183 PrefService* pref_service, |
184 scoped_refptr<net::URLRequestContextGetter> getter) | 184 scoped_refptr<net::URLRequestContextGetter> getter) |
185 : server_url_(kTimeServiceURL), | 185 : server_url_(kTimeServiceURL), |
186 max_response_size_(1024), | 186 max_response_size_(1024), |
187 backoff_(base::TimeDelta::FromMinutes(kBackoffMinutes)), | 187 backoff_(base::TimeDelta::FromMinutes(kBackoffMinutes)), |
188 getter_(std::move(getter)), | 188 getter_(std::move(getter)), |
189 clock_(std::move(clock)), | 189 clock_(std::move(clock)), |
190 tick_clock_(std::move(tick_clock)), | 190 tick_clock_(std::move(tick_clock)), |
191 pref_service_(pref_service) { | 191 pref_service_(pref_service), |
| 192 time_query_completed_(false) { |
192 const base::DictionaryValue* time_mapping = | 193 const base::DictionaryValue* time_mapping = |
193 pref_service_->GetDictionary(prefs::kNetworkTimeMapping); | 194 pref_service_->GetDictionary(prefs::kNetworkTimeMapping); |
194 double time_js = 0; | 195 double time_js = 0; |
195 double ticks_js = 0; | 196 double ticks_js = 0; |
196 double network_time_js = 0; | 197 double network_time_js = 0; |
197 double uncertainty_js = 0; | 198 double uncertainty_js = 0; |
198 if (time_mapping->GetDouble(kPrefTime, &time_js) && | 199 if (time_mapping->GetDouble(kPrefTime, &time_js) && |
199 time_mapping->GetDouble(kPrefTicks, &ticks_js) && | 200 time_mapping->GetDouble(kPrefTicks, &ticks_js) && |
200 time_mapping->GetDouble(kPrefUncertainty, &uncertainty_js) && | 201 time_mapping->GetDouble(kPrefUncertainty, &uncertainty_js) && |
201 time_mapping->GetDouble(kPrefNetworkTime, &network_time_js)) { | 202 time_mapping->GetDouble(kPrefNetworkTime, &network_time_js)) { |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
303 DCHECK(timer_.IsRunning()); | 304 DCHECK(timer_.IsRunning()); |
304 return timer_.GetCurrentDelay(); | 305 return timer_.GetCurrentDelay(); |
305 } | 306 } |
306 | 307 |
307 NetworkTimeTracker::NetworkTimeResult NetworkTimeTracker::GetNetworkTime( | 308 NetworkTimeTracker::NetworkTimeResult NetworkTimeTracker::GetNetworkTime( |
308 base::Time* network_time, | 309 base::Time* network_time, |
309 base::TimeDelta* uncertainty) const { | 310 base::TimeDelta* uncertainty) const { |
310 DCHECK(thread_checker_.CalledOnValidThread()); | 311 DCHECK(thread_checker_.CalledOnValidThread()); |
311 DCHECK(network_time); | 312 DCHECK(network_time); |
312 if (network_time_at_last_measurement_.is_null()) { | 313 if (network_time_at_last_measurement_.is_null()) { |
313 return NETWORK_TIME_NO_SYNC; | 314 if (time_query_completed_) { |
| 315 // Time query attempts have been made in the past and failed. |
| 316 if (time_fetcher_) { |
| 317 // A fetch (not the first attempt) is in progress. |
| 318 return NETWORK_TIME_SUBSEQUENT_SYNC_PENDING; |
| 319 } else { |
| 320 return NETWORK_TIME_NO_SUCCESSFUL_SYNC; |
| 321 } |
| 322 } else { |
| 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 } |
314 } | 330 } |
315 DCHECK(!ticks_at_last_measurement_.is_null()); | 331 DCHECK(!ticks_at_last_measurement_.is_null()); |
316 DCHECK(!time_at_last_measurement_.is_null()); | 332 DCHECK(!time_at_last_measurement_.is_null()); |
317 base::TimeDelta tick_delta = | 333 base::TimeDelta tick_delta = |
318 tick_clock_->NowTicks() - ticks_at_last_measurement_; | 334 tick_clock_->NowTicks() - ticks_at_last_measurement_; |
319 base::TimeDelta time_delta = clock_->Now() - time_at_last_measurement_; | 335 base::TimeDelta time_delta = clock_->Now() - time_at_last_measurement_; |
320 if (time_delta.InMilliseconds() < 0) { // Has wall clock run backward? | 336 if (time_delta.InMilliseconds() < 0) { // Has wall clock run backward? |
321 DVLOG(1) << "Discarding network time due to wall clock running backward"; | 337 DVLOG(1) << "Discarding network time due to wall clock running backward"; |
322 UMA_HISTOGRAM_CUSTOM_TIMES( | 338 UMA_HISTOGRAM_CUSTOM_TIMES( |
323 "NetworkTimeTracker.WallClockRanBackwards", time_delta.magnitude(), | 339 "NetworkTimeTracker.WallClockRanBackwards", time_delta.magnitude(), |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
393 | 409 |
394 time_fetcher_->Start(); | 410 time_fetcher_->Start(); |
395 fetch_started_ = tick_clock_->NowTicks(); | 411 fetch_started_ = tick_clock_->NowTicks(); |
396 | 412 |
397 timer_.Stop(); // Restarted in OnURLFetchComplete(). | 413 timer_.Stop(); // Restarted in OnURLFetchComplete(). |
398 } | 414 } |
399 | 415 |
400 bool NetworkTimeTracker::UpdateTimeFromResponse() { | 416 bool NetworkTimeTracker::UpdateTimeFromResponse() { |
401 if (time_fetcher_->GetStatus().status() != net::URLRequestStatus::SUCCESS || | 417 if (time_fetcher_->GetStatus().status() != net::URLRequestStatus::SUCCESS || |
402 time_fetcher_->GetResponseCode() != 200) { | 418 time_fetcher_->GetResponseCode() != 200) { |
| 419 time_query_completed_ = true; |
403 DVLOG(1) << "fetch failed, status=" << time_fetcher_->GetStatus().status() | 420 DVLOG(1) << "fetch failed, status=" << time_fetcher_->GetStatus().status() |
404 << ",code=" << time_fetcher_->GetResponseCode(); | 421 << ",code=" << time_fetcher_->GetResponseCode(); |
405 // The error code is negated because net errors are negative, but | 422 // The error code is negated because net errors are negative, but |
406 // the corresponding histogram enum is positive. | 423 // the corresponding histogram enum is positive. |
407 UMA_HISTOGRAM_SPARSE_SLOWLY("NetworkTimeTracker.UpdateTimeFetchFailed", | 424 UMA_HISTOGRAM_SPARSE_SLOWLY("NetworkTimeTracker.UpdateTimeFetchFailed", |
408 -time_fetcher_->GetStatus().error()); | 425 -time_fetcher_->GetStatus().error()); |
409 return false; | 426 return false; |
410 } | 427 } |
411 | 428 |
412 std::string response_body; | 429 std::string response_body; |
(...skipping 30 matching lines...) Expand all Loading... |
443 | 460 |
444 RecordFetchValidHistogram(true); | 461 RecordFetchValidHistogram(true); |
445 | 462 |
446 // There is a "server_nonce" key here too, but it serves no purpose other than | 463 // There is a "server_nonce" key here too, but it serves no purpose other than |
447 // to make the server's response unpredictable. | 464 // to make the server's response unpredictable. |
448 base::Time current_time = base::Time::FromJsTime(current_time_millis); | 465 base::Time current_time = base::Time::FromJsTime(current_time_millis); |
449 base::TimeDelta resolution = | 466 base::TimeDelta resolution = |
450 base::TimeDelta::FromMilliseconds(1) + | 467 base::TimeDelta::FromMilliseconds(1) + |
451 base::TimeDelta::FromSeconds(kTimeServerMaxSkewSeconds); | 468 base::TimeDelta::FromSeconds(kTimeServerMaxSkewSeconds); |
452 base::TimeDelta latency = tick_clock_->NowTicks() - fetch_started_; | 469 base::TimeDelta latency = tick_clock_->NowTicks() - fetch_started_; |
| 470 UMA_HISTOGRAM_TIMES("NetworkTimeTracker.TimeQueryLatency", latency); |
453 UpdateNetworkTime(current_time, resolution, latency, tick_clock_->NowTicks()); | 471 UpdateNetworkTime(current_time, resolution, latency, tick_clock_->NowTicks()); |
454 return true; | 472 return true; |
455 } | 473 } |
456 | 474 |
457 void NetworkTimeTracker::OnURLFetchComplete(const net::URLFetcher* source) { | 475 void NetworkTimeTracker::OnURLFetchComplete(const net::URLFetcher* source) { |
458 DCHECK(thread_checker_.CalledOnValidThread()); | 476 DCHECK(thread_checker_.CalledOnValidThread()); |
459 DCHECK(time_fetcher_); | 477 DCHECK(time_fetcher_); |
460 DCHECK_EQ(source, time_fetcher_.get()); | 478 DCHECK_EQ(source, time_fetcher_.get()); |
461 | 479 |
| 480 time_query_completed_ = true; |
| 481 |
462 // After completion of a query, whether succeeded or failed, go to sleep for a | 482 // After completion of a query, whether succeeded or failed, go to sleep for a |
463 // long time. | 483 // long time. |
464 if (!UpdateTimeFromResponse()) { // On error, back off. | 484 if (!UpdateTimeFromResponse()) { // On error, back off. |
465 if (backoff_ < base::TimeDelta::FromDays(2)) { | 485 if (backoff_ < base::TimeDelta::FromDays(2)) { |
466 backoff_ *= 2; | 486 backoff_ *= 2; |
467 } | 487 } |
468 } else { | 488 } else { |
469 backoff_ = base::TimeDelta::FromMinutes(kBackoffMinutes); | 489 backoff_ = base::TimeDelta::FromMinutes(kBackoffMinutes); |
470 } | 490 } |
471 QueueCheckTime(backoff_); | 491 QueueCheckTime(backoff_); |
(...skipping 17 matching lines...) Expand all Loading... |
489 base::Time network_time; | 509 base::Time network_time; |
490 if (GetNetworkTime(&network_time, nullptr) != NETWORK_TIME_AVAILABLE) { | 510 if (GetNetworkTime(&network_time, nullptr) != NETWORK_TIME_AVAILABLE) { |
491 return true; | 511 return true; |
492 } | 512 } |
493 | 513 |
494 // Otherwise, make the decision at random. | 514 // Otherwise, make the decision at random. |
495 return base::RandDouble() < RandomQueryProbability(); | 515 return base::RandDouble() < RandomQueryProbability(); |
496 } | 516 } |
497 | 517 |
498 } // namespace network_time | 518 } // namespace network_time |
OLD | NEW |