Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(127)

Side by Side Diff: chrome/browser/chromeos/dbus/bluetooth_adapter_client.cc

Issue 8375042: Chrome OS: Add bluetooth dbus clients for device discovery (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: address more satorux@ review comments Created 9 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2011 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_adapter_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/system/runtime_environment.h"
13 #include "dbus/bus.h"
14 #include "dbus/message.h"
15 #include "dbus/object_proxy.h"
16 #include "third_party/cros_system_api/dbus/service_constants.h"
17
18 namespace {
19
20 // Utility function to convert an array of dbus dict_entry objects into a
21 // DictionaryValue object.
22 //
23 // The dict_entry objects must have keys that are strings and values that are
24 // simple variants.
25 //
26 // When converting integral types, we use Integer Value objects to represent
27 // uint8, int16, uint16, int32, and uint32 values and Double Value objects to
28 // represent int64 and uint64 values.
29 //
30 // We intend to move this to the chrome dbus library's MessageReader class when
31 // it's more fully baked.
32 //
33 // TODO(vlaviano):
34 // - Can we handle integral types better?
35 // - Add support for nested complex types.
36 // - Write an equivalent function to convert in the opposite direction.
37 // - Write unit tests.
38 bool PopArrayOfDictEntries(dbus::MessageReader* reader,
39 dbus::Message* message,
40 DictionaryValue* dictionary) {
41 DCHECK(reader);
42 DCHECK(message);
43 DCHECK(dictionary);
44 dbus::MessageReader array_reader(message);
45 if (!reader->PopArray(&array_reader)) {
46 return false;
47 }
48 while (array_reader.HasMoreData()) {
49 dbus::MessageReader dict_entry_reader(message);
50 if (!array_reader.PopDictEntry(&dict_entry_reader)) {
51 return false;
52 }
53 std::string key;
54 if (!dict_entry_reader.PopString(&key)) {
55 return false;
56 }
57 dbus::MessageReader variant_reader(message);
58 if (!dict_entry_reader.PopVariant(&variant_reader)) {
59 return false;
60 }
61 const dbus::Message::DataType type = variant_reader.GetDataType();
62 switch (type) {
63 case dbus::Message::BYTE: {
64 uint8 value = 0;
65 if (!variant_reader.PopByte(&value)) {
66 return false;
67 }
68 dictionary->SetInteger(key, value);
69 break;
70 }
71 case dbus::Message::BOOL: {
72 bool value = false;
73 if (!variant_reader.PopBool(&value)) {
74 return false;
75 }
76 dictionary->SetBoolean(key, value);
77 break;
78 }
79 case dbus::Message::INT16: {
80 int16 value = 0;
81 if (!variant_reader.PopInt16(&value)) {
82 return false;
83 }
84 dictionary->SetInteger(key, value);
85 break;
86 }
87 case dbus::Message::UINT16: {
88 uint16 value = 0;
89 if (!variant_reader.PopUint16(&value)) {
90 return false;
91 }
92 dictionary->SetInteger(key, value);
93 break;
94 }
95 case dbus::Message::INT32: {
96 int32 value = 0;
97 if (!variant_reader.PopInt32(&value)) {
98 return false;
99 }
100 dictionary->SetInteger(key, value);
101 break;
102 }
103 case dbus::Message::UINT32: {
104 uint32 value = 0;
105 if (!variant_reader.PopUint32(&value)) {
106 return false;
107 }
108 dictionary->SetInteger(key, value);
109 break;
110 }
111 case dbus::Message::INT64: {
112 int64 value = 0;
113 if (!variant_reader.PopInt64(&value)) {
114 return false;
115 }
116 dictionary->SetDouble(key, value);
117 break;
118 }
119 case dbus::Message::UINT64: {
120 uint64 value = 0;
121 if (!variant_reader.PopUint64(&value)) {
122 return false;
123 }
124 dictionary->SetDouble(key, value);
125 break;
126 }
127 case dbus::Message::DOUBLE: {
128 double value = 0;
129 if (!variant_reader.PopDouble(&value)) {
130 return false;
131 }
132 dictionary->SetDouble(key, value);
133 break;
134 }
135 case dbus::Message::STRING: {
136 std::string value;
137 if (!variant_reader.PopString(&value)) {
138 return false;
139 }
140 dictionary->SetString(key, value);
141 break;
142 }
143 case dbus::Message::OBJECT_PATH: {
144 std::string value;
145 if (!variant_reader.PopObjectPath(&value)) {
146 return false;
147 }
148 dictionary->SetString(key, value);
149 break;
150 }
151 case dbus::Message::ARRAY: {
152 // Not yet supported.
153 return false;
154 }
155 case dbus::Message::STRUCT: {
156 // Not yet supported.
157 return false;
158 }
159 case dbus::Message::DICT_ENTRY: {
160 // Not yet supported.
161 return false;
162 }
163 case dbus::Message::VARIANT: {
164 // Not yet supported.
165 return false;
166 }
167 default:
168 LOG(FATAL) << "Unknown type: " << type;
169 }
170 }
171 return true;
172 }
173
174 } // namespace
175
176 namespace chromeos {
177
178 // The BluetoothAdapterClient implementation used in production.
179 class BluetoothAdapterClientImpl: public BluetoothAdapterClient {
180 public:
181 explicit BluetoothAdapterClientImpl(dbus::Bus* bus)
182 : weak_ptr_factory_(this),
183 bus_(bus) {
184 VLOG(1) << "Creating BluetoothAdapterClientImpl";
185 }
186
187 virtual ~BluetoothAdapterClientImpl() {
188 }
189
190 // BluetoothAdapterClient override.
191 virtual void AddObserver(Observer* observer, const std::string& object_path) {
192 VLOG(1) << "AddObserver: " << object_path;
193 DCHECK(observer);
194 observers_.AddObserver(observer);
195 AddObjectProxyForPath(object_path);
196 }
197
198 // BluetoothAdapterClient override.
199 virtual void RemoveObserver(Observer* observer,
200 const std::string& object_path) {
201 VLOG(1) << "RemoveObserver: " << object_path;
202 DCHECK(observer);
203 observers_.RemoveObserver(observer);
204 RemoveObjectProxyForPath(object_path);
205 }
206
207 // BluetoothAdapterClient override.
208 virtual void StartDiscovery(const std::string& object_path) {
209 VLOG(1) << "StartDiscovery: " << object_path;
210
211 dbus::MethodCall method_call(
212 bluetooth_adapter::kBluetoothAdapterInterface,
213 bluetooth_adapter::kStartDiscovery);
214
215 ProxyMap::iterator it = proxy_map_.find(object_path);
216 if (it == proxy_map_.end()) {
217 LOG(ERROR) << "Couldn't find proxy for object path " << object_path;
218 return;
219 }
220 dbus::ObjectProxy* adapter_proxy = it->second;
221
222 adapter_proxy->CallMethod(
223 &method_call,
224 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
225 base::Bind(&BluetoothAdapterClientImpl::OnStartDiscovery,
226 weak_ptr_factory_.GetWeakPtr(), object_path));
227 }
228
229 // BluetoothAdapterClient override.
230 virtual void StopDiscovery(const std::string& object_path) {
231 VLOG(1) << "StopDiscovery: " << object_path;
232
233 dbus::MethodCall method_call(
234 bluetooth_adapter::kBluetoothAdapterInterface,
235 bluetooth_adapter::kStopDiscovery);
236
237 ProxyMap::iterator it = proxy_map_.find(object_path);
238 if (it == proxy_map_.end()) {
239 LOG(ERROR) << "Couldn't find proxy for object path " << object_path;
240 return;
241 }
242 dbus::ObjectProxy* adapter_proxy = it->second;
243
244 adapter_proxy->CallMethod(
245 &method_call,
246 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
247 base::Bind(&BluetoothAdapterClientImpl::OnStopDiscovery,
248 weak_ptr_factory_.GetWeakPtr(), object_path));
249 }
250
251 private:
252 // Gets a dbus object proxy for an adapter with dbus object path |object_path|
253 // and stores it in our |proxy_map_| map.
254 void AddObjectProxyForPath(const std::string& object_path) {
255 VLOG(1) << "AddObjectProxyForPath: " << object_path;
256
257 DCHECK(bus_);
258 dbus::ObjectProxy* adapter_proxy = bus_->GetObjectProxy(
259 bluetooth_adapter::kBluetoothAdapterServiceName, object_path);
260
261 proxy_map_[object_path] = adapter_proxy;
262
263 adapter_proxy->ConnectToSignal(
264 bluetooth_adapter::kBluetoothAdapterInterface,
265 bluetooth_adapter::kPropertyChangedSignal,
266 base::Bind(&BluetoothAdapterClientImpl::PropertyChangedReceived,
267 weak_ptr_factory_.GetWeakPtr(), object_path),
268 base::Bind(&BluetoothAdapterClientImpl::PropertyChangedConnected,
269 weak_ptr_factory_.GetWeakPtr(), object_path));
270
271 adapter_proxy->ConnectToSignal(
272 bluetooth_adapter::kBluetoothAdapterInterface,
273 bluetooth_adapter::kDeviceFoundSignal,
274 base::Bind(&BluetoothAdapterClientImpl::DeviceFoundReceived,
275 weak_ptr_factory_.GetWeakPtr(), object_path),
276 base::Bind(&BluetoothAdapterClientImpl::DeviceFoundConnected,
277 weak_ptr_factory_.GetWeakPtr(), object_path));
278
279 adapter_proxy->ConnectToSignal(
280 bluetooth_adapter::kBluetoothAdapterInterface,
281 bluetooth_adapter::kDeviceDisappearedSignal,
282 base::Bind(&BluetoothAdapterClientImpl::DeviceDisappearedReceived,
283 weak_ptr_factory_.GetWeakPtr(), object_path),
284 base::Bind(&BluetoothAdapterClientImpl::DeviceDisappearedConnected,
285 weak_ptr_factory_.GetWeakPtr(), object_path));
286 }
287
288 // Removes the dbus object proxy for the adapter with dbus object path
289 // |object_path| from our |proxy_map_| map.
290 void RemoveObjectProxyForPath(const std::string& object_path) {
291 VLOG(1) << "RemoveObjectProxyForPath: " << object_path;
292 proxy_map_.erase(object_path);
293 }
294
295 // Called by dbus:: when a PropertyChanged signal is received.
296 void PropertyChangedReceived(const std::string& object_path,
297 dbus::Signal* signal) {
298 DCHECK(signal);
299 dbus::MessageReader reader(signal);
300 std::string property_name;
301 if (!reader.PopString(&property_name)) {
302 LOG(ERROR) << object_path
303 << ": PropertyChanged signal has incorrect parameters: "
304 << signal->ToString();
305 return;
306 }
307
308 if (property_name != bluetooth_adapter::kDiscoveringProperty) {
309 VLOG(1) << object_path << ": PropertyChanged: " << property_name;
310 // We don't care.
311 return;
312 }
313
314 bool discovering = false;
315 if (!reader.PopVariantOfBool(&discovering)) {
316 LOG(ERROR) << object_path
317 << ": PropertyChanged signal has incorrect parameters: "
318 << signal->ToString();
319 return;
320 }
321 VLOG(1) << object_path << ": PropertyChanged: Discovering = "
322 << discovering;
323
324 FOR_EACH_OBSERVER(Observer, observers_,
325 DiscoveringPropertyChanged(object_path, discovering));
326 }
327
328 // Called by dbus:: when the PropertyChanged signal is initially connected.
329 void PropertyChangedConnected(const std::string& object_path,
330 const std::string& interface_name,
331 const std::string& signal_name,
332 bool success) {
333 LOG_IF(WARNING, !success) << object_path
334 << ": Failed to connect to PropertyChanged signal.";
335 }
336
337 // Called by dbus:: when a DeviceFound signal is received.
338 void DeviceFoundReceived(const std::string& object_path,
339 dbus::Signal* signal) {
340 DCHECK(signal);
341 dbus::MessageReader reader(signal);
342 std::string address;
343 if (!reader.PopString(&address)) {
344 LOG(ERROR) << object_path
345 << ": DeviceFound signal has incorrect parameters: "
346 << signal->ToString();
347 return;
348 }
349 VLOG(1) << object_path << ": Device found: " << address;
350
351 DictionaryValue device_properties;
352 if (!PopArrayOfDictEntries(&reader, signal, &device_properties)) {
353 LOG(ERROR) << object_path
354 << ": DeviceFound signal has incorrect parameters: "
355 << signal->ToString();
356 return;
357 }
358
359 FOR_EACH_OBSERVER(Observer, observers_, DeviceFound(object_path, address,
360 device_properties));
361 }
362
363 // Called by dbus:: when the DeviceFound signal is initially connected.
364 void DeviceFoundConnected(const std::string& object_path,
365 const std::string& interface_name,
366 const std::string& signal_name,
367 bool success) {
368 LOG_IF(WARNING, !success) << object_path
369 << ": Failed to connect to DeviceFound signal.";
370 }
371
372 // Called by dbus:: when a DeviceDisappeared signal is received.
373 void DeviceDisappearedReceived(const std::string& object_path,
374 dbus::Signal* signal) {
375 DCHECK(signal);
376 dbus::MessageReader reader(signal);
377 std::string address;
378 if (!reader.PopString(&address)) {
379 LOG(ERROR) << object_path
380 << ": DeviceDisappeared signal has incorrect parameters: "
381 << signal->ToString();
382 return;
383 }
384 VLOG(1) << object_path << ": Device disappeared: " << address;
385 FOR_EACH_OBSERVER(Observer, observers_, DeviceDisappeared(object_path,
386 address));
387 }
388
389 // Called by dbus:: when the DeviceDisappeared signal is initially connected.
390 void DeviceDisappearedConnected(const std::string& object_path,
391 const std::string& interface_name,
392 const std::string& signal_name,
393 bool success) {
394 LOG_IF(WARNING, !success) << object_path
395 << ": Failed to connect to DeviceDisappeared signal.";
396 }
397
398 // Called when a response for StartDiscovery() is received.
399 void OnStartDiscovery(const std::string& object_path,
400 dbus::Response* response) {
401 VLOG(1) << "OnStartDiscovery: " << object_path;
402 LOG_IF(WARNING, !response) << object_path << ": OnStartDiscovery: failed.";
403 }
404
405 // Called when a response for StopDiscovery() is received.
406 void OnStopDiscovery(const std::string& object_path,
407 dbus::Response* response) {
408 VLOG(1) << "OnStopDiscovery: " << object_path;
409 LOG_IF(WARNING, !response) << object_path << ": OnStopDiscovery: failed.";
410 }
411
412 // Weak pointer factory for generating 'this' pointers that might live longer
413 // than we do.
414 base::WeakPtrFactory<BluetoothAdapterClientImpl> weak_ptr_factory_;
415
416 dbus::Bus* bus_;
417
418 // We maintain a collection of dbus object proxies, one for each adapter.
419 typedef std::map<const std::string, dbus::ObjectProxy*> ProxyMap;
420 ProxyMap proxy_map_;
421
422 // List of observers interested in event notifications from us.
423 ObserverList<Observer> observers_;
424
425 DISALLOW_COPY_AND_ASSIGN(BluetoothAdapterClientImpl);
426 };
427
428 // The BluetoothAdapterClient implementation used on Linux desktop, which does
429 // nothing.
430 class BluetoothAdapterClientStubImpl : public BluetoothAdapterClient {
431 public:
432 // BluetoothAdapterClient override.
433 virtual void AddObserver(Observer* observer, const std::string& object_path) {
434 VLOG(1) << "AddObserver: " << object_path;
435 }
436
437 // BluetoothAdapterClient override.
438 virtual void RemoveObserver(Observer* observer,
439 const std::string& object_path) {
440 VLOG(1) << "RemoveObserver: " << object_path;
441 }
442
443 // BluetoothAdapterClient override.
444 virtual void StartDiscovery(const std::string& object_path) {
445 VLOG(1) << "StartDiscovery: " << object_path;
446 }
447
448 // BluetoothAdapterClient override.
449 virtual void StopDiscovery(const std::string& object_path) {
450 VLOG(1) << "StopDiscovery: " << object_path;
451 }
452 };
453
454 BluetoothAdapterClient::BluetoothAdapterClient() {
455 }
456
457 BluetoothAdapterClient::~BluetoothAdapterClient() {
458 }
459
460 BluetoothAdapterClient* BluetoothAdapterClient::Create(dbus::Bus* bus) {
461 if (system::runtime_environment::IsRunningOnChromeOS()) {
462 return new BluetoothAdapterClientImpl(bus);
463 } else {
464 return new BluetoothAdapterClientStubImpl();
465 }
466 }
467
468 } // namespace chromeos
OLDNEW
« no previous file with comments | « chrome/browser/chromeos/dbus/bluetooth_adapter_client.h ('k') | chrome/browser/chromeos/dbus/bluetooth_manager_client.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698