Adding Peter Thatcher to the owners file.
[chromium-blink-merge.git] / chromeos / dbus / metronome_client.cc
blobbe3a8b676db4baa4fa4bd79583b459e617aa52a6
1 // Copyright 2015 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 "chromeos/dbus/metronome_client.h"
7 #include "base/bind.h"
8 #include "base/rand_util.h"
9 #include "base/command_line.h"
10 #include "base/logging.h"
11 #include "base/memory/weak_ptr.h"
12 #include "base/observer_list.h"
13 #include "base/time/time.h"
14 #include "base/timer/timer.h"
15 #include "chromeos/chromeos_switches.h"
16 #include "dbus/bus.h"
17 #include "dbus/message.h"
18 #include "dbus/object_path.h"
19 #include "dbus/object_proxy.h"
21 // TODO(benchan): Move these DBus constants to system_api.
22 namespace metronome {
24 const char kMetronomeInterface[] = "org.chromium.Metronome";
25 const char kMetronomeServiceName[] = "org.chromium.Metronome";
26 const char kMetronomeServicePath[] = "/org/chromium/Metronome";
27 const char kTimestampUpdatedSignal[] = "TimestampUpdated";
29 } // namespace metronome
31 namespace chromeos {
33 namespace {
35 ////////////////////////////////////////////////////////////////////////////////
37 // The MetronomeClient implementation.
38 class MetronomeClientImpl : public MetronomeClient {
39 public:
40 MetronomeClientImpl()
41 : proxy_(nullptr), signal_connected_(false), weak_ptr_factory_(this) {}
43 ~MetronomeClientImpl() override {}
45 // MetronomeClient:
46 void AddObserver(Observer* observer) override;
47 void RemoveObserver(Observer* observer) override;
49 protected:
50 // DBusClient:
51 void Init(dbus::Bus* bus) override;
53 private:
54 // Handles TimestampUpdated signal and notifies |observers_|.
55 void OnTimestampUpdated(dbus::Signal* signal);
57 // Handles the result of signal connection setup.
58 void OnSignalConnected(const std::string& interface,
59 const std::string& signal,
60 bool succeeded);
62 dbus::ObjectProxy* proxy_;
64 // True when |proxy_| has been connected.
65 bool signal_connected_;
67 // List of observers interested in event notifications from us.
68 ObserverList<Observer> observers_;
70 // Note: This should remain the last member so it'll be destroyed and
71 // invalidate its weak pointers before any other members are destroyed.
72 base::WeakPtrFactory<MetronomeClientImpl> weak_ptr_factory_;
74 DISALLOW_COPY_AND_ASSIGN(MetronomeClientImpl);
77 void MetronomeClientImpl::AddObserver(Observer* observer) {
78 DCHECK(observer);
79 if (!signal_connected_) {
80 signal_connected_ = true;
81 proxy_->ConnectToSignal(metronome::kMetronomeInterface,
82 metronome::kTimestampUpdatedSignal,
83 base::Bind(&MetronomeClientImpl::OnTimestampUpdated,
84 weak_ptr_factory_.GetWeakPtr()),
85 base::Bind(&MetronomeClientImpl::OnSignalConnected,
86 weak_ptr_factory_.GetWeakPtr()));
88 observers_.AddObserver(observer);
91 void MetronomeClientImpl::RemoveObserver(Observer* observer) {
92 DCHECK(observer);
93 observers_.RemoveObserver(observer);
96 void MetronomeClientImpl::Init(dbus::Bus* bus) {
97 proxy_ =
98 bus->GetObjectProxy(metronome::kMetronomeServiceName,
99 dbus::ObjectPath(metronome::kMetronomeServicePath));
102 void MetronomeClientImpl::OnTimestampUpdated(dbus::Signal* signal) {
103 dbus::MessageReader reader(signal);
104 uint64 beacon_timestamp = 0;
105 uint64 local_timestamp = 0;
106 if (!reader.PopUint64(&beacon_timestamp) ||
107 !reader.PopUint64(&local_timestamp)) {
108 LOG(ERROR) << "Invalid signal: " << signal->ToString();
109 return;
111 FOR_EACH_OBSERVER(Observer, observers_,
112 OnTimestampUpdated(beacon_timestamp, local_timestamp));
115 void MetronomeClientImpl::OnSignalConnected(const std::string& interface,
116 const std::string& signal,
117 bool succeeded) {
118 LOG_IF(ERROR, !succeeded) << "Connect to " << interface << " " << signal
119 << " failed.";
122 ////////////////////////////////////////////////////////////////////////////////
124 // A fake implementation of MetronomeClient. It does not provide true
125 // synchronization and only exists to exercise the interfaces.
126 class MetronomeClientFakeImpl : public MetronomeClient {
127 public:
128 MetronomeClientFakeImpl()
129 : random_offset_(base::RandInt(-1000000, 1000000)) {}
131 ~MetronomeClientFakeImpl() override { beacon_timer_.Stop(); }
133 // MetronomeClient:
134 void AddObserver(Observer* observer) override {
135 DCHECK(observer);
136 observers_.AddObserver(observer);
139 void RemoveObserver(Observer* observer) override {
140 DCHECK(observer);
141 observers_.RemoveObserver(observer);
144 // DBusClient:
145 void Init(dbus::Bus* bus) override {
146 beacon_timer_.Start(FROM_HERE,
147 base::TimeDelta::FromMilliseconds(1000),
148 this,
149 &MetronomeClientFakeImpl::UpdateBeacon);
152 private:
153 void UpdateBeacon() {
154 base::Time now_time = base::Time::Now();
155 base::TimeTicks now_ticks = base::TimeTicks::Now();
156 uint64 fake_beacon_timestamp = now_time.ToInternalValue() +
157 base::RandInt(-1000, 1000);
158 uint64 fake_local_timestamp = now_ticks.ToInternalValue() + random_offset_ +
159 base::RandInt(-1000, 1000);
160 FOR_EACH_OBSERVER(
161 Observer, observers_,
162 OnTimestampUpdated(fake_beacon_timestamp, fake_local_timestamp));
165 int64 random_offset_;
166 base::RepeatingTimer<MetronomeClientFakeImpl> beacon_timer_;
168 // List of observers interested in event notifications from us.
169 ObserverList<Observer> observers_;
171 DISALLOW_COPY_AND_ASSIGN(MetronomeClientFakeImpl);
174 ////////////////////////////////////////////////////////////////////////////////
176 // A stub implementation of MetronomeClient. It allows unit tests to complete.
177 class MetronomeClientStubImpl : public MetronomeClient {
178 public:
179 MetronomeClientStubImpl() {}
180 ~MetronomeClientStubImpl() override {}
182 // MetronomeClient:
183 void AddObserver(Observer* observer) override {}
184 void RemoveObserver(Observer* observer) override {}
186 // DBusClient:
187 void Init(dbus::Bus* bus) override {}
189 private:
190 DISALLOW_COPY_AND_ASSIGN(MetronomeClientStubImpl);
193 } // namespace
195 ////////////////////////////////////////////////////////////////////////////////
197 MetronomeClient::MetronomeClient() {
200 MetronomeClient::~MetronomeClient() {
203 // static
204 MetronomeClient* MetronomeClient::Create(DBusClientImplementationType type) {
205 if (type == REAL_DBUS_CLIENT_IMPLEMENTATION)
206 return new MetronomeClientImpl();
207 DCHECK_EQ(STUB_DBUS_CLIENT_IMPLEMENTATION, type);
209 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
210 switches::kTestMetronomeTimer)) {
211 return new MetronomeClientFakeImpl();
213 return new MetronomeClientStubImpl();
216 } // namespace chromeos