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 #include "extensions/browser/api/bluetooth_low_energy/bluetooth_low_energy_event_router.h"
8 #include "base/logging.h"
9 #include "base/values.h"
10 #include "content/public/browser/browser_thread.h"
11 #include "device/bluetooth/bluetooth_adapter_factory.h"
12 #include "device/bluetooth/bluetooth_gatt_characteristic.h"
13 #include "device/bluetooth/bluetooth_gatt_connection.h"
14 #include "device/bluetooth/bluetooth_gatt_descriptor.h"
15 #include "extensions/browser/api/bluetooth_low_energy/bluetooth_low_energy_connection.h"
16 #include "extensions/browser/api/bluetooth_low_energy/bluetooth_low_energy_notify_session.h"
17 #include "extensions/browser/api/bluetooth_low_energy/utils.h"
18 #include "extensions/browser/event_router.h"
19 #include "extensions/browser/extension_registry.h"
20 #include "extensions/common/api/bluetooth/bluetooth_manifest_data.h"
22 using content::BrowserThread
;
24 using device::BluetoothAdapter
;
25 using device::BluetoothAdapterFactory
;
26 using device::BluetoothDevice
;
27 using device::BluetoothGattCharacteristic
;
28 using device::BluetoothGattConnection
;
29 using device::BluetoothGattDescriptor
;
30 using device::BluetoothGattService
;
32 namespace apibtle
= extensions::core_api::bluetooth_low_energy
;
36 void PopulateService(const BluetoothGattService
* service
,
37 apibtle::Service
* out
) {
40 out
->uuid
= service
->GetUUID().canonical_value();
41 out
->is_primary
= service
->IsPrimary();
42 out
->is_local
= service
->IsLocal();
43 out
->instance_id
.reset(new std::string(service
->GetIdentifier()));
45 if (!service
->GetDevice())
48 out
->device_address
.reset(
49 new std::string(service
->GetDevice()->GetAddress()));
52 void PopulateCharacteristicProperties(
53 BluetoothGattCharacteristic::Properties properties
,
54 std::vector
<apibtle::CharacteristicProperty
>* api_properties
) {
55 DCHECK(api_properties
&& api_properties
->empty());
57 if (properties
== BluetoothGattCharacteristic::PROPERTY_NONE
)
60 if (properties
& BluetoothGattCharacteristic::PROPERTY_BROADCAST
)
61 api_properties
->push_back(apibtle::CHARACTERISTIC_PROPERTY_BROADCAST
);
62 if (properties
& BluetoothGattCharacteristic::PROPERTY_READ
)
63 api_properties
->push_back(apibtle::CHARACTERISTIC_PROPERTY_READ
);
65 BluetoothGattCharacteristic::PROPERTY_WRITE_WITHOUT_RESPONSE
) {
66 api_properties
->push_back(
67 apibtle::CHARACTERISTIC_PROPERTY_WRITEWITHOUTRESPONSE
);
69 if (properties
& BluetoothGattCharacteristic::PROPERTY_WRITE
)
70 api_properties
->push_back(apibtle::CHARACTERISTIC_PROPERTY_WRITE
);
71 if (properties
& BluetoothGattCharacteristic::PROPERTY_NOTIFY
)
72 api_properties
->push_back(apibtle::CHARACTERISTIC_PROPERTY_NOTIFY
);
73 if (properties
& BluetoothGattCharacteristic::PROPERTY_INDICATE
)
74 api_properties
->push_back(apibtle::CHARACTERISTIC_PROPERTY_INDICATE
);
76 BluetoothGattCharacteristic::PROPERTY_AUTHENTICATED_SIGNED_WRITES
) {
77 api_properties
->push_back(
78 apibtle::CHARACTERISTIC_PROPERTY_AUTHENTICATEDSIGNEDWRITES
);
80 if (properties
& BluetoothGattCharacteristic::PROPERTY_EXTENDED_PROPERTIES
) {
81 api_properties
->push_back(
82 apibtle::CHARACTERISTIC_PROPERTY_EXTENDEDPROPERTIES
);
84 if (properties
& BluetoothGattCharacteristic::PROPERTY_RELIABLE_WRITE
)
85 api_properties
->push_back(apibtle::CHARACTERISTIC_PROPERTY_RELIABLEWRITE
);
86 if (properties
& BluetoothGattCharacteristic::PROPERTY_WRITABLE_AUXILIARIES
) {
87 api_properties
->push_back(
88 apibtle::CHARACTERISTIC_PROPERTY_WRITABLEAUXILIARIES
);
92 void PopulateCharacteristic(const BluetoothGattCharacteristic
* characteristic
,
93 apibtle::Characteristic
* out
) {
96 out
->uuid
= characteristic
->GetUUID().canonical_value();
97 out
->is_local
= characteristic
->IsLocal();
98 out
->instance_id
.reset(new std::string(characteristic
->GetIdentifier()));
100 PopulateService(characteristic
->GetService(), &out
->service
);
101 PopulateCharacteristicProperties(characteristic
->GetProperties(),
104 const std::vector
<uint8
>& value
= characteristic
->GetValue();
108 out
->value
.reset(new std::vector
<char>(value
.begin(), value
.end()));
111 void PopulateDescriptor(const BluetoothGattDescriptor
* descriptor
,
112 apibtle::Descriptor
* out
) {
115 out
->uuid
= descriptor
->GetUUID().canonical_value();
116 out
->is_local
= descriptor
->IsLocal();
117 out
->instance_id
.reset(new std::string(descriptor
->GetIdentifier()));
119 PopulateCharacteristic(descriptor
->GetCharacteristic(), &out
->characteristic
);
121 const std::vector
<uint8
>& value
= descriptor
->GetValue();
125 out
->value
.reset(new std::vector
<char>(value
.begin(), value
.end()));
128 typedef extensions::ApiResourceManager
<extensions::BluetoothLowEnergyConnection
>
129 ConnectionResourceManager
;
130 ConnectionResourceManager
* GetConnectionResourceManager(
131 content::BrowserContext
* context
) {
132 ConnectionResourceManager
* manager
= ConnectionResourceManager::Get(context
);
134 << "There is no Bluetooth low energy connection manager. "
135 "If this assertion is failing during a test, then it is likely that "
136 "TestExtensionSystem is failing to provide an instance of "
137 "ApiResourceManager<BluetoothLowEnergyConnection>.";
141 typedef extensions::ApiResourceManager
<
142 extensions::BluetoothLowEnergyNotifySession
> NotifySessionResourceManager
;
143 NotifySessionResourceManager
* GetNotifySessionResourceManager(
144 content::BrowserContext
* context
) {
145 NotifySessionResourceManager
* manager
=
146 NotifySessionResourceManager::Get(context
);
148 << "There is no Bluetooth low energy value update session manager."
149 "If this assertion is failing during a test, then it is likely that "
150 "TestExtensionSystem is failing to provide an instance of "
151 "ApiResourceManager<BluetoothLowEnergyNotifySession>.";
155 // Translates GattErrorCodes to RouterError Codes
156 extensions::BluetoothLowEnergyEventRouter::Status
GattErrorToRouterError(
157 BluetoothGattService::GattErrorCode error_code
) {
158 extensions::BluetoothLowEnergyEventRouter::Status error_status
=
159 extensions::BluetoothLowEnergyEventRouter::kStatusErrorFailed
;
160 if (error_code
== BluetoothGattService::GATT_ERROR_IN_PROGRESS
) {
162 extensions::BluetoothLowEnergyEventRouter::kStatusErrorInProgress
;
163 } else if (error_code
== BluetoothGattService::GATT_ERROR_INVALID_LENGTH
) {
165 extensions::BluetoothLowEnergyEventRouter::kStatusErrorInvalidLength
;
166 } else if (error_code
== BluetoothGattService::GATT_ERROR_NOT_PERMITTED
) {
168 extensions::BluetoothLowEnergyEventRouter::kStatusErrorPermissionDenied
;
169 } else if (error_code
== BluetoothGattService::GATT_ERROR_NOT_AUTHORIZED
) {
170 error_status
= extensions::BluetoothLowEnergyEventRouter::
171 kStatusErrorInsufficientAuthorization
;
172 } else if (error_code
== BluetoothGattService::GATT_ERROR_NOT_PAIRED
) {
174 extensions::BluetoothLowEnergyEventRouter::kStatusErrorHigherSecurity
;
175 } else if (error_code
== BluetoothGattService::GATT_ERROR_NOT_SUPPORTED
) {
177 extensions::BluetoothLowEnergyEventRouter::kStatusErrorGattNotSupported
;
185 namespace extensions
{
187 BluetoothLowEnergyEventRouter::BluetoothLowEnergyEventRouter(
188 content::BrowserContext
* context
)
189 : adapter_(NULL
), browser_context_(context
), weak_ptr_factory_(this) {
190 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
191 DCHECK(browser_context_
);
192 VLOG(1) << "Initializing BluetoothLowEnergyEventRouter.";
194 if (!IsBluetoothSupported()) {
195 VLOG(1) << "Bluetooth not supported on the current platform.";
200 BluetoothLowEnergyEventRouter::~BluetoothLowEnergyEventRouter() {
201 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
205 adapter_
->RemoveObserver(this);
209 bool BluetoothLowEnergyEventRouter::IsBluetoothSupported() const {
210 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
211 return adapter_
.get() ||
212 BluetoothAdapterFactory::IsBluetoothAdapterAvailable();
215 bool BluetoothLowEnergyEventRouter::InitializeAdapterAndInvokeCallback(
216 const base::Closure
& callback
) {
217 if (!IsBluetoothSupported())
220 if (adapter_
.get()) {
225 BluetoothAdapterFactory::GetAdapter(
226 base::Bind(&BluetoothLowEnergyEventRouter::OnGetAdapter
,
227 weak_ptr_factory_
.GetWeakPtr(),
232 bool BluetoothLowEnergyEventRouter::HasAdapter() const {
233 return (adapter_
.get() != NULL
);
236 void BluetoothLowEnergyEventRouter::Connect(
238 const Extension
* extension
,
239 const std::string
& device_address
,
240 const base::Closure
& callback
,
241 const ErrorCallback
& error_callback
) {
242 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
243 if (!adapter_
.get()) {
244 VLOG(1) << "BluetoothAdapter not ready.";
245 error_callback
.Run(kStatusErrorFailed
);
249 const std::string extension_id
= extension
->id();
250 const std::string connect_id
= extension_id
+ device_address
;
252 if (connecting_devices_
.count(connect_id
) != 0) {
253 error_callback
.Run(kStatusErrorInProgress
);
257 BluetoothLowEnergyConnection
* conn
=
258 FindConnection(extension_id
, device_address
);
260 if (conn
->GetConnection()->IsConnected()) {
261 VLOG(1) << "Application already connected to device: " << device_address
;
262 error_callback
.Run(kStatusErrorAlreadyConnected
);
266 // There is a connection object but it's no longer active. Simply remove it.
267 RemoveConnection(extension_id
, device_address
);
270 BluetoothDevice
* device
= adapter_
->GetDevice(device_address
);
272 VLOG(1) << "Bluetooth device not found: " << device_address
;
273 error_callback
.Run(kStatusErrorNotFound
);
277 connecting_devices_
.insert(connect_id
);
278 device
->CreateGattConnection(
279 base::Bind(&BluetoothLowEnergyEventRouter::OnCreateGattConnection
,
280 weak_ptr_factory_
.GetWeakPtr(),
285 base::Bind(&BluetoothLowEnergyEventRouter::OnConnectError
,
286 weak_ptr_factory_
.GetWeakPtr(),
292 void BluetoothLowEnergyEventRouter::Disconnect(
293 const Extension
* extension
,
294 const std::string
& device_address
,
295 const base::Closure
& callback
,
296 const ErrorCallback
& error_callback
) {
297 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
298 if (!adapter_
.get()) {
299 VLOG(1) << "BluetoothAdapter not ready.";
300 error_callback
.Run(kStatusErrorFailed
);
304 const std::string extension_id
= extension
->id();
305 const std::string disconnect_id
= extension_id
+ device_address
;
307 if (disconnecting_devices_
.count(disconnect_id
) != 0) {
308 error_callback
.Run(kStatusErrorInProgress
);
312 BluetoothLowEnergyConnection
* conn
=
313 FindConnection(extension_id
, device_address
);
314 if (!conn
|| !conn
->GetConnection()->IsConnected()) {
315 VLOG(1) << "Application not connected to device: " << device_address
;
316 error_callback
.Run(kStatusErrorNotConnected
);
320 disconnecting_devices_
.insert(disconnect_id
);
321 conn
->GetConnection()->Disconnect(
322 base::Bind(&BluetoothLowEnergyEventRouter::OnDisconnect
,
323 weak_ptr_factory_
.GetWeakPtr(),
329 bool BluetoothLowEnergyEventRouter::GetServices(
330 const std::string
& device_address
,
331 ServiceList
* out_services
) const {
332 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
333 DCHECK(out_services
);
334 if (!adapter_
.get()) {
335 VLOG(1) << "BluetoothAdapter not ready.";
339 BluetoothDevice
* device
= adapter_
->GetDevice(device_address
);
341 VLOG(1) << "Bluetooth device not found: " << device_address
;
345 out_services
->clear();
347 const std::vector
<BluetoothGattService
*>& services
=
348 device
->GetGattServices();
349 for (std::vector
<BluetoothGattService
*>::const_iterator iter
=
351 iter
!= services
.end();
353 // Populate an API service and add it to the return value.
354 const BluetoothGattService
* service
= *iter
;
355 linked_ptr
<apibtle::Service
> api_service(new apibtle::Service());
356 PopulateService(service
, api_service
.get());
358 out_services
->push_back(api_service
);
364 BluetoothLowEnergyEventRouter::Status
BluetoothLowEnergyEventRouter::GetService(
365 const std::string
& instance_id
,
366 apibtle::Service
* out_service
) const {
367 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
369 if (!adapter_
.get()) {
370 VLOG(1) << "BluetoothAdapter not ready.";
371 return kStatusErrorFailed
;
374 BluetoothGattService
* gatt_service
= FindServiceById(instance_id
);
376 VLOG(1) << "Service not found: " << instance_id
;
377 return kStatusErrorNotFound
;
380 PopulateService(gatt_service
, out_service
);
381 return kStatusSuccess
;
384 BluetoothLowEnergyEventRouter::Status
385 BluetoothLowEnergyEventRouter::GetIncludedServices(
386 const std::string
& instance_id
,
387 ServiceList
* out_services
) const {
388 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
389 DCHECK(out_services
);
390 if (!adapter_
.get()) {
391 VLOG(1) << "BluetoothAdapter not ready.";
392 return kStatusErrorFailed
;
395 BluetoothGattService
* service
= FindServiceById(instance_id
);
397 VLOG(1) << "Service not found: " << instance_id
;
398 return kStatusErrorNotFound
;
401 out_services
->clear();
403 const std::vector
<BluetoothGattService
*>& includes
=
404 service
->GetIncludedServices();
405 for (std::vector
<BluetoothGattService
*>::const_iterator iter
=
407 iter
!= includes
.end();
409 // Populate an API service and add it to the return value.
410 const BluetoothGattService
* included
= *iter
;
411 linked_ptr
<apibtle::Service
> api_service(new apibtle::Service());
412 PopulateService(included
, api_service
.get());
414 out_services
->push_back(api_service
);
417 return kStatusSuccess
;
420 BluetoothLowEnergyEventRouter::Status
421 BluetoothLowEnergyEventRouter::GetCharacteristics(
422 const Extension
* extension
,
423 const std::string
& instance_id
,
424 CharacteristicList
* out_characteristics
) const {
425 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
427 DCHECK(out_characteristics
);
428 if (!adapter_
.get()) {
429 VLOG(1) << "BlutoothAdapter not ready.";
430 return kStatusErrorFailed
;
433 BluetoothGattService
* service
= FindServiceById(instance_id
);
435 VLOG(1) << "Service not found: " << instance_id
;
436 return kStatusErrorNotFound
;
439 BluetoothPermissionRequest
request(service
->GetUUID().value());
440 if (!BluetoothManifestData::CheckRequest(extension
, request
)) {
441 VLOG(1) << "App has no permission to access the characteristics of this "
442 << "service: " << instance_id
;
443 return kStatusErrorPermissionDenied
;
446 out_characteristics
->clear();
448 const std::vector
<BluetoothGattCharacteristic
*>& characteristics
=
449 service
->GetCharacteristics();
450 for (std::vector
<BluetoothGattCharacteristic
*>::const_iterator iter
=
451 characteristics
.begin();
452 iter
!= characteristics
.end();
454 // Populate an API characteristic and add it to the return value.
455 const BluetoothGattCharacteristic
* characteristic
= *iter
;
456 linked_ptr
<apibtle::Characteristic
> api_characteristic(
457 new apibtle::Characteristic());
458 PopulateCharacteristic(characteristic
, api_characteristic
.get());
460 out_characteristics
->push_back(api_characteristic
);
463 return kStatusSuccess
;
466 BluetoothLowEnergyEventRouter::Status
467 BluetoothLowEnergyEventRouter::GetCharacteristic(
468 const Extension
* extension
,
469 const std::string
& instance_id
,
470 apibtle::Characteristic
* out_characteristic
) const {
471 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
473 DCHECK(out_characteristic
);
474 if (!adapter_
.get()) {
475 VLOG(1) << "BluetoothAdapter not ready.";
476 return kStatusErrorFailed
;
479 BluetoothGattCharacteristic
* characteristic
=
480 FindCharacteristicById(instance_id
);
481 if (!characteristic
) {
482 VLOG(1) << "Characteristic not found: " << instance_id
;
483 return kStatusErrorNotFound
;
486 BluetoothPermissionRequest
request(
487 characteristic
->GetService()->GetUUID().value());
488 if (!BluetoothManifestData::CheckRequest(extension
, request
)) {
489 VLOG(1) << "App has no permission to access this characteristic: "
491 return kStatusErrorPermissionDenied
;
494 PopulateCharacteristic(characteristic
, out_characteristic
);
495 return kStatusSuccess
;
498 BluetoothLowEnergyEventRouter::Status
499 BluetoothLowEnergyEventRouter::GetDescriptors(
500 const Extension
* extension
,
501 const std::string
& instance_id
,
502 DescriptorList
* out_descriptors
) const {
503 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
505 DCHECK(out_descriptors
);
506 if (!adapter_
.get()) {
507 VLOG(1) << "BlutoothAdapter not ready.";
508 return kStatusErrorFailed
;
511 BluetoothGattCharacteristic
* characteristic
=
512 FindCharacteristicById(instance_id
);
513 if (!characteristic
) {
514 VLOG(1) << "Characteristic not found: " << instance_id
;
515 return kStatusErrorNotFound
;
518 BluetoothPermissionRequest
request(
519 characteristic
->GetService()->GetUUID().value());
520 if (!BluetoothManifestData::CheckRequest(extension
, request
)) {
521 VLOG(1) << "App has no permission to access the descriptors of this "
522 << "characteristic: " << instance_id
;
523 return kStatusErrorPermissionDenied
;
526 out_descriptors
->clear();
528 const std::vector
<BluetoothGattDescriptor
*>& descriptors
=
529 characteristic
->GetDescriptors();
530 for (std::vector
<BluetoothGattDescriptor
*>::const_iterator iter
=
532 iter
!= descriptors
.end();
534 // Populate an API descriptor and add it to the return value.
535 const BluetoothGattDescriptor
* descriptor
= *iter
;
536 linked_ptr
<apibtle::Descriptor
> api_descriptor(new apibtle::Descriptor());
537 PopulateDescriptor(descriptor
, api_descriptor
.get());
539 out_descriptors
->push_back(api_descriptor
);
542 return kStatusSuccess
;
545 BluetoothLowEnergyEventRouter::Status
546 BluetoothLowEnergyEventRouter::GetDescriptor(
547 const Extension
* extension
,
548 const std::string
& instance_id
,
549 core_api::bluetooth_low_energy::Descriptor
* out_descriptor
) const {
550 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
552 DCHECK(out_descriptor
);
553 if (!adapter_
.get()) {
554 VLOG(1) << "BluetoothAdapter not ready.";
555 return kStatusErrorFailed
;
558 BluetoothGattDescriptor
* descriptor
= FindDescriptorById(instance_id
);
560 VLOG(1) << "Descriptor not found: " << instance_id
;
561 return kStatusErrorNotFound
;
564 BluetoothPermissionRequest
request(
565 descriptor
->GetCharacteristic()->GetService()->GetUUID().value());
566 if (!BluetoothManifestData::CheckRequest(extension
, request
)) {
567 VLOG(1) << "App has no permission to access this descriptor: "
569 return kStatusErrorPermissionDenied
;
572 PopulateDescriptor(descriptor
, out_descriptor
);
573 return kStatusSuccess
;
576 void BluetoothLowEnergyEventRouter::ReadCharacteristicValue(
577 const Extension
* extension
,
578 const std::string
& instance_id
,
579 const base::Closure
& callback
,
580 const ErrorCallback
& error_callback
) {
581 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
583 if (!adapter_
.get()) {
584 VLOG(1) << "BluetoothAdapter not ready.";
585 error_callback
.Run(kStatusErrorFailed
);
589 BluetoothGattCharacteristic
* characteristic
=
590 FindCharacteristicById(instance_id
);
591 if (!characteristic
) {
592 VLOG(1) << "Characteristic not found: " << instance_id
;
593 error_callback
.Run(kStatusErrorNotFound
);
597 BluetoothPermissionRequest
request(
598 characteristic
->GetService()->GetUUID().value());
599 if (!BluetoothManifestData::CheckRequest(extension
, request
)) {
600 VLOG(1) << "App has no permission to access this characteristic: "
602 error_callback
.Run(kStatusErrorPermissionDenied
);
606 characteristic
->ReadRemoteCharacteristic(
607 base::Bind(&BluetoothLowEnergyEventRouter::OnValueSuccess
,
608 weak_ptr_factory_
.GetWeakPtr(),
610 base::Bind(&BluetoothLowEnergyEventRouter::OnError
,
611 weak_ptr_factory_
.GetWeakPtr(),
615 void BluetoothLowEnergyEventRouter::WriteCharacteristicValue(
616 const Extension
* extension
,
617 const std::string
& instance_id
,
618 const std::vector
<uint8
>& value
,
619 const base::Closure
& callback
,
620 const ErrorCallback
& error_callback
) {
621 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
623 if (!adapter_
.get()) {
624 VLOG(1) << "BluetoothAdapter not ready.";
625 error_callback
.Run(kStatusErrorFailed
);
629 BluetoothGattCharacteristic
* characteristic
=
630 FindCharacteristicById(instance_id
);
631 if (!characteristic
) {
632 VLOG(1) << "Characteristic not found: " << instance_id
;
633 error_callback
.Run(kStatusErrorNotFound
);
637 BluetoothPermissionRequest
request(
638 characteristic
->GetService()->GetUUID().value());
639 if (!BluetoothManifestData::CheckRequest(extension
, request
)) {
640 VLOG(1) << "App has no permission to access this characteristic: "
642 error_callback
.Run(kStatusErrorPermissionDenied
);
646 characteristic
->WriteRemoteCharacteristic(
649 base::Bind(&BluetoothLowEnergyEventRouter::OnError
,
650 weak_ptr_factory_
.GetWeakPtr(),
654 void BluetoothLowEnergyEventRouter::StartCharacteristicNotifications(
656 const Extension
* extension
,
657 const std::string
& instance_id
,
658 const base::Closure
& callback
,
659 const ErrorCallback
& error_callback
) {
660 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
661 if (!adapter_
.get()) {
662 VLOG(1) << "BluetoothAdapter not ready.";
663 error_callback
.Run(kStatusErrorFailed
);
667 const std::string extension_id
= extension
->id();
668 const std::string session_id
= extension_id
+ instance_id
;
670 if (pending_session_calls_
.count(session_id
) != 0) {
671 error_callback
.Run(kStatusErrorInProgress
);
675 BluetoothLowEnergyNotifySession
* session
=
676 FindNotifySession(extension_id
, instance_id
);
678 if (session
->GetSession()->IsActive()) {
679 VLOG(1) << "Application has already enabled notifications from "
680 << "characteristic: " << instance_id
;
681 error_callback
.Run(kStatusErrorAlreadyNotifying
);
685 RemoveNotifySession(extension_id
, instance_id
);
688 BluetoothGattCharacteristic
* characteristic
=
689 FindCharacteristicById(instance_id
);
690 if (!characteristic
) {
691 VLOG(1) << "Characteristic not found: " << instance_id
;
692 error_callback
.Run(kStatusErrorNotFound
);
696 BluetoothPermissionRequest
request(
697 characteristic
->GetService()->GetUUID().value());
698 if (!BluetoothManifestData::CheckRequest(extension
, request
)) {
699 VLOG(1) << "App has no permission to access this characteristic: "
701 error_callback
.Run(kStatusErrorPermissionDenied
);
705 pending_session_calls_
.insert(session_id
);
706 characteristic
->StartNotifySession(
707 base::Bind(&BluetoothLowEnergyEventRouter::OnStartNotifySession
,
708 weak_ptr_factory_
.GetWeakPtr(),
713 base::Bind(&BluetoothLowEnergyEventRouter::OnStartNotifySessionError
,
714 weak_ptr_factory_
.GetWeakPtr(),
720 void BluetoothLowEnergyEventRouter::StopCharacteristicNotifications(
721 const Extension
* extension
,
722 const std::string
& instance_id
,
723 const base::Closure
& callback
,
724 const ErrorCallback
& error_callback
) {
725 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
726 if (!adapter_
.get()) {
727 VLOG(1) << "BluetoothAdapter not ready.";
728 error_callback
.Run(kStatusErrorFailed
);
732 const std::string extension_id
= extension
->id();
734 BluetoothLowEnergyNotifySession
* session
=
735 FindNotifySession(extension_id
, instance_id
);
736 if (!session
|| !session
->GetSession()->IsActive()) {
737 VLOG(1) << "Application has not enabled notifications from "
738 << "characteristic: " << instance_id
;
739 error_callback
.Run(kStatusErrorNotNotifying
);
743 session
->GetSession()->Stop(
744 base::Bind(&BluetoothLowEnergyEventRouter::OnStopNotifySession
,
745 weak_ptr_factory_
.GetWeakPtr(),
751 void BluetoothLowEnergyEventRouter::ReadDescriptorValue(
752 const Extension
* extension
,
753 const std::string
& instance_id
,
754 const base::Closure
& callback
,
755 const ErrorCallback
& error_callback
) {
756 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
758 if (!adapter_
.get()) {
759 VLOG(1) << "BluetoothAdapter not ready.";
760 error_callback
.Run(kStatusErrorFailed
);
764 BluetoothGattDescriptor
* descriptor
= FindDescriptorById(instance_id
);
766 VLOG(1) << "Descriptor not found: " << instance_id
;
767 error_callback
.Run(kStatusErrorNotFound
);
771 BluetoothPermissionRequest
request(
772 descriptor
->GetCharacteristic()->GetService()->GetUUID().value());
773 if (!BluetoothManifestData::CheckRequest(extension
, request
)) {
774 VLOG(1) << "App has no permission to access this descriptor: "
776 error_callback
.Run(kStatusErrorPermissionDenied
);
780 descriptor
->ReadRemoteDescriptor(
781 base::Bind(&BluetoothLowEnergyEventRouter::OnValueSuccess
,
782 weak_ptr_factory_
.GetWeakPtr(),
784 base::Bind(&BluetoothLowEnergyEventRouter::OnError
,
785 weak_ptr_factory_
.GetWeakPtr(),
789 void BluetoothLowEnergyEventRouter::WriteDescriptorValue(
790 const Extension
* extension
,
791 const std::string
& instance_id
,
792 const std::vector
<uint8
>& value
,
793 const base::Closure
& callback
,
794 const ErrorCallback
& error_callback
) {
795 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
797 if (!adapter_
.get()) {
798 VLOG(1) << "BluetoothAdapter not ready.";
799 error_callback
.Run(kStatusErrorFailed
);
803 BluetoothGattDescriptor
* descriptor
= FindDescriptorById(instance_id
);
805 VLOG(1) << "Descriptor not found: " << instance_id
;
806 error_callback
.Run(kStatusErrorNotFound
);
810 BluetoothPermissionRequest
request(
811 descriptor
->GetCharacteristic()->GetService()->GetUUID().value());
812 if (!BluetoothManifestData::CheckRequest(extension
, request
)) {
813 VLOG(1) << "App has no permission to access this descriptor: "
815 error_callback
.Run(kStatusErrorPermissionDenied
);
819 descriptor
->WriteRemoteDescriptor(
822 base::Bind(&BluetoothLowEnergyEventRouter::OnError
,
823 weak_ptr_factory_
.GetWeakPtr(),
827 void BluetoothLowEnergyEventRouter::SetAdapterForTesting(
828 device::BluetoothAdapter
* adapter
) {
830 InitializeIdentifierMappings();
833 void BluetoothLowEnergyEventRouter::GattServiceAdded(
834 BluetoothAdapter
* adapter
,
835 BluetoothDevice
* device
,
836 BluetoothGattService
* service
) {
837 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
838 DCHECK_EQ(adapter
, adapter_
.get());
839 VLOG(2) << "GATT service added: " << service
->GetIdentifier();
841 DCHECK(service_id_to_device_address_
.find(service
->GetIdentifier()) ==
842 service_id_to_device_address_
.end());
844 service_id_to_device_address_
[service
->GetIdentifier()] =
845 device
->GetAddress();
848 void BluetoothLowEnergyEventRouter::GattServiceRemoved(
849 BluetoothAdapter
* adapter
,
850 BluetoothDevice
* device
,
851 BluetoothGattService
* service
) {
852 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
853 DCHECK_EQ(adapter
, adapter_
.get());
854 VLOG(2) << "GATT service removed: " << service
->GetIdentifier();
856 DCHECK(service_id_to_device_address_
.find(service
->GetIdentifier()) !=
857 service_id_to_device_address_
.end());
859 DCHECK(device
->GetAddress() ==
860 service_id_to_device_address_
[service
->GetIdentifier()]);
861 service_id_to_device_address_
.erase(service
->GetIdentifier());
864 apibtle::Service api_service
;
865 PopulateService(service
, &api_service
);
867 scoped_ptr
<base::ListValue
> args
=
868 apibtle::OnServiceRemoved::Create(api_service
);
869 scoped_ptr
<Event
> event(
870 new Event(apibtle::OnServiceRemoved::kEventName
, args
.Pass()));
871 EventRouter::Get(browser_context_
)->BroadcastEvent(event
.Pass());
874 void BluetoothLowEnergyEventRouter::GattDiscoveryCompleteForService(
875 BluetoothAdapter
* adapter
,
876 BluetoothGattService
* service
) {
877 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
878 DCHECK_EQ(adapter
, adapter_
.get());
879 VLOG(2) << "GATT service discovery complete: " << service
->GetIdentifier();
881 DCHECK(service_id_to_device_address_
.find(service
->GetIdentifier()) !=
882 service_id_to_device_address_
.end());
884 // Signal the service added event here.
885 apibtle::Service api_service
;
886 PopulateService(service
, &api_service
);
888 scoped_ptr
<base::ListValue
> args
=
889 apibtle::OnServiceAdded::Create(api_service
);
890 scoped_ptr
<Event
> event(
891 new Event(apibtle::OnServiceAdded::kEventName
, args
.Pass()));
892 EventRouter::Get(browser_context_
)->BroadcastEvent(event
.Pass());
895 void BluetoothLowEnergyEventRouter::GattServiceChanged(
896 BluetoothAdapter
* adapter
,
897 BluetoothGattService
* service
) {
898 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
899 DCHECK_EQ(adapter
, adapter_
.get());
900 VLOG(2) << "GATT service changed: " << service
->GetIdentifier();
901 DCHECK(service_id_to_device_address_
.find(service
->GetIdentifier()) !=
902 service_id_to_device_address_
.end());
905 apibtle::Service api_service
;
906 PopulateService(service
, &api_service
);
908 DispatchEventToExtensionsWithPermission(
909 apibtle::OnServiceChanged::kEventName
,
911 "" /* characteristic_id */,
912 apibtle::OnServiceChanged::Create(api_service
));
915 void BluetoothLowEnergyEventRouter::GattCharacteristicAdded(
916 BluetoothAdapter
* adapter
,
917 BluetoothGattCharacteristic
* characteristic
) {
918 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
919 DCHECK_EQ(adapter
, adapter_
.get());
920 VLOG(2) << "GATT characteristic added: " << characteristic
->GetIdentifier();
922 BluetoothGattService
* service
= characteristic
->GetService();
925 DCHECK(chrc_id_to_service_id_
.find(characteristic
->GetIdentifier()) ==
926 chrc_id_to_service_id_
.end());
927 DCHECK(service_id_to_device_address_
.find(service
->GetIdentifier()) !=
928 service_id_to_device_address_
.end());
930 chrc_id_to_service_id_
[characteristic
->GetIdentifier()] =
931 service
->GetIdentifier();
934 void BluetoothLowEnergyEventRouter::GattCharacteristicRemoved(
935 BluetoothAdapter
* adapter
,
936 BluetoothGattCharacteristic
* characteristic
) {
937 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
938 DCHECK_EQ(adapter
, adapter_
.get());
939 VLOG(2) << "GATT characteristic removed: " << characteristic
->GetIdentifier();
941 BluetoothGattService
* service
= characteristic
->GetService();
944 DCHECK(chrc_id_to_service_id_
.find(characteristic
->GetIdentifier()) !=
945 chrc_id_to_service_id_
.end());
946 DCHECK(service
->GetIdentifier() ==
947 chrc_id_to_service_id_
[characteristic
->GetIdentifier()]);
949 chrc_id_to_service_id_
.erase(characteristic
->GetIdentifier());
952 void BluetoothLowEnergyEventRouter::GattDescriptorAdded(
953 BluetoothAdapter
* adapter
,
954 BluetoothGattDescriptor
* descriptor
) {
955 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
956 DCHECK_EQ(adapter
, adapter_
.get());
957 VLOG(2) << "GATT descriptor added: " << descriptor
->GetIdentifier();
959 BluetoothGattCharacteristic
* characteristic
= descriptor
->GetCharacteristic();
960 DCHECK(characteristic
);
962 DCHECK(desc_id_to_chrc_id_
.find(descriptor
->GetIdentifier()) ==
963 desc_id_to_chrc_id_
.end());
964 DCHECK(chrc_id_to_service_id_
.find(characteristic
->GetIdentifier()) !=
965 chrc_id_to_service_id_
.end());
967 desc_id_to_chrc_id_
[descriptor
->GetIdentifier()] =
968 characteristic
->GetIdentifier();
971 void BluetoothLowEnergyEventRouter::GattDescriptorRemoved(
972 BluetoothAdapter
* adapter
,
973 BluetoothGattDescriptor
* descriptor
) {
974 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
975 DCHECK_EQ(adapter
, adapter_
.get());
976 VLOG(2) << "GATT descriptor removed: " << descriptor
->GetIdentifier();
978 BluetoothGattCharacteristic
* characteristic
= descriptor
->GetCharacteristic();
979 DCHECK(characteristic
);
981 DCHECK(desc_id_to_chrc_id_
.find(descriptor
->GetIdentifier()) !=
982 desc_id_to_chrc_id_
.end());
983 DCHECK(characteristic
->GetIdentifier() ==
984 desc_id_to_chrc_id_
[descriptor
->GetIdentifier()]);
986 desc_id_to_chrc_id_
.erase(descriptor
->GetIdentifier());
989 void BluetoothLowEnergyEventRouter::GattCharacteristicValueChanged(
990 BluetoothAdapter
* adapter
,
991 BluetoothGattCharacteristic
* characteristic
,
992 const std::vector
<uint8
>& value
) {
993 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
994 DCHECK_EQ(adapter
, adapter_
.get());
995 VLOG(2) << "GATT characteristic value changed: "
996 << characteristic
->GetIdentifier();
998 BluetoothGattService
* service
= characteristic
->GetService();
1001 DCHECK(service_id_to_device_address_
.find(service
->GetIdentifier()) !=
1002 service_id_to_device_address_
.end());
1003 DCHECK(chrc_id_to_service_id_
.find(characteristic
->GetIdentifier()) !=
1004 chrc_id_to_service_id_
.end());
1005 DCHECK(chrc_id_to_service_id_
[characteristic
->GetIdentifier()] ==
1006 service
->GetIdentifier());
1008 // Send the event; manually construct the arguments, instead of using
1009 // apibtle::OnCharacteristicValueChanged::Create, as it doesn't convert
1010 // lists of enums correctly.
1011 apibtle::Characteristic api_characteristic
;
1012 PopulateCharacteristic(characteristic
, &api_characteristic
);
1013 scoped_ptr
<base::ListValue
> args(new base::ListValue());
1014 args
->Append(apibtle::CharacteristicToValue(&api_characteristic
).release());
1016 DispatchEventToExtensionsWithPermission(
1017 apibtle::OnCharacteristicValueChanged::kEventName
,
1019 characteristic
->GetIdentifier(),
1023 void BluetoothLowEnergyEventRouter::GattDescriptorValueChanged(
1024 BluetoothAdapter
* adapter
,
1025 BluetoothGattDescriptor
* descriptor
,
1026 const std::vector
<uint8
>& value
) {
1027 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
1028 DCHECK_EQ(adapter
, adapter_
.get());
1029 VLOG(2) << "GATT descriptor value changed: " << descriptor
->GetIdentifier();
1031 BluetoothGattCharacteristic
* characteristic
= descriptor
->GetCharacteristic();
1032 DCHECK(characteristic
);
1034 DCHECK(desc_id_to_chrc_id_
.find(descriptor
->GetIdentifier()) !=
1035 desc_id_to_chrc_id_
.end());
1036 DCHECK(characteristic
->GetIdentifier() ==
1037 desc_id_to_chrc_id_
[descriptor
->GetIdentifier()]);
1039 // Send the event; manually construct the arguments, instead of using
1040 // apibtle::OnDescriptorValueChanged::Create, as it doesn't convert
1041 // lists of enums correctly.
1042 apibtle::Descriptor api_descriptor
;
1043 PopulateDescriptor(descriptor
, &api_descriptor
);
1044 scoped_ptr
<base::ListValue
> args(new base::ListValue());
1045 args
->Append(apibtle::DescriptorToValue(&api_descriptor
).release());
1047 DispatchEventToExtensionsWithPermission(
1048 apibtle::OnDescriptorValueChanged::kEventName
,
1049 characteristic
->GetService()->GetUUID(),
1050 "" /* characteristic_id */,
1054 void BluetoothLowEnergyEventRouter::OnGetAdapter(
1055 const base::Closure
& callback
,
1056 scoped_refptr
<device::BluetoothAdapter
> adapter
) {
1059 // Initialize instance ID mappings for all discovered GATT objects and add
1061 InitializeIdentifierMappings();
1062 adapter_
->AddObserver(this);
1067 void BluetoothLowEnergyEventRouter::InitializeIdentifierMappings() {
1068 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
1069 DCHECK(service_id_to_device_address_
.empty());
1070 DCHECK(chrc_id_to_service_id_
.empty());
1073 BluetoothAdapter::DeviceList devices
= adapter_
->GetDevices();
1074 for (BluetoothAdapter::DeviceList::iterator iter
= devices
.begin();
1075 iter
!= devices
.end();
1077 BluetoothDevice
* device
= *iter
;
1080 std::vector
<BluetoothGattService
*> services
= device
->GetGattServices();
1081 for (std::vector
<BluetoothGattService
*>::iterator siter
= services
.begin();
1082 siter
!= services
.end();
1084 BluetoothGattService
* service
= *siter
;
1086 const std::string
& service_id
= service
->GetIdentifier();
1087 service_id_to_device_address_
[service_id
] = device
->GetAddress();
1090 const std::vector
<BluetoothGattCharacteristic
*>& characteristics
=
1091 service
->GetCharacteristics();
1092 for (std::vector
<BluetoothGattCharacteristic
*>::const_iterator citer
=
1093 characteristics
.begin();
1094 citer
!= characteristics
.end();
1096 BluetoothGattCharacteristic
* characteristic
= *citer
;
1098 const std::string
& chrc_id
= characteristic
->GetIdentifier();
1099 chrc_id_to_service_id_
[chrc_id
] = service_id
;
1102 const std::vector
<BluetoothGattDescriptor
*>& descriptors
=
1103 characteristic
->GetDescriptors();
1104 for (std::vector
<BluetoothGattDescriptor
*>::const_iterator diter
=
1105 descriptors
.begin();
1106 diter
!= descriptors
.end();
1108 BluetoothGattDescriptor
* descriptor
= *diter
;
1110 const std::string
& desc_id
= descriptor
->GetIdentifier();
1111 desc_id_to_chrc_id_
[desc_id
] = chrc_id
;
1118 void BluetoothLowEnergyEventRouter::DispatchEventToExtensionsWithPermission(
1119 const std::string
& event_name
,
1120 const device::BluetoothUUID
& uuid
,
1121 const std::string
& characteristic_id
,
1122 scoped_ptr
<base::ListValue
> args
) {
1123 // Obtain the listeners of |event_name|. The list can contain multiple
1124 // entries for the same extension, so we keep track of the extensions that we
1125 // already sent the event to, since we want the send an event to an extension
1127 BluetoothPermissionRequest
request(uuid
.value());
1128 std::set
<std::string
> handled_extensions
;
1129 const EventListenerMap::ListenerList listeners
=
1130 EventRouter::Get(browser_context_
)->listeners().GetEventListenersByName(
1133 for (EventListenerMap::ListenerList::const_iterator iter
= listeners
.begin();
1134 iter
!= listeners
.end();
1136 const std::string extension_id
= (*iter
)->extension_id();
1137 if (handled_extensions
.find(extension_id
) != handled_extensions
.end())
1140 handled_extensions
.insert(extension_id
);
1142 const Extension
* extension
=
1143 ExtensionRegistry::Get(browser_context_
)
1144 ->GetExtensionById(extension_id
, ExtensionRegistry::EVERYTHING
);
1146 // For all API methods, the "low_energy" permission check is handled by
1147 // BluetoothLowEnergyExtensionFunction but for events we have to do the
1149 if (!BluetoothManifestData::CheckRequest(extension
, request
) ||
1150 !BluetoothManifestData::CheckLowEnergyPermitted(extension
))
1153 // If |event_name| is "onCharacteristicValueChanged", then send the
1154 // event only if the extension has requested notifications from the
1155 // related characteristic.
1156 if (event_name
== apibtle::OnCharacteristicValueChanged::kEventName
&&
1157 !characteristic_id
.empty() &&
1158 !FindNotifySession(extension_id
, characteristic_id
))
1162 scoped_ptr
<base::ListValue
> args_copy(args
->DeepCopy());
1163 scoped_ptr
<Event
> event(new Event(event_name
, args_copy
.Pass()));
1164 EventRouter::Get(browser_context_
)->DispatchEventToExtension(
1165 extension_id
, event
.Pass());
1169 BluetoothGattService
* BluetoothLowEnergyEventRouter::FindServiceById(
1170 const std::string
& instance_id
) const {
1171 InstanceIdMap::const_iterator iter
=
1172 service_id_to_device_address_
.find(instance_id
);
1173 if (iter
== service_id_to_device_address_
.end()) {
1174 VLOG(1) << "GATT service identifier unknown: " << instance_id
;
1178 const std::string
& address
= iter
->second
;
1180 BluetoothDevice
* device
= adapter_
->GetDevice(address
);
1182 VLOG(1) << "Bluetooth device not found: " << address
;
1186 BluetoothGattService
* service
= device
->GetGattService(instance_id
);
1188 VLOG(1) << "GATT service with ID \"" << instance_id
1189 << "\" not found on device \"" << address
<< "\"";
1196 BluetoothGattCharacteristic
*
1197 BluetoothLowEnergyEventRouter::FindCharacteristicById(
1198 const std::string
& instance_id
) const {
1199 InstanceIdMap::const_iterator iter
= chrc_id_to_service_id_
.find(instance_id
);
1200 if (iter
== chrc_id_to_service_id_
.end()) {
1201 VLOG(1) << "GATT characteristic identifier unknown: " << instance_id
;
1205 const std::string
& service_id
= iter
->second
;
1207 BluetoothGattService
* service
= FindServiceById(service_id
);
1209 VLOG(1) << "Failed to obtain service for characteristic: " << instance_id
;
1213 BluetoothGattCharacteristic
* characteristic
=
1214 service
->GetCharacteristic(instance_id
);
1215 if (!characteristic
) {
1216 VLOG(1) << "GATT characteristic with ID \"" << instance_id
1217 << "\" not found on service \"" << service_id
<< "\"";
1221 return characteristic
;
1224 BluetoothGattDescriptor
* BluetoothLowEnergyEventRouter::FindDescriptorById(
1225 const std::string
& instance_id
) const {
1226 InstanceIdMap::const_iterator iter
= desc_id_to_chrc_id_
.find(instance_id
);
1227 if (iter
== desc_id_to_chrc_id_
.end()) {
1228 VLOG(1) << "GATT descriptor identifier unknown: " << instance_id
;
1232 const std::string
& chrc_id
= iter
->second
;
1233 BluetoothGattCharacteristic
* chrc
= FindCharacteristicById(chrc_id
);
1235 VLOG(1) << "Failed to obtain characteristic for descriptor: "
1240 BluetoothGattDescriptor
* descriptor
= chrc
->GetDescriptor(instance_id
);
1242 VLOG(1) << "GATT descriptor with ID \"" << instance_id
1243 << "\" not found on characteristic \"" << chrc_id
<< "\"";
1250 void BluetoothLowEnergyEventRouter::OnValueSuccess(
1251 const base::Closure
& callback
,
1252 const std::vector
<uint8
>& value
) {
1253 VLOG(2) << "Remote characteristic/descriptor value read successful.";
1257 void BluetoothLowEnergyEventRouter::OnCreateGattConnection(
1259 const std::string
& extension_id
,
1260 const std::string
& device_address
,
1261 const base::Closure
& callback
,
1262 scoped_ptr
<BluetoothGattConnection
> connection
) {
1263 VLOG(2) << "GATT connection created.";
1264 DCHECK(connection
.get());
1265 DCHECK(!FindConnection(extension_id
, device_address
));
1266 DCHECK_EQ(device_address
, connection
->GetDeviceAddress());
1268 const std::string connect_id
= extension_id
+ device_address
;
1269 DCHECK_NE(0U, connecting_devices_
.count(connect_id
));
1271 BluetoothLowEnergyConnection
* conn
= new BluetoothLowEnergyConnection(
1272 persistent
, extension_id
, connection
.Pass());
1273 ConnectionResourceManager
* manager
=
1274 GetConnectionResourceManager(browser_context_
);
1277 connecting_devices_
.erase(connect_id
);
1281 void BluetoothLowEnergyEventRouter::OnDisconnect(
1282 const std::string
& extension_id
,
1283 const std::string
& device_address
,
1284 const base::Closure
& callback
) {
1285 VLOG(2) << "GATT connection terminated.";
1287 const std::string disconnect_id
= extension_id
+ device_address
;
1288 DCHECK_NE(0U, disconnecting_devices_
.count(disconnect_id
));
1290 if (!RemoveConnection(extension_id
, device_address
)) {
1291 VLOG(1) << "The connection was removed before disconnect completed, id: "
1292 << extension_id
<< ", device: " << device_address
;
1295 disconnecting_devices_
.erase(disconnect_id
);
1299 void BluetoothLowEnergyEventRouter::OnError(
1300 const ErrorCallback
& error_callback
,
1301 BluetoothGattService::GattErrorCode error_code
) {
1302 VLOG(2) << "Remote characteristic/descriptor value read/write failed.";
1304 error_callback
.Run(GattErrorToRouterError(error_code
));
1307 void BluetoothLowEnergyEventRouter::OnConnectError(
1308 const std::string
& extension_id
,
1309 const std::string
& device_address
,
1310 const ErrorCallback
& error_callback
,
1311 BluetoothDevice::ConnectErrorCode error_code
) {
1312 VLOG(2) << "Failed to create GATT connection: " << error_code
;
1314 const std::string connect_id
= extension_id
+ device_address
;
1315 DCHECK_NE(0U, connecting_devices_
.count(connect_id
));
1317 connecting_devices_
.erase(connect_id
);
1318 Status error_status
= kStatusErrorFailed
;
1319 if (error_code
== BluetoothDevice::ERROR_INPROGRESS
) {
1320 error_status
= kStatusErrorInProgress
;
1321 } else if (error_code
== BluetoothDevice::ERROR_AUTH_FAILED
||
1322 error_code
== BluetoothDevice::ERROR_AUTH_REJECTED
) {
1323 error_status
= kStatusErrorAuthenticationFailed
;
1324 } else if (error_code
== BluetoothDevice::ERROR_AUTH_CANCELED
) {
1325 error_status
= kStatusErrorCanceled
;
1326 } else if (error_code
== BluetoothDevice::ERROR_AUTH_TIMEOUT
) {
1327 error_status
= kStatusErrorTimeout
;
1328 } else if (error_code
== BluetoothDevice::ERROR_UNSUPPORTED_DEVICE
) {
1329 error_status
= kStatusErrorUnsupportedDevice
;
1331 // ERROR_UNKNOWN and ERROR_FAILED defaulted to kStatusErrorFailed
1333 error_callback
.Run(error_status
);
1336 void BluetoothLowEnergyEventRouter::OnStartNotifySession(
1338 const std::string
& extension_id
,
1339 const std::string
& characteristic_id
,
1340 const base::Closure
& callback
,
1341 scoped_ptr
<device::BluetoothGattNotifySession
> session
) {
1342 VLOG(2) << "Value update session created for characteristic: "
1343 << characteristic_id
;
1344 DCHECK(session
.get());
1345 DCHECK(!FindNotifySession(extension_id
, characteristic_id
));
1346 DCHECK_EQ(characteristic_id
, session
->GetCharacteristicIdentifier());
1348 const std::string session_id
= extension_id
+ characteristic_id
;
1349 DCHECK_NE(0U, pending_session_calls_
.count(session_id
));
1351 BluetoothLowEnergyNotifySession
* resource
=
1352 new BluetoothLowEnergyNotifySession(
1353 persistent
, extension_id
, session
.Pass());
1355 NotifySessionResourceManager
* manager
=
1356 GetNotifySessionResourceManager(browser_context_
);
1357 manager
->Add(resource
);
1359 pending_session_calls_
.erase(session_id
);
1363 void BluetoothLowEnergyEventRouter::OnStartNotifySessionError(
1364 const std::string
& extension_id
,
1365 const std::string
& characteristic_id
,
1366 const ErrorCallback
& error_callback
,
1367 device::BluetoothGattService::GattErrorCode error_code
) {
1368 VLOG(2) << "Failed to create value update session for characteristic: "
1369 << characteristic_id
;
1371 const std::string session_id
= extension_id
+ characteristic_id
;
1372 DCHECK_NE(0U, pending_session_calls_
.count(session_id
));
1374 pending_session_calls_
.erase(session_id
);
1375 error_callback
.Run(GattErrorToRouterError(error_code
));
1378 void BluetoothLowEnergyEventRouter::OnStopNotifySession(
1379 const std::string
& extension_id
,
1380 const std::string
& characteristic_id
,
1381 const base::Closure
& callback
) {
1382 VLOG(2) << "Value update session terminated.";
1384 if (!RemoveNotifySession(extension_id
, characteristic_id
)) {
1385 VLOG(1) << "The value update session was removed before Stop completed, "
1386 << "id: " << extension_id
1387 << ", characteristic: " << characteristic_id
;
1393 BluetoothLowEnergyConnection
* BluetoothLowEnergyEventRouter::FindConnection(
1394 const std::string
& extension_id
,
1395 const std::string
& device_address
) {
1396 ConnectionResourceManager
* manager
=
1397 GetConnectionResourceManager(browser_context_
);
1399 base::hash_set
<int>* connection_ids
= manager
->GetResourceIds(extension_id
);
1400 if (!connection_ids
)
1403 for (base::hash_set
<int>::const_iterator iter
= connection_ids
->begin();
1404 iter
!= connection_ids
->end();
1406 extensions::BluetoothLowEnergyConnection
* conn
=
1407 manager
->Get(extension_id
, *iter
);
1411 if (conn
->GetConnection()->GetDeviceAddress() == device_address
)
1418 bool BluetoothLowEnergyEventRouter::RemoveConnection(
1419 const std::string
& extension_id
,
1420 const std::string
& device_address
) {
1421 ConnectionResourceManager
* manager
=
1422 GetConnectionResourceManager(browser_context_
);
1424 base::hash_set
<int>* connection_ids
= manager
->GetResourceIds(extension_id
);
1425 if (!connection_ids
)
1428 for (base::hash_set
<int>::const_iterator iter
= connection_ids
->begin();
1429 iter
!= connection_ids
->end();
1431 extensions::BluetoothLowEnergyConnection
* conn
=
1432 manager
->Get(extension_id
, *iter
);
1433 if (!conn
|| conn
->GetConnection()->GetDeviceAddress() != device_address
)
1436 manager
->Remove(extension_id
, *iter
);
1443 BluetoothLowEnergyNotifySession
*
1444 BluetoothLowEnergyEventRouter::FindNotifySession(
1445 const std::string
& extension_id
,
1446 const std::string
& characteristic_id
) {
1447 NotifySessionResourceManager
* manager
=
1448 GetNotifySessionResourceManager(browser_context_
);
1450 base::hash_set
<int>* ids
= manager
->GetResourceIds(extension_id
);
1454 for (base::hash_set
<int>::const_iterator iter
= ids
->begin();
1457 BluetoothLowEnergyNotifySession
* session
=
1458 manager
->Get(extension_id
, *iter
);
1462 if (session
->GetSession()->GetCharacteristicIdentifier() ==
1470 bool BluetoothLowEnergyEventRouter::RemoveNotifySession(
1471 const std::string
& extension_id
,
1472 const std::string
& characteristic_id
) {
1473 NotifySessionResourceManager
* manager
=
1474 GetNotifySessionResourceManager(browser_context_
);
1476 base::hash_set
<int>* ids
= manager
->GetResourceIds(extension_id
);
1480 for (base::hash_set
<int>::const_iterator iter
= ids
->begin();
1483 BluetoothLowEnergyNotifySession
* session
=
1484 manager
->Get(extension_id
, *iter
);
1486 session
->GetSession()->GetCharacteristicIdentifier() !=
1490 manager
->Remove(extension_id
, *iter
);
1497 } // namespace extensions