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