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