1// Copyright 2013 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 "chromeos/dbus/bluetooth_device_client.h" 6 7#include "base/bind.h" 8#include "base/logging.h" 9#include "base/stl_util.h" 10#include "dbus/bus.h" 11#include "dbus/message.h" 12#include "dbus/object_manager.h" 13#include "dbus/object_path.h" 14#include "dbus/object_proxy.h" 15#include "third_party/cros_system_api/dbus/service_constants.h" 16 17namespace chromeos { 18 19const char BluetoothDeviceClient::kNoResponseError[] = 20 "org.chromium.Error.NoResponse"; 21const char BluetoothDeviceClient::kUnknownDeviceError[] = 22 "org.chromium.Error.UnknownDevice"; 23 24BluetoothDeviceClient::Properties::Properties( 25 dbus::ObjectProxy* object_proxy, 26 const std::string& interface_name, 27 const PropertyChangedCallback& callback) 28 : dbus::PropertySet(object_proxy, interface_name, callback) { 29 RegisterProperty(bluetooth_device::kAddressProperty, &address); 30 RegisterProperty(bluetooth_device::kNameProperty, &name); 31 RegisterProperty(bluetooth_device::kIconProperty, &icon); 32 RegisterProperty(bluetooth_device::kClassProperty, &bluetooth_class); 33 RegisterProperty(bluetooth_device::kAppearanceProperty, &appearance); 34 RegisterProperty(bluetooth_device::kUUIDsProperty, &uuids); 35 RegisterProperty(bluetooth_device::kPairedProperty, &paired); 36 RegisterProperty(bluetooth_device::kConnectedProperty, &connected); 37 RegisterProperty(bluetooth_device::kTrustedProperty, &trusted); 38 RegisterProperty(bluetooth_device::kBlockedProperty, &blocked); 39 RegisterProperty(bluetooth_device::kAliasProperty, &alias); 40 RegisterProperty(bluetooth_device::kAdapterProperty, &adapter); 41 RegisterProperty(bluetooth_device::kLegacyPairingProperty, &legacy_pairing); 42 RegisterProperty(bluetooth_device::kModaliasProperty, &modalias); 43 RegisterProperty(bluetooth_device::kRSSIProperty, &rssi); 44 RegisterProperty(bluetooth_device::kConnectionRSSI, &connection_rssi); 45 RegisterProperty(bluetooth_device::kConnectionTXPower, &connection_tx_power); 46 RegisterProperty(bluetooth_device::kConnectionTXPowerMax, 47 &connection_tx_power_max); 48} 49 50BluetoothDeviceClient::Properties::~Properties() { 51} 52 53 54// The BluetoothDeviceClient implementation used in production. 55class BluetoothDeviceClientImpl 56 : public BluetoothDeviceClient, 57 public dbus::ObjectManager::Interface { 58 public: 59 BluetoothDeviceClientImpl() 60 : object_manager_(NULL), weak_ptr_factory_(this) {} 61 62 virtual ~BluetoothDeviceClientImpl() { 63 object_manager_->UnregisterInterface( 64 bluetooth_device::kBluetoothDeviceInterface); 65 } 66 67 // BluetoothDeviceClient override. 68 virtual void AddObserver(BluetoothDeviceClient::Observer* observer) 69 OVERRIDE { 70 DCHECK(observer); 71 observers_.AddObserver(observer); 72 } 73 74 // BluetoothDeviceClient override. 75 virtual void RemoveObserver(BluetoothDeviceClient::Observer* observer) 76 OVERRIDE { 77 DCHECK(observer); 78 observers_.RemoveObserver(observer); 79 } 80 81 // dbus::ObjectManager::Interface override. 82 virtual dbus::PropertySet* CreateProperties( 83 dbus::ObjectProxy* object_proxy, 84 const dbus::ObjectPath& object_path, 85 const std::string& interface_name) OVERRIDE { 86 Properties* properties = new Properties( 87 object_proxy, 88 interface_name, 89 base::Bind(&BluetoothDeviceClientImpl::OnPropertyChanged, 90 weak_ptr_factory_.GetWeakPtr(), 91 object_path)); 92 return static_cast<dbus::PropertySet*>(properties); 93 } 94 95 // BluetoothDeviceClient override. 96 virtual std::vector<dbus::ObjectPath> GetDevicesForAdapter( 97 const dbus::ObjectPath& adapter_path) OVERRIDE { 98 std::vector<dbus::ObjectPath> object_paths, device_paths; 99 device_paths = object_manager_->GetObjectsWithInterface( 100 bluetooth_device::kBluetoothDeviceInterface); 101 for (std::vector<dbus::ObjectPath>::iterator iter = device_paths.begin(); 102 iter != device_paths.end(); ++iter) { 103 Properties* properties = GetProperties(*iter); 104 if (properties->adapter.value() == adapter_path) 105 object_paths.push_back(*iter); 106 } 107 return object_paths; 108 } 109 110 // BluetoothDeviceClient override. 111 virtual Properties* GetProperties(const dbus::ObjectPath& object_path) 112 OVERRIDE { 113 return static_cast<Properties*>( 114 object_manager_->GetProperties( 115 object_path, 116 bluetooth_device::kBluetoothDeviceInterface)); 117 } 118 119 // BluetoothDeviceClient override. 120 virtual void Connect(const dbus::ObjectPath& object_path, 121 const base::Closure& callback, 122 const ErrorCallback& error_callback) OVERRIDE { 123 dbus::MethodCall method_call( 124 bluetooth_device::kBluetoothDeviceInterface, 125 bluetooth_device::kConnect); 126 127 dbus::ObjectProxy* object_proxy = 128 object_manager_->GetObjectProxy(object_path); 129 if (!object_proxy) { 130 error_callback.Run(kUnknownDeviceError, ""); 131 return; 132 } 133 134 // Connect may take an arbitrary length of time, so use no timeout. 135 object_proxy->CallMethodWithErrorCallback( 136 &method_call, 137 dbus::ObjectProxy::TIMEOUT_INFINITE, 138 base::Bind(&BluetoothDeviceClientImpl::OnSuccess, 139 weak_ptr_factory_.GetWeakPtr(), callback), 140 base::Bind(&BluetoothDeviceClientImpl::OnError, 141 weak_ptr_factory_.GetWeakPtr(), error_callback)); 142 } 143 144 // BluetoothDeviceClient override. 145 virtual void Disconnect(const dbus::ObjectPath& object_path, 146 const base::Closure& callback, 147 const ErrorCallback& error_callback) OVERRIDE { 148 dbus::MethodCall method_call( 149 bluetooth_device::kBluetoothDeviceInterface, 150 bluetooth_device::kDisconnect); 151 152 dbus::ObjectProxy* object_proxy = 153 object_manager_->GetObjectProxy(object_path); 154 if (!object_proxy) { 155 error_callback.Run(kUnknownDeviceError, ""); 156 return; 157 } 158 159 object_proxy->CallMethodWithErrorCallback( 160 &method_call, 161 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, 162 base::Bind(&BluetoothDeviceClientImpl::OnSuccess, 163 weak_ptr_factory_.GetWeakPtr(), callback), 164 base::Bind(&BluetoothDeviceClientImpl::OnError, 165 weak_ptr_factory_.GetWeakPtr(), error_callback)); 166 } 167 168 // BluetoothDeviceClient override. 169 virtual void ConnectProfile(const dbus::ObjectPath& object_path, 170 const std::string& uuid, 171 const base::Closure& callback, 172 const ErrorCallback& error_callback) OVERRIDE { 173 dbus::MethodCall method_call( 174 bluetooth_device::kBluetoothDeviceInterface, 175 bluetooth_device::kConnectProfile); 176 177 dbus::MessageWriter writer(&method_call); 178 writer.AppendString(uuid); 179 180 dbus::ObjectProxy* object_proxy = 181 object_manager_->GetObjectProxy(object_path); 182 if (!object_proxy) { 183 error_callback.Run(kUnknownDeviceError, ""); 184 return; 185 } 186 187 // Connect may take an arbitrary length of time, so use no timeout. 188 object_proxy->CallMethodWithErrorCallback( 189 &method_call, 190 dbus::ObjectProxy::TIMEOUT_INFINITE, 191 base::Bind(&BluetoothDeviceClientImpl::OnSuccess, 192 weak_ptr_factory_.GetWeakPtr(), callback), 193 base::Bind(&BluetoothDeviceClientImpl::OnError, 194 weak_ptr_factory_.GetWeakPtr(), error_callback)); 195 } 196 197 // BluetoothDeviceClient override. 198 virtual void DisconnectProfile(const dbus::ObjectPath& object_path, 199 const std::string& uuid, 200 const base::Closure& callback, 201 const ErrorCallback& error_callback) 202 OVERRIDE { 203 dbus::MethodCall method_call( 204 bluetooth_device::kBluetoothDeviceInterface, 205 bluetooth_device::kDisconnectProfile); 206 207 dbus::MessageWriter writer(&method_call); 208 writer.AppendString(uuid); 209 210 dbus::ObjectProxy* object_proxy = 211 object_manager_->GetObjectProxy(object_path); 212 if (!object_proxy) { 213 error_callback.Run(kUnknownDeviceError, ""); 214 return; 215 } 216 217 object_proxy->CallMethodWithErrorCallback( 218 &method_call, 219 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, 220 base::Bind(&BluetoothDeviceClientImpl::OnSuccess, 221 weak_ptr_factory_.GetWeakPtr(), callback), 222 base::Bind(&BluetoothDeviceClientImpl::OnError, 223 weak_ptr_factory_.GetWeakPtr(), error_callback)); 224 } 225 226 // BluetoothDeviceClient override. 227 virtual void Pair(const dbus::ObjectPath& object_path, 228 const base::Closure& callback, 229 const ErrorCallback& error_callback) OVERRIDE { 230 dbus::MethodCall method_call( 231 bluetooth_device::kBluetoothDeviceInterface, 232 bluetooth_device::kPair); 233 234 dbus::ObjectProxy* object_proxy = 235 object_manager_->GetObjectProxy(object_path); 236 if (!object_proxy) { 237 error_callback.Run(kUnknownDeviceError, ""); 238 return; 239 } 240 241 // Pairing may take an arbitrary length of time, so use no timeout. 242 object_proxy->CallMethodWithErrorCallback( 243 &method_call, 244 dbus::ObjectProxy::TIMEOUT_INFINITE, 245 base::Bind(&BluetoothDeviceClientImpl::OnSuccess, 246 weak_ptr_factory_.GetWeakPtr(), callback), 247 base::Bind(&BluetoothDeviceClientImpl::OnError, 248 weak_ptr_factory_.GetWeakPtr(), error_callback)); 249 } 250 251 // BluetoothDeviceClient override. 252 virtual void CancelPairing(const dbus::ObjectPath& object_path, 253 const base::Closure& callback, 254 const ErrorCallback& error_callback) 255 OVERRIDE { 256 dbus::MethodCall method_call( 257 bluetooth_device::kBluetoothDeviceInterface, 258 bluetooth_device::kCancelPairing); 259 260 dbus::ObjectProxy* object_proxy = 261 object_manager_->GetObjectProxy(object_path); 262 if (!object_proxy) { 263 error_callback.Run(kUnknownDeviceError, ""); 264 return; 265 } 266 object_proxy->CallMethodWithErrorCallback( 267 &method_call, 268 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, 269 base::Bind(&BluetoothDeviceClientImpl::OnSuccess, 270 weak_ptr_factory_.GetWeakPtr(), callback), 271 base::Bind(&BluetoothDeviceClientImpl::OnError, 272 weak_ptr_factory_.GetWeakPtr(), error_callback)); 273 } 274 275 // BluetoothDeviceClient override. 276 virtual void StartConnectionMonitor( 277 const dbus::ObjectPath& object_path, 278 const base::Closure& callback, 279 const ErrorCallback& error_callback) OVERRIDE { 280 dbus::MethodCall method_call(bluetooth_device::kBluetoothDeviceInterface, 281 bluetooth_device::kStartConnectionMonitor); 282 283 dbus::ObjectProxy* object_proxy = 284 object_manager_->GetObjectProxy(object_path); 285 if (!object_proxy) { 286 error_callback.Run(kUnknownDeviceError, ""); 287 return; 288 } 289 object_proxy->CallMethodWithErrorCallback( 290 &method_call, 291 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, 292 base::Bind(&BluetoothDeviceClientImpl::OnSuccess, 293 weak_ptr_factory_.GetWeakPtr(), 294 callback), 295 base::Bind(&BluetoothDeviceClientImpl::OnError, 296 weak_ptr_factory_.GetWeakPtr(), 297 error_callback)); 298 } 299 300 // BluetoothDeviceClient override. 301 virtual void StopConnectionMonitor( 302 const dbus::ObjectPath& object_path, 303 const base::Closure& callback, 304 const ErrorCallback& error_callback) OVERRIDE { 305 dbus::MethodCall method_call(bluetooth_device::kBluetoothDeviceInterface, 306 bluetooth_device::kStopConnectionMonitor); 307 308 dbus::ObjectProxy* object_proxy = 309 object_manager_->GetObjectProxy(object_path); 310 if (!object_proxy) { 311 error_callback.Run(kUnknownDeviceError, ""); 312 return; 313 } 314 object_proxy->CallMethodWithErrorCallback( 315 &method_call, 316 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, 317 base::Bind(&BluetoothDeviceClientImpl::OnSuccess, 318 weak_ptr_factory_.GetWeakPtr(), 319 callback), 320 base::Bind(&BluetoothDeviceClientImpl::OnError, 321 weak_ptr_factory_.GetWeakPtr(), 322 error_callback)); 323 } 324 325 protected: 326 virtual void Init(dbus::Bus* bus) OVERRIDE { 327 object_manager_ = bus->GetObjectManager( 328 bluetooth_object_manager::kBluetoothObjectManagerServiceName, 329 dbus::ObjectPath( 330 bluetooth_object_manager::kBluetoothObjectManagerServicePath)); 331 object_manager_->RegisterInterface( 332 bluetooth_device::kBluetoothDeviceInterface, this); 333 } 334 335 private: 336 // Called by dbus::ObjectManager when an object with the device interface 337 // is created. Informs observers. 338 virtual void ObjectAdded(const dbus::ObjectPath& object_path, 339 const std::string& interface_name) OVERRIDE { 340 FOR_EACH_OBSERVER(BluetoothDeviceClient::Observer, observers_, 341 DeviceAdded(object_path)); 342 } 343 344 // Called by dbus::ObjectManager when an object with the device interface 345 // is removed. Informs observers. 346 virtual void ObjectRemoved(const dbus::ObjectPath& object_path, 347 const std::string& interface_name) OVERRIDE { 348 FOR_EACH_OBSERVER(BluetoothDeviceClient::Observer, observers_, 349 DeviceRemoved(object_path)); 350 } 351 352 // Called by BluetoothPropertySet when a property value is changed, 353 // either by result of a signal or response to a GetAll() or Get() 354 // call. Informs observers. 355 void OnPropertyChanged(const dbus::ObjectPath& object_path, 356 const std::string& property_name) { 357 FOR_EACH_OBSERVER(BluetoothDeviceClient::Observer, observers_, 358 DevicePropertyChanged(object_path, property_name)); 359 } 360 361 // Called when a response for successful method call is received. 362 void OnSuccess(const base::Closure& callback, 363 dbus::Response* response) { 364 DCHECK(response); 365 callback.Run(); 366 } 367 368 // Called when a response for a failed method call is received. 369 void OnError(const ErrorCallback& error_callback, 370 dbus::ErrorResponse* response) { 371 // Error response has optional error message argument. 372 std::string error_name; 373 std::string error_message; 374 if (response) { 375 dbus::MessageReader reader(response); 376 error_name = response->GetErrorName(); 377 reader.PopString(&error_message); 378 } else { 379 error_name = kNoResponseError; 380 error_message = ""; 381 } 382 error_callback.Run(error_name, error_message); 383 } 384 385 dbus::ObjectManager* object_manager_; 386 387 // List of observers interested in event notifications from us. 388 ObserverList<BluetoothDeviceClient::Observer> observers_; 389 390 // Weak pointer factory for generating 'this' pointers that might live longer 391 // than we do. 392 // Note: This should remain the last member so it'll be destroyed and 393 // invalidate its weak pointers before any other members are destroyed. 394 base::WeakPtrFactory<BluetoothDeviceClientImpl> weak_ptr_factory_; 395 396 DISALLOW_COPY_AND_ASSIGN(BluetoothDeviceClientImpl); 397}; 398 399BluetoothDeviceClient::BluetoothDeviceClient() { 400} 401 402BluetoothDeviceClient::~BluetoothDeviceClient() { 403} 404 405BluetoothDeviceClient* BluetoothDeviceClient::Create() { 406 return new BluetoothDeviceClientImpl(); 407} 408 409} // namespace chromeos 410