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