1 // Copyright 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 "chrome/browser/network_time/network_time_tracker.h"
7 #include "base/sequenced_task_runner.h"
8 #include "chrome/browser/browser_process.h"
9 #include "chrome/browser/io_thread.h"
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 |
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
23 // | Thread N | | UI thread| | IO Thread |
24 // UpdateNetworkNotifier
25 // UpdateNetworkNotifierOnIOThread
26 // NetworkTimeNotifier::UpdateNetworkTime
27 // OnNetworkTimeUpdatedOnIOThread
28 // OnNetworkTimeUpdated
29 void RegisterObserverOnIOThread(
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
);
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(),
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
);
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
,
63 base::Bind(&UpdateNetworkNotifierOnIOThread
,
68 base::TimeTicks::Now()));
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(
79 base::Bind(observer_callback
,
82 network_time_uncertainty
));
87 NetworkTimeTracker::TimeMapping::TimeMapping(base::Time local_time
,
88 base::Time network_time
)
89 : local_time(local_time
),
90 network_time(network_time
) {}
92 NetworkTimeTracker::NetworkTimeTracker()
93 : weak_ptr_factory_(this),
94 received_network_time_(false) {
97 NetworkTimeTracker::~NetworkTimeTracker() {
100 void NetworkTimeTracker::Start() {
101 DCHECK(thread_checker_
.CalledOnValidThread());
102 content::BrowserThread::PostTask(
103 content::BrowserThread::UI
,
105 base::Bind(&RegisterObserverOnUIThread
,
106 BuildObserverCallback()));
109 void NetworkTimeTracker::InitFromSavedTime(const TimeMapping
& saved
) {
110 DCHECK(thread_checker_
.CalledOnValidThread());
111 if (!network_time_
.is_null() || saved
.local_time
.is_null() ||
112 saved
.network_time
.is_null())
115 base::Time local_time_now
= base::Time::Now();
116 if (local_time_now
< saved
.local_time
) {
117 DLOG(WARNING
) << "Can't initialize because clock skew has changed.";
121 network_time_
= saved
.network_time
+ (local_time_now
- saved
.local_time
);
122 network_time_ticks_
= base::TimeTicks::Now();
125 bool NetworkTimeTracker::GetNetworkTime(const base::TimeTicks
& time_ticks
,
126 base::Time
* network_time
,
127 base::TimeDelta
* uncertainty
) const {
128 DCHECK(thread_checker_
.CalledOnValidThread());
129 DCHECK(network_time
);
130 if (network_time_
.is_null())
132 DCHECK(!network_time_ticks_
.is_null());
133 *network_time
= network_time_
+ (time_ticks
- network_time_ticks_
);
135 *uncertainty
= network_time_uncertainty_
;
140 // Note: UpdateNetworkNotifier is exposed via callback because getting the IO
141 // thread pointer must be done on the UI thread, while components that provide
142 // network time updates may live on other threads.
143 NetworkTimeTracker::UpdateCallback
144 NetworkTimeTracker::BuildNotifierUpdateCallback() {
145 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
146 return base::Bind(&UpdateNetworkNotifier
,
147 g_browser_process
->io_thread());
150 net::NetworkTimeNotifier::ObserverCallback
151 NetworkTimeTracker::BuildObserverCallback() {
152 return base::Bind(&OnNetworkTimeUpdatedOnIOThread
,
153 base::MessageLoop::current()->message_loop_proxy(),
154 base::Bind(&NetworkTimeTracker::OnNetworkTimeUpdate
,
155 weak_ptr_factory_
.GetWeakPtr()));
158 void NetworkTimeTracker::OnNetworkTimeUpdate(
159 const base::Time
& network_time
,
160 const base::TimeTicks
& network_time_ticks
,
161 const base::TimeDelta
& network_time_uncertainty
) {
162 DCHECK(thread_checker_
.CalledOnValidThread());
163 network_time_
= network_time
;
164 network_time_ticks_
= network_time_ticks
;
165 network_time_uncertainty_
= network_time_uncertainty
;
166 received_network_time_
= true;