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/leadership_daemon_manager_client.h"
8 #include "base/logging.h"
9 #include "base/memory/weak_ptr.h"
10 #include "base/message_loop/message_loop.h"
11 #include "base/observer_list.h"
13 #include "dbus/message.h"
14 #include "dbus/object_manager.h"
15 #include "dbus/object_proxy.h"
16 #include "dbus/values_util.h"
20 // TODO(benchan): Move these constants to system_api.
22 const char kLeaderdServiceName
[] = "org.chromium.leaderd";
23 const char kLeaderdObjectManagerServicePath
[] = "/org/chromium/leaderd";
24 const char kLeaderdManagerPath
[] = "/org/chromium/leaderd/Manager";
25 const char kManagerInterface
[] = "org.chromium.leaderd.Manager";
26 const char kGroupInterface
[] = "org.chromium.leaderd.Group";
27 const char kJoinGroupMethod
[] = "JoinGroup";
28 const char kLeaveGroupMethod
[] = "LeaveGroup";
29 const char kSetScoreMethod
[] = "SetScore";
30 const char kPokeLeaderMethod
[] = "PokeLeader";
31 const char kPingMethod
[] = "Ping";
32 const char kLeaderUUID
[] = "LeaderUUID";
33 const char kGroupMembers
[] = "GroupMembers";
34 } // namespace leaderd
38 // Since there is no property associated with Manager objects, an empty callback
40 void DoNothing(const std::string
& property_name
) {
43 // The LeadershipDaemonManagerClient implementation used in production.
44 class LeadershipDaemonManagerClientImpl
45 : public LeadershipDaemonManagerClient
,
46 public dbus::ObjectManager::Interface
{
48 LeadershipDaemonManagerClientImpl();
49 ~LeadershipDaemonManagerClientImpl() override
;
51 // LeadershipDaemonManagerClient overrides.
52 void AddObserver(Observer
* observer
) override
;
53 void RemoveObserver(Observer
* observer
) override
;
54 void JoinGroup(const std::string
& group
,
55 const base::DictionaryValue
& options
,
56 const ObjectPathDBusMethodCallback
& callback
) override
;
57 void LeaveGroup(const std::string
& object_path
,
58 const VoidDBusMethodCallback
& callback
) override
;
59 void SetScore(const std::string
& object_path
,
61 const VoidDBusMethodCallback
& callback
) override
;
62 void PokeLeader(const std::string
& object_path
,
63 const VoidDBusMethodCallback
& callback
) override
;
64 void Ping(const StringDBusMethodCallback
& callback
) override
;
65 const GroupProperties
* GetGroupProperties(
66 const dbus::ObjectPath
& object_path
) override
;
68 // DBusClient overrides.
69 void Init(dbus::Bus
* bus
) override
;
71 // dbus::ObjectManager::Interface overrides.
72 dbus::PropertySet
* CreateProperties(
73 dbus::ObjectProxy
* object_proxy
,
74 const dbus::ObjectPath
& object_path
,
75 const std::string
& interface_name
) override
;
76 void ObjectAdded(const dbus::ObjectPath
& object_path
,
77 const std::string
& interface_name
) override
;
78 void ObjectRemoved(const dbus::ObjectPath
& object_path
,
79 const std::string
& interface_name
) override
;
82 // Called by dbus::PropertySet when a property value is changed,
83 // either by result of a signal or response to a GetAll() or Get()
84 // call. Informs observers.
85 void OnGroupPropertyChanged(const dbus::ObjectPath
& object_path
,
86 const std::string
& property_name
);
88 void OnObjectPathDBusMethod(const ObjectPathDBusMethodCallback
& callback
,
89 dbus::Response
* response
);
90 void OnStringDBusMethod(const StringDBusMethodCallback
& callback
,
91 dbus::Response
* response
);
92 void OnVoidDBusMethod(const VoidDBusMethodCallback
& callback
,
93 dbus::Response
* response
);
95 // List of observers interested in event notifications from us.
96 ObserverList
<Observer
> observers_
;
97 dbus::ObjectManager
* object_manager_
;
98 base::WeakPtrFactory
<LeadershipDaemonManagerClientImpl
> weak_ptr_factory_
;
100 DISALLOW_COPY_AND_ASSIGN(LeadershipDaemonManagerClientImpl
);
103 LeadershipDaemonManagerClientImpl::LeadershipDaemonManagerClientImpl()
104 : object_manager_(nullptr), weak_ptr_factory_(this) {
107 LeadershipDaemonManagerClientImpl::~LeadershipDaemonManagerClientImpl() {
108 if (object_manager_
) {
109 object_manager_
->UnregisterInterface(leaderd::kManagerInterface
);
110 object_manager_
->UnregisterInterface(leaderd::kGroupInterface
);
114 void LeadershipDaemonManagerClientImpl::AddObserver(Observer
* observer
) {
116 observers_
.AddObserver(observer
);
119 void LeadershipDaemonManagerClientImpl::RemoveObserver(Observer
* observer
) {
121 observers_
.RemoveObserver(observer
);
124 void LeadershipDaemonManagerClientImpl::JoinGroup(
125 const std::string
& group
,
126 const base::DictionaryValue
& options
,
127 const ObjectPathDBusMethodCallback
& callback
) {
128 dbus::ObjectProxy
* object_proxy
= object_manager_
->GetObjectProxy(
129 dbus::ObjectPath(leaderd::kLeaderdManagerPath
));
131 base::MessageLoop::current()->PostTask(
133 base::Bind(&LeadershipDaemonManagerClientImpl::OnObjectPathDBusMethod
,
134 weak_ptr_factory_
.GetWeakPtr(), callback
, nullptr));
138 dbus::MethodCall
method_call(leaderd::kManagerInterface
,
139 leaderd::kJoinGroupMethod
);
140 dbus::MessageWriter
writer(&method_call
);
141 writer
.AppendString(group
);
142 dbus::AppendValueData(&writer
, options
);
143 object_proxy
->CallMethod(
144 &method_call
, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
145 base::Bind(&LeadershipDaemonManagerClientImpl::OnObjectPathDBusMethod
,
146 weak_ptr_factory_
.GetWeakPtr(), callback
));
149 void LeadershipDaemonManagerClientImpl::LeaveGroup(
150 const std::string
& object_path
,
151 const VoidDBusMethodCallback
& callback
) {
152 dbus::ObjectProxy
* object_proxy
=
153 object_manager_
->GetObjectProxy(dbus::ObjectPath(object_path
));
155 base::MessageLoop::current()->PostTask(
157 base::Bind(&LeadershipDaemonManagerClientImpl::OnVoidDBusMethod
,
158 weak_ptr_factory_
.GetWeakPtr(), callback
, nullptr));
162 dbus::MethodCall
method_call(leaderd::kGroupInterface
,
163 leaderd::kLeaveGroupMethod
);
164 dbus::MessageWriter
writer(&method_call
);
165 object_proxy
->CallMethod(
166 &method_call
, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
167 base::Bind(&LeadershipDaemonManagerClientImpl::OnVoidDBusMethod
,
168 weak_ptr_factory_
.GetWeakPtr(), callback
));
171 void LeadershipDaemonManagerClientImpl::SetScore(
172 const std::string
& object_path
,
174 const VoidDBusMethodCallback
& callback
) {
175 dbus::ObjectProxy
* object_proxy
=
176 object_manager_
->GetObjectProxy(dbus::ObjectPath(object_path
));
178 base::MessageLoop::current()->PostTask(
180 base::Bind(&LeadershipDaemonManagerClientImpl::OnVoidDBusMethod
,
181 weak_ptr_factory_
.GetWeakPtr(), callback
, nullptr));
185 dbus::MethodCall
method_call(leaderd::kGroupInterface
,
186 leaderd::kSetScoreMethod
);
187 dbus::MessageWriter
writer(&method_call
);
188 writer
.AppendInt32(score
);
189 object_proxy
->CallMethod(
190 &method_call
, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
191 base::Bind(&LeadershipDaemonManagerClientImpl::OnVoidDBusMethod
,
192 weak_ptr_factory_
.GetWeakPtr(), callback
));
195 void LeadershipDaemonManagerClientImpl::PokeLeader(
196 const std::string
& object_path
,
197 const VoidDBusMethodCallback
& callback
) {
198 dbus::ObjectProxy
* object_proxy
=
199 object_manager_
->GetObjectProxy(dbus::ObjectPath(object_path
));
201 base::MessageLoop::current()->PostTask(
203 base::Bind(&LeadershipDaemonManagerClientImpl::OnVoidDBusMethod
,
204 weak_ptr_factory_
.GetWeakPtr(), callback
, nullptr));
208 dbus::MethodCall
method_call(leaderd::kGroupInterface
,
209 leaderd::kPokeLeaderMethod
);
210 dbus::MessageWriter
writer(&method_call
);
211 object_proxy
->CallMethod(
212 &method_call
, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
213 base::Bind(&LeadershipDaemonManagerClientImpl::OnVoidDBusMethod
,
214 weak_ptr_factory_
.GetWeakPtr(), callback
));
217 void LeadershipDaemonManagerClientImpl::Ping(
218 const StringDBusMethodCallback
& callback
) {
219 dbus::ObjectProxy
* object_proxy
= object_manager_
->GetObjectProxy(
220 dbus::ObjectPath(leaderd::kLeaderdManagerPath
));
222 base::MessageLoop::current()->PostTask(
224 base::Bind(&LeadershipDaemonManagerClientImpl::OnStringDBusMethod
,
225 weak_ptr_factory_
.GetWeakPtr(), callback
, nullptr));
229 dbus::MethodCall
method_call(leaderd::kManagerInterface
,
230 leaderd::kPingMethod
);
231 dbus::MessageWriter
writer(&method_call
);
232 object_proxy
->CallMethod(
233 &method_call
, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
234 base::Bind(&LeadershipDaemonManagerClientImpl::OnStringDBusMethod
,
235 weak_ptr_factory_
.GetWeakPtr(), callback
));
238 const LeadershipDaemonManagerClient::GroupProperties
*
239 LeadershipDaemonManagerClientImpl::GetGroupProperties(
240 const dbus::ObjectPath
& object_path
) {
241 return static_cast<GroupProperties
*>(
242 object_manager_
->GetProperties(object_path
, leaderd::kGroupInterface
));
245 void LeadershipDaemonManagerClientImpl::Init(dbus::Bus
* bus
) {
246 object_manager_
= bus
->GetObjectManager(
247 leaderd::kLeaderdServiceName
,
248 dbus::ObjectPath(leaderd::kLeaderdObjectManagerServicePath
));
249 object_manager_
->RegisterInterface(leaderd::kManagerInterface
, this);
250 object_manager_
->RegisterInterface(leaderd::kGroupInterface
, this);
253 dbus::PropertySet
* LeadershipDaemonManagerClientImpl::CreateProperties(
254 dbus::ObjectProxy
* object_proxy
,
255 const dbus::ObjectPath
& object_path
,
256 const std::string
& interface_name
) {
257 dbus::PropertySet
* properties
= nullptr;
258 if (interface_name
== leaderd::kManagerInterface
) {
259 properties
= new dbus::PropertySet(object_proxy
, interface_name
,
260 base::Bind(&DoNothing
));
261 } else if (interface_name
== leaderd::kGroupInterface
) {
262 properties
= new GroupProperties(
263 object_proxy
, interface_name
,
264 base::Bind(&LeadershipDaemonManagerClientImpl::OnGroupPropertyChanged
,
265 weak_ptr_factory_
.GetWeakPtr(), object_path
));
267 NOTREACHED() << "Unhandled interface name " << interface_name
;
272 void LeadershipDaemonManagerClientImpl::ObjectAdded(
273 const dbus::ObjectPath
& object_path
,
274 const std::string
& interface_name
) {
275 if (interface_name
== leaderd::kManagerInterface
) {
276 FOR_EACH_OBSERVER(Observer
, observers_
, ManagerAdded());
277 } else if (interface_name
== leaderd::kGroupInterface
) {
278 FOR_EACH_OBSERVER(Observer
, observers_
, GroupAdded(object_path
));
280 NOTREACHED() << "Unhandled interface name " << interface_name
;
284 void LeadershipDaemonManagerClientImpl::ObjectRemoved(
285 const dbus::ObjectPath
& object_path
,
286 const std::string
& interface_name
) {
287 if (interface_name
== leaderd::kManagerInterface
) {
288 FOR_EACH_OBSERVER(Observer
, observers_
, ManagerRemoved());
289 } else if (interface_name
== leaderd::kGroupInterface
) {
290 FOR_EACH_OBSERVER(Observer
, observers_
, GroupRemoved(object_path
));
292 NOTREACHED() << "Unhandled interface name " << interface_name
;
296 void LeadershipDaemonManagerClientImpl::OnGroupPropertyChanged(
297 const dbus::ObjectPath
& object_path
,
298 const std::string
& property_name
) {
299 FOR_EACH_OBSERVER(Observer
, observers_
,
300 GroupPropertyChanged(object_path
, property_name
));
303 void LeadershipDaemonManagerClientImpl::OnObjectPathDBusMethod(
304 const ObjectPathDBusMethodCallback
& callback
,
305 dbus::Response
* response
) {
307 callback
.Run(DBUS_METHOD_CALL_FAILURE
, dbus::ObjectPath());
311 dbus::MessageReader
reader(response
);
312 dbus::ObjectPath result
;
313 if (!reader
.PopObjectPath(&result
)) {
314 callback
.Run(DBUS_METHOD_CALL_FAILURE
, result
);
318 callback
.Run(DBUS_METHOD_CALL_SUCCESS
, result
);
321 void LeadershipDaemonManagerClientImpl::OnStringDBusMethod(
322 const StringDBusMethodCallback
& callback
,
323 dbus::Response
* response
) {
325 callback
.Run(DBUS_METHOD_CALL_FAILURE
, std::string());
329 dbus::MessageReader
reader(response
);
331 if (!reader
.PopString(&result
)) {
332 callback
.Run(DBUS_METHOD_CALL_FAILURE
, std::string());
336 callback
.Run(DBUS_METHOD_CALL_SUCCESS
, result
);
339 void LeadershipDaemonManagerClientImpl::OnVoidDBusMethod(
340 const VoidDBusMethodCallback
& callback
,
341 dbus::Response
* response
) {
342 callback
.Run(response
? DBUS_METHOD_CALL_SUCCESS
: DBUS_METHOD_CALL_FAILURE
);
347 LeadershipDaemonManagerClient::GroupProperties::GroupProperties(
348 dbus::ObjectProxy
* object_proxy
,
349 const std::string
& interface_name
,
350 const PropertyChangedCallback
& callback
)
351 : dbus::PropertySet(object_proxy
, interface_name
, callback
) {
352 RegisterProperty(leaderd::kLeaderUUID
, &leader_uuid_
);
353 RegisterProperty(leaderd::kGroupMembers
, &group_members_
);
356 LeadershipDaemonManagerClient::GroupProperties::~GroupProperties() {
359 LeadershipDaemonManagerClient::Observer::~Observer() {
362 void LeadershipDaemonManagerClient::Observer::ManagerAdded() {
365 void LeadershipDaemonManagerClient::Observer::ManagerRemoved() {
368 void LeadershipDaemonManagerClient::Observer::GroupAdded(
369 const dbus::ObjectPath
& object_path
) {
372 void LeadershipDaemonManagerClient::Observer::GroupRemoved(
373 const dbus::ObjectPath
& object_path
) {
376 void LeadershipDaemonManagerClient::Observer::GroupPropertyChanged(
377 const dbus::ObjectPath
& object_path
,
378 const std::string
& property_name
) {
381 LeadershipDaemonManagerClient::LeadershipDaemonManagerClient() {
384 LeadershipDaemonManagerClient::~LeadershipDaemonManagerClient() {
388 LeadershipDaemonManagerClient
* LeadershipDaemonManagerClient::Create() {
389 return new LeadershipDaemonManagerClientImpl();
392 } // namespace chromeos