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