Separate Simple Backend creation from initialization.
[chromium-blink-merge.git] / chromeos / dbus / bluetooth_device_client.cc
blob00a0f2e1418ec5bd4028c508ccec86551aaa60f9
1 // Copyright (c) 2012 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/bluetooth_device_client.h"
7 #include <map>
8 #include <utility>
10 #include "base/bind.h"
11 #include "base/logging.h"
12 #include "base/stl_util.h"
13 #include "chromeos/dbus/bluetooth_adapter_client.h"
14 #include "chromeos/dbus/bluetooth_property.h"
15 #include "dbus/bus.h"
16 #include "dbus/message.h"
17 #include "dbus/object_path.h"
18 #include "dbus/object_proxy.h"
19 #include "third_party/cros_system_api/dbus/service_constants.h"
21 namespace chromeos {
23 BluetoothDeviceClient::Properties::Properties(
24 dbus::ObjectProxy* object_proxy,
25 const PropertyChangedCallback& callback)
26 : BluetoothPropertySet(object_proxy,
27 bluetooth_device::kBluetoothDeviceInterface,
28 callback) {
29 RegisterProperty(bluetooth_device::kAddressProperty, &address);
30 RegisterProperty(bluetooth_device::kNameProperty, &name);
31 RegisterProperty(bluetooth_device::kVendorProperty, &vendor);
32 RegisterProperty(bluetooth_device::kProductProperty, &product);
33 RegisterProperty(bluetooth_device::kVersionProperty, &version);
34 RegisterProperty(bluetooth_device::kIconProperty, &icon);
35 RegisterProperty(bluetooth_device::kClassProperty, &bluetooth_class);
36 RegisterProperty(bluetooth_device::kUUIDsProperty, &uuids);
37 RegisterProperty(bluetooth_device::kServicesProperty, &services);
38 RegisterProperty(bluetooth_device::kPairedProperty, &paired);
39 RegisterProperty(bluetooth_device::kConnectedProperty, &connected);
40 RegisterProperty(bluetooth_device::kTrustedProperty, &trusted);
41 RegisterProperty(bluetooth_device::kBlockedProperty, &blocked);
42 RegisterProperty(bluetooth_device::kAliasProperty, &alias);
43 RegisterProperty(bluetooth_device::kNodesProperty, &nodes);
44 RegisterProperty(bluetooth_device::kAdapterProperty, &adapter);
45 RegisterProperty(bluetooth_device::kLegacyPairingProperty, &legacy_pairing);
48 BluetoothDeviceClient::Properties::~Properties() {
52 // The BluetoothDeviceClient implementation used in production.
53 class BluetoothDeviceClientImpl: public BluetoothDeviceClient,
54 private BluetoothAdapterClient::Observer {
55 public:
56 BluetoothDeviceClientImpl(dbus::Bus* bus,
57 BluetoothAdapterClient* adapter_client)
58 : bus_(bus),
59 weak_ptr_factory_(this) {
60 VLOG(1) << "Creating BluetoothDeviceClientImpl";
62 DCHECK(adapter_client);
63 adapter_client->AddObserver(this);
66 virtual ~BluetoothDeviceClientImpl() {
67 // Clean up Properties structures
68 for (ObjectMap::iterator iter = object_map_.begin();
69 iter != object_map_.end(); ++iter) {
70 Object object = iter->second;
71 Properties* properties = object.second;
72 delete properties;
76 // BluetoothDeviceClient override.
77 virtual void AddObserver(BluetoothDeviceClient::Observer* observer)
78 OVERRIDE {
79 DCHECK(observer);
80 observers_.AddObserver(observer);
83 // BluetoothDeviceClient override.
84 virtual void RemoveObserver(BluetoothDeviceClient::Observer* observer)
85 OVERRIDE {
86 DCHECK(observer);
87 observers_.RemoveObserver(observer);
90 // BluetoothDeviceClient override.
91 virtual Properties* GetProperties(const dbus::ObjectPath& object_path)
92 OVERRIDE {
93 return GetObject(object_path).second;
96 // BluetoothDeviceClient override.
97 virtual void DiscoverServices(const dbus::ObjectPath& object_path,
98 const std::string& pattern,
99 const ServicesCallback& callback) OVERRIDE {
100 dbus::MethodCall method_call(
101 bluetooth_device::kBluetoothDeviceInterface,
102 bluetooth_device::kDiscoverServices);
104 dbus::MessageWriter writer(&method_call);
105 writer.AppendString(pattern);
107 dbus::ObjectProxy* object_proxy = GetObjectProxy(object_path);
109 object_proxy->CallMethod(
110 &method_call,
111 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
112 base::Bind(&BluetoothDeviceClientImpl::OnDiscoverServices,
113 weak_ptr_factory_.GetWeakPtr(), object_path, callback));
116 // BluetoothDeviceClient override.
117 virtual void CancelDiscovery(const dbus::ObjectPath& object_path,
118 const DeviceCallback& callback) OVERRIDE {
119 dbus::MethodCall method_call(
120 bluetooth_device::kBluetoothDeviceInterface,
121 bluetooth_device::kCancelDiscovery);
123 dbus::ObjectProxy* object_proxy = GetObjectProxy(object_path);
125 object_proxy->CallMethod(
126 &method_call,
127 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
128 base::Bind(&BluetoothDeviceClientImpl::OnCancelDiscovery,
129 weak_ptr_factory_.GetWeakPtr(), object_path, callback));
132 // BluetoothDeviceClient override.
133 virtual void Disconnect(const dbus::ObjectPath& object_path,
134 const DeviceCallback& callback) OVERRIDE {
135 dbus::MethodCall method_call(
136 bluetooth_device::kBluetoothDeviceInterface,
137 bluetooth_device::kDisconnect);
139 dbus::ObjectProxy* object_proxy = GetObjectProxy(object_path);
141 object_proxy->CallMethod(
142 &method_call,
143 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
144 base::Bind(&BluetoothDeviceClientImpl::OnDisconnect,
145 weak_ptr_factory_.GetWeakPtr(), object_path, callback));
148 // BluetoothDeviceClient override.
149 virtual void CreateNode(const dbus::ObjectPath& object_path,
150 const std::string& uuid,
151 const NodeCallback& callback) OVERRIDE {
152 dbus::MethodCall method_call(
153 bluetooth_device::kBluetoothDeviceInterface,
154 bluetooth_device::kCreateNode);
156 dbus::MessageWriter writer(&method_call);
157 writer.AppendString(uuid);
159 dbus::ObjectProxy* object_proxy = GetObjectProxy(object_path);
161 object_proxy->CallMethod(
162 &method_call,
163 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
164 base::Bind(&BluetoothDeviceClientImpl::OnCreateNode,
165 weak_ptr_factory_.GetWeakPtr(), object_path, callback));
168 // BluetoothDeviceClient override.
169 virtual void RemoveNode(const dbus::ObjectPath& object_path,
170 const dbus::ObjectPath& node_path,
171 const DeviceCallback& callback) OVERRIDE {
172 dbus::MethodCall method_call(
173 bluetooth_device::kBluetoothDeviceInterface,
174 bluetooth_device::kRemoveNode);
176 dbus::MessageWriter writer(&method_call);
177 writer.AppendObjectPath(node_path);
179 dbus::ObjectProxy* object_proxy = GetObjectProxy(object_path);
181 object_proxy->CallMethod(
182 &method_call,
183 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
184 base::Bind(&BluetoothDeviceClientImpl::OnRemoveNode,
185 weak_ptr_factory_.GetWeakPtr(), object_path, callback));
188 private:
189 // We maintain a collection of dbus object proxies and properties structures
190 // for each device.
191 typedef std::pair<dbus::ObjectProxy*, Properties*> Object;
192 typedef std::map<const dbus::ObjectPath, Object> ObjectMap;
193 ObjectMap object_map_;
195 // BluetoothAdapterClient::Observer override.
196 virtual void DeviceCreated(const dbus::ObjectPath& adapter_path,
197 const dbus::ObjectPath& object_path) OVERRIDE {
200 // BluetoothAdapterClient::Observer override.
201 virtual void DeviceRemoved(const dbus::ObjectPath& adapter_path,
202 const dbus::ObjectPath& object_path) OVERRIDE {
203 RemoveObject(object_path);
206 // Ensures that we have an object proxy and properties structure for
207 // a device with object path |object_path|, creating it if not and
208 // storing it in our |object_map_| map.
209 Object GetObject(const dbus::ObjectPath& object_path) {
210 ObjectMap::iterator iter = object_map_.find(object_path);
211 if (iter != object_map_.end())
212 return iter->second;
214 // Create the object proxy.
215 DCHECK(bus_);
216 dbus::ObjectProxy* object_proxy = bus_->GetObjectProxy(
217 bluetooth_device::kBluetoothDeviceServiceName, object_path);
219 object_proxy->ConnectToSignal(
220 bluetooth_device::kBluetoothDeviceInterface,
221 bluetooth_device::kDisconnectRequestedSignal,
222 base::Bind(&BluetoothDeviceClientImpl::DisconnectRequestedReceived,
223 weak_ptr_factory_.GetWeakPtr(), object_path),
224 base::Bind(&BluetoothDeviceClientImpl::DisconnectRequestedConnected,
225 weak_ptr_factory_.GetWeakPtr(), object_path));
227 object_proxy->ConnectToSignal(
228 bluetooth_device::kBluetoothDeviceInterface,
229 bluetooth_device::kNodeCreatedSignal,
230 base::Bind(&BluetoothDeviceClientImpl::NodeCreatedReceived,
231 weak_ptr_factory_.GetWeakPtr(), object_path),
232 base::Bind(&BluetoothDeviceClientImpl::NodeCreatedConnected,
233 weak_ptr_factory_.GetWeakPtr(), object_path));
235 object_proxy->ConnectToSignal(
236 bluetooth_device::kBluetoothDeviceInterface,
237 bluetooth_device::kNodeRemovedSignal,
238 base::Bind(&BluetoothDeviceClientImpl::NodeRemovedReceived,
239 weak_ptr_factory_.GetWeakPtr(), object_path),
240 base::Bind(&BluetoothDeviceClientImpl::NodeRemovedConnected,
241 weak_ptr_factory_.GetWeakPtr(), object_path));
243 // Create the properties structure.
244 Properties* properties = new Properties(
245 object_proxy,
246 base::Bind(&BluetoothDeviceClientImpl::OnPropertyChanged,
247 weak_ptr_factory_.GetWeakPtr(), object_path));
249 properties->ConnectSignals();
250 properties->GetAll();
252 Object object = std::make_pair(object_proxy, properties);
253 object_map_[object_path] = object;
254 return object;
257 // Removes the dbus object proxy and properties for the device with
258 // dbus object path |object_path| from our |object_map_| map.
259 void RemoveObject(const dbus::ObjectPath& object_path) {
260 ObjectMap::iterator iter = object_map_.find(object_path);
261 if (iter != object_map_.end()) {
262 // Clean up the Properties structure.
263 Object object = iter->second;
264 Properties* properties = object.second;
265 delete properties;
267 object_map_.erase(iter);
271 // Returns a pointer to the object proxy for |object_path|, creating
272 // it if necessary.
273 dbus::ObjectProxy* GetObjectProxy(const dbus::ObjectPath& object_path) {
274 return GetObject(object_path).first;
277 // Called by BluetoothPropertySet when a property value is changed,
278 // either by result of a signal or response to a GetAll() or Get()
279 // call. Informs observers.
280 void OnPropertyChanged(const dbus::ObjectPath& object_path,
281 const std::string& property_name) {
282 FOR_EACH_OBSERVER(BluetoothDeviceClient::Observer, observers_,
283 DevicePropertyChanged(object_path, property_name));
286 // Called by dbus:: when a DisconnectRequested signal is received.
287 void DisconnectRequestedReceived(const dbus::ObjectPath& object_path,
288 dbus::Signal* signal) {
289 DCHECK(signal);
291 VLOG(1) << object_path.value() << ": Disconnect requested.";
292 FOR_EACH_OBSERVER(BluetoothDeviceClient::Observer, observers_,
293 DisconnectRequested(object_path));
296 // Called by dbus:: when the DisconnectRequested signal is initially
297 // connected.
298 void DisconnectRequestedConnected(const dbus::ObjectPath& object_path,
299 const std::string& interface_name,
300 const std::string& signal_name,
301 bool success) {
302 LOG_IF(WARNING, !success) << object_path.value()
303 << ": Failed to connect to "
304 "DisconnectRequested signal.";
307 // Called by dbus:: when a NodeCreated signal is received.
308 void NodeCreatedReceived(const dbus::ObjectPath& object_path,
309 dbus::Signal* signal) {
310 DCHECK(signal);
311 dbus::MessageReader reader(signal);
312 dbus::ObjectPath node_path;
313 if (!reader.PopObjectPath(&node_path)) {
314 LOG(WARNING) << object_path.value()
315 << ": NodeCreated signal has incorrect parameters: "
316 << signal->ToString();
317 return;
320 VLOG(1) << object_path.value() << ": Node created: "
321 << node_path.value();
322 FOR_EACH_OBSERVER(BluetoothDeviceClient::Observer, observers_,
323 NodeCreated(object_path, node_path));
326 // Called by dbus:: when the NodeCreated signal is initially connected.
327 void NodeCreatedConnected(const dbus::ObjectPath& object_path,
328 const std::string& interface_name,
329 const std::string& signal_name,
330 bool success) {
331 LOG_IF(WARNING, !success) << object_path.value()
332 << ": Failed to connect to NodeCreated signal.";
335 // Called by dbus:: when a NodeRemoved signal is received.
336 void NodeRemovedReceived(const dbus::ObjectPath& object_path,
337 dbus::Signal* signal) {
338 DCHECK(signal);
339 dbus::MessageReader reader(signal);
340 dbus::ObjectPath node_path;
341 if (!reader.PopObjectPath(&node_path)) {
342 LOG(WARNING) << object_path.value()
343 << ": NodeRemoved signal has incorrect parameters: "
344 << signal->ToString();
345 return;
348 VLOG(1) << object_path.value() << ": Node removed: "
349 << node_path.value();
350 FOR_EACH_OBSERVER(BluetoothDeviceClient::Observer, observers_,
351 NodeRemoved(object_path, node_path));
354 // Called by dbus:: when the NodeRemoved signal is initially connected.
355 void NodeRemovedConnected(const dbus::ObjectPath& object_path,
356 const std::string& interface_name,
357 const std::string& signal_name,
358 bool success) {
359 LOG_IF(WARNING, !success) << object_path.value()
360 << ": Failed to connect to NodeRemoved signal.";
363 // Called when a response for DiscoverServices() is received.
364 void OnDiscoverServices(const dbus::ObjectPath& object_path,
365 const ServicesCallback& callback,
366 dbus::Response* response) {
367 // Parse response.
368 bool success = false;
369 ServiceMap services;
370 if (response != NULL) {
371 dbus::MessageReader reader(response);
373 dbus::MessageReader array_reader(NULL);
374 if (!reader.PopArray(&array_reader)) {
375 LOG(WARNING) << "DiscoverServices response has incorrect parameters: "
376 << response->ToString();
377 } else {
378 while (array_reader.HasMoreData()) {
379 dbus::MessageReader dict_entry_reader(NULL);
380 uint32 key = 0;
381 std::string value;
382 if (!array_reader.PopDictEntry(&dict_entry_reader)
383 || !dict_entry_reader.PopUint32(&key)
384 || !dict_entry_reader.PopString(&value)) {
385 LOG(WARNING) << "DiscoverServices response has "
386 "incorrect parameters: " << response->ToString();
387 } else {
388 services[key] = value;
392 success = true;
394 } else {
395 LOG(WARNING) << "Failed to discover services.";
398 // Notify client.
399 callback.Run(object_path, services, success);
402 // Called when a response for CancelDiscovery() is received.
403 void OnCancelDiscovery(const dbus::ObjectPath& object_path,
404 const DeviceCallback& callback,
405 dbus::Response* response) {
406 LOG_IF(WARNING, !response) << object_path.value()
407 << ": OnCancelDiscovery: failed.";
408 callback.Run(object_path, response);
411 // Called when a response for Disconnect() is received.
412 void OnDisconnect(const dbus::ObjectPath& object_path,
413 const DeviceCallback& callback,
414 dbus::Response* response) {
415 LOG_IF(WARNING, !response) << object_path.value()
416 << ": OnDisconnect: failed.";
417 callback.Run(object_path, response);
420 // Called when a response for CreateNode() is received.
421 void OnCreateNode(const dbus::ObjectPath& object_path,
422 const NodeCallback& callback,
423 dbus::Response* response) {
424 // Parse response.
425 bool success = false;
426 dbus::ObjectPath node_path;
427 if (response != NULL) {
428 dbus::MessageReader reader(response);
429 if (!reader.PopObjectPath(&node_path)) {
430 LOG(WARNING) << "CreateNode response has incorrect parameters: "
431 << response->ToString();
432 } else {
433 success = true;
435 } else {
436 LOG(WARNING) << "Failed to create node.";
439 // Notify client.
440 callback.Run(node_path, success);
443 // Called when a response for RemoveNode() is received.
444 void OnRemoveNode(const dbus::ObjectPath& object_path,
445 const DeviceCallback& callback,
446 dbus::Response* response) {
447 LOG_IF(WARNING, !response) << object_path.value()
448 << ": OnRemoveNode: failed.";
449 callback.Run(object_path, response);
452 dbus::Bus* bus_;
454 // List of observers interested in event notifications from us.
455 ObserverList<BluetoothDeviceClient::Observer> observers_;
457 // Weak pointer factory for generating 'this' pointers that might live longer
458 // than we do.
459 // Note: This should remain the last member so it'll be destroyed and
460 // invalidate its weak pointers before any other members are destroyed.
461 base::WeakPtrFactory<BluetoothDeviceClientImpl> weak_ptr_factory_;
463 DISALLOW_COPY_AND_ASSIGN(BluetoothDeviceClientImpl);
466 // The BluetoothDeviceClient implementation used on Linux desktop, which does
467 // nothing.
468 class BluetoothDeviceClientStubImpl : public BluetoothDeviceClient {
469 public:
470 struct Properties : public BluetoothDeviceClient::Properties {
471 explicit Properties(const PropertyChangedCallback& callback)
472 : BluetoothDeviceClient::Properties(NULL, callback) {
475 virtual ~Properties() {
478 virtual void Get(dbus::PropertyBase* property,
479 dbus::PropertySet::GetCallback callback) OVERRIDE {
480 VLOG(1) << "Get " << property->name();
481 callback.Run(false);
484 virtual void GetAll() OVERRIDE {
485 VLOG(1) << "GetAll";
488 virtual void Set(dbus::PropertyBase *property,
489 dbus::PropertySet::SetCallback callback) OVERRIDE {
490 VLOG(1) << "Set " << property->name();
491 callback.Run(false);
495 BluetoothDeviceClientStubImpl() {
496 dbus::ObjectPath dev0("/fake/hci0/dev0");
498 Properties* properties = new Properties(base::Bind(
499 &BluetoothDeviceClientStubImpl::OnPropertyChanged,
500 base::Unretained(this),
501 dev0));
502 properties->address.ReplaceValue("00:11:22:33:44:55");
503 properties->name.ReplaceValue("Fake Device");
504 properties->paired.ReplaceValue(true);
505 properties->trusted.ReplaceValue(true);
507 properties_map_[dev0] = properties;
510 virtual ~BluetoothDeviceClientStubImpl() {
511 // Clean up Properties structures
512 STLDeleteValues(&properties_map_);
515 // BluetoothDeviceClient override.
516 virtual void AddObserver(Observer* observer) OVERRIDE {
517 observers_.AddObserver(observer);
520 // BluetoothDeviceClient override.
521 virtual void RemoveObserver(Observer* observer) OVERRIDE {
522 observers_.RemoveObserver(observer);
525 // BluetoothDeviceClient override.
526 virtual Properties* GetProperties(const dbus::ObjectPath& object_path)
527 OVERRIDE {
528 VLOG(1) << "GetProperties: " << object_path.value();
529 PropertiesMap::iterator iter = properties_map_.find(object_path);
530 if (iter != properties_map_.end())
531 return iter->second;
532 return NULL;
535 // BluetoothDeviceClient override.
536 virtual void DiscoverServices(const dbus::ObjectPath& object_path,
537 const std::string& pattern,
538 const ServicesCallback& callback) OVERRIDE {
539 VLOG(1) << "DiscoverServices: " << object_path.value() << " " << pattern;
541 ServiceMap services;
542 callback.Run(object_path, services, false);
545 // BluetoothDeviceClient override.
546 virtual void CancelDiscovery(const dbus::ObjectPath& object_path,
547 const DeviceCallback& callback) OVERRIDE {
548 VLOG(1) << "CancelDiscovery: " << object_path.value();
549 callback.Run(object_path, false);
552 // BluetoothDeviceClient override.
553 virtual void Disconnect(const dbus::ObjectPath& object_path,
554 const DeviceCallback& callback) OVERRIDE {
555 VLOG(1) << "Disconnect: " << object_path.value();
556 callback.Run(object_path, false);
559 // BluetoothDeviceClient override.
560 virtual void CreateNode(const dbus::ObjectPath& object_path,
561 const std::string& uuid,
562 const NodeCallback& callback) OVERRIDE {
563 VLOG(1) << "CreateNode: " << object_path.value() << " " << uuid;
564 callback.Run(dbus::ObjectPath(), false);
567 // BluetoothDeviceClient override.
568 virtual void RemoveNode(const dbus::ObjectPath& object_path,
569 const dbus::ObjectPath& node_path,
570 const DeviceCallback& callback) OVERRIDE {
571 VLOG(1) << "RemoveNode: " << object_path.value()
572 << " " << node_path.value();
573 callback.Run(object_path, false);
576 private:
577 void OnPropertyChanged(dbus::ObjectPath object_path,
578 const std::string& property_name) {
579 FOR_EACH_OBSERVER(BluetoothDeviceClient::Observer, observers_,
580 DevicePropertyChanged(object_path, property_name));
583 // List of observers interested in event notifications from us.
584 ObserverList<Observer> observers_;
586 // Static properties we typedef.
587 typedef std::map<const dbus::ObjectPath, Properties *> PropertiesMap;
588 PropertiesMap properties_map_;
591 BluetoothDeviceClient::BluetoothDeviceClient() {
594 BluetoothDeviceClient::~BluetoothDeviceClient() {
597 BluetoothDeviceClient* BluetoothDeviceClient::Create(
598 DBusClientImplementationType type,
599 dbus::Bus* bus,
600 BluetoothAdapterClient* adapter_client) {
601 if (type == REAL_DBUS_CLIENT_IMPLEMENTATION)
602 return new BluetoothDeviceClientImpl(bus, adapter_client);
603 DCHECK_EQ(STUB_DBUS_CLIENT_IMPLEMENTATION, type);
604 return new BluetoothDeviceClientStubImpl();
607 } // namespace chromeos