• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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