Home | History | Annotate | Download | only in net
      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 "chrome/browser/net/network_time_tracker.h"
      6 
      7 #include "base/sequenced_task_runner.h"
      8 #include "chrome/browser/browser_process.h"
      9 #include "chrome/browser/io_thread.h"
     10 
     11 namespace {
     12 
     13 // Helper functions for interacting with the NetworkTimeNotifier.
     14 // Registration happens as follows (assuming tracker lives on thread N):
     15 // | Thread N |                   | UI thread|                     | IO Thread |
     16 // Start
     17 //                         RegisterObserverOnUIThread
     18 //                                                    RegisterObserverOnIOThread
     19 //                                              NetworkTimeNotifier::AddObserver
     20 // after which updates to the notifier and the subsequent observer calls
     21 // happen as follows (assuming the network time update comes from the same
     22 // thread):
     23 // | Thread N |                   | UI thread|                     | IO Thread |
     24 // UpdateNetworkNotifier
     25 //                                               UpdateNetworkNotifierOnIOThread
     26 //                                        NetworkTimeNotifier::UpdateNetworkTime
     27 //                                                OnNetworkTimeUpdatedOnIOThread
     28 // OnNetworkTimeUpdated
     29 void RegisterObserverOnIOThread(
     30     IOThread* io_thread,
     31     const net::NetworkTimeNotifier::ObserverCallback& observer_callback) {
     32   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
     33   io_thread->globals()->network_time_notifier->AddObserver(observer_callback);
     34 }
     35 
     36 void RegisterObserverOnUIThread(
     37     const net::NetworkTimeNotifier::ObserverCallback& observer_callback) {
     38   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
     39   content::BrowserThread::PostTask(
     40       content::BrowserThread::IO, FROM_HERE,
     41       base::Bind(&RegisterObserverOnIOThread,
     42                  g_browser_process->io_thread(),
     43                  observer_callback));
     44 }
     45 
     46 void UpdateNetworkNotifierOnIOThread(IOThread* io_thread,
     47                                      const base::Time& network_time,
     48                                      const base::TimeDelta& resolution,
     49                                      const base::TimeDelta& latency,
     50                                      const base::TimeTicks& post_time) {
     51   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
     52   io_thread->globals()->network_time_notifier->UpdateNetworkTime(
     53       network_time, resolution, latency, post_time);
     54 }
     55 
     56 void UpdateNetworkNotifier(IOThread* io_thread,
     57                            const base::Time& network_time,
     58                            const base::TimeDelta& resolution,
     59                            const base::TimeDelta& latency) {
     60   content::BrowserThread::PostTask(
     61       content::BrowserThread::IO,
     62       FROM_HERE,
     63       base::Bind(&UpdateNetworkNotifierOnIOThread,
     64                  io_thread,
     65                  network_time,
     66                  resolution,
     67                  latency,
     68                  base::TimeTicks::Now()));
     69 }
     70 
     71 void OnNetworkTimeUpdatedOnIOThread(
     72     const scoped_refptr<base::SequencedTaskRunner>& task_runner,
     73     const net::NetworkTimeNotifier::ObserverCallback& observer_callback,
     74     const base::Time& network_time,
     75     const base::TimeTicks& network_time_ticks,
     76     const base::TimeDelta& network_time_uncertainty) {
     77   task_runner->PostTask(
     78       FROM_HERE,
     79       base::Bind(observer_callback,
     80                  network_time,
     81                  network_time_ticks,
     82                  network_time_uncertainty));
     83 }
     84 
     85 }  // namespace
     86 
     87 NetworkTimeTracker::NetworkTimeTracker()
     88     : weak_ptr_factory_(this) {
     89 }
     90 
     91 NetworkTimeTracker::~NetworkTimeTracker() {
     92 }
     93 
     94 void NetworkTimeTracker::Start() {
     95   DCHECK(thread_checker_.CalledOnValidThread());
     96   content::BrowserThread::PostTask(
     97       content::BrowserThread::UI,
     98       FROM_HERE,
     99       base::Bind(&RegisterObserverOnUIThread,
    100                  BuildObserverCallback()));
    101 }
    102 
    103 bool NetworkTimeTracker::GetNetworkTime(const base::TimeTicks& time_ticks,
    104                                         base::Time* network_time,
    105                                         base::TimeDelta* uncertainty) const {
    106   DCHECK(thread_checker_.CalledOnValidThread());
    107   DCHECK(network_time);
    108   if (network_time_.is_null())
    109     return false;
    110   DCHECK(!network_time_ticks_.is_null());
    111   *network_time = network_time_ + (time_ticks - network_time_ticks_);
    112   if (uncertainty)
    113     *uncertainty = network_time_uncertainty_;
    114   return true;
    115 }
    116 
    117 // static
    118 // Note: UpdateNetworkNotifier is exposed via callback because getting the IO
    119 // thread pointer must be done on the UI thread, while components that provide
    120 // network time updates may live on other threads.
    121 NetworkTimeTracker::UpdateCallback
    122 NetworkTimeTracker::BuildNotifierUpdateCallback() {
    123   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
    124   return base::Bind(&UpdateNetworkNotifier,
    125                     g_browser_process->io_thread());
    126 }
    127 
    128 net::NetworkTimeNotifier::ObserverCallback
    129 NetworkTimeTracker::BuildObserverCallback() {
    130   return base::Bind(&OnNetworkTimeUpdatedOnIOThread,
    131                     base::MessageLoop::current()->message_loop_proxy(),
    132                     base::Bind(&NetworkTimeTracker::OnNetworkTimeUpdate,
    133                                weak_ptr_factory_.GetWeakPtr()));
    134 }
    135 
    136 void NetworkTimeTracker::OnNetworkTimeUpdate(
    137     const base::Time& network_time,
    138     const base::TimeTicks& network_time_ticks,
    139     const base::TimeDelta& network_time_uncertainty) {
    140   DCHECK(thread_checker_.CalledOnValidThread());
    141   network_time_ = network_time;
    142   network_time_ticks_ = network_time_ticks;
    143   network_time_uncertainty_ = network_time_uncertainty;
    144 }
    145 
    146