Home | History | Annotate | Download | only in base
      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