Revert "Fix broken channel icon in chrome://help on CrOS" and try again
[chromium-blink-merge.git] / extensions / browser / api / bluetooth_low_energy / bluetooth_low_energy_api.cc
blob5efefe1ab910990b28ae4d21de6b2466b49d3cef
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"
7 #include <algorithm>
9 #include "base/bind.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 {
27 namespace {
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) {
60 switch (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:
84 return kErrorTimeout;
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:
92 NOTREACHED();
93 break;
94 default:
95 return kErrorOperationFailed;
97 return "";
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());
108 callback.Run();
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;
121 return created_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;
133 return created_data;
136 } // namespace
139 static base::LazyInstance<BrowserContextKeyedAPIFactory<BluetoothLowEnergyAPI> >
140 g_factory = LAZY_INSTANCE_INITIALIZER;
142 // static
143 BrowserContextKeyedAPIFactory<BluetoothLowEnergyAPI>*
144 BluetoothLowEnergyAPI::GetFactoryInstance() {
145 return g_factory.Pointer();
148 // static
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);
166 namespace api {
168 BluetoothLowEnergyExtensionFunction::BluetoothLowEnergyExtensionFunction() {
171 BluetoothLowEnergyExtensionFunction::~BluetoothLowEnergyExtensionFunction() {
174 bool BluetoothLowEnergyExtensionFunction::RunAsync() {
175 DCHECK_CURRENTLY_ON(BrowserThread::UI);
177 if (!BluetoothManifestData::CheckLowEnergyPermitted(extension())) {
178 error_ = kErrorPermissionDenied;
179 return false;
182 BluetoothLowEnergyEventRouter* event_router =
183 GetEventRouter(browser_context());
184 if (!event_router->IsBluetoothSupported()) {
185 SetError(kErrorPlatformNotSupported);
186 return false;
189 // It is safe to pass |this| here as ExtensionFunction is refcounted.
190 if (!event_router->InitializeAdapterAndInvokeCallback(base::Bind(
191 &DoWorkCallback,
192 base::Bind(&BluetoothLowEnergyExtensionFunction::DoWork, this)))) {
193 SetError(kErrorAdapterNotInitialized);
194 return false;
197 return true;
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
207 // of asserting.
208 if (!event_router->HasAdapter()) {
209 SetError(kErrorAdapterNotInitialized);
210 SendResponse(false);
211 return false;
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();
220 if (properties)
221 persistent = properties->persistent;
223 event_router->Connect(
224 persistent,
225 extension(),
226 params->device_address,
227 base::Bind(&BluetoothLowEnergyConnectFunction::SuccessCallback, this),
228 base::Bind(&BluetoothLowEnergyConnectFunction::ErrorCallback, this));
230 return true;
233 void BluetoothLowEnergyConnectFunction::SuccessCallback() {
234 SendResponse(true);
237 void BluetoothLowEnergyConnectFunction::ErrorCallback(
238 BluetoothLowEnergyEventRouter::Status status) {
239 SetError(StatusToString(status));
240 SendResponse(false);
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
250 // of asserting.
251 if (!event_router->HasAdapter()) {
252 SetError(kErrorAdapterNotInitialized);
253 SendResponse(false);
254 return false;
257 scoped_ptr<apibtle::Disconnect::Params> params(
258 apibtle::Disconnect::Params::Create(*args_));
259 EXTENSION_FUNCTION_VALIDATE(params.get() != NULL);
261 event_router->Disconnect(
262 extension(),
263 params->device_address,
264 base::Bind(&BluetoothLowEnergyDisconnectFunction::SuccessCallback, this),
265 base::Bind(&BluetoothLowEnergyDisconnectFunction::ErrorCallback, this));
267 return true;
270 void BluetoothLowEnergyDisconnectFunction::SuccessCallback() {
271 SendResponse(true);
274 void BluetoothLowEnergyDisconnectFunction::ErrorCallback(
275 BluetoothLowEnergyEventRouter::Status status) {
276 SetError(StatusToString(status));
277 SendResponse(false);
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
287 // of asserting.
288 if (!event_router->HasAdapter()) {
289 SetError(kErrorAdapterNotInitialized);
290 SendResponse(false);
291 return false;
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));
303 SendResponse(false);
304 return false;
307 results_ = apibtle::GetService::Results::Create(service);
308 SendResponse(true);
310 return true;
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
320 // of asserting.
321 if (!event_router->HasAdapter()) {
322 SetError(kErrorAdapterNotInitialized);
323 SendResponse(false);
324 return false;
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);
334 SendResponse(false);
335 return false;
338 results_ = apibtle::GetServices::Results::Create(service_list);
339 SendResponse(true);
341 return true;
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
351 // of asserting.
352 if (!event_router->HasAdapter()) {
353 SetError(kErrorAdapterNotInitialized);
354 SendResponse(false);
355 return false;
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));
368 SendResponse(false);
369 return false;
372 // Manually construct the result instead of using
373 // apibtle::GetCharacteristic::Result::Create as it doesn't convert lists of
374 // enums correctly.
375 SetResult(apibtle::CharacteristicToValue(&characteristic).release());
376 SendResponse(true);
378 return true;
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
388 // of asserting.
389 if (!event_router->HasAdapter()) {
390 SetError(kErrorAdapterNotInitialized);
391 SendResponse(false);
392 return false;
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));
405 SendResponse(false);
406 return false;
409 // Manually construct the result instead of using
410 // apibtle::GetCharacteristics::Result::Create as it doesn't convert lists of
411 // enums correctly.
412 scoped_ptr<base::ListValue> result(new base::ListValue());
413 for (BluetoothLowEnergyEventRouter::CharacteristicList::iterator iter =
414 characteristic_list.begin();
415 iter != characteristic_list.end();
416 ++iter)
417 result->Append(apibtle::CharacteristicToValue(iter->get()).release());
419 SetResult(result.release());
420 SendResponse(true);
422 return true;
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
432 // of asserting.
433 if (!event_router->HasAdapter()) {
434 SetError(kErrorAdapterNotInitialized);
435 SendResponse(false);
436 return false;
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));
448 SendResponse(false);
449 return false;
452 results_ = apibtle::GetIncludedServices::Results::Create(service_list);
453 SendResponse(true);
455 return true;
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
465 // of asserting.
466 if (!event_router->HasAdapter()) {
467 SetError(kErrorAdapterNotInitialized);
468 SendResponse(false);
469 return false;
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));
481 SendResponse(false);
482 return false;
485 // Manually construct the result instead of using
486 // apibtle::GetDescriptor::Result::Create as it doesn't convert lists of enums
487 // correctly.
488 SetResult(apibtle::DescriptorToValue(&descriptor).release());
489 SendResponse(true);
491 return true;
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
501 // of asserting.
502 if (!event_router->HasAdapter()) {
503 SetError(kErrorAdapterNotInitialized);
504 SendResponse(false);
505 return false;
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));
517 SendResponse(false);
518 return false;
521 // Manually construct the result instead of using
522 // apibtle::GetDescriptors::Result::Create as it doesn't convert lists of
523 // enums correctly.
524 scoped_ptr<base::ListValue> result(new base::ListValue());
525 for (BluetoothLowEnergyEventRouter::DescriptorList::iterator iter =
526 descriptor_list.begin();
527 iter != descriptor_list.end();
528 ++iter)
529 result->Append(apibtle::DescriptorToValue(iter->get()).release());
531 SetResult(result.release());
532 SendResponse(true);
534 return true;
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
544 // of asserting.
545 if (!event_router->HasAdapter()) {
546 SetError(kErrorAdapterNotInitialized);
547 SendResponse(false);
548 return false;
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(
557 extension(),
558 instance_id_,
559 base::Bind(
560 &BluetoothLowEnergyReadCharacteristicValueFunction::SuccessCallback,
561 this),
562 base::Bind(
563 &BluetoothLowEnergyReadCharacteristicValueFunction::ErrorCallback,
564 this));
566 return true;
569 void BluetoothLowEnergyReadCharacteristicValueFunction::SuccessCallback() {
570 // Obtain info on the characteristic and see whether or not the characteristic
571 // is still around.
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));
578 SendResponse(false);
579 return;
582 // Manually construct the result instead of using
583 // apibtle::GetCharacteristic::Result::Create as it doesn't convert lists of
584 // enums correctly.
585 SetResult(apibtle::CharacteristicToValue(&characteristic).release());
586 SendResponse(true);
589 void BluetoothLowEnergyReadCharacteristicValueFunction::ErrorCallback(
590 BluetoothLowEnergyEventRouter::Status status) {
591 SetError(StatusToString(status));
592 SendResponse(false);
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
602 // of asserting.
603 if (!event_router->HasAdapter()) {
604 SetError(kErrorAdapterNotInitialized);
605 SendResponse(false);
606 return false;
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(
615 extension(),
616 params->characteristic_id,
617 value,
618 base::Bind(
619 &BluetoothLowEnergyWriteCharacteristicValueFunction::SuccessCallback,
620 this),
621 base::Bind(
622 &BluetoothLowEnergyWriteCharacteristicValueFunction::ErrorCallback,
623 this));
625 return true;
628 void BluetoothLowEnergyWriteCharacteristicValueFunction::SuccessCallback() {
629 results_ = apibtle::WriteCharacteristicValue::Results::Create();
630 SendResponse(true);
633 void BluetoothLowEnergyWriteCharacteristicValueFunction::ErrorCallback(
634 BluetoothLowEnergyEventRouter::Status status) {
635 SetError(StatusToString(status));
636 SendResponse(false);
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
646 // of asserting.
647 if (!event_router->HasAdapter()) {
648 SetError(kErrorAdapterNotInitialized);
649 SendResponse(false);
650 return false;
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();
659 if (properties)
660 persistent = properties->persistent;
662 event_router->StartCharacteristicNotifications(
663 persistent,
664 extension(),
665 params->characteristic_id,
666 base::Bind(&BluetoothLowEnergyStartCharacteristicNotificationsFunction::
667 SuccessCallback,
668 this),
669 base::Bind(&BluetoothLowEnergyStartCharacteristicNotificationsFunction::
670 ErrorCallback,
671 this));
673 return true;
676 void
677 BluetoothLowEnergyStartCharacteristicNotificationsFunction::SuccessCallback() {
678 SendResponse(true);
681 void BluetoothLowEnergyStartCharacteristicNotificationsFunction::ErrorCallback(
682 BluetoothLowEnergyEventRouter::Status status) {
683 SetError(StatusToString(status));
684 SendResponse(false);
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
694 // of asserting.
695 if (!event_router->HasAdapter()) {
696 SetError(kErrorAdapterNotInitialized);
697 SendResponse(false);
698 return false;
701 scoped_ptr<apibtle::StopCharacteristicNotifications::Params> params(
702 apibtle::StopCharacteristicNotifications::Params::Create(*args_));
703 EXTENSION_FUNCTION_VALIDATE(params.get() != NULL);
705 event_router->StopCharacteristicNotifications(
706 extension(),
707 params->characteristic_id,
708 base::Bind(&BluetoothLowEnergyStopCharacteristicNotificationsFunction::
709 SuccessCallback,
710 this),
711 base::Bind(&BluetoothLowEnergyStopCharacteristicNotificationsFunction::
712 ErrorCallback,
713 this));
715 return true;
718 void
719 BluetoothLowEnergyStopCharacteristicNotificationsFunction::SuccessCallback() {
720 SendResponse(true);
723 void BluetoothLowEnergyStopCharacteristicNotificationsFunction::ErrorCallback(
724 BluetoothLowEnergyEventRouter::Status status) {
725 SetError(StatusToString(status));
726 SendResponse(false);
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
736 // of asserting.
737 if (!event_router->HasAdapter()) {
738 SetError(kErrorAdapterNotInitialized);
739 SendResponse(false);
740 return false;
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(
749 extension(),
750 instance_id_,
751 base::Bind(
752 &BluetoothLowEnergyReadDescriptorValueFunction::SuccessCallback,
753 this),
754 base::Bind(&BluetoothLowEnergyReadDescriptorValueFunction::ErrorCallback,
755 this));
757 return true;
760 void BluetoothLowEnergyReadDescriptorValueFunction::SuccessCallback() {
761 // Obtain info on the descriptor and see whether or not the descriptor is
762 // still around.
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));
769 SendResponse(false);
770 return;
773 // Manually construct the result instead of using
774 // apibtle::GetDescriptor::Results::Create as it doesn't convert lists of
775 // enums correctly.
776 SetResult(apibtle::DescriptorToValue(&descriptor).release());
777 SendResponse(true);
780 void BluetoothLowEnergyReadDescriptorValueFunction::ErrorCallback(
781 BluetoothLowEnergyEventRouter::Status status) {
782 SetError(StatusToString(status));
783 SendResponse(false);
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
793 // of asserting.
794 if (!event_router->HasAdapter()) {
795 SetError(kErrorAdapterNotInitialized);
796 SendResponse(false);
797 return false;
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(
806 extension(),
807 params->descriptor_id,
808 value,
809 base::Bind(
810 &BluetoothLowEnergyWriteDescriptorValueFunction::SuccessCallback,
811 this),
812 base::Bind(&BluetoothLowEnergyWriteDescriptorValueFunction::ErrorCallback,
813 this));
815 return true;
818 void BluetoothLowEnergyWriteDescriptorValueFunction::SuccessCallback() {
819 results_ = apibtle::WriteDescriptorValue::Results::Create();
820 SendResponse(true);
823 void BluetoothLowEnergyWriteDescriptorValueFunction::ErrorCallback(
824 BluetoothLowEnergyEventRouter::Status status) {
825 SetError(StatusToString(status));
826 SendResponse(false);
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() {
858 Initialize();
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;
874 SendResponse(false);
875 return false;
878 BluetoothLowEnergyEventRouter* event_router =
879 GetEventRouter(browser_context());
881 // The adapter must be initialized at this point, but return an error instead
882 // of asserting.
883 if (!event_router->HasAdapter()) {
884 SetError(kErrorAdapterNotInitialized);
885 SendResponse(false);
886 return false;
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())
909 .Pass());
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(),
918 base::Bind(
919 &BluetoothLowEnergyRegisterAdvertisementFunction::SuccessCallback,
920 this),
921 base::Bind(
922 &BluetoothLowEnergyRegisterAdvertisementFunction::ErrorCallback,
923 this));
925 return true;
928 void BluetoothLowEnergyRegisterAdvertisementFunction::SuccessCallback(
929 scoped_refptr<device::BluetoothAdvertisement> advertisement) {
930 results_ = apibtle::RegisterAdvertisement::Results::Create(AddAdvertisement(
931 new BluetoothApiAdvertisement(extension_id(), advertisement)));
932 SendResponse(true);
935 void BluetoothLowEnergyRegisterAdvertisementFunction::ErrorCallback(
936 device::BluetoothAdvertisement::ErrorCode status) {
937 switch (status) {
938 case device::BluetoothAdvertisement::ErrorCode::
939 ERROR_ADVERTISEMENT_ALREADY_EXISTS:
940 SetError(kStatusAdvertisementAlreadyExists);
941 break;
942 case device::BluetoothAdvertisement::ErrorCode::
943 ERROR_ADVERTISEMENT_INVALID_LENGTH:
944 SetError(kErrorInvalidAdvertisementLength);
945 break;
946 default:
947 SetError(kErrorOperationFailed);
949 SendResponse(false);
952 // UnregisterAdvertisement:
954 bool BluetoothLowEnergyUnregisterAdvertisementFunction::DoWork() {
955 DCHECK_CURRENTLY_ON(BrowserThread::UI);
957 if (!BluetoothManifestData::CheckPeripheralPermitted(extension())) {
958 error_ = kErrorPermissionDenied;
959 SendResponse(false);
960 return false;
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())
968 return true;
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;
978 SendResponse(false);
979 return false;
982 advertisement->advertisement()->Unregister(
983 base::Bind(
984 &BluetoothLowEnergyUnregisterAdvertisementFunction::SuccessCallback,
985 this, params->advertisement_id),
986 base::Bind(
987 &BluetoothLowEnergyUnregisterAdvertisementFunction::ErrorCallback,
988 this, params->advertisement_id));
990 return true;
993 void BluetoothLowEnergyUnregisterAdvertisementFunction::SuccessCallback(
994 int advertisement_id) {
995 RemoveAdvertisement(advertisement_id);
996 SendResponse(true);
999 void BluetoothLowEnergyUnregisterAdvertisementFunction::ErrorCallback(
1000 int advertisement_id,
1001 device::BluetoothAdvertisement::ErrorCode status) {
1002 RemoveAdvertisement(advertisement_id);
1003 switch (status) {
1004 case device::BluetoothAdvertisement::ErrorCode::
1005 ERROR_ADVERTISEMENT_DOES_NOT_EXIST:
1006 SetError(kStatusAdvertisementDoesNotExist);
1007 break;
1008 default:
1009 SetError(kErrorOperationFailed);
1011 SendResponse(false);
1014 } // namespace api
1015 } // namespace extensions