root/chrome/browser/network_time/network_time_tracker.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. RegisterObserverOnIOThread
  2. RegisterObserverOnUIThread
  3. UpdateNetworkNotifierOnIOThread
  4. UpdateNetworkNotifier
  5. OnNetworkTimeUpdatedOnIOThread
  6. network_time
  7. received_network_time_
  8. Start
  9. InitFromSavedTime
  10. GetNetworkTime
  11. BuildNotifierUpdateCallback
  12. BuildObserverCallback
  13. OnNetworkTimeUpdate

// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#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"

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()));
}

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));
}

}  // namespace

NetworkTimeTracker::TimeMapping::TimeMapping(base::Time local_time,
                                             base::Time network_time)
    : local_time(local_time),
      network_time(network_time) {}

NetworkTimeTracker::NetworkTimeTracker()
    : weak_ptr_factory_(this),
      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) {
  DCHECK(thread_checker_.CalledOnValidThread());
  if (!network_time_.is_null() || saved.local_time.is_null() ||
      saved.network_time.is_null())
    return;

  base::Time local_time_now = base::Time::Now();
  if (local_time_now < saved.local_time) {
    DLOG(WARNING) << "Can't initialize because clock skew has changed.";
    return;
  }

  network_time_ = saved.network_time + (local_time_now - saved.local_time);
  network_time_ticks_ = base::TimeTicks::Now();
}

bool NetworkTimeTracker::GetNetworkTime(const base::TimeTicks& time_ticks,
                                        base::Time* network_time,
                                        base::TimeDelta* uncertainty) const {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK(network_time);
  if (network_time_.is_null())
    return false;
  DCHECK(!network_time_ticks_.is_null());
  *network_time = network_time_ + (time_ticks - network_time_ticks_);
  if (uncertainty)
    *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;
}


/* [<][>][^][v][top][bottom][index][help] */