OLD | NEW |
| (Empty) |
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. | |
4 | |
5 #include "chrome/browser/chromeos/dbus/bluetooth_device_client.h" | |
6 | |
7 #include <map> | |
8 | |
9 #include "base/bind.h" | |
10 #include "base/logging.h" | |
11 #include "base/stl_util.h" | |
12 #include "chrome/browser/chromeos/dbus/bluetooth_adapter_client.h" | |
13 #include "chrome/browser/chromeos/dbus/bluetooth_property.h" | |
14 #include "dbus/bus.h" | |
15 #include "dbus/message.h" | |
16 #include "dbus/object_path.h" | |
17 #include "dbus/object_proxy.h" | |
18 #include "third_party/cros_system_api/dbus/service_constants.h" | |
19 | |
20 namespace chromeos { | |
21 | |
22 BluetoothDeviceClient::Properties::Properties(dbus::ObjectProxy* object_proxy, | |
23 PropertyChangedCallback callback) | |
24 : BluetoothPropertySet(object_proxy, | |
25 bluetooth_device::kBluetoothDeviceInterface, | |
26 callback) { | |
27 RegisterProperty(bluetooth_device::kAddressProperty, &address); | |
28 RegisterProperty(bluetooth_device::kNameProperty, &name); | |
29 RegisterProperty(bluetooth_device::kVendorProperty, &vendor); | |
30 RegisterProperty(bluetooth_device::kProductProperty, &product); | |
31 RegisterProperty(bluetooth_device::kVersionProperty, &version); | |
32 RegisterProperty(bluetooth_device::kIconProperty, &icon); | |
33 RegisterProperty(bluetooth_device::kClassProperty, &bluetooth_class); | |
34 RegisterProperty(bluetooth_device::kUUIDsProperty, &uuids); | |
35 RegisterProperty(bluetooth_device::kServicesProperty, &services); | |
36 RegisterProperty(bluetooth_device::kPairedProperty, &paired); | |
37 RegisterProperty(bluetooth_device::kConnectedProperty, &connected); | |
38 RegisterProperty(bluetooth_device::kTrustedProperty, &trusted); | |
39 RegisterProperty(bluetooth_device::kBlockedProperty, &blocked); | |
40 RegisterProperty(bluetooth_device::kAliasProperty, &alias); | |
41 RegisterProperty(bluetooth_device::kNodesProperty, &nodes); | |
42 RegisterProperty(bluetooth_device::kAdapterProperty, &adapter); | |
43 RegisterProperty(bluetooth_device::kLegacyPairingProperty, &legacy_pairing); | |
44 } | |
45 | |
46 BluetoothDeviceClient::Properties::~Properties() { | |
47 } | |
48 | |
49 | |
50 // The BluetoothDeviceClient implementation used in production. | |
51 class BluetoothDeviceClientImpl: public BluetoothDeviceClient, | |
52 private BluetoothAdapterClient::Observer { | |
53 public: | |
54 BluetoothDeviceClientImpl(dbus::Bus* bus, | |
55 BluetoothAdapterClient* adapter_client) | |
56 : weak_ptr_factory_(this), | |
57 bus_(bus) { | |
58 DVLOG(1) << "Creating BluetoothDeviceClientImpl"; | |
59 | |
60 DCHECK(adapter_client); | |
61 adapter_client->AddObserver(this); | |
62 } | |
63 | |
64 virtual ~BluetoothDeviceClientImpl() { | |
65 // Clean up Properties structures | |
66 for (ObjectMap::iterator iter = object_map_.begin(); | |
67 iter != object_map_.end(); ++iter) { | |
68 Object object = iter->second; | |
69 Properties* properties = object.second; | |
70 delete properties; | |
71 } | |
72 } | |
73 | |
74 // BluetoothDeviceClient override. | |
75 virtual void AddObserver(BluetoothDeviceClient::Observer* observer) | |
76 OVERRIDE { | |
77 DCHECK(observer); | |
78 observers_.AddObserver(observer); | |
79 } | |
80 | |
81 // BluetoothDeviceClient override. | |
82 virtual void RemoveObserver(BluetoothDeviceClient::Observer* observer) | |
83 OVERRIDE { | |
84 DCHECK(observer); | |
85 observers_.RemoveObserver(observer); | |
86 } | |
87 | |
88 // BluetoothDeviceClient override. | |
89 virtual Properties* GetProperties(const dbus::ObjectPath& object_path) | |
90 OVERRIDE { | |
91 return GetObject(object_path).second; | |
92 } | |
93 | |
94 // BluetoothDeviceClient override. | |
95 virtual void DiscoverServices(const dbus::ObjectPath& object_path, | |
96 const std::string& pattern, | |
97 const ServicesCallback& callback) OVERRIDE { | |
98 dbus::MethodCall method_call( | |
99 bluetooth_device::kBluetoothDeviceInterface, | |
100 bluetooth_device::kDiscoverServices); | |
101 | |
102 dbus::MessageWriter writer(&method_call); | |
103 writer.AppendString(pattern); | |
104 | |
105 dbus::ObjectProxy* object_proxy = GetObjectProxy(object_path); | |
106 | |
107 object_proxy->CallMethod( | |
108 &method_call, | |
109 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, | |
110 base::Bind(&BluetoothDeviceClientImpl::OnDiscoverServices, | |
111 weak_ptr_factory_.GetWeakPtr(), object_path, callback)); | |
112 } | |
113 | |
114 // BluetoothDeviceClient override. | |
115 virtual void CancelDiscovery(const dbus::ObjectPath& object_path, | |
116 const DeviceCallback& callback) OVERRIDE { | |
117 dbus::MethodCall method_call( | |
118 bluetooth_device::kBluetoothDeviceInterface, | |
119 bluetooth_device::kCancelDiscovery); | |
120 | |
121 dbus::ObjectProxy* object_proxy = GetObjectProxy(object_path); | |
122 | |
123 object_proxy->CallMethod( | |
124 &method_call, | |
125 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, | |
126 base::Bind(&BluetoothDeviceClientImpl::OnCancelDiscovery, | |
127 weak_ptr_factory_.GetWeakPtr(), object_path, callback)); | |
128 } | |
129 | |
130 // BluetoothDeviceClient override. | |
131 virtual void Disconnect(const dbus::ObjectPath& object_path, | |
132 const DeviceCallback& callback) OVERRIDE { | |
133 dbus::MethodCall method_call( | |
134 bluetooth_device::kBluetoothDeviceInterface, | |
135 bluetooth_device::kDisconnect); | |
136 | |
137 dbus::ObjectProxy* object_proxy = GetObjectProxy(object_path); | |
138 | |
139 object_proxy->CallMethod( | |
140 &method_call, | |
141 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, | |
142 base::Bind(&BluetoothDeviceClientImpl::OnDisconnect, | |
143 weak_ptr_factory_.GetWeakPtr(), object_path, callback)); | |
144 } | |
145 | |
146 // BluetoothDeviceClient override. | |
147 virtual void CreateNode(const dbus::ObjectPath& object_path, | |
148 const std::string& uuid, | |
149 const NodeCallback& callback) OVERRIDE { | |
150 dbus::MethodCall method_call( | |
151 bluetooth_device::kBluetoothDeviceInterface, | |
152 bluetooth_device::kCreateNode); | |
153 | |
154 dbus::MessageWriter writer(&method_call); | |
155 writer.AppendString(uuid); | |
156 | |
157 dbus::ObjectProxy* object_proxy = GetObjectProxy(object_path); | |
158 | |
159 object_proxy->CallMethod( | |
160 &method_call, | |
161 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, | |
162 base::Bind(&BluetoothDeviceClientImpl::OnCreateNode, | |
163 weak_ptr_factory_.GetWeakPtr(), object_path, callback)); | |
164 } | |
165 | |
166 // BluetoothDeviceClient override. | |
167 virtual void RemoveNode(const dbus::ObjectPath& object_path, | |
168 const dbus::ObjectPath& node_path, | |
169 const DeviceCallback& callback) OVERRIDE { | |
170 dbus::MethodCall method_call( | |
171 bluetooth_device::kBluetoothDeviceInterface, | |
172 bluetooth_device::kRemoveNode); | |
173 | |
174 dbus::MessageWriter writer(&method_call); | |
175 writer.AppendObjectPath(node_path); | |
176 | |
177 dbus::ObjectProxy* object_proxy = GetObjectProxy(object_path); | |
178 | |
179 object_proxy->CallMethod( | |
180 &method_call, | |
181 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, | |
182 base::Bind(&BluetoothDeviceClientImpl::OnRemoveNode, | |
183 weak_ptr_factory_.GetWeakPtr(), object_path, callback)); | |
184 } | |
185 | |
186 private: | |
187 // We maintain a collection of dbus object proxies and properties structures | |
188 // for each device. | |
189 typedef std::pair<dbus::ObjectProxy*, Properties*> Object; | |
190 typedef std::map<const dbus::ObjectPath, Object> ObjectMap; | |
191 ObjectMap object_map_; | |
192 | |
193 // BluetoothAdapterClient::Observer override. | |
194 virtual void DeviceCreated(const dbus::ObjectPath& adapter_path, | |
195 const dbus::ObjectPath& object_path) OVERRIDE { | |
196 } | |
197 | |
198 // BluetoothAdapterClient::Observer override. | |
199 virtual void DeviceRemoved(const dbus::ObjectPath& adapter_path, | |
200 const dbus::ObjectPath& object_path) OVERRIDE { | |
201 RemoveObject(object_path); | |
202 } | |
203 | |
204 // Ensures that we have an object proxy and properties structure for | |
205 // a device with object path |object_path|, creating it if not and | |
206 // storing it in our |object_map_| map. | |
207 Object GetObject(const dbus::ObjectPath& object_path) { | |
208 ObjectMap::iterator iter = object_map_.find(object_path); | |
209 if (iter != object_map_.end()) | |
210 return iter->second; | |
211 | |
212 // Create the object proxy. | |
213 DCHECK(bus_); | |
214 dbus::ObjectProxy* object_proxy = bus_->GetObjectProxy( | |
215 bluetooth_device::kBluetoothDeviceServiceName, object_path); | |
216 | |
217 object_proxy->ConnectToSignal( | |
218 bluetooth_device::kBluetoothDeviceInterface, | |
219 bluetooth_device::kDisconnectRequestedSignal, | |
220 base::Bind(&BluetoothDeviceClientImpl::DisconnectRequestedReceived, | |
221 weak_ptr_factory_.GetWeakPtr(), object_path), | |
222 base::Bind(&BluetoothDeviceClientImpl::DisconnectRequestedConnected, | |
223 weak_ptr_factory_.GetWeakPtr(), object_path)); | |
224 | |
225 object_proxy->ConnectToSignal( | |
226 bluetooth_device::kBluetoothDeviceInterface, | |
227 bluetooth_device::kNodeCreatedSignal, | |
228 base::Bind(&BluetoothDeviceClientImpl::NodeCreatedReceived, | |
229 weak_ptr_factory_.GetWeakPtr(), object_path), | |
230 base::Bind(&BluetoothDeviceClientImpl::NodeCreatedConnected, | |
231 weak_ptr_factory_.GetWeakPtr(), object_path)); | |
232 | |
233 object_proxy->ConnectToSignal( | |
234 bluetooth_device::kBluetoothDeviceInterface, | |
235 bluetooth_device::kNodeRemovedSignal, | |
236 base::Bind(&BluetoothDeviceClientImpl::NodeRemovedReceived, | |
237 weak_ptr_factory_.GetWeakPtr(), object_path), | |
238 base::Bind(&BluetoothDeviceClientImpl::NodeRemovedConnected, | |
239 weak_ptr_factory_.GetWeakPtr(), object_path)); | |
240 | |
241 // Create the properties structure. | |
242 Properties* properties = new Properties( | |
243 object_proxy, | |
244 base::Bind(&BluetoothDeviceClientImpl::OnPropertyChanged, | |
245 weak_ptr_factory_.GetWeakPtr(), object_path)); | |
246 | |
247 properties->ConnectSignals(); | |
248 properties->GetAll(); | |
249 | |
250 Object object = std::make_pair(object_proxy, properties); | |
251 object_map_[object_path] = object; | |
252 return object; | |
253 } | |
254 | |
255 // Removes the dbus object proxy and properties for the device with | |
256 // dbus object path |object_path| from our |object_map_| map. | |
257 void RemoveObject(const dbus::ObjectPath& object_path) { | |
258 ObjectMap::iterator iter = object_map_.find(object_path); | |
259 if (iter != object_map_.end()) { | |
260 // Clean up the Properties structure. | |
261 Object object = iter->second; | |
262 Properties* properties = object.second; | |
263 delete properties; | |
264 | |
265 object_map_.erase(iter); | |
266 } | |
267 } | |
268 | |
269 // Returns a pointer to the object proxy for |object_path|, creating | |
270 // it if necessary. | |
271 dbus::ObjectProxy* GetObjectProxy(const dbus::ObjectPath& object_path) { | |
272 return GetObject(object_path).first; | |
273 } | |
274 | |
275 // Called by BluetoothPropertySet when a property value is changed, | |
276 // either by result of a signal or response to a GetAll() or Get() | |
277 // call. Informs observers. | |
278 void OnPropertyChanged(const dbus::ObjectPath& object_path, | |
279 const std::string& property_name) { | |
280 FOR_EACH_OBSERVER(BluetoothDeviceClient::Observer, observers_, | |
281 DevicePropertyChanged(object_path, property_name)); | |
282 } | |
283 | |
284 // Called by dbus:: when a DisconnectRequested signal is received. | |
285 void DisconnectRequestedReceived(const dbus::ObjectPath& object_path, | |
286 dbus::Signal* signal) { | |
287 DCHECK(signal); | |
288 | |
289 DVLOG(1) << object_path.value() << ": Disconnect requested."; | |
290 FOR_EACH_OBSERVER(BluetoothDeviceClient::Observer, observers_, | |
291 DisconnectRequested(object_path)); | |
292 } | |
293 | |
294 // Called by dbus:: when the DisconnectRequested signal is initially | |
295 // connected. | |
296 void DisconnectRequestedConnected(const dbus::ObjectPath& object_path, | |
297 const std::string& interface_name, | |
298 const std::string& signal_name, | |
299 bool success) { | |
300 LOG_IF(WARNING, !success) << object_path.value() | |
301 << ": Failed to connect to " | |
302 "DisconnectRequested signal."; | |
303 } | |
304 | |
305 // Called by dbus:: when a NodeCreated signal is received. | |
306 void NodeCreatedReceived(const dbus::ObjectPath& object_path, | |
307 dbus::Signal* signal) { | |
308 DCHECK(signal); | |
309 dbus::MessageReader reader(signal); | |
310 dbus::ObjectPath node_path; | |
311 if (!reader.PopObjectPath(&node_path)) { | |
312 LOG(WARNING) << object_path.value() | |
313 << ": NodeCreated signal has incorrect parameters: " | |
314 << signal->ToString(); | |
315 return; | |
316 } | |
317 | |
318 DVLOG(1) << object_path.value() << ": Node created: " | |
319 << node_path.value(); | |
320 FOR_EACH_OBSERVER(BluetoothDeviceClient::Observer, observers_, | |
321 NodeCreated(object_path, node_path)); | |
322 } | |
323 | |
324 // Called by dbus:: when the NodeCreated signal is initially connected. | |
325 void NodeCreatedConnected(const dbus::ObjectPath& object_path, | |
326 const std::string& interface_name, | |
327 const std::string& signal_name, | |
328 bool success) { | |
329 LOG_IF(WARNING, !success) << object_path.value() | |
330 << ": Failed to connect to NodeCreated signal."; | |
331 } | |
332 | |
333 // Called by dbus:: when a NodeRemoved signal is received. | |
334 void NodeRemovedReceived(const dbus::ObjectPath& object_path, | |
335 dbus::Signal* signal) { | |
336 DCHECK(signal); | |
337 dbus::MessageReader reader(signal); | |
338 dbus::ObjectPath node_path; | |
339 if (!reader.PopObjectPath(&node_path)) { | |
340 LOG(WARNING) << object_path.value() | |
341 << ": NodeRemoved signal has incorrect parameters: " | |
342 << signal->ToString(); | |
343 return; | |
344 } | |
345 | |
346 DVLOG(1) << object_path.value() << ": Node removed: " | |
347 << node_path.value(); | |
348 FOR_EACH_OBSERVER(BluetoothDeviceClient::Observer, observers_, | |
349 NodeRemoved(object_path, node_path)); | |
350 } | |
351 | |
352 // Called by dbus:: when the NodeRemoved signal is initially connected. | |
353 void NodeRemovedConnected(const dbus::ObjectPath& object_path, | |
354 const std::string& interface_name, | |
355 const std::string& signal_name, | |
356 bool success) { | |
357 LOG_IF(WARNING, !success) << object_path.value() | |
358 << ": Failed to connect to NodeRemoved signal."; | |
359 } | |
360 | |
361 // Called when a response for DiscoverServices() is received. | |
362 void OnDiscoverServices(const dbus::ObjectPath& object_path, | |
363 const ServicesCallback& callback, | |
364 dbus::Response* response) { | |
365 // Parse response. | |
366 bool success = false; | |
367 ServiceMap services; | |
368 if (response != NULL) { | |
369 dbus::MessageReader reader(response); | |
370 | |
371 dbus::MessageReader array_reader(NULL); | |
372 if (!reader.PopArray(&array_reader)) { | |
373 LOG(WARNING) << "DiscoverServices response has incorrect parameters: " | |
374 << response->ToString(); | |
375 } else { | |
376 while (array_reader.HasMoreData()) { | |
377 dbus::MessageReader dict_entry_reader(NULL); | |
378 uint32 key = 0; | |
379 std::string value; | |
380 if (!array_reader.PopDictEntry(&dict_entry_reader) | |
381 || !dict_entry_reader.PopUint32(&key) | |
382 || !dict_entry_reader.PopString(&value)) { | |
383 LOG(WARNING) << "DiscoverServices response has " | |
384 "incorrect parameters: " << response->ToString(); | |
385 } else { | |
386 services[key] = value; | |
387 } | |
388 } | |
389 | |
390 success = true; | |
391 } | |
392 } else { | |
393 LOG(WARNING) << "Failed to discover services."; | |
394 } | |
395 | |
396 // Notify client. | |
397 callback.Run(object_path, services, success); | |
398 } | |
399 | |
400 // Called when a response for CancelDiscovery() is received. | |
401 void OnCancelDiscovery(const dbus::ObjectPath& object_path, | |
402 const DeviceCallback& callback, | |
403 dbus::Response* response) { | |
404 LOG_IF(WARNING, !response) << object_path.value() | |
405 << ": OnCancelDiscovery: failed."; | |
406 callback.Run(object_path, response); | |
407 } | |
408 | |
409 // Called when a response for Disconnect() is received. | |
410 void OnDisconnect(const dbus::ObjectPath& object_path, | |
411 const DeviceCallback& callback, | |
412 dbus::Response* response) { | |
413 LOG_IF(WARNING, !response) << object_path.value() | |
414 << ": OnDisconnect: failed."; | |
415 callback.Run(object_path, response); | |
416 } | |
417 | |
418 // Called when a response for CreateNode() is received. | |
419 void OnCreateNode(const dbus::ObjectPath& object_path, | |
420 const NodeCallback& callback, | |
421 dbus::Response* response) { | |
422 // Parse response. | |
423 bool success = false; | |
424 dbus::ObjectPath node_path; | |
425 if (response != NULL) { | |
426 dbus::MessageReader reader(response); | |
427 if (!reader.PopObjectPath(&node_path)) { | |
428 LOG(WARNING) << "CreateNode response has incorrect parameters: " | |
429 << response->ToString(); | |
430 } else { | |
431 success = true; | |
432 } | |
433 } else { | |
434 LOG(WARNING) << "Failed to create node."; | |
435 } | |
436 | |
437 // Notify client. | |
438 callback.Run(node_path, success); | |
439 } | |
440 | |
441 // Called when a response for RemoveNode() is received. | |
442 void OnRemoveNode(const dbus::ObjectPath& object_path, | |
443 const DeviceCallback& callback, | |
444 dbus::Response* response) { | |
445 LOG_IF(WARNING, !response) << object_path.value() | |
446 << ": OnRemoveNode: failed."; | |
447 callback.Run(object_path, response); | |
448 } | |
449 | |
450 // Weak pointer factory for generating 'this' pointers that might live longer | |
451 // than we do. | |
452 base::WeakPtrFactory<BluetoothDeviceClientImpl> weak_ptr_factory_; | |
453 | |
454 dbus::Bus* bus_; | |
455 | |
456 // List of observers interested in event notifications from us. | |
457 ObserverList<BluetoothDeviceClient::Observer> observers_; | |
458 | |
459 DISALLOW_COPY_AND_ASSIGN(BluetoothDeviceClientImpl); | |
460 }; | |
461 | |
462 // The BluetoothDeviceClient implementation used on Linux desktop, which does | |
463 // nothing. | |
464 class BluetoothDeviceClientStubImpl : public BluetoothDeviceClient { | |
465 public: | |
466 // BluetoothDeviceClient override. | |
467 virtual void AddObserver(Observer* observer) OVERRIDE { | |
468 } | |
469 | |
470 // BluetoothDeviceClient override. | |
471 virtual void RemoveObserver(Observer* observer) OVERRIDE { | |
472 } | |
473 | |
474 // BluetoothDeviceClient override. | |
475 virtual Properties* GetProperties(const dbus::ObjectPath& object_path) | |
476 OVERRIDE { | |
477 VLOG(1) << "GetProperties: " << object_path.value(); | |
478 return NULL; | |
479 } | |
480 | |
481 // BluetoothDeviceClient override. | |
482 virtual void DiscoverServices(const dbus::ObjectPath& object_path, | |
483 const std::string& pattern, | |
484 const ServicesCallback& callback) OVERRIDE { | |
485 VLOG(1) << "DiscoverServices: " << object_path.value() << " " << pattern; | |
486 | |
487 ServiceMap services; | |
488 callback.Run(object_path, services, false); | |
489 } | |
490 | |
491 // BluetoothDeviceClient override. | |
492 virtual void CancelDiscovery(const dbus::ObjectPath& object_path, | |
493 const DeviceCallback& callback) OVERRIDE { | |
494 VLOG(1) << "CancelDiscovery: " << object_path.value(); | |
495 callback.Run(object_path, false); | |
496 } | |
497 | |
498 // BluetoothDeviceClient override. | |
499 virtual void Disconnect(const dbus::ObjectPath& object_path, | |
500 const DeviceCallback& callback) OVERRIDE { | |
501 VLOG(1) << "Disconnect: " << object_path.value(); | |
502 callback.Run(object_path, false); | |
503 } | |
504 | |
505 // BluetoothDeviceClient override. | |
506 virtual void CreateNode(const dbus::ObjectPath& object_path, | |
507 const std::string& uuid, | |
508 const NodeCallback& callback) OVERRIDE { | |
509 VLOG(1) << "CreateNode: " << object_path.value() << " " << uuid; | |
510 callback.Run(dbus::ObjectPath(), false); | |
511 } | |
512 | |
513 // BluetoothDeviceClient override. | |
514 virtual void RemoveNode(const dbus::ObjectPath& object_path, | |
515 const dbus::ObjectPath& node_path, | |
516 const DeviceCallback& callback) OVERRIDE { | |
517 VLOG(1) << "RemoveNode: " << object_path.value() | |
518 << " " << node_path.value(); | |
519 callback.Run(object_path, false); | |
520 } | |
521 }; | |
522 | |
523 BluetoothDeviceClient::BluetoothDeviceClient() { | |
524 } | |
525 | |
526 BluetoothDeviceClient::~BluetoothDeviceClient() { | |
527 } | |
528 | |
529 BluetoothDeviceClient* BluetoothDeviceClient::Create( | |
530 DBusClientImplementationType type, | |
531 dbus::Bus* bus, | |
532 BluetoothAdapterClient* adapter_client) { | |
533 if (type == REAL_DBUS_CLIENT_IMPLEMENTATION) | |
534 return new BluetoothDeviceClientImpl(bus, adapter_client); | |
535 DCHECK_EQ(STUB_DBUS_CLIENT_IMPLEMENTATION, type); | |
536 return new BluetoothDeviceClientStubImpl(); | |
537 } | |
538 | |
539 } // namespace chromeos | |
OLD | NEW |