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.
5 #include "net/base/network_time_notifier.h"
7 #include "base/basictypes.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"
17 // Clock resolution is platform dependent.
19 const int64 kTicksResolutionMs
= base::Time::kMinLowResolutionThresholdMs
;
21 const int64 kTicksResolutionMs
= 1; // Assume 1ms for non-windows platforms.
24 // Number of time measurements performed in a given network time calculation.
25 const int kNumTimeMeasurements
= 5;
31 NetworkTimeNotifier::NetworkTimeNotifier(
32 scoped_ptr
<base::TickClock
> tick_clock
) {
33 tick_clock_
= tick_clock
.Pass();
36 NetworkTimeNotifier::~NetworkTimeNotifier() {}
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
;
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;
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
63 network_time_uncertainty_
=
64 resolution
+ latency
+ kNumTimeMeasurements
*
65 base::TimeDelta::FromMilliseconds(kTicksResolutionMs
);
67 for (size_t i
= 0; i
< observers_
.size(); ++i
) {
68 base::MessageLoop::current()->PostTask(
70 base::Bind(observers_
[i
],
73 network_time_uncertainty_
));
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(
84 base::Bind(observer_callback
,
87 network_time_uncertainty_
));