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 17 namespace chromeos { 18 19 const char BluetoothDeviceClient::kNoResponseError[] = 20 "org.chromium.Error.NoResponse"; 21 const char BluetoothDeviceClient::kUnknownDeviceError[] = 22 "org.chromium.Error.UnknownDevice"; 23 24 BluetoothDeviceClient::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 } 45 46 BluetoothDeviceClient::Properties::~Properties() { 47 } 48 49 50 // The BluetoothDeviceClient implementation used in production. 51 class BluetoothDeviceClientImpl 52 : public BluetoothDeviceClient, 53 public dbus::ObjectManager::Interface { 54 public: 55 BluetoothDeviceClientImpl() : weak_ptr_factory_(this) {} 56 57 virtual ~BluetoothDeviceClientImpl() { 58 object_manager_->UnregisterInterface( 59 bluetooth_device::kBluetoothDeviceInterface); 60 } 61 62 // BluetoothDeviceClient override. 63 virtual void AddObserver(BluetoothDeviceClient::Observer* observer) 64 OVERRIDE { 65 DCHECK(observer); 66 observers_.AddObserver(observer); 67 } 68 69 // BluetoothDeviceClient override. 70 virtual void RemoveObserver(BluetoothDeviceClient::Observer* observer) 71 OVERRIDE { 72 DCHECK(observer); 73 observers_.RemoveObserver(observer); 74 } 75 76 // dbus::ObjectManager::Interface override. 77 virtual dbus::PropertySet* CreateProperties( 78 dbus::ObjectProxy* object_proxy, 79 const dbus::ObjectPath& object_path, 80 const std::string& interface_name) OVERRIDE { 81 Properties* properties = new Properties( 82 object_proxy, 83 interface_name, 84 base::Bind(&BluetoothDeviceClientImpl::OnPropertyChanged, 85 weak_ptr_factory_.GetWeakPtr(), 86 object_path)); 87 return static_cast<dbus::PropertySet*>(properties); 88 } 89 90 // BluetoothDeviceClient override. 91 virtual std::vector<dbus::ObjectPath> GetDevicesForAdapter( 92 const dbus::ObjectPath& adapter_path) OVERRIDE { 93 std::vector<dbus::ObjectPath> object_paths, device_paths; 94 device_paths = object_manager_->GetObjectsWithInterface( 95 bluetooth_device::kBluetoothDeviceInterface); 96 for (std::vector<dbus::ObjectPath>::iterator iter = device_paths.begin(); 97 iter != device_paths.end(); ++iter) { 98 Properties* properties = GetProperties(*iter); 99 if (properties->adapter.value() == adapter_path) 100 object_paths.push_back(*iter); 101 } 102 return object_paths; 103 } 104 105 // BluetoothDeviceClient override. 106 virtual Properties* GetProperties(const dbus::ObjectPath& object_path) 107 OVERRIDE { 108 return static_cast<Properties*>( 109 object_manager_->GetProperties( 110 object_path, 111 bluetooth_device::kBluetoothDeviceInterface)); 112 } 113 114 // BluetoothDeviceClient override. 115 virtual void Connect(const dbus::ObjectPath& object_path, 116 const base::Closure& callback, 117 const ErrorCallback& error_callback) OVERRIDE { 118 dbus::MethodCall method_call( 119 bluetooth_device::kBluetoothDeviceInterface, 120 bluetooth_device::kConnect); 121 122 dbus::ObjectProxy* object_proxy = 123 object_manager_->GetObjectProxy(object_path); 124 if (!object_proxy) { 125 error_callback.Run(kUnknownDeviceError, ""); 126 return; 127 } 128 129 // Connect may take an arbitrary length of time, so use no timeout. 130 object_proxy->CallMethodWithErrorCallback( 131 &method_call, 132 dbus::ObjectProxy::TIMEOUT_INFINITE, 133 base::Bind(&BluetoothDeviceClientImpl::OnSuccess, 134 weak_ptr_factory_.GetWeakPtr(), callback), 135 base::Bind(&BluetoothDeviceClientImpl::OnError, 136 weak_ptr_factory_.GetWeakPtr(), error_callback)); 137 } 138 139 // BluetoothDeviceClient override. 140 virtual void Disconnect(const dbus::ObjectPath& object_path, 141 const base::Closure& callback, 142 const ErrorCallback& error_callback) OVERRIDE { 143 dbus::MethodCall method_call( 144 bluetooth_device::kBluetoothDeviceInterface, 145 bluetooth_device::kDisconnect); 146 147 dbus::ObjectProxy* object_proxy = 148 object_manager_->GetObjectProxy(object_path); 149 if (!object_proxy) { 150 error_callback.Run(kUnknownDeviceError, ""); 151 return; 152 } 153 154 object_proxy->CallMethodWithErrorCallback( 155 &method_call, 156 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, 157 base::Bind(&BluetoothDeviceClientImpl::OnSuccess, 158 weak_ptr_factory_.GetWeakPtr(), callback), 159 base::Bind(&BluetoothDeviceClientImpl::OnError, 160 weak_ptr_factory_.GetWeakPtr(), error_callback)); 161 } 162 163 // BluetoothDeviceClient override. 164 virtual void ConnectProfile(const dbus::ObjectPath& object_path, 165 const std::string& uuid, 166 const base::Closure& callback, 167 const ErrorCallback& error_callback) OVERRIDE { 168 dbus::MethodCall method_call( 169 bluetooth_device::kBluetoothDeviceInterface, 170 bluetooth_device::kConnectProfile); 171 172 dbus::MessageWriter writer(&method_call); 173 writer.AppendString(uuid); 174 175 dbus::ObjectProxy* object_proxy = 176 object_manager_->GetObjectProxy(object_path); 177 if (!object_proxy) { 178 error_callback.Run(kUnknownDeviceError, ""); 179 return; 180 } 181 182 // Connect may take an arbitrary length of time, so use no timeout. 183 object_proxy->CallMethodWithErrorCallback( 184 &method_call, 185 dbus::ObjectProxy::TIMEOUT_INFINITE, 186 base::Bind(&BluetoothDeviceClientImpl::OnSuccess, 187 weak_ptr_factory_.GetWeakPtr(), callback), 188 base::Bind(&BluetoothDeviceClientImpl::OnError, 189 weak_ptr_factory_.GetWeakPtr(), error_callback)); 190 } 191 192 // BluetoothDeviceClient override. 193 virtual void DisconnectProfile(const dbus::ObjectPath& object_path, 194 const std::string& uuid, 195 const base::Closure& callback, 196 const ErrorCallback& error_callback) 197 OVERRIDE { 198 dbus::MethodCall method_call( 199 bluetooth_device::kBluetoothDeviceInterface, 200 bluetooth_device::kDisconnectProfile); 201 202 dbus::MessageWriter writer(&method_call); 203 writer.AppendString(uuid); 204 205 dbus::ObjectProxy* object_proxy = 206 object_manager_->GetObjectProxy(object_path); 207 if (!object_proxy) { 208 error_callback.Run(kUnknownDeviceError, ""); 209 return; 210 } 211 212 object_proxy->CallMethodWithErrorCallback( 213 &method_call, 214 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, 215 base::Bind(&BluetoothDeviceClientImpl::OnSuccess, 216 weak_ptr_factory_.GetWeakPtr(), callback), 217 base::Bind(&BluetoothDeviceClientImpl::OnError, 218 weak_ptr_factory_.GetWeakPtr(), error_callback)); 219 } 220 221 // BluetoothDeviceClient override. 222 virtual void Pair(const dbus::ObjectPath& object_path, 223 const base::Closure& callback, 224 const ErrorCallback& error_callback) OVERRIDE { 225 dbus::MethodCall method_call( 226 bluetooth_device::kBluetoothDeviceInterface, 227 bluetooth_device::kPair); 228 229 dbus::ObjectProxy* object_proxy = 230 object_manager_->GetObjectProxy(object_path); 231 if (!object_proxy) { 232 error_callback.Run(kUnknownDeviceError, ""); 233 return; 234 } 235 236 // Pairing may take an arbitrary length of time, so use no timeout. 237 object_proxy->CallMethodWithErrorCallback( 238 &method_call, 239 dbus::ObjectProxy::TIMEOUT_INFINITE, 240 base::Bind(&BluetoothDeviceClientImpl::OnSuccess, 241 weak_ptr_factory_.GetWeakPtr(), callback), 242 base::Bind(&BluetoothDeviceClientImpl::OnError, 243 weak_ptr_factory_.GetWeakPtr(), error_callback)); 244 } 245 246 // BluetoothDeviceClient override. 247 virtual void CancelPairing(const dbus::ObjectPath& object_path, 248 const base::Closure& callback, 249 const ErrorCallback& error_callback) 250 OVERRIDE { 251 dbus::MethodCall method_call( 252 bluetooth_device::kBluetoothDeviceInterface, 253 bluetooth_device::kCancelPairing); 254 255 dbus::ObjectProxy* object_proxy = 256 object_manager_->GetObjectProxy(object_path); 257 if (!object_proxy) { 258 error_callback.Run(kUnknownDeviceError, ""); 259 return; 260 } 261 object_proxy->CallMethodWithErrorCallback( 262 &method_call, 263 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, 264 base::Bind(&BluetoothDeviceClientImpl::OnSuccess, 265 weak_ptr_factory_.GetWeakPtr(), callback), 266 base::Bind(&BluetoothDeviceClientImpl::OnError, 267 weak_ptr_factory_.GetWeakPtr(), error_callback)); 268 } 269 270 protected: 271 virtual void Init(dbus::Bus* bus) OVERRIDE { 272 object_manager_ = bus->GetObjectManager( 273 bluetooth_object_manager::kBluetoothObjectManagerServiceName, 274 dbus::ObjectPath( 275 bluetooth_object_manager::kBluetoothObjectManagerServicePath)); 276 object_manager_->RegisterInterface( 277 bluetooth_device::kBluetoothDeviceInterface, this); 278 } 279 280 private: 281 // Called by dbus::ObjectManager when an object with the device interface 282 // is created. Informs observers. 283 virtual void ObjectAdded(const dbus::ObjectPath& object_path, 284 const std::string& interface_name) OVERRIDE { 285 FOR_EACH_OBSERVER(BluetoothDeviceClient::Observer, observers_, 286 DeviceAdded(object_path)); 287 } 288 289 // Called by dbus::ObjectManager when an object with the device interface 290 // is removed. Informs observers. 291 virtual void ObjectRemoved(const dbus::ObjectPath& object_path, 292 const std::string& interface_name) OVERRIDE { 293 FOR_EACH_OBSERVER(BluetoothDeviceClient::Observer, observers_, 294 DeviceRemoved(object_path)); 295 } 296 297 // Called by BluetoothPropertySet when a property value is changed, 298 // either by result of a signal or response to a GetAll() or Get() 299 // call. Informs observers. 300 void OnPropertyChanged(const dbus::ObjectPath& object_path, 301 const std::string& property_name) { 302 FOR_EACH_OBSERVER(BluetoothDeviceClient::Observer, observers_, 303 DevicePropertyChanged(object_path, property_name)); 304 } 305 306 // Called when a response for successful method call is received. 307 void OnSuccess(const base::Closure& callback, 308 dbus::Response* response) { 309 DCHECK(response); 310 callback.Run(); 311 } 312 313 // Called when a response for a failed method call is received. 314 void OnError(const ErrorCallback& error_callback, 315 dbus::ErrorResponse* response) { 316 // Error response has optional error message argument. 317 std::string error_name; 318 std::string error_message; 319 if (response) { 320 dbus::MessageReader reader(response); 321 error_name = response->GetErrorName(); 322 reader.PopString(&error_message); 323 } else { 324 error_name = kNoResponseError; 325 error_message = ""; 326 } 327 error_callback.Run(error_name, error_message); 328 } 329 330 dbus::ObjectManager* object_manager_; 331 332 // List of observers interested in event notifications from us. 333 ObserverList<BluetoothDeviceClient::Observer> observers_; 334 335 // Weak pointer factory for generating 'this' pointers that might live longer 336 // than we do. 337 // Note: This should remain the last member so it'll be destroyed and 338 // invalidate its weak pointers before any other members are destroyed. 339 base::WeakPtrFactory<BluetoothDeviceClientImpl> weak_ptr_factory_; 340 341 DISALLOW_COPY_AND_ASSIGN(BluetoothDeviceClientImpl); 342 }; 343 344 BluetoothDeviceClient::BluetoothDeviceClient() { 345 } 346 347 BluetoothDeviceClient::~BluetoothDeviceClient() { 348 } 349 350 BluetoothDeviceClient* BluetoothDeviceClient::Create() { 351 return new BluetoothDeviceClientImpl(); 352 } 353 354 } // namespace chromeos 355