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/common/api/bluetooth_low_energy.h"
32 } // namespace content
36 class BluetoothGattNotifySession;
40 namespace extensions {
42 class BluetoothLowEnergyConnection;
43 class BluetoothLowEnergyNotifySession;
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 {
51 explicit BluetoothLowEnergyEventRouter(content::BrowserContext* context);
52 ~BluetoothLowEnergyEventRouter() override;
54 // Possible ways that an API method can fail or succeed.
57 kStatusErrorAlreadyConnected,
58 kStatusErrorAlreadyNotifying,
59 kStatusErrorAuthenticationFailed,
62 kStatusErrorGattNotSupported,
63 kStatusErrorHigherSecurity,
64 kStatusErrorInProgress,
65 kStatusErrorInsufficientAuthorization,
66 kStatusErrorInvalidLength,
67 kStatusErrorNotConnected,
69 kStatusErrorNotNotifying,
70 kStatusErrorPermissionDenied,
72 kStatusErrorUnsupportedDevice,
75 // Error callback is used by asynchronous methods to report failures.
76 typedef base::Callback<void(Status)> ErrorCallback;
78 // Returns true if Bluetooth is supported on the current platform or if the
79 // internal |adapter_| instance has been initialized for testing.
80 bool IsBluetoothSupported() const;
82 // Obtains a handle on the BluetoothAdapter and invokes |callback|. Returns
83 // false, if Bluetooth is not supported. Otherwise, asynchronously initializes
84 // it and invokes |callback|. Until the first successful call to this method,
85 // none of the methods in this class will succeed and no device::Bluetooth*
86 // API events will be observed.
87 bool InitializeAdapterAndInvokeCallback(const base::Closure& callback);
89 // Returns true, if the BluetoothAdapter was initialized.
90 bool HasAdapter() const;
92 // Creates a GATT connection to the device with address |device_address| for
93 // extension |extension|. The connection is kept alive until the extension is
94 // unloaded, the device is removed, or is disconnect by the host subsystem.
95 // |error_callback| is called with an error status in case of failure. If
96 // |persistent| is true, then the allocated connection resource is persistent
98 void Connect(bool persistent,
99 const Extension* extension,
100 const std::string& device_address,
101 const base::Closure& callback,
102 const ErrorCallback& error_callback);
104 // Disconnects the currently open GATT connection of extension |extension| to
105 // device with address |device_address|. |error_callback| is called with an
106 // error status in case of failure, e.g. if the device is not found or the
108 // extension does not have an open connection to the device.
109 void Disconnect(const Extension* extension,
110 const std::string& device_address,
111 const base::Closure& callback,
112 const ErrorCallback& error_callback);
114 // Returns the list of core_api::bluetooth_low_energy::Service objects
115 // associated with the Bluetooth device with address |device_address| in
117 // Returns false, if no device with the given address is known. If the device
118 // is found but it has no GATT services, then returns true and leaves
119 // |out_services| empty. Returns true, on success. |out_services| must not
120 // be NULL. If it is non-empty, then its contents will be cleared.
121 typedef std::vector<linked_ptr<core_api::bluetooth_low_energy::Service> >
123 bool GetServices(const std::string& device_address,
124 ServiceList* out_services) const;
126 // Populates |out_service| based on GATT service with instance ID
127 // |instance_id|. |out_service| must not be NULL.
128 Status GetService(const std::string& instance_id,
129 core_api::bluetooth_low_energy::Service* out_service) const;
131 // Populates |out_services| with the list of GATT services that are included
132 // by the GATT service with instance ID |instance_id|. Returns false, if not
133 // GATT service with the given ID is known. If the given service has no
134 // included services, then |out_service| will be empty. |out_service| must not
135 // be NULL. If it is non-empty, then its contents will be cleared.
136 Status GetIncludedServices(const std::string& instance_id,
137 ServiceList* out_services) const;
139 // Returns the list of core_api::bluetooth_low_energy::Characteristic objects
140 // associated with the GATT service with instance ID |instance_id| in
141 // |out_characteristics|. Returns false, if no service with the given instance
142 // ID is known. If the service is found but it has no characteristics, then
143 // returns true and leaves |out_characteristics| empty.
144 // |out_characteristics| must not be NULL and if it is non-empty,
145 // then its contents will be cleared. |extension| is the extension that made
148 linked_ptr<core_api::bluetooth_low_energy::Characteristic> >
150 Status GetCharacteristics(const Extension* extension,
151 const std::string& instance_id,
152 CharacteristicList* out_characteristics) const;
154 // Populates |out_characteristic| based on GATT characteristic with instance
155 // ID |instance_id|. |out_characteristic| must not be NULL. |extension| is the
156 // extension that made the call.
157 Status GetCharacteristic(
158 const Extension* extension,
159 const std::string& instance_id,
160 core_api::bluetooth_low_energy::Characteristic* out_characteristic) const;
162 // Returns the list of core_api::bluetooth_low_energy::Descriptor objects
163 // associated with the GATT characteristic with instance ID |instance_id| in
164 // |out_descriptors|. If the characteristic is found but it has no
165 // descriptors, then returns true and leaves |out_descriptors| empty.
166 // |out_descriptors| must not be NULL and if it is non-empty,
167 // then its contents will be cleared. |extension| is the extension that made
169 typedef std::vector<linked_ptr<core_api::bluetooth_low_energy::Descriptor> >
171 Status GetDescriptors(const Extension* extension,
172 const std::string& instance_id,
173 DescriptorList* out_descriptors) const;
175 // Populates |out_descriptor| based on GATT characteristic descriptor with
176 // instance ID |instance_id|. |out_descriptor| must not be NULL.
177 // |extension| is the extension that made the call.
178 Status GetDescriptor(
179 const Extension* extension,
180 const std::string& instance_id,
181 core_api::bluetooth_low_energy::Descriptor* out_descriptor) const;
183 // Sends a request to read the value of the characteristic with intance ID
184 // |instance_id|. Invokes |callback| on success and |error_callback| on
185 // failure. |extension| is the extension that made the call.
186 void ReadCharacteristicValue(const Extension* extension,
187 const std::string& instance_id,
188 const base::Closure& callback,
189 const ErrorCallback& error_callback);
191 // Sends a request to write the value of the characteristic with instance ID
192 // |instance_id|. Invokes |callback| on success and |error_callback| on
193 // failure. |extension| is the extension that made the call.
194 void WriteCharacteristicValue(const Extension* extension,
195 const std::string& instance_id,
196 const std::vector<uint8>& value,
197 const base::Closure& callback,
198 const ErrorCallback& error_callback);
200 // Sends a request to start characteristic notifications from characteristic
201 // with instance ID |instance_id|, for extension |extension|. Invokes
202 // |callback| on success and |error_callback| on failure. If |persistent| is
203 // true, then the allocated connection resource is persistent across unloads.
204 void StartCharacteristicNotifications(bool persistent,
205 const Extension* extension,
206 const std::string& instance_id,
207 const base::Closure& callback,
208 const ErrorCallback& error_callback);
210 // Sends a request to stop characteristic notifications from characteristic
211 // with instance ID |instance_id|, for extension |extension|. Invokes
212 // |callback| on success and |error_callback| on failure.
213 void StopCharacteristicNotifications(const Extension* extension,
214 const std::string& instance_id,
215 const base::Closure& callback,
216 const ErrorCallback& error_callback);
218 // Sends a request to read 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 ReadDescriptorValue(const Extension* extension,
222 const std::string& instance_id,
223 const base::Closure& callback,
224 const ErrorCallback& error_callback);
226 // Sends a request to write the value of the descriptor with instance ID
227 // |instance_id|. Invokes |callback| on success and |error_callback| on
228 // failure. |extension| is the extension that made the call.
229 void WriteDescriptorValue(const Extension* extension,
230 const std::string& instance_id,
231 const std::vector<uint8>& value,
232 const base::Closure& callback,
233 const ErrorCallback& error_callback);
235 // Initializes the adapter for testing. Used by unit tests only.
236 void SetAdapterForTesting(device::BluetoothAdapter* adapter);
238 // device::BluetoothAdapter::Observer overrides.
239 void GattServiceAdded(device::BluetoothAdapter* adapter,
240 device::BluetoothDevice* device,
241 device::BluetoothGattService* service) override;
242 void GattServiceRemoved(device::BluetoothAdapter* adapter,
243 device::BluetoothDevice* device,
244 device::BluetoothGattService* service) override;
245 void GattDiscoveryCompleteForService(
246 device::BluetoothAdapter* adapter,
247 device::BluetoothGattService* service) override;
248 void GattServiceChanged(device::BluetoothAdapter* adapter,
249 device::BluetoothGattService* service) override;
250 void GattCharacteristicAdded(
251 device::BluetoothAdapter* adapter,
252 device::BluetoothGattCharacteristic* characteristic) override;
253 void GattCharacteristicRemoved(
254 device::BluetoothAdapter* adapter,
255 device::BluetoothGattCharacteristic* characteristic) override;
256 void GattDescriptorAdded(
257 device::BluetoothAdapter* adapter,
258 device::BluetoothGattDescriptor* descriptor) override;
259 void GattDescriptorRemoved(
260 device::BluetoothAdapter* adapter,
261 device::BluetoothGattDescriptor* descriptor) override;
262 void GattCharacteristicValueChanged(
263 device::BluetoothAdapter* adapter,
264 device::BluetoothGattCharacteristic* characteristic,
265 const std::vector<uint8>& value) override;
266 void GattDescriptorValueChanged(device::BluetoothAdapter* adapter,
267 device::BluetoothGattDescriptor* descriptor,
268 const std::vector<uint8>& value) override;
271 // Called by BluetoothAdapterFactory.
272 void OnGetAdapter(const base::Closure& callback,
273 scoped_refptr<device::BluetoothAdapter> adapter);
275 // Initializes the identifier for all existing GATT objects and devices.
276 // Called by OnGetAdapter and SetAdapterForTesting.
277 void InitializeIdentifierMappings();
279 // Sends the event named |event_name| to all listeners of that event that
280 // have the Bluetooth UUID manifest permission for UUID |uuid| and the
281 // "low_energy" manifest permission, with |args| as the argument to that
282 // event. If the event involves a characteristic, then |characteristic_id|
283 // should be the instance ID of the involved characteristic. Otherwise, an
284 // empty string should be passed.
285 void DispatchEventToExtensionsWithPermission(
286 const std::string& event_name,
287 const device::BluetoothUUID& uuid,
288 const std::string& characteristic_id,
289 scoped_ptr<base::ListValue> args);
291 // Returns a BluetoothGattService by its instance ID |instance_id|. Returns
292 // NULL, if the service cannot be found.
293 device::BluetoothGattService* FindServiceById(
294 const std::string& instance_id) const;
296 // Returns a BluetoothGattCharacteristic by its instance ID |instance_id|.
297 // Returns NULL, if the characteristic cannot be found.
298 device::BluetoothGattCharacteristic* FindCharacteristicById(
299 const std::string& instance_id) const;
301 // Returns a BluetoothGattDescriptor by its instance ID |instance_id|.
302 // Returns NULL, if the descriptor cannot be found.
303 device::BluetoothGattDescriptor* FindDescriptorById(
304 const std::string& instance_id) const;
306 // Called by BluetoothGattCharacteristic and BluetoothGattDescriptor in
307 // response to ReadRemoteCharacteristic and ReadRemoteDescriptor.
308 void OnValueSuccess(const base::Closure& callback,
309 const std::vector<uint8>& value);
311 // Called by BluetoothDevice in response to a call to CreateGattConnection.
312 void OnCreateGattConnection(
314 const std::string& extension_id,
315 const std::string& device_address,
316 const base::Closure& callback,
317 scoped_ptr<device::BluetoothGattConnection> connection);
319 // Called by BluetoothGattConnection in response to a call to Disconnect.
320 void OnDisconnect(const std::string& extension_id,
321 const std::string& device_address,
322 const base::Closure& callback);
324 // Called by BluetoothGattCharacteristic and BluetoothGattDescriptor in
325 // case of an error during the read/write operations.
326 void OnError(const ErrorCallback& error_callback,
327 device::BluetoothGattService::GattErrorCode error_code);
329 // Called by BluetoothDevice in response to a call to CreateGattConnection.
330 void OnConnectError(const std::string& extension_id,
331 const std::string& device_address,
332 const ErrorCallback& error_callback,
333 device::BluetoothDevice::ConnectErrorCode error_code);
335 // Called by BluetoothGattCharacteristic in response to a call to
336 // StartNotifySession.
337 void OnStartNotifySession(
339 const std::string& extension_id,
340 const std::string& characteristic_id,
341 const base::Closure& callback,
342 scoped_ptr<device::BluetoothGattNotifySession> session);
344 // Called by BluetoothGattCharacteristic in response to a call to
345 // StartNotifySession.
346 void OnStartNotifySessionError(
347 const std::string& extension_id,
348 const std::string& characteristic_id,
349 const ErrorCallback& error_callback,
350 device::BluetoothGattService::GattErrorCode error_code);
352 // Called by BluetoothGattNotifySession in response to a call to Stop.
353 void OnStopNotifySession(const std::string& extension_id,
354 const std::string& characteristic_id,
355 const base::Closure& callback);
357 // Finds and returns a BluetoothLowEnergyConnection to device with address
358 // |device_address| from the managed API resources for extension with ID
360 BluetoothLowEnergyConnection* FindConnection(
361 const std::string& extension_id,
362 const std::string& device_address);
364 // Removes the connection to device with address |device_address| from the
365 // managed API resources for extension with ID |extension_id|. Returns false,
366 // if the connection could not be found.
367 bool RemoveConnection(const std::string& extension_id,
368 const std::string& device_address);
370 // Finds and returns a BluetoothLowEnergyNotifySession associated with
371 // characteristic with instance ID |characteristic_id| from the managed API
372 // API resources for extension with ID |extension_id|.
373 BluetoothLowEnergyNotifySession* FindNotifySession(
374 const std::string& extension_id,
375 const std::string& characteristic_id);
377 // Removes the notify session associated with characteristic with
378 // instance ID |characteristic_id| from the managed API resources for
379 // extension with ID |extension_id|. Returns false, if the session could
381 bool RemoveNotifySession(const std::string& extension_id,
382 const std::string& characteristic_id);
384 // Mapping from instance ids to identifiers of owning instances. The keys are
385 // used to identify individual instances of GATT objects and are used by
386 // bluetoothLowEnergy API functions to obtain the correct GATT object to
387 // operate on. Instance IDs are string identifiers that are returned by the
388 // device/bluetooth API, by calling GetIdentifier() on the corresponding
389 // device::BluetoothGatt* instance.
391 // This mapping is necessary, as GATT object instances can only be obtained
392 // from the object that owns it, where raw pointers should not be cached. E.g.
393 // to obtain a device::BluetoothGattCharacteristic, it is necessary to obtain
394 // a pointer to the associated device::BluetoothDevice, and then to the
395 // device::BluetoothGattService that owns the characteristic.
396 typedef std::map<std::string, std::string> InstanceIdMap;
397 InstanceIdMap service_id_to_device_address_;
398 InstanceIdMap chrc_id_to_service_id_;
399 InstanceIdMap desc_id_to_chrc_id_;
401 // Pointer to the current BluetoothAdapter instance. This represents a local
402 // Bluetooth adapter of the system.
403 scoped_refptr<device::BluetoothAdapter> adapter_;
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_;
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_;
414 // BrowserContext passed during initialization.
415 content::BrowserContext* browser_context_;
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_;
421 DISALLOW_COPY_AND_ASSIGN(BluetoothLowEnergyEventRouter);
424 } // namespace extensions
426 #endif // EXTENSIONS_BROWSER_API_BLUETOOTH_LOW_ENERGY_BLUETOOTH_LOW_ENERGY_EVENT_ROUTER_H_