1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 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 "net/base/network_time_notifier.h" 6 7 #include "base/basictypes.h" 8 #include "base/bind.h" 9 #include "base/i18n/time_formatting.h" 10 #include "base/location.h" 11 #include "base/message_loop/message_loop.h" 12 #include "base/stl_util.h" 13 #include "base/strings/utf_string_conversions.h" 14 15 namespace { 16 17 // Clock resolution is platform dependent. 18 #if defined(OS_WIN) 19 const int64 kTicksResolutionMs = base::Time::kMinLowResolutionThresholdMs; 20 #else 21 const int64 kTicksResolutionMs = 1; // Assume 1ms for non-windows platforms. 22 #endif 23 24 // Number of time measurements performed in a given network time calculation. 25 const int kNumTimeMeasurements = 5; 26 27 } // namespace 28 29 namespace net { 30 31 NetworkTimeNotifier::NetworkTimeNotifier( 32 scoped_ptr<base::TickClock> tick_clock) { 33 tick_clock_ = tick_clock.Pass(); 34 } 35 36 NetworkTimeNotifier::~NetworkTimeNotifier() {} 37 38 void NetworkTimeNotifier::UpdateNetworkTime(const base::Time& network_time, 39 const base::TimeDelta& resolution, 40 const base::TimeDelta& latency, 41 const base::TimeTicks& post_time) { 42 DCHECK(thread_checker_.CalledOnValidThread()); 43 DVLOG(1) << "Network time updating to " 44 << UTF16ToUTF8(base::TimeFormatFriendlyDateAndTime(network_time)); 45 // Update network time on every request to limit dependency on ticks lag. 46 // TODO(mad): Find a heuristic to avoid augmenting the 47 // network_time_uncertainty_ too much by a particularly long latency. 48 // Maybe only update when the the new time either improves in accuracy or 49 // drifts too far from |network_time_|. 50 network_time_ = network_time; 51 52 // Calculate the delay since the network time was received. 53 base::TimeTicks now = tick_clock_->NowTicks(); 54 base::TimeDelta task_delay = now - post_time; 55 // Estimate that the time was set midway through the latency time. 56 network_time_ticks_ = now - task_delay - latency / 2; 57 58 // Can't assume a better time than the resolution of the given time 59 // and 5 ticks measurements are involved, each with their own uncertainty. 60 // 1 & 2 are the ones used to compute the latency, 3 is the Now() from when 61 // this task was posted, 4 is the Now() above and 5 will be the Now() used in 62 // GetNetworkTime(). 63 network_time_uncertainty_ = 64 resolution + latency + kNumTimeMeasurements * 65 base::TimeDelta::FromMilliseconds(kTicksResolutionMs); 66 67 for (size_t i = 0; i < observers_.size(); ++i) { 68 base::MessageLoop::current()->PostTask( 69 FROM_HERE, 70 base::Bind(observers_[i], 71 network_time_, 72 network_time_ticks_, 73 network_time_uncertainty_)); 74 } 75 } 76 77 void NetworkTimeNotifier::AddObserver( 78 const ObserverCallback& observer_callback) { 79 DCHECK(thread_checker_.CalledOnValidThread()); 80 observers_.push_back(observer_callback); 81 if (!network_time_.is_null()) { 82 base::MessageLoop::current()->PostTask( 83 FROM_HERE, 84 base::Bind(observer_callback, 85 network_time_, 86 network_time_ticks_, 87 network_time_uncertainty_)); 88 } 89 } 90 91 } // namespace net 92