- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / network_time / network_time_tracker.cc
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.
4
5 #include "chrome/browser/network_time/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::TimeMapping::TimeMapping(base::Time local_time,
88                                              base::Time network_time)
89     : local_time(local_time),
90       network_time(network_time) {}
91
92 NetworkTimeTracker::NetworkTimeTracker()
93     : weak_ptr_factory_(this),
94       received_network_time_(false) {
95 }
96
97 NetworkTimeTracker::~NetworkTimeTracker() {
98 }
99
100 void NetworkTimeTracker::Start() {
101   DCHECK(thread_checker_.CalledOnValidThread());
102   content::BrowserThread::PostTask(
103       content::BrowserThread::UI,
104       FROM_HERE,
105       base::Bind(&RegisterObserverOnUIThread,
106                  BuildObserverCallback()));
107 }
108
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())
113     return;
114
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.";
118     return;
119   }
120
121   network_time_ = saved.network_time + (local_time_now - saved.local_time);
122   network_time_ticks_ = base::TimeTicks::Now();
123 }
124
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())
131     return false;
132   DCHECK(!network_time_ticks_.is_null());
133   *network_time = network_time_ + (time_ticks - network_time_ticks_);
134   if (uncertainty)
135     *uncertainty = network_time_uncertainty_;
136   return true;
137 }
138
139 // static
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());
148 }
149
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()));
156 }
157
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;
167 }
168