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 22namespace base { 23 24class ListValue; 25 26} // namespace base 27 28namespace content { 29 30class BrowserContext; 31 32} // namespace content 33 34namespace device { 35 36class BluetoothGattNotifySession; 37 38} // namespace device 39 40namespace extensions { 41 42class BluetoothLowEnergyConnection; 43class BluetoothLowEnergyNotifySession; 44class Extension; 45 46// The BluetoothLowEnergyEventRouter is used by the bluetoothLowEnergy API to 47// interface with the internal Bluetooth API in device/bluetooth. 48class 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