Home | History | Annotate | Download | only in bluetooth_low_energy
      1 // Copyright 2014 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 #ifndef CHROME_BROWSER_EXTENSIONS_API_BLUETOOTH_LOW_ENERGY_BLUETOOTH_LOW_ENERGY_EVENT_ROUTER_H_
      6 #define CHROME_BROWSER_EXTENSIONS_API_BLUETOOTH_LOW_ENERGY_BLUETOOTH_LOW_ENERGY_EVENT_ROUTER_H_
      7 
      8 #include <map>
      9 #include <set>
     10 #include <string>
     11 #include <vector>
     12 
     13 #include "base/callback.h"
     14 #include "base/memory/linked_ptr.h"
     15 #include "base/memory/weak_ptr.h"
     16 #include "chrome/common/extensions/api/bluetooth_low_energy.h"
     17 #include "content/public/browser/notification_observer.h"
     18 #include "device/bluetooth/bluetooth_adapter.h"
     19 #include "device/bluetooth/bluetooth_device.h"
     20 #include "device/bluetooth/bluetooth_gatt_service.h"
     21 
     22 namespace base {
     23 
     24 class ListValue;
     25 
     26 }  // namespace base
     27 
     28 namespace content {
     29 
     30 class BrowserContext;
     31 
     32 }  // namespace content
     33 
     34 namespace device {
     35 
     36 class BluetoothGattNotifySession;
     37 
     38 }  // namespace device
     39 
     40 namespace extensions {
     41 
     42 class BluetoothLowEnergyConnection;
     43 class BluetoothLowEnergyNotifySession;
     44 class Extension;
     45 
     46 // The BluetoothLowEnergyEventRouter is used by the bluetoothLowEnergy API to
     47 // interface with the internal Bluetooth API in device/bluetooth.
     48 class BluetoothLowEnergyEventRouter
     49     : public device::BluetoothAdapter::Observer,
     50       public device::BluetoothDevice::Observer,
     51       public device::BluetoothGattService::Observer {
     52  public:
     53   explicit BluetoothLowEnergyEventRouter(content::BrowserContext* context);
     54   virtual ~BluetoothLowEnergyEventRouter();
     55 
     56   // Possible ways that an API method can fail or succeed.
     57   enum Status {
     58     kStatusSuccess = 0,
     59     kStatusErrorPermissionDenied,
     60     kStatusErrorNotFound,
     61     kStatusErrorAlreadyConnected,
     62     kStatusErrorAlreadyNotifying,
     63     kStatusErrorNotConnected,
     64     kStatusErrorNotNotifying,
     65     kStatusErrorInProgress,
     66     kStatusErrorFailed
     67   };
     68 
     69   // Error callback is used by asynchronous methods to report failures.
     70   typedef base::Callback<void(Status)> ErrorCallback;
     71 
     72   // Returns true if Bluetooth is supported on the current platform or if the
     73   // internal |adapter_| instance has been initialized for testing.
     74   bool IsBluetoothSupported() const;
     75 
     76   // Obtains a handle on the BluetoothAdapter and invokes |callback|. Returns
     77   // false, if Bluetooth is not supported. Otherwise, asynchronously initializes
     78   // it and invokes |callback|. Until the first successful call to this method,
     79   // none of the methods in this class will succeed and no device::Bluetooth*
     80   // API events will be observed.
     81   bool InitializeAdapterAndInvokeCallback(const base::Closure& callback);
     82 
     83   // Returns true, if the BluetoothAdapter was initialized.
     84   bool HasAdapter() const;
     85 
     86   // Creates a GATT connection to the device with address |device_address| for
     87   // extension |extension|. The connection is kept alive until the extension is
     88   // unloaded, the device is removed, or is disconnect by the host subsystem.
     89   // |error_callback| is called with an error status in case of failure. If
     90   // |persistent| is true, then the allocated connection resource is persistent
     91   // across unloads.
     92   void Connect(bool persistent,
     93                const Extension* extension,
     94                const std::string& device_address,
     95                const base::Closure& callback,
     96                const ErrorCallback& error_callback);
     97 
     98   // Disconnects the currently open GATT connection of extension |extension| to
     99   // device with address |device_address|. |error_callback| is called with an
    100   // error status in case of failure, e.g. if the device is not found or the
    101   // given
    102   // extension does not have an open connection to the device.
    103   void Disconnect(const Extension* extension,
    104                   const std::string& device_address,
    105                   const base::Closure& callback,
    106                   const ErrorCallback& error_callback);
    107 
    108   // Returns the list of api::bluetooth_low_energy::Service objects associated
    109   // with the Bluetooth device with address |device_address| in |out_services|.
    110   // Returns false, if no device with the given address is known. If the device
    111   // is found but it has no GATT services, then returns true and leaves
    112   // |out_services| empty. Returns true, on success. |out_services| must not
    113   // be NULL. If it is non-empty, then its contents will be cleared.
    114   typedef std::vector<linked_ptr<api::bluetooth_low_energy::Service> >
    115       ServiceList;
    116   bool GetServices(const std::string& device_address,
    117                    ServiceList* out_services) const;
    118 
    119   // Populates |out_service| based on GATT service with instance ID
    120   // |instance_id|. |out_service| must not be NULL.
    121   Status GetService(const std::string& instance_id,
    122                     api::bluetooth_low_energy::Service* out_service) const;
    123 
    124   // Populates |out_services| with the list of GATT services that are included
    125   // by the GATT service with instance ID |instance_id|. Returns false, if not
    126   // GATT service with the given ID is known. If the given service has no
    127   // included services, then |out_service| will be empty. |out_service| must not
    128   // be NULL. If it is non-empty, then its contents will be cleared.
    129   Status GetIncludedServices(const std::string& instance_id,
    130                              ServiceList* out_services) const;
    131 
    132   // Returns the list of api::bluetooth_low_energy::Characteristic objects
    133   // associated with the GATT service with instance ID |instance_id| in
    134   // |out_characteristics|. Returns false, if no service with the given instance
    135   // ID is known. If the service is found but it has no characteristics, then
    136   // returns true and leaves |out_characteristics| empty.
    137   // |out_characteristics| must not be NULL and if it is non-empty,
    138   // then its contents will be cleared. |extension| is the extension that made
    139   // the call.
    140   typedef std::vector<linked_ptr<api::bluetooth_low_energy::Characteristic> >
    141       CharacteristicList;
    142   Status GetCharacteristics(const Extension* extension,
    143                             const std::string& instance_id,
    144                             CharacteristicList* out_characteristics) const;
    145 
    146   // Populates |out_characteristic| based on GATT characteristic with instance
    147   // ID |instance_id|. |out_characteristic| must not be NULL. |extension| is the
    148   // extension that made the call.
    149   Status GetCharacteristic(
    150       const Extension* extension,
    151       const std::string& instance_id,
    152       api::bluetooth_low_energy::Characteristic* out_characteristic) const;
    153 
    154   // Returns the list of api::bluetooth_low_energy::Descriptor objects
    155   // associated with the GATT characteristic with instance ID |instance_id| in
    156   // |out_descriptors|. If the characteristic is found but it has no
    157   // descriptors, then returns true and leaves |out_descriptors| empty.
    158   // |out_descriptors| must not be NULL and if it is non-empty,
    159   // then its contents will be cleared. |extension| is the extension that made
    160   // the call.
    161   typedef std::vector<linked_ptr<api::bluetooth_low_energy::Descriptor> >
    162       DescriptorList;
    163   Status GetDescriptors(const Extension* extension,
    164                         const std::string& instance_id,
    165                         DescriptorList* out_descriptors) const;
    166 
    167   // Populates |out_descriptor| based on GATT characteristic descriptor with
    168   // instance ID |instance_id|. |out_descriptor| must not be NULL.
    169   // |extension| is the extension that made the call.
    170   Status GetDescriptor(
    171       const Extension* extension,
    172       const std::string& instance_id,
    173       api::bluetooth_low_energy::Descriptor* out_descriptor) const;
    174 
    175   // Sends a request to read the value of the characteristic with intance ID
    176   // |instance_id|. Invokes |callback| on success and |error_callback| on
    177   // failure. |extension| is the extension that made the call.
    178   void ReadCharacteristicValue(const Extension* extension,
    179                                const std::string& instance_id,
    180                                const base::Closure& callback,
    181                                const ErrorCallback& error_callback);
    182 
    183   // Sends a request to write the value of the characteristic with instance ID
    184   // |instance_id|. Invokes |callback| on success and |error_callback| on
    185   // failure. |extension| is the extension that made the call.
    186   void WriteCharacteristicValue(const Extension* extension,
    187                                 const std::string& instance_id,
    188                                 const std::vector<uint8>& value,
    189                                 const base::Closure& callback,
    190                                 const ErrorCallback& error_callback);
    191 
    192   // Sends a request to start characteristic notifications from characteristic
    193   // with instance ID |instance_id|, for extension |extension|. Invokes
    194   // |callback| on success and |error_callback| on failure. If |persistent| is
    195   // true, then the allocated connection resource is persistent across unloads.
    196   void StartCharacteristicNotifications(bool persistent,
    197                                         const Extension* extension,
    198                                         const std::string& instance_id,
    199                                         const base::Closure& callback,
    200                                         const ErrorCallback& error_callback);
    201 
    202   // Sends a request to stop characteristic notifications from characteristic
    203   // with instance ID |instance_id|, for extension |extension|. Invokes
    204   // |callback| on success and |error_callback| on failure.
    205   void StopCharacteristicNotifications(const Extension* extension,
    206                                        const std::string& instance_id,
    207                                        const base::Closure& callback,
    208                                        const ErrorCallback& error_callback);
    209 
    210   // Sends a request to read the value of the descriptor with instance ID
    211   // |instance_id|. Invokes |callback| on success and |error_callback| on
    212   // failure. |extension| is the extension that made the call.
    213   void ReadDescriptorValue(const Extension* extension,
    214                            const std::string& instance_id,
    215                            const base::Closure& callback,
    216                            const ErrorCallback& error_callback);
    217 
    218   // Sends a request to write the value of the descriptor with instance ID
    219   // |instance_id|. Invokes |callback| on success and |error_callback| on
    220   // failure. |extension| is the extension that made the call.
    221   void WriteDescriptorValue(const Extension* extension,
    222                             const std::string& instance_id,
    223                             const std::vector<uint8>& value,
    224                             const base::Closure& callback,
    225                             const ErrorCallback& error_callback);
    226 
    227   // Initializes the adapter for testing. Used by unit tests only.
    228   void SetAdapterForTesting(device::BluetoothAdapter* adapter);
    229 
    230   // device::BluetoothAdapter::Observer overrides.
    231   virtual void DeviceAdded(device::BluetoothAdapter* adapter,
    232                            device::BluetoothDevice* device) OVERRIDE;
    233   virtual void DeviceRemoved(device::BluetoothAdapter* adapter,
    234                              device::BluetoothDevice* device) OVERRIDE;
    235 
    236   // device::BluetoothDevice::Observer overrides.
    237   virtual void GattServiceAdded(device::BluetoothDevice* device,
    238                                 device::BluetoothGattService* service) OVERRIDE;
    239   virtual void GattServiceRemoved(
    240       device::BluetoothDevice* device,
    241       device::BluetoothGattService* service) OVERRIDE;
    242 
    243   // device::BluetoothGattService::Observer overrides.
    244   virtual void GattServiceChanged(
    245       device::BluetoothGattService* service) OVERRIDE;
    246   virtual void GattCharacteristicAdded(
    247       device::BluetoothGattService* service,
    248       device::BluetoothGattCharacteristic* characteristic) OVERRIDE;
    249   virtual void GattCharacteristicRemoved(
    250       device::BluetoothGattService* service,
    251       device::BluetoothGattCharacteristic* characteristic) OVERRIDE;
    252   virtual void GattDescriptorAdded(
    253       device::BluetoothGattCharacteristic* characteristic,
    254       device::BluetoothGattDescriptor* descriptor) OVERRIDE;
    255   virtual void GattDescriptorRemoved(
    256       device::BluetoothGattCharacteristic* characteristic,
    257       device::BluetoothGattDescriptor* descriptor) OVERRIDE;
    258   virtual void GattCharacteristicValueChanged(
    259       device::BluetoothGattService* service,
    260       device::BluetoothGattCharacteristic* characteristic,
    261       const std::vector<uint8>& value) OVERRIDE;
    262   virtual void GattDescriptorValueChanged(
    263       device::BluetoothGattCharacteristic* characteristic,
    264       device::BluetoothGattDescriptor* descriptor,
    265       const std::vector<uint8>& value) OVERRIDE;
    266 
    267  private:
    268   // Called by BluetoothAdapterFactory.
    269   void OnGetAdapter(const base::Closure& callback,
    270                     scoped_refptr<device::BluetoothAdapter> adapter);
    271 
    272   // Initializes the identifier for all existing GATT objects and devices.
    273   // Called by OnGetAdapter and SetAdapterForTesting.
    274   void InitializeIdentifierMappings();
    275 
    276   // Sends the event named |event_name| to all listeners of that event that
    277   // have the Bluetooth UUID manifest permission for UUID |uuid| and the
    278   // "low_energy" manifest permission, with |args| as the argument to that
    279   // event. If the event involves a characteristic, then |characteristic_id|
    280   // should be the instance ID of the involved characteristic. Otherwise, an
    281   // empty string should be passed.
    282   void DispatchEventToExtensionsWithPermission(
    283       const std::string& event_name,
    284       const device::BluetoothUUID& uuid,
    285       const std::string& characteristic_id,
    286       scoped_ptr<base::ListValue> args);
    287 
    288   // Returns a BluetoothGattService by its instance ID |instance_id|. Returns
    289   // NULL, if the service cannot be found.
    290   device::BluetoothGattService* FindServiceById(
    291       const std::string& instance_id) const;
    292 
    293   // Returns a BluetoothGattCharacteristic by its instance ID |instance_id|.
    294   // Returns NULL, if the characteristic cannot be found.
    295   device::BluetoothGattCharacteristic* FindCharacteristicById(
    296       const std::string& instance_id) const;
    297 
    298   // Returns a BluetoothGattDescriptor by its instance ID |instance_id|.
    299   // Returns NULL, if the descriptor cannot be found.
    300   device::BluetoothGattDescriptor* FindDescriptorById(
    301       const std::string& instance_id) const;
    302 
    303   // Called by BluetoothGattCharacteristic and BluetoothGattDescriptor in
    304   // response to ReadRemoteCharacteristic and ReadRemoteDescriptor.
    305   void OnValueSuccess(const base::Closure& callback,
    306                       const std::vector<uint8>& value);
    307 
    308   // Called by BluetoothDevice in response to a call to CreateGattConnection.
    309   void OnCreateGattConnection(
    310       bool persistent,
    311       const std::string& extension_id,
    312       const std::string& device_address,
    313       const base::Closure& callback,
    314       scoped_ptr<device::BluetoothGattConnection> connection);
    315 
    316   // Called by BluetoothGattConnection in response to a call to Disconnect.
    317   void OnDisconnect(const std::string& extension_id,
    318                     const std::string& device_address,
    319                     const base::Closure& callback);
    320 
    321   // Called by BluetoothGattCharacteristic and BluetoothGattDescriptor in
    322   // case of an error during the read/write operations.
    323   void OnError(const ErrorCallback& error_callback);
    324 
    325   // Called by BluetoothDevice in response to a call to CreateGattConnection.
    326   void OnConnectError(const std::string& extension_id,
    327                       const std::string& device_address,
    328                       const ErrorCallback& error_callback,
    329                       device::BluetoothDevice::ConnectErrorCode error_code);
    330 
    331   // Called by BluetoothGattCharacteristic in response to a call to
    332   // StartNotifySession.
    333   void OnStartNotifySession(
    334       bool persistent,
    335       const std::string& extension_id,
    336       const std::string& characteristic_id,
    337       const base::Closure& callback,
    338       scoped_ptr<device::BluetoothGattNotifySession> session);
    339 
    340   // Called by BluetoothGattCharacteristic in response to a call to
    341   // StartNotifySession.
    342   void OnStartNotifySessionError(const std::string& extension_id,
    343                                  const std::string& characteristic_id,
    344                                  const ErrorCallback& error_callback);
    345 
    346   // Called by BluetoothGattNotifySession in response to a call to Stop.
    347   void OnStopNotifySession(const std::string& extension_id,
    348                            const std::string& characteristic_id,
    349                            const base::Closure& callback);
    350 
    351   // Finds and returns a BluetoothLowEnergyConnection to device with address
    352   // |device_address| from the managed API resources for extension with ID
    353   // |extension_id|.
    354   BluetoothLowEnergyConnection* FindConnection(
    355       const std::string& extension_id,
    356       const std::string& device_address);
    357 
    358   // Removes the connection to device with address |device_address| from the
    359   // managed API resources for extension with ID |extension_id|. Returns false,
    360   // if the connection could not be found.
    361   bool RemoveConnection(const std::string& extension_id,
    362                         const std::string& device_address);
    363 
    364   // Finds and returns a BluetoothLowEnergyNotifySession associated with
    365   // characteristic with instance ID |characteristic_id| from the managed API
    366   // API resources for extension with ID |extension_id|.
    367   BluetoothLowEnergyNotifySession* FindNotifySession(
    368       const std::string& extension_id,
    369       const std::string& characteristic_id);
    370 
    371   // Removes the notify session associated with characteristic with
    372   // instance ID |characteristic_id| from the managed API resources for
    373   // extension with ID |extension_id|. Returns false, if the session could
    374   // not be found.
    375   bool RemoveNotifySession(const std::string& extension_id,
    376                            const std::string& characteristic_id);
    377 
    378   // Mapping from instance ids to identifiers of owning instances. The keys are
    379   // used to identify individual instances of GATT objects and are used by
    380   // bluetoothLowEnergy API functions to obtain the correct GATT object to
    381   // operate on. Instance IDs are string identifiers that are returned by the
    382   // device/bluetooth API, by calling GetIdentifier() on the corresponding
    383   // device::BluetoothGatt* instance.
    384   //
    385   // This mapping is necessary, as GATT object instances can only be obtained
    386   // from the object that owns it, where raw pointers should not be cached. E.g.
    387   // to obtain a device::BluetoothGattCharacteristic, it is necessary to obtain
    388   // a pointer to the associated device::BluetoothDevice, and then to the
    389   // device::BluetoothGattService that owns the characteristic.
    390   typedef std::map<std::string, std::string> InstanceIdMap;
    391   InstanceIdMap service_id_to_device_address_;
    392   InstanceIdMap chrc_id_to_service_id_;
    393   InstanceIdMap desc_id_to_chrc_id_;
    394 
    395   // Sets of BluetoothDevice and BluetoothGattService objects that are being
    396   // observed, used to remove the BluetoothLowEnergyEventRouter as an observer
    397   // during clean up.
    398   std::set<std::string> observed_devices_;
    399   std::set<std::string> observed_gatt_services_;
    400 
    401   // Pointer to the current BluetoothAdapter instance. This represents a local
    402   // Bluetooth adapter of the system.
    403   scoped_refptr<device::BluetoothAdapter> adapter_;
    404 
    405   // Set of extension ID + device addresses to which a connect/disconnect is
    406   // currently pending.
    407   std::set<std::string> connecting_devices_;
    408   std::set<std::string> disconnecting_devices_;
    409 
    410   // Set of extension ID + characteristic ID to which a request to start a
    411   // notify session is currently pending.
    412   std::set<std::string> pending_session_calls_;
    413 
    414   // BrowserContext passed during initialization.
    415   content::BrowserContext* browser_context_;
    416 
    417   // Note: This should remain the last member so it'll be destroyed and
    418   // invalidate its weak pointers before any other members are destroyed.
    419   base::WeakPtrFactory<BluetoothLowEnergyEventRouter> weak_ptr_factory_;
    420 
    421   DISALLOW_COPY_AND_ASSIGN(BluetoothLowEnergyEventRouter);
    422 };
    423 
    424 }  // namespace extensions
    425 
    426 #endif  // CHROME_BROWSER_EXTENSIONS_API_BLUETOOTH_LOW_ENERGY_BLUETOOTH_LOW_ENERGY_EVENT_ROUTER_H_
    427