Index: chrome/browser/network_time/network_time_tracker.cc |
diff --git a/chrome/browser/network_time/network_time_tracker.cc b/chrome/browser/network_time/network_time_tracker.cc |
index b97005a8f2b3388c910b781b3fb8c3efb15f05fa..885c9722f13b1ab7976cb95289a67c8c2ac50025 100644 |
--- a/chrome/browser/network_time/network_time_tracker.cc |
+++ b/chrome/browser/network_time/network_time_tracker.cc |
@@ -4,83 +4,23 @@ |
#include "chrome/browser/network_time/network_time_tracker.h" |
-#include "base/sequenced_task_runner.h" |
-#include "chrome/browser/browser_process.h" |
-#include "chrome/browser/io_thread.h" |
+#include "base/basictypes.h" |
+#include "base/i18n/time_formatting.h" |
+#include "base/logging.h" |
+#include "base/strings/utf_string_conversions.h" |
+#include "base/time/tick_clock.h" |
namespace { |
-// Helper functions for interacting with the NetworkTimeNotifier. |
-// Registration happens as follows (assuming tracker lives on thread N): |
-// | Thread N | | UI thread| | IO Thread | |
-// Start |
-// RegisterObserverOnUIThread |
-// RegisterObserverOnIOThread |
-// NetworkTimeNotifier::AddObserver |
-// after which updates to the notifier and the subsequent observer calls |
-// happen as follows (assuming the network time update comes from the same |
-// thread): |
-// | Thread N | | UI thread| | IO Thread | |
-// UpdateNetworkNotifier |
-// UpdateNetworkNotifierOnIOThread |
-// NetworkTimeNotifier::UpdateNetworkTime |
-// OnNetworkTimeUpdatedOnIOThread |
-// OnNetworkTimeUpdated |
-void RegisterObserverOnIOThread( |
- IOThread* io_thread, |
- const net::NetworkTimeNotifier::ObserverCallback& observer_callback) { |
- DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); |
- io_thread->globals()->network_time_notifier->AddObserver(observer_callback); |
-} |
- |
-void RegisterObserverOnUIThread( |
- const net::NetworkTimeNotifier::ObserverCallback& observer_callback) { |
- DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
- content::BrowserThread::PostTask( |
- content::BrowserThread::IO, FROM_HERE, |
- base::Bind(&RegisterObserverOnIOThread, |
- g_browser_process->io_thread(), |
- observer_callback)); |
-} |
- |
-void UpdateNetworkNotifierOnIOThread(IOThread* io_thread, |
- const base::Time& network_time, |
- const base::TimeDelta& resolution, |
- const base::TimeDelta& latency, |
- const base::TimeTicks& post_time) { |
- DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); |
- io_thread->globals()->network_time_notifier->UpdateNetworkTime( |
- network_time, resolution, latency, post_time); |
-} |
- |
-void UpdateNetworkNotifier(IOThread* io_thread, |
- const base::Time& network_time, |
- const base::TimeDelta& resolution, |
- const base::TimeDelta& latency) { |
- content::BrowserThread::PostTask( |
- content::BrowserThread::IO, |
- FROM_HERE, |
- base::Bind(&UpdateNetworkNotifierOnIOThread, |
- io_thread, |
- network_time, |
- resolution, |
- latency, |
- base::TimeTicks::Now())); |
-} |
+// Clock resolution is platform dependent. |
+#if defined(OS_WIN) |
+const int64 kTicksResolutionMs = base::Time::kMinLowResolutionThresholdMs; |
+#else |
+const int64 kTicksResolutionMs = 1; // Assume 1ms for non-windows platforms. |
+#endif |
-void OnNetworkTimeUpdatedOnIOThread( |
- const scoped_refptr<base::SequencedTaskRunner>& task_runner, |
- const net::NetworkTimeNotifier::ObserverCallback& observer_callback, |
- const base::Time& network_time, |
- const base::TimeTicks& network_time_ticks, |
- const base::TimeDelta& network_time_uncertainty) { |
- task_runner->PostTask( |
- FROM_HERE, |
- base::Bind(observer_callback, |
- network_time, |
- network_time_ticks, |
- network_time_uncertainty)); |
-} |
+// Number of time measurements performed in a given network time calculation. |
+const int kNumTimeMeasurements = 5; |
} // namespace |
@@ -89,21 +29,13 @@ NetworkTimeTracker::TimeMapping::TimeMapping(base::Time local_time, |
: local_time(local_time), |
network_time(network_time) {} |
-NetworkTimeTracker::NetworkTimeTracker() |
- : weak_ptr_factory_(this), |
+NetworkTimeTracker::NetworkTimeTracker(scoped_ptr<base::TickClock> tick_clock) |
+ : tick_clock_(tick_clock.Pass()), |
received_network_time_(false) { |
} |
NetworkTimeTracker::~NetworkTimeTracker() { |
-} |
- |
-void NetworkTimeTracker::Start() { |
DCHECK(thread_checker_.CalledOnValidThread()); |
- content::BrowserThread::PostTask( |
- content::BrowserThread::UI, |
- FROM_HERE, |
- base::Bind(&RegisterObserverOnUIThread, |
- BuildObserverCallback())); |
} |
void NetworkTimeTracker::InitFromSavedTime(const TimeMapping& saved) { |
@@ -122,7 +54,40 @@ void NetworkTimeTracker::InitFromSavedTime(const TimeMapping& saved) { |
network_time_ticks_ = base::TimeTicks::Now(); |
} |
-bool NetworkTimeTracker::GetNetworkTime(const base::TimeTicks& time_ticks, |
+void NetworkTimeTracker::UpdateNetworkTime(base::Time network_time, |
+ base::TimeDelta resolution, |
+ base::TimeDelta latency, |
+ base::TimeTicks post_time) { |
+ DCHECK(thread_checker_.CalledOnValidThread()); |
+ DVLOG(1) << "Network time updating to " |
+ << base::UTF16ToUTF8( |
+ base::TimeFormatFriendlyDateAndTime(network_time)); |
+ // Update network time on every request to limit dependency on ticks lag. |
+ // TODO(mad): Find a heuristic to avoid augmenting the |
+ // network_time_uncertainty_ too much by a particularly long latency. |
+ // Maybe only update when the the new time either improves in accuracy or |
+ // drifts too far from |network_time_|. |
+ network_time_ = network_time; |
+ |
+ // Calculate the delay since the network time was received. |
+ base::TimeTicks now = tick_clock_->NowTicks(); |
+ base::TimeDelta task_delay = now - post_time; |
+ // Estimate that the time was set midway through the latency time. |
+ network_time_ticks_ = now - task_delay - latency / 2; |
+ |
+ // Can't assume a better time than the resolution of the given time |
+ // and 5 ticks measurements are involved, each with their own uncertainty. |
+ // 1 & 2 are the ones used to compute the latency, 3 is the Now() from when |
+ // this task was posted, 4 is the Now() above and 5 will be the Now() used in |
+ // GetNetworkTime(). |
+ network_time_uncertainty_ = |
+ resolution + latency + kNumTimeMeasurements * |
+ base::TimeDelta::FromMilliseconds(kTicksResolutionMs); |
+ |
+ received_network_time_ = true; |
+} |
+ |
+bool NetworkTimeTracker::GetNetworkTime(base::TimeTicks time_ticks, |
base::Time* network_time, |
base::TimeDelta* uncertainty) const { |
DCHECK(thread_checker_.CalledOnValidThread()); |
@@ -135,34 +100,3 @@ bool NetworkTimeTracker::GetNetworkTime(const base::TimeTicks& time_ticks, |
*uncertainty = network_time_uncertainty_; |
return true; |
} |
- |
-// static |
-// Note: UpdateNetworkNotifier is exposed via callback because getting the IO |
-// thread pointer must be done on the UI thread, while components that provide |
-// network time updates may live on other threads. |
-NetworkTimeTracker::UpdateCallback |
-NetworkTimeTracker::BuildNotifierUpdateCallback() { |
- DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
- return base::Bind(&UpdateNetworkNotifier, |
- g_browser_process->io_thread()); |
-} |
- |
-net::NetworkTimeNotifier::ObserverCallback |
-NetworkTimeTracker::BuildObserverCallback() { |
- return base::Bind(&OnNetworkTimeUpdatedOnIOThread, |
- base::MessageLoop::current()->message_loop_proxy(), |
- base::Bind(&NetworkTimeTracker::OnNetworkTimeUpdate, |
- weak_ptr_factory_.GetWeakPtr())); |
-} |
- |
-void NetworkTimeTracker::OnNetworkTimeUpdate( |
- const base::Time& network_time, |
- const base::TimeTicks& network_time_ticks, |
- const base::TimeDelta& network_time_uncertainty) { |
- DCHECK(thread_checker_.CalledOnValidThread()); |
- network_time_ = network_time; |
- network_time_ticks_ = network_time_ticks; |
- network_time_uncertainty_ = network_time_uncertainty; |
- received_network_time_ = true; |
-} |
- |