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_api.h"
10 #include "base/lazy_instance.h"
11 #include "base/strings/stringprintf.h"
12 #include "content/public/browser/browser_thread.h"
13 #include "extensions/browser/api/bluetooth_low_energy/bluetooth_api_advertisement.h"
14 #include "extensions/browser/api/bluetooth_low_energy/utils.h"
15 #include "extensions/browser/event_router.h"
16 #include "extensions/common/api/bluetooth/bluetooth_manifest_data.h"
17 #include "extensions/common/api/bluetooth_low_energy.h"
18 #include "extensions/common/permissions/permissions_data.h"
20 using content::BrowserContext
;
21 using content::BrowserThread
;
23 namespace apibtle
= extensions::api::bluetooth_low_energy
;
25 namespace extensions
{
29 const char kErrorAdapterNotInitialized
[] =
30 "Could not initialize Bluetooth adapter";
31 const char kErrorAlreadyConnected
[] = "Already connected";
32 const char kErrorAlreadyNotifying
[] = "Already notifying";
33 const char kErrorAuthenticationFailed
[] = "Authentication failed";
34 const char kErrorCanceled
[] = "Request canceled";
35 const char kErrorGattNotSupported
[] = "Operation not supported by this service";
36 const char kErrorHigherSecurity
[] = "Higher security needed";
37 const char kErrorInProgress
[] = "In progress";
38 const char kErrorInsufficientAuthorization
[] = "Insufficient authorization";
39 const char kErrorInvalidLength
[] = "Invalid attribute value length";
40 const char kErrorNotConnected
[] = "Not connected";
41 const char kErrorNotFound
[] = "Instance not found";
42 const char kErrorNotNotifying
[] = "Not notifying";
43 const char kErrorOperationFailed
[] = "Operation failed";
44 const char kErrorPermissionDenied
[] = "Permission denied";
45 const char kErrorPlatformNotSupported
[] =
46 "This operation is not supported on the current platform";
47 const char kErrorTimeout
[] = "Operation timed out";
48 const char kErrorUnsupportedDevice
[] =
49 "This device is not supported on the current platform";
50 const char kErrorInvalidAdvertisementLength
[] = "Invalid advertisement length";
51 const char kStatusAdvertisementAlreadyExists
[] =
52 "An advertisement is already advertising";
53 const char kStatusAdvertisementDoesNotExist
[] =
54 "This advertisement does not exist";
56 // Returns the correct error string based on error status |status|. This is used
57 // to set the value of |chrome.runtime.lastError.message| and should not be
58 // passed |BluetoothLowEnergyEventRouter::kStatusSuccess|.
59 std::string
StatusToString(BluetoothLowEnergyEventRouter::Status status
) {
61 case BluetoothLowEnergyEventRouter::kStatusErrorPermissionDenied
:
62 return kErrorPermissionDenied
;
63 case BluetoothLowEnergyEventRouter::kStatusErrorNotFound
:
64 return kErrorNotFound
;
65 case BluetoothLowEnergyEventRouter::kStatusErrorAlreadyConnected
:
66 return kErrorAlreadyConnected
;
67 case BluetoothLowEnergyEventRouter::kStatusErrorAlreadyNotifying
:
68 return kErrorAlreadyNotifying
;
69 case BluetoothLowEnergyEventRouter::kStatusErrorNotConnected
:
70 return kErrorNotConnected
;
71 case BluetoothLowEnergyEventRouter::kStatusErrorInsufficientAuthorization
:
72 return kErrorInsufficientAuthorization
;
73 case BluetoothLowEnergyEventRouter::kStatusErrorNotNotifying
:
74 return kErrorNotNotifying
;
75 case BluetoothLowEnergyEventRouter::kStatusErrorInProgress
:
76 return kErrorInProgress
;
77 case BluetoothLowEnergyEventRouter::kStatusErrorAuthenticationFailed
:
78 return kErrorAuthenticationFailed
;
79 case BluetoothLowEnergyEventRouter::kStatusErrorHigherSecurity
:
80 return kErrorHigherSecurity
;
81 case BluetoothLowEnergyEventRouter::kStatusErrorCanceled
:
82 return kErrorCanceled
;
83 case BluetoothLowEnergyEventRouter::kStatusErrorTimeout
:
85 case BluetoothLowEnergyEventRouter::kStatusErrorUnsupportedDevice
:
86 return kErrorUnsupportedDevice
;
87 case BluetoothLowEnergyEventRouter::kStatusErrorInvalidLength
:
88 return kErrorInvalidLength
;
89 case BluetoothLowEnergyEventRouter::kStatusErrorGattNotSupported
:
90 return kErrorGattNotSupported
;
91 case BluetoothLowEnergyEventRouter::kStatusSuccess
:
95 return kErrorOperationFailed
;
100 extensions::BluetoothLowEnergyEventRouter
* GetEventRouter(
101 BrowserContext
* context
) {
102 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
103 return extensions::BluetoothLowEnergyAPI::Get(context
)->event_router();
106 void DoWorkCallback(const base::Callback
<bool()>& callback
) {
107 DCHECK(!callback
.is_null());
111 scoped_ptr
<device::BluetoothAdvertisement::ManufacturerData
>
112 CreateManufacturerData(
113 std::vector
<linked_ptr
<apibtle::ManufacturerData
>>* manufacturer_data
) {
114 scoped_ptr
<device::BluetoothAdvertisement::ManufacturerData
> created_data(
115 new device::BluetoothAdvertisement::ManufacturerData());
116 for (const auto& it
: *manufacturer_data
) {
117 std::vector
<uint8_t> data(it
->data
.size());
118 std::copy(it
->data
.begin(), it
->data
.end(), data
.begin());
119 (*created_data
)[it
->id
] = data
;
124 scoped_ptr
<device::BluetoothAdvertisement::ServiceData
> CreateServiceData(
125 std::vector
<linked_ptr
<apibtle::ServiceData
>>* service_data
) {
126 scoped_ptr
<device::BluetoothAdvertisement::ServiceData
> created_data(
127 new device::BluetoothAdvertisement::ServiceData());
128 for (const auto& it
: *service_data
) {
129 std::vector
<uint8_t> data(it
->data
.size());
130 std::copy(it
->data
.begin(), it
->data
.end(), data
.begin());
131 (*created_data
)[it
->uuid
] = data
;
139 static base::LazyInstance
<BrowserContextKeyedAPIFactory
<BluetoothLowEnergyAPI
> >
140 g_factory
= LAZY_INSTANCE_INITIALIZER
;
143 BrowserContextKeyedAPIFactory
<BluetoothLowEnergyAPI
>*
144 BluetoothLowEnergyAPI::GetFactoryInstance() {
145 return g_factory
.Pointer();
149 BluetoothLowEnergyAPI
* BluetoothLowEnergyAPI::Get(BrowserContext
* context
) {
150 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
151 return GetFactoryInstance()->Get(context
);
154 BluetoothLowEnergyAPI::BluetoothLowEnergyAPI(BrowserContext
* context
)
155 : event_router_(new BluetoothLowEnergyEventRouter(context
)) {
156 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
159 BluetoothLowEnergyAPI::~BluetoothLowEnergyAPI() {
162 void BluetoothLowEnergyAPI::Shutdown() {
163 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
168 BluetoothLowEnergyExtensionFunction::BluetoothLowEnergyExtensionFunction() {
171 BluetoothLowEnergyExtensionFunction::~BluetoothLowEnergyExtensionFunction() {
174 bool BluetoothLowEnergyExtensionFunction::RunAsync() {
175 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
177 if (!BluetoothManifestData::CheckLowEnergyPermitted(extension())) {
178 error_
= kErrorPermissionDenied
;
182 BluetoothLowEnergyEventRouter
* event_router
=
183 GetEventRouter(browser_context());
184 if (!event_router
->IsBluetoothSupported()) {
185 SetError(kErrorPlatformNotSupported
);
189 // It is safe to pass |this| here as ExtensionFunction is refcounted.
190 if (!event_router
->InitializeAdapterAndInvokeCallback(base::Bind(
192 base::Bind(&BluetoothLowEnergyExtensionFunction::DoWork
, this)))) {
193 SetError(kErrorAdapterNotInitialized
);
200 bool BluetoothLowEnergyConnectFunction::DoWork() {
201 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
203 BluetoothLowEnergyEventRouter
* event_router
=
204 GetEventRouter(browser_context());
206 // The adapter must be initialized at this point, but return an error instead
208 if (!event_router
->HasAdapter()) {
209 SetError(kErrorAdapterNotInitialized
);
214 scoped_ptr
<apibtle::Connect::Params
> params(
215 apibtle::Connect::Params::Create(*args_
));
216 EXTENSION_FUNCTION_VALIDATE(params
.get() != NULL
);
218 bool persistent
= false; // Not persistent by default.
219 apibtle::ConnectProperties
* properties
= params
.get()->properties
.get();
221 persistent
= properties
->persistent
;
223 event_router
->Connect(
226 params
->device_address
,
227 base::Bind(&BluetoothLowEnergyConnectFunction::SuccessCallback
, this),
228 base::Bind(&BluetoothLowEnergyConnectFunction::ErrorCallback
, this));
233 void BluetoothLowEnergyConnectFunction::SuccessCallback() {
237 void BluetoothLowEnergyConnectFunction::ErrorCallback(
238 BluetoothLowEnergyEventRouter::Status status
) {
239 SetError(StatusToString(status
));
243 bool BluetoothLowEnergyDisconnectFunction::DoWork() {
244 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
246 BluetoothLowEnergyEventRouter
* event_router
=
247 GetEventRouter(browser_context());
249 // The adapter must be initialized at this point, but return an error instead
251 if (!event_router
->HasAdapter()) {
252 SetError(kErrorAdapterNotInitialized
);
257 scoped_ptr
<apibtle::Disconnect::Params
> params(
258 apibtle::Disconnect::Params::Create(*args_
));
259 EXTENSION_FUNCTION_VALIDATE(params
.get() != NULL
);
261 event_router
->Disconnect(
263 params
->device_address
,
264 base::Bind(&BluetoothLowEnergyDisconnectFunction::SuccessCallback
, this),
265 base::Bind(&BluetoothLowEnergyDisconnectFunction::ErrorCallback
, this));
270 void BluetoothLowEnergyDisconnectFunction::SuccessCallback() {
274 void BluetoothLowEnergyDisconnectFunction::ErrorCallback(
275 BluetoothLowEnergyEventRouter::Status status
) {
276 SetError(StatusToString(status
));
280 bool BluetoothLowEnergyGetServiceFunction::DoWork() {
281 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
283 BluetoothLowEnergyEventRouter
* event_router
=
284 GetEventRouter(browser_context());
286 // The adapter must be initialized at this point, but return an error instead
288 if (!event_router
->HasAdapter()) {
289 SetError(kErrorAdapterNotInitialized
);
294 scoped_ptr
<apibtle::GetService::Params
> params(
295 apibtle::GetService::Params::Create(*args_
));
296 EXTENSION_FUNCTION_VALIDATE(params
.get() != NULL
);
298 apibtle::Service service
;
299 BluetoothLowEnergyEventRouter::Status status
=
300 event_router
->GetService(params
->service_id
, &service
);
301 if (status
!= BluetoothLowEnergyEventRouter::kStatusSuccess
) {
302 SetError(StatusToString(status
));
307 results_
= apibtle::GetService::Results::Create(service
);
313 bool BluetoothLowEnergyGetServicesFunction::DoWork() {
314 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
316 BluetoothLowEnergyEventRouter
* event_router
=
317 GetEventRouter(browser_context());
319 // The adapter must be initialized at this point, but return an error instead
321 if (!event_router
->HasAdapter()) {
322 SetError(kErrorAdapterNotInitialized
);
327 scoped_ptr
<apibtle::GetServices::Params
> params(
328 apibtle::GetServices::Params::Create(*args_
));
329 EXTENSION_FUNCTION_VALIDATE(params
.get() != NULL
);
331 BluetoothLowEnergyEventRouter::ServiceList service_list
;
332 if (!event_router
->GetServices(params
->device_address
, &service_list
)) {
333 SetError(kErrorNotFound
);
338 results_
= apibtle::GetServices::Results::Create(service_list
);
344 bool BluetoothLowEnergyGetCharacteristicFunction::DoWork() {
345 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
347 BluetoothLowEnergyEventRouter
* event_router
=
348 GetEventRouter(browser_context());
350 // The adapter must be initialized at this point, but return an error instead
352 if (!event_router
->HasAdapter()) {
353 SetError(kErrorAdapterNotInitialized
);
358 scoped_ptr
<apibtle::GetCharacteristic::Params
> params(
359 apibtle::GetCharacteristic::Params::Create(*args_
));
360 EXTENSION_FUNCTION_VALIDATE(params
.get() != NULL
);
362 apibtle::Characteristic characteristic
;
363 BluetoothLowEnergyEventRouter::Status status
=
364 event_router
->GetCharacteristic(
365 extension(), params
->characteristic_id
, &characteristic
);
366 if (status
!= BluetoothLowEnergyEventRouter::kStatusSuccess
) {
367 SetError(StatusToString(status
));
372 // Manually construct the result instead of using
373 // apibtle::GetCharacteristic::Result::Create as it doesn't convert lists of
375 SetResult(apibtle::CharacteristicToValue(&characteristic
).release());
381 bool BluetoothLowEnergyGetCharacteristicsFunction::DoWork() {
382 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
384 BluetoothLowEnergyEventRouter
* event_router
=
385 GetEventRouter(browser_context());
387 // The adapter must be initialized at this point, but return an error instead
389 if (!event_router
->HasAdapter()) {
390 SetError(kErrorAdapterNotInitialized
);
395 scoped_ptr
<apibtle::GetCharacteristics::Params
> params(
396 apibtle::GetCharacteristics::Params::Create(*args_
));
397 EXTENSION_FUNCTION_VALIDATE(params
.get() != NULL
);
399 BluetoothLowEnergyEventRouter::CharacteristicList characteristic_list
;
400 BluetoothLowEnergyEventRouter::Status status
=
401 event_router
->GetCharacteristics(
402 extension(), params
->service_id
, &characteristic_list
);
403 if (status
!= BluetoothLowEnergyEventRouter::kStatusSuccess
) {
404 SetError(StatusToString(status
));
409 // Manually construct the result instead of using
410 // apibtle::GetCharacteristics::Result::Create as it doesn't convert lists of
412 scoped_ptr
<base::ListValue
> result(new base::ListValue());
413 for (BluetoothLowEnergyEventRouter::CharacteristicList::iterator iter
=
414 characteristic_list
.begin();
415 iter
!= characteristic_list
.end();
417 result
->Append(apibtle::CharacteristicToValue(iter
->get()).release());
419 SetResult(result
.release());
425 bool BluetoothLowEnergyGetIncludedServicesFunction::DoWork() {
426 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
428 BluetoothLowEnergyEventRouter
* event_router
=
429 GetEventRouter(browser_context());
431 // The adapter must be initialized at this point, but return an error instead
433 if (!event_router
->HasAdapter()) {
434 SetError(kErrorAdapterNotInitialized
);
439 scoped_ptr
<apibtle::GetIncludedServices::Params
> params(
440 apibtle::GetIncludedServices::Params::Create(*args_
));
441 EXTENSION_FUNCTION_VALIDATE(params
.get() != NULL
);
443 BluetoothLowEnergyEventRouter::ServiceList service_list
;
444 BluetoothLowEnergyEventRouter::Status status
=
445 event_router
->GetIncludedServices(params
->service_id
, &service_list
);
446 if (status
!= BluetoothLowEnergyEventRouter::kStatusSuccess
) {
447 SetError(StatusToString(status
));
452 results_
= apibtle::GetIncludedServices::Results::Create(service_list
);
458 bool BluetoothLowEnergyGetDescriptorFunction::DoWork() {
459 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
461 BluetoothLowEnergyEventRouter
* event_router
=
462 GetEventRouter(browser_context());
464 // The adapter must be initialized at this point, but return an error instead
466 if (!event_router
->HasAdapter()) {
467 SetError(kErrorAdapterNotInitialized
);
472 scoped_ptr
<apibtle::GetDescriptor::Params
> params(
473 apibtle::GetDescriptor::Params::Create(*args_
));
474 EXTENSION_FUNCTION_VALIDATE(params
.get() != NULL
);
476 apibtle::Descriptor descriptor
;
477 BluetoothLowEnergyEventRouter::Status status
= event_router
->GetDescriptor(
478 extension(), params
->descriptor_id
, &descriptor
);
479 if (status
!= BluetoothLowEnergyEventRouter::kStatusSuccess
) {
480 SetError(StatusToString(status
));
485 // Manually construct the result instead of using
486 // apibtle::GetDescriptor::Result::Create as it doesn't convert lists of enums
488 SetResult(apibtle::DescriptorToValue(&descriptor
).release());
494 bool BluetoothLowEnergyGetDescriptorsFunction::DoWork() {
495 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
497 BluetoothLowEnergyEventRouter
* event_router
=
498 GetEventRouter(browser_context());
500 // The adapter must be initialized at this point, but return an error instead
502 if (!event_router
->HasAdapter()) {
503 SetError(kErrorAdapterNotInitialized
);
508 scoped_ptr
<apibtle::GetDescriptors::Params
> params(
509 apibtle::GetDescriptors::Params::Create(*args_
));
510 EXTENSION_FUNCTION_VALIDATE(params
.get() != NULL
);
512 BluetoothLowEnergyEventRouter::DescriptorList descriptor_list
;
513 BluetoothLowEnergyEventRouter::Status status
= event_router
->GetDescriptors(
514 extension(), params
->characteristic_id
, &descriptor_list
);
515 if (status
!= BluetoothLowEnergyEventRouter::kStatusSuccess
) {
516 SetError(StatusToString(status
));
521 // Manually construct the result instead of using
522 // apibtle::GetDescriptors::Result::Create as it doesn't convert lists of
524 scoped_ptr
<base::ListValue
> result(new base::ListValue());
525 for (BluetoothLowEnergyEventRouter::DescriptorList::iterator iter
=
526 descriptor_list
.begin();
527 iter
!= descriptor_list
.end();
529 result
->Append(apibtle::DescriptorToValue(iter
->get()).release());
531 SetResult(result
.release());
537 bool BluetoothLowEnergyReadCharacteristicValueFunction::DoWork() {
538 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
540 BluetoothLowEnergyEventRouter
* event_router
=
541 GetEventRouter(browser_context());
543 // The adapter must be initialized at this point, but return an error instead
545 if (!event_router
->HasAdapter()) {
546 SetError(kErrorAdapterNotInitialized
);
551 scoped_ptr
<apibtle::ReadCharacteristicValue::Params
> params(
552 apibtle::ReadCharacteristicValue::Params::Create(*args_
));
553 EXTENSION_FUNCTION_VALIDATE(params
.get() != NULL
);
555 instance_id_
= params
->characteristic_id
;
556 event_router
->ReadCharacteristicValue(
560 &BluetoothLowEnergyReadCharacteristicValueFunction::SuccessCallback
,
563 &BluetoothLowEnergyReadCharacteristicValueFunction::ErrorCallback
,
569 void BluetoothLowEnergyReadCharacteristicValueFunction::SuccessCallback() {
570 // Obtain info on the characteristic and see whether or not the characteristic
572 apibtle::Characteristic characteristic
;
573 BluetoothLowEnergyEventRouter::Status status
=
574 GetEventRouter(browser_context())
575 ->GetCharacteristic(extension(), instance_id_
, &characteristic
);
576 if (status
!= BluetoothLowEnergyEventRouter::kStatusSuccess
) {
577 SetError(StatusToString(status
));
582 // Manually construct the result instead of using
583 // apibtle::GetCharacteristic::Result::Create as it doesn't convert lists of
585 SetResult(apibtle::CharacteristicToValue(&characteristic
).release());
589 void BluetoothLowEnergyReadCharacteristicValueFunction::ErrorCallback(
590 BluetoothLowEnergyEventRouter::Status status
) {
591 SetError(StatusToString(status
));
595 bool BluetoothLowEnergyWriteCharacteristicValueFunction::DoWork() {
596 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
598 BluetoothLowEnergyEventRouter
* event_router
=
599 GetEventRouter(browser_context());
601 // The adapter must be initialized at this point, but return an error instead
603 if (!event_router
->HasAdapter()) {
604 SetError(kErrorAdapterNotInitialized
);
609 scoped_ptr
<apibtle::WriteCharacteristicValue::Params
> params(
610 apibtle::WriteCharacteristicValue::Params::Create(*args_
));
611 EXTENSION_FUNCTION_VALIDATE(params
.get() != NULL
);
613 std::vector
<uint8
> value(params
->value
.begin(), params
->value
.end());
614 event_router
->WriteCharacteristicValue(
616 params
->characteristic_id
,
619 &BluetoothLowEnergyWriteCharacteristicValueFunction::SuccessCallback
,
622 &BluetoothLowEnergyWriteCharacteristicValueFunction::ErrorCallback
,
628 void BluetoothLowEnergyWriteCharacteristicValueFunction::SuccessCallback() {
629 results_
= apibtle::WriteCharacteristicValue::Results::Create();
633 void BluetoothLowEnergyWriteCharacteristicValueFunction::ErrorCallback(
634 BluetoothLowEnergyEventRouter::Status status
) {
635 SetError(StatusToString(status
));
639 bool BluetoothLowEnergyStartCharacteristicNotificationsFunction::DoWork() {
640 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
642 BluetoothLowEnergyEventRouter
* event_router
=
643 GetEventRouter(browser_context());
645 // The adapter must be initialized at this point, but return an error instead
647 if (!event_router
->HasAdapter()) {
648 SetError(kErrorAdapterNotInitialized
);
653 scoped_ptr
<apibtle::StartCharacteristicNotifications::Params
> params(
654 apibtle::StartCharacteristicNotifications::Params::Create(*args_
));
655 EXTENSION_FUNCTION_VALIDATE(params
.get() != NULL
);
657 bool persistent
= false; // Not persistent by default.
658 apibtle::NotificationProperties
* properties
= params
.get()->properties
.get();
660 persistent
= properties
->persistent
;
662 event_router
->StartCharacteristicNotifications(
665 params
->characteristic_id
,
666 base::Bind(&BluetoothLowEnergyStartCharacteristicNotificationsFunction::
669 base::Bind(&BluetoothLowEnergyStartCharacteristicNotificationsFunction::
677 BluetoothLowEnergyStartCharacteristicNotificationsFunction::SuccessCallback() {
681 void BluetoothLowEnergyStartCharacteristicNotificationsFunction::ErrorCallback(
682 BluetoothLowEnergyEventRouter::Status status
) {
683 SetError(StatusToString(status
));
687 bool BluetoothLowEnergyStopCharacteristicNotificationsFunction::DoWork() {
688 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
690 BluetoothLowEnergyEventRouter
* event_router
=
691 GetEventRouter(browser_context());
693 // The adapter must be initialized at this point, but return an error instead
695 if (!event_router
->HasAdapter()) {
696 SetError(kErrorAdapterNotInitialized
);
701 scoped_ptr
<apibtle::StopCharacteristicNotifications::Params
> params(
702 apibtle::StopCharacteristicNotifications::Params::Create(*args_
));
703 EXTENSION_FUNCTION_VALIDATE(params
.get() != NULL
);
705 event_router
->StopCharacteristicNotifications(
707 params
->characteristic_id
,
708 base::Bind(&BluetoothLowEnergyStopCharacteristicNotificationsFunction::
711 base::Bind(&BluetoothLowEnergyStopCharacteristicNotificationsFunction::
719 BluetoothLowEnergyStopCharacteristicNotificationsFunction::SuccessCallback() {
723 void BluetoothLowEnergyStopCharacteristicNotificationsFunction::ErrorCallback(
724 BluetoothLowEnergyEventRouter::Status status
) {
725 SetError(StatusToString(status
));
729 bool BluetoothLowEnergyReadDescriptorValueFunction::DoWork() {
730 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
732 BluetoothLowEnergyEventRouter
* event_router
=
733 GetEventRouter(browser_context());
735 // The adapter must be initialized at this point, but return an error instead
737 if (!event_router
->HasAdapter()) {
738 SetError(kErrorAdapterNotInitialized
);
743 scoped_ptr
<apibtle::ReadDescriptorValue::Params
> params(
744 apibtle::ReadDescriptorValue::Params::Create(*args_
));
745 EXTENSION_FUNCTION_VALIDATE(params
.get() != NULL
);
747 instance_id_
= params
->descriptor_id
;
748 event_router
->ReadDescriptorValue(
752 &BluetoothLowEnergyReadDescriptorValueFunction::SuccessCallback
,
754 base::Bind(&BluetoothLowEnergyReadDescriptorValueFunction::ErrorCallback
,
760 void BluetoothLowEnergyReadDescriptorValueFunction::SuccessCallback() {
761 // Obtain info on the descriptor and see whether or not the descriptor is
763 apibtle::Descriptor descriptor
;
764 BluetoothLowEnergyEventRouter::Status status
=
765 GetEventRouter(browser_context())
766 ->GetDescriptor(extension(), instance_id_
, &descriptor
);
767 if (status
!= BluetoothLowEnergyEventRouter::kStatusSuccess
) {
768 SetError(StatusToString(status
));
773 // Manually construct the result instead of using
774 // apibtle::GetDescriptor::Results::Create as it doesn't convert lists of
776 SetResult(apibtle::DescriptorToValue(&descriptor
).release());
780 void BluetoothLowEnergyReadDescriptorValueFunction::ErrorCallback(
781 BluetoothLowEnergyEventRouter::Status status
) {
782 SetError(StatusToString(status
));
786 bool BluetoothLowEnergyWriteDescriptorValueFunction::DoWork() {
787 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
789 BluetoothLowEnergyEventRouter
* event_router
=
790 GetEventRouter(browser_context());
792 // The adapter must be initialized at this point, but return an error instead
794 if (!event_router
->HasAdapter()) {
795 SetError(kErrorAdapterNotInitialized
);
800 scoped_ptr
<apibtle::WriteDescriptorValue::Params
> params(
801 apibtle::WriteDescriptorValue::Params::Create(*args_
));
802 EXTENSION_FUNCTION_VALIDATE(params
.get() != NULL
);
804 std::vector
<uint8
> value(params
->value
.begin(), params
->value
.end());
805 event_router
->WriteDescriptorValue(
807 params
->descriptor_id
,
810 &BluetoothLowEnergyWriteDescriptorValueFunction::SuccessCallback
,
812 base::Bind(&BluetoothLowEnergyWriteDescriptorValueFunction::ErrorCallback
,
818 void BluetoothLowEnergyWriteDescriptorValueFunction::SuccessCallback() {
819 results_
= apibtle::WriteDescriptorValue::Results::Create();
823 void BluetoothLowEnergyWriteDescriptorValueFunction::ErrorCallback(
824 BluetoothLowEnergyEventRouter::Status status
) {
825 SetError(StatusToString(status
));
829 BluetoothLowEnergyAdvertisementFunction::
830 BluetoothLowEnergyAdvertisementFunction()
831 : advertisements_manager_(nullptr) {
834 BluetoothLowEnergyAdvertisementFunction::
835 ~BluetoothLowEnergyAdvertisementFunction() {
838 int BluetoothLowEnergyAdvertisementFunction::AddAdvertisement(
839 BluetoothApiAdvertisement
* advertisement
) {
840 DCHECK(advertisements_manager_
);
841 return advertisements_manager_
->Add(advertisement
);
844 BluetoothApiAdvertisement
*
845 BluetoothLowEnergyAdvertisementFunction::GetAdvertisement(
846 int advertisement_id
) {
847 DCHECK(advertisements_manager_
);
848 return advertisements_manager_
->Get(extension_id(), advertisement_id
);
851 void BluetoothLowEnergyAdvertisementFunction::RemoveAdvertisement(
852 int advertisement_id
) {
853 DCHECK(advertisements_manager_
);
854 advertisements_manager_
->Remove(extension_id(), advertisement_id
);
857 bool BluetoothLowEnergyAdvertisementFunction::RunAsync() {
859 return BluetoothLowEnergyExtensionFunction::RunAsync();
862 void BluetoothLowEnergyAdvertisementFunction::Initialize() {
863 advertisements_manager_
=
864 ApiResourceManager
<BluetoothApiAdvertisement
>::Get(browser_context());
867 // RegisterAdvertisement:
869 bool BluetoothLowEnergyRegisterAdvertisementFunction::DoWork() {
870 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
872 if (!BluetoothManifestData::CheckPeripheralPermitted(extension())) {
873 error_
= kErrorPermissionDenied
;
878 BluetoothLowEnergyEventRouter
* event_router
=
879 GetEventRouter(browser_context());
881 // The adapter must be initialized at this point, but return an error instead
883 if (!event_router
->HasAdapter()) {
884 SetError(kErrorAdapterNotInitialized
);
889 scoped_ptr
<apibtle::RegisterAdvertisement::Params
> params(
890 apibtle::RegisterAdvertisement::Params::Create(*args_
));
891 EXTENSION_FUNCTION_VALIDATE(params
.get() != NULL
);
893 scoped_ptr
<device::BluetoothAdvertisement::Data
> advertisement_data(
894 new device::BluetoothAdvertisement::Data(
895 params
->advertisement
.type
==
896 apibtle::AdvertisementType::ADVERTISEMENT_TYPE_BROADCAST
897 ? device::BluetoothAdvertisement::AdvertisementType::
898 ADVERTISEMENT_TYPE_BROADCAST
899 : device::BluetoothAdvertisement::AdvertisementType::
900 ADVERTISEMENT_TYPE_PERIPHERAL
));
902 advertisement_data
->set_service_uuids(
903 params
->advertisement
.service_uuids
.Pass());
904 advertisement_data
->set_solicit_uuids(
905 params
->advertisement
.solicit_uuids
.Pass());
906 if (params
->advertisement
.manufacturer_data
) {
907 advertisement_data
->set_manufacturer_data(
908 CreateManufacturerData(params
->advertisement
.manufacturer_data
.get())
911 if (params
->advertisement
.service_data
) {
912 advertisement_data
->set_service_data(
913 CreateServiceData(params
->advertisement
.service_data
.get()).Pass());
916 event_router
->adapter()->RegisterAdvertisement(
917 advertisement_data
.Pass(),
919 &BluetoothLowEnergyRegisterAdvertisementFunction::SuccessCallback
,
922 &BluetoothLowEnergyRegisterAdvertisementFunction::ErrorCallback
,
928 void BluetoothLowEnergyRegisterAdvertisementFunction::SuccessCallback(
929 scoped_refptr
<device::BluetoothAdvertisement
> advertisement
) {
930 results_
= apibtle::RegisterAdvertisement::Results::Create(AddAdvertisement(
931 new BluetoothApiAdvertisement(extension_id(), advertisement
)));
935 void BluetoothLowEnergyRegisterAdvertisementFunction::ErrorCallback(
936 device::BluetoothAdvertisement::ErrorCode status
) {
938 case device::BluetoothAdvertisement::ErrorCode::
939 ERROR_ADVERTISEMENT_ALREADY_EXISTS
:
940 SetError(kStatusAdvertisementAlreadyExists
);
942 case device::BluetoothAdvertisement::ErrorCode::
943 ERROR_ADVERTISEMENT_INVALID_LENGTH
:
944 SetError(kErrorInvalidAdvertisementLength
);
947 SetError(kErrorOperationFailed
);
952 // UnregisterAdvertisement:
954 bool BluetoothLowEnergyUnregisterAdvertisementFunction::DoWork() {
955 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
957 if (!BluetoothManifestData::CheckPeripheralPermitted(extension())) {
958 error_
= kErrorPermissionDenied
;
963 BluetoothLowEnergyEventRouter
* event_router
=
964 GetEventRouter(browser_context());
966 // If we don't have an initialized adapter, unregistering is a no-op.
967 if (!event_router
->HasAdapter())
970 scoped_ptr
<apibtle::UnregisterAdvertisement::Params
> params(
971 apibtle::UnregisterAdvertisement::Params::Create(*args_
));
972 EXTENSION_FUNCTION_VALIDATE(params
.get() != NULL
);
974 BluetoothApiAdvertisement
* advertisement
=
975 GetAdvertisement(params
->advertisement_id
);
976 if (!advertisement
) {
977 error_
= kStatusAdvertisementDoesNotExist
;
982 advertisement
->advertisement()->Unregister(
984 &BluetoothLowEnergyUnregisterAdvertisementFunction::SuccessCallback
,
985 this, params
->advertisement_id
),
987 &BluetoothLowEnergyUnregisterAdvertisementFunction::ErrorCallback
,
988 this, params
->advertisement_id
));
993 void BluetoothLowEnergyUnregisterAdvertisementFunction::SuccessCallback(
994 int advertisement_id
) {
995 RemoveAdvertisement(advertisement_id
);
999 void BluetoothLowEnergyUnregisterAdvertisementFunction::ErrorCallback(
1000 int advertisement_id
,
1001 device::BluetoothAdvertisement::ErrorCode status
) {
1002 RemoveAdvertisement(advertisement_id
);
1004 case device::BluetoothAdvertisement::ErrorCode::
1005 ERROR_ADVERTISEMENT_DOES_NOT_EXIST
:
1006 SetError(kStatusAdvertisementDoesNotExist
);
1009 SetError(kErrorOperationFailed
);
1011 SendResponse(false);
1015 } // namespace extensions