Home | History | Annotate | Download | only in dbus
      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