• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "chrome/browser/extensions/api/bluetooth_low_energy/bluetooth_low_energy_api.h"
6 
7 #include "base/bind.h"
8 #include "base/lazy_instance.h"
9 #include "base/strings/stringprintf.h"
10 #include "chrome/browser/extensions/api/bluetooth_low_energy/utils.h"
11 #include "chrome/common/extensions/api/bluetooth/bluetooth_manifest_data.h"
12 #include "chrome/common/extensions/api/bluetooth_low_energy.h"
13 #include "content/public/browser/browser_thread.h"
14 #include "extensions/browser/event_router.h"
15 #include "extensions/common/permissions/permissions_data.h"
16 
17 using content::BrowserContext;
18 using content::BrowserThread;
19 
20 namespace apibtle = extensions::api::bluetooth_low_energy;
21 
22 namespace extensions {
23 
24 namespace {
25 
26 const char kErrorAdapterNotInitialized[] =
27     "Could not initialize Bluetooth adapter";
28 const char kErrorAlreadyConnected[] = "Already connected";
29 const char kErrorAlreadyNotifying[] = "Already notifying";
30 const char kErrorInProgress[] = "In progress";
31 const char kErrorNotConnected[] = "Not connected";
32 const char kErrorNotNotifying[] = "Not notifying";
33 const char kErrorNotFound[] = "Instance not found";
34 const char kErrorOperationFailed[] = "Operation failed";
35 const char kErrorPermissionDenied[] = "Permission denied";
36 const char kErrorPlatformNotSupported[] =
37     "This operation is not supported on the current platform";
38 
39 // Returns the correct error string based on error status |status|. This is used
40 // to set the value of |chrome.runtime.lastError.message| and should not be
41 // passed |BluetoothLowEnergyEventRouter::kStatusSuccess|.
StatusToString(BluetoothLowEnergyEventRouter::Status status)42 std::string StatusToString(BluetoothLowEnergyEventRouter::Status status) {
43   switch (status) {
44     case BluetoothLowEnergyEventRouter::kStatusErrorPermissionDenied:
45       return kErrorPermissionDenied;
46     case BluetoothLowEnergyEventRouter::kStatusErrorNotFound:
47       return kErrorNotFound;
48     case BluetoothLowEnergyEventRouter::kStatusErrorAlreadyConnected:
49       return kErrorAlreadyConnected;
50     case BluetoothLowEnergyEventRouter::kStatusErrorAlreadyNotifying:
51       return kErrorAlreadyNotifying;
52     case BluetoothLowEnergyEventRouter::kStatusErrorNotConnected:
53       return kErrorNotConnected;
54     case BluetoothLowEnergyEventRouter::kStatusErrorNotNotifying:
55       return kErrorNotNotifying;
56     case BluetoothLowEnergyEventRouter::kStatusErrorInProgress:
57       return kErrorInProgress;
58     case BluetoothLowEnergyEventRouter::kStatusSuccess:
59       NOTREACHED();
60       break;
61     default:
62       return kErrorOperationFailed;
63   }
64   return "";
65 }
66 
GetEventRouter(BrowserContext * context)67 extensions::BluetoothLowEnergyEventRouter* GetEventRouter(
68     BrowserContext* context) {
69   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
70   return extensions::BluetoothLowEnergyAPI::Get(context)->event_router();
71 }
72 
DoWorkCallback(const base::Callback<bool ()> & callback)73 void DoWorkCallback(const base::Callback<bool()>& callback) {
74   DCHECK(!callback.is_null());
75   callback.Run();
76 }
77 
78 }  // namespace
79 
80 
81 static base::LazyInstance<BrowserContextKeyedAPIFactory<BluetoothLowEnergyAPI> >
82     g_factory = LAZY_INSTANCE_INITIALIZER;
83 
84 // static
85 BrowserContextKeyedAPIFactory<BluetoothLowEnergyAPI>*
GetFactoryInstance()86 BluetoothLowEnergyAPI::GetFactoryInstance() {
87   return g_factory.Pointer();
88 }
89 
90 // static
Get(BrowserContext * context)91 BluetoothLowEnergyAPI* BluetoothLowEnergyAPI::Get(BrowserContext* context) {
92   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
93   return GetFactoryInstance()->Get(context);
94 }
95 
BluetoothLowEnergyAPI(BrowserContext * context)96 BluetoothLowEnergyAPI::BluetoothLowEnergyAPI(BrowserContext* context)
97     : event_router_(new BluetoothLowEnergyEventRouter(context)),
98       browser_context_(context) {
99   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
100 }
101 
~BluetoothLowEnergyAPI()102 BluetoothLowEnergyAPI::~BluetoothLowEnergyAPI() {
103 }
104 
Shutdown()105 void BluetoothLowEnergyAPI::Shutdown() {
106   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
107 }
108 
109 namespace api {
110 
BluetoothLowEnergyExtensionFunction()111 BluetoothLowEnergyExtensionFunction::BluetoothLowEnergyExtensionFunction() {
112 }
113 
~BluetoothLowEnergyExtensionFunction()114 BluetoothLowEnergyExtensionFunction::~BluetoothLowEnergyExtensionFunction() {
115 }
116 
RunAsync()117 bool BluetoothLowEnergyExtensionFunction::RunAsync() {
118   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
119 
120   if (!BluetoothManifestData::CheckLowEnergyPermitted(GetExtension())) {
121     error_ = kErrorPermissionDenied;
122     return false;
123   }
124 
125   BluetoothLowEnergyEventRouter* event_router =
126       GetEventRouter(browser_context());
127   if (!event_router->IsBluetoothSupported()) {
128     SetError(kErrorPlatformNotSupported);
129     return false;
130   }
131 
132   // It is safe to pass |this| here as ExtensionFunction is refcounted.
133   if (!event_router->InitializeAdapterAndInvokeCallback(base::Bind(
134           &DoWorkCallback,
135           base::Bind(&BluetoothLowEnergyExtensionFunction::DoWork, this)))) {
136     SetError(kErrorAdapterNotInitialized);
137     return false;
138   }
139 
140   return true;
141 }
142 
DoWork()143 bool BluetoothLowEnergyConnectFunction::DoWork() {
144   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
145 
146   BluetoothLowEnergyEventRouter* event_router =
147       GetEventRouter(browser_context());
148 
149   // The adapter must be initialized at this point, but return an error instead
150   // of asserting.
151   if (!event_router->HasAdapter()) {
152     SetError(kErrorAdapterNotInitialized);
153     SendResponse(false);
154     return false;
155   }
156 
157   scoped_ptr<apibtle::Connect::Params> params(
158       apibtle::Connect::Params::Create(*args_));
159   EXTENSION_FUNCTION_VALIDATE(params.get() != NULL);
160 
161   bool persistent = false;  // Not persistent by default.
162   apibtle::ConnectProperties* properties = params.get()->properties.get();
163   if (properties)
164     persistent = properties->persistent;
165 
166   event_router->Connect(
167       persistent,
168       GetExtension(),
169       params->device_address,
170       base::Bind(&BluetoothLowEnergyConnectFunction::SuccessCallback, this),
171       base::Bind(&BluetoothLowEnergyConnectFunction::ErrorCallback, this));
172 
173   return true;
174 }
175 
SuccessCallback()176 void BluetoothLowEnergyConnectFunction::SuccessCallback() {
177   SendResponse(true);
178 }
179 
ErrorCallback(BluetoothLowEnergyEventRouter::Status status)180 void BluetoothLowEnergyConnectFunction::ErrorCallback(
181     BluetoothLowEnergyEventRouter::Status status) {
182   SetError(StatusToString(status));
183   SendResponse(false);
184 }
185 
DoWork()186 bool BluetoothLowEnergyDisconnectFunction::DoWork() {
187   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
188 
189   BluetoothLowEnergyEventRouter* event_router =
190       GetEventRouter(browser_context());
191 
192   // The adapter must be initialized at this point, but return an error instead
193   // of asserting.
194   if (!event_router->HasAdapter()) {
195     SetError(kErrorAdapterNotInitialized);
196     SendResponse(false);
197     return false;
198   }
199 
200   scoped_ptr<apibtle::Disconnect::Params> params(
201       apibtle::Disconnect::Params::Create(*args_));
202   EXTENSION_FUNCTION_VALIDATE(params.get() != NULL);
203 
204   event_router->Disconnect(
205       GetExtension(),
206       params->device_address,
207       base::Bind(&BluetoothLowEnergyDisconnectFunction::SuccessCallback, this),
208       base::Bind(&BluetoothLowEnergyDisconnectFunction::ErrorCallback, this));
209 
210   return true;
211 }
212 
SuccessCallback()213 void BluetoothLowEnergyDisconnectFunction::SuccessCallback() {
214   SendResponse(true);
215 }
216 
ErrorCallback(BluetoothLowEnergyEventRouter::Status status)217 void BluetoothLowEnergyDisconnectFunction::ErrorCallback(
218     BluetoothLowEnergyEventRouter::Status status) {
219   SetError(StatusToString(status));
220   SendResponse(false);
221 }
222 
DoWork()223 bool BluetoothLowEnergyGetServiceFunction::DoWork() {
224   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
225 
226   BluetoothLowEnergyEventRouter* event_router =
227       GetEventRouter(browser_context());
228 
229   // The adapter must be initialized at this point, but return an error instead
230   // of asserting.
231   if (!event_router->HasAdapter()) {
232     SetError(kErrorAdapterNotInitialized);
233     SendResponse(false);
234     return false;
235   }
236 
237   scoped_ptr<apibtle::GetService::Params> params(
238       apibtle::GetService::Params::Create(*args_));
239   EXTENSION_FUNCTION_VALIDATE(params.get() != NULL);
240 
241   apibtle::Service service;
242   BluetoothLowEnergyEventRouter::Status status =
243       event_router->GetService(params->service_id, &service);
244   if (status != BluetoothLowEnergyEventRouter::kStatusSuccess) {
245     SetError(StatusToString(status));
246     SendResponse(false);
247     return false;
248   }
249 
250   results_ = apibtle::GetService::Results::Create(service);
251   SendResponse(true);
252 
253   return true;
254 }
255 
DoWork()256 bool BluetoothLowEnergyGetServicesFunction::DoWork() {
257   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
258 
259   BluetoothLowEnergyEventRouter* event_router =
260       GetEventRouter(browser_context());
261 
262   // The adapter must be initialized at this point, but return an error instead
263   // of asserting.
264   if (!event_router->HasAdapter()) {
265     SetError(kErrorAdapterNotInitialized);
266     SendResponse(false);
267     return false;
268   }
269 
270   scoped_ptr<apibtle::GetServices::Params> params(
271       apibtle::GetServices::Params::Create(*args_));
272   EXTENSION_FUNCTION_VALIDATE(params.get() != NULL);
273 
274   BluetoothLowEnergyEventRouter::ServiceList service_list;
275   if (!event_router->GetServices(params->device_address, &service_list)) {
276     SetError(kErrorNotFound);
277     SendResponse(false);
278     return false;
279   }
280 
281   results_ = apibtle::GetServices::Results::Create(service_list);
282   SendResponse(true);
283 
284   return true;
285 }
286 
DoWork()287 bool BluetoothLowEnergyGetCharacteristicFunction::DoWork() {
288   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
289 
290   BluetoothLowEnergyEventRouter* event_router =
291       GetEventRouter(browser_context());
292 
293   // The adapter must be initialized at this point, but return an error instead
294   // of asserting.
295   if (!event_router->HasAdapter()) {
296     SetError(kErrorAdapterNotInitialized);
297     SendResponse(false);
298     return false;
299   }
300 
301   scoped_ptr<apibtle::GetCharacteristic::Params> params(
302       apibtle::GetCharacteristic::Params::Create(*args_));
303   EXTENSION_FUNCTION_VALIDATE(params.get() != NULL);
304 
305   apibtle::Characteristic characteristic;
306   BluetoothLowEnergyEventRouter::Status status =
307       event_router->GetCharacteristic(
308           GetExtension(), params->characteristic_id, &characteristic);
309   if (status != BluetoothLowEnergyEventRouter::kStatusSuccess) {
310     SetError(StatusToString(status));
311     SendResponse(false);
312     return false;
313   }
314 
315   // Manually construct the result instead of using
316   // apibtle::GetCharacteristic::Result::Create as it doesn't convert lists of
317   // enums correctly.
318   SetResult(apibtle::CharacteristicToValue(&characteristic).release());
319   SendResponse(true);
320 
321   return true;
322 }
323 
DoWork()324 bool BluetoothLowEnergyGetCharacteristicsFunction::DoWork() {
325   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
326 
327   BluetoothLowEnergyEventRouter* event_router =
328       GetEventRouter(browser_context());
329 
330   // The adapter must be initialized at this point, but return an error instead
331   // of asserting.
332   if (!event_router->HasAdapter()) {
333     SetError(kErrorAdapterNotInitialized);
334     SendResponse(false);
335     return false;
336   }
337 
338   scoped_ptr<apibtle::GetCharacteristics::Params> params(
339       apibtle::GetCharacteristics::Params::Create(*args_));
340   EXTENSION_FUNCTION_VALIDATE(params.get() != NULL);
341 
342   BluetoothLowEnergyEventRouter::CharacteristicList characteristic_list;
343   BluetoothLowEnergyEventRouter::Status status =
344       event_router->GetCharacteristics(
345           GetExtension(), params->service_id, &characteristic_list);
346   if (status != BluetoothLowEnergyEventRouter::kStatusSuccess) {
347     SetError(StatusToString(status));
348     SendResponse(false);
349     return false;
350   }
351 
352   // Manually construct the result instead of using
353   // apibtle::GetCharacteristics::Result::Create as it doesn't convert lists of
354   // enums correctly.
355   scoped_ptr<base::ListValue> result(new base::ListValue());
356   for (BluetoothLowEnergyEventRouter::CharacteristicList::iterator iter =
357            characteristic_list.begin();
358        iter != characteristic_list.end();
359        ++iter)
360     result->Append(apibtle::CharacteristicToValue(iter->get()).release());
361 
362   SetResult(result.release());
363   SendResponse(true);
364 
365   return true;
366 }
367 
DoWork()368 bool BluetoothLowEnergyGetIncludedServicesFunction::DoWork() {
369   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
370 
371   BluetoothLowEnergyEventRouter* event_router =
372       GetEventRouter(browser_context());
373 
374   // The adapter must be initialized at this point, but return an error instead
375   // of asserting.
376   if (!event_router->HasAdapter()) {
377     SetError(kErrorAdapterNotInitialized);
378     SendResponse(false);
379     return false;
380   }
381 
382   scoped_ptr<apibtle::GetIncludedServices::Params> params(
383       apibtle::GetIncludedServices::Params::Create(*args_));
384   EXTENSION_FUNCTION_VALIDATE(params.get() != NULL);
385 
386   BluetoothLowEnergyEventRouter::ServiceList service_list;
387   BluetoothLowEnergyEventRouter::Status status =
388       event_router->GetIncludedServices(params->service_id, &service_list);
389   if (status != BluetoothLowEnergyEventRouter::kStatusSuccess) {
390     SetError(StatusToString(status));
391     SendResponse(false);
392     return false;
393   }
394 
395   results_ = apibtle::GetIncludedServices::Results::Create(service_list);
396   SendResponse(true);
397 
398   return true;
399 }
400 
DoWork()401 bool BluetoothLowEnergyGetDescriptorFunction::DoWork() {
402   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
403 
404   BluetoothLowEnergyEventRouter* event_router =
405       GetEventRouter(browser_context());
406 
407   // The adapter must be initialized at this point, but return an error instead
408   // of asserting.
409   if (!event_router->HasAdapter()) {
410     SetError(kErrorAdapterNotInitialized);
411     SendResponse(false);
412     return false;
413   }
414 
415   scoped_ptr<apibtle::GetDescriptor::Params> params(
416       apibtle::GetDescriptor::Params::Create(*args_));
417   EXTENSION_FUNCTION_VALIDATE(params.get() != NULL);
418 
419   apibtle::Descriptor descriptor;
420   BluetoothLowEnergyEventRouter::Status status = event_router->GetDescriptor(
421       GetExtension(), params->descriptor_id, &descriptor);
422   if (status != BluetoothLowEnergyEventRouter::kStatusSuccess) {
423     SetError(StatusToString(status));
424     SendResponse(false);
425     return false;
426   }
427 
428   // Manually construct the result instead of using
429   // apibtle::GetDescriptor::Result::Create as it doesn't convert lists of enums
430   // correctly.
431   SetResult(apibtle::DescriptorToValue(&descriptor).release());
432   SendResponse(true);
433 
434   return true;
435 }
436 
DoWork()437 bool BluetoothLowEnergyGetDescriptorsFunction::DoWork() {
438   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
439 
440   BluetoothLowEnergyEventRouter* event_router =
441       GetEventRouter(browser_context());
442 
443   // The adapter must be initialized at this point, but return an error instead
444   // of asserting.
445   if (!event_router->HasAdapter()) {
446     SetError(kErrorAdapterNotInitialized);
447     SendResponse(false);
448     return false;
449   }
450 
451   scoped_ptr<apibtle::GetDescriptors::Params> params(
452       apibtle::GetDescriptors::Params::Create(*args_));
453   EXTENSION_FUNCTION_VALIDATE(params.get() != NULL);
454 
455   BluetoothLowEnergyEventRouter::DescriptorList descriptor_list;
456   BluetoothLowEnergyEventRouter::Status status = event_router->GetDescriptors(
457       GetExtension(), params->characteristic_id, &descriptor_list);
458   if (status != BluetoothLowEnergyEventRouter::kStatusSuccess) {
459     SetError(StatusToString(status));
460     SendResponse(false);
461     return false;
462   }
463 
464   // Manually construct the result instead of using
465   // apibtle::GetDescriptors::Result::Create as it doesn't convert lists of
466   // enums correctly.
467   scoped_ptr<base::ListValue> result(new base::ListValue());
468   for (BluetoothLowEnergyEventRouter::DescriptorList::iterator iter =
469            descriptor_list.begin();
470        iter != descriptor_list.end();
471        ++iter)
472     result->Append(apibtle::DescriptorToValue(iter->get()).release());
473 
474   SetResult(result.release());
475   SendResponse(true);
476 
477   return true;
478 }
479 
DoWork()480 bool BluetoothLowEnergyReadCharacteristicValueFunction::DoWork() {
481   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
482 
483   BluetoothLowEnergyEventRouter* event_router =
484       GetEventRouter(browser_context());
485 
486   // The adapter must be initialized at this point, but return an error instead
487   // of asserting.
488   if (!event_router->HasAdapter()) {
489     SetError(kErrorAdapterNotInitialized);
490     SendResponse(false);
491     return false;
492   }
493 
494   scoped_ptr<apibtle::ReadCharacteristicValue::Params> params(
495       apibtle::ReadCharacteristicValue::Params::Create(*args_));
496   EXTENSION_FUNCTION_VALIDATE(params.get() != NULL);
497 
498   instance_id_ = params->characteristic_id;
499   event_router->ReadCharacteristicValue(
500       GetExtension(),
501       instance_id_,
502       base::Bind(
503           &BluetoothLowEnergyReadCharacteristicValueFunction::SuccessCallback,
504           this),
505       base::Bind(
506           &BluetoothLowEnergyReadCharacteristicValueFunction::ErrorCallback,
507           this));
508 
509   return true;
510 }
511 
SuccessCallback()512 void BluetoothLowEnergyReadCharacteristicValueFunction::SuccessCallback() {
513   // Obtain info on the characteristic and see whether or not the characteristic
514   // is still around.
515   apibtle::Characteristic characteristic;
516   BluetoothLowEnergyEventRouter::Status status =
517       GetEventRouter(browser_context())
518           ->GetCharacteristic(GetExtension(), instance_id_, &characteristic);
519   if (status != BluetoothLowEnergyEventRouter::kStatusSuccess) {
520     SetError(StatusToString(status));
521     SendResponse(false);
522     return;
523   }
524 
525   // Manually construct the result instead of using
526   // apibtle::GetCharacteristic::Result::Create as it doesn't convert lists of
527   // enums correctly.
528   SetResult(apibtle::CharacteristicToValue(&characteristic).release());
529   SendResponse(true);
530 }
531 
ErrorCallback(BluetoothLowEnergyEventRouter::Status status)532 void BluetoothLowEnergyReadCharacteristicValueFunction::ErrorCallback(
533     BluetoothLowEnergyEventRouter::Status status) {
534   SetError(StatusToString(status));
535   SendResponse(false);
536 }
537 
DoWork()538 bool BluetoothLowEnergyWriteCharacteristicValueFunction::DoWork() {
539   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
540 
541   BluetoothLowEnergyEventRouter* event_router =
542       GetEventRouter(browser_context());
543 
544   // The adapter must be initialized at this point, but return an error instead
545   // of asserting.
546   if (!event_router->HasAdapter()) {
547     SetError(kErrorAdapterNotInitialized);
548     SendResponse(false);
549     return false;
550   }
551 
552   scoped_ptr<apibtle::WriteCharacteristicValue::Params> params(
553       apibtle::WriteCharacteristicValue::Params::Create(*args_));
554   EXTENSION_FUNCTION_VALIDATE(params.get() != NULL);
555 
556   std::vector<uint8> value(params->value.begin(), params->value.end());
557   event_router->WriteCharacteristicValue(
558       GetExtension(),
559       params->characteristic_id,
560       value,
561       base::Bind(
562           &BluetoothLowEnergyWriteCharacteristicValueFunction::SuccessCallback,
563           this),
564       base::Bind(
565           &BluetoothLowEnergyWriteCharacteristicValueFunction::ErrorCallback,
566           this));
567 
568   return true;
569 }
570 
SuccessCallback()571 void BluetoothLowEnergyWriteCharacteristicValueFunction::SuccessCallback() {
572   results_ = apibtle::WriteCharacteristicValue::Results::Create();
573   SendResponse(true);
574 }
575 
ErrorCallback(BluetoothLowEnergyEventRouter::Status status)576 void BluetoothLowEnergyWriteCharacteristicValueFunction::ErrorCallback(
577     BluetoothLowEnergyEventRouter::Status status) {
578   SetError(StatusToString(status));
579   SendResponse(false);
580 }
581 
DoWork()582 bool BluetoothLowEnergyStartCharacteristicNotificationsFunction::DoWork() {
583   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
584 
585   BluetoothLowEnergyEventRouter* event_router =
586       GetEventRouter(browser_context());
587 
588   // The adapter must be initialized at this point, but return an error instead
589   // of asserting.
590   if (!event_router->HasAdapter()) {
591     SetError(kErrorAdapterNotInitialized);
592     SendResponse(false);
593     return false;
594   }
595 
596   scoped_ptr<apibtle::StartCharacteristicNotifications::Params> params(
597       apibtle::StartCharacteristicNotifications::Params::Create(*args_));
598   EXTENSION_FUNCTION_VALIDATE(params.get() != NULL);
599 
600   bool persistent = false;  // Not persistent by default.
601   apibtle::NotificationProperties* properties = params.get()->properties.get();
602   if (properties)
603     persistent = properties->persistent;
604 
605   event_router->StartCharacteristicNotifications(
606       persistent,
607       GetExtension(),
608       params->characteristic_id,
609       base::Bind(&BluetoothLowEnergyStartCharacteristicNotificationsFunction::
610                      SuccessCallback,
611                  this),
612       base::Bind(&BluetoothLowEnergyStartCharacteristicNotificationsFunction::
613                      ErrorCallback,
614                  this));
615 
616   return true;
617 }
618 
619 void
SuccessCallback()620 BluetoothLowEnergyStartCharacteristicNotificationsFunction::SuccessCallback() {
621   SendResponse(true);
622 }
623 
ErrorCallback(BluetoothLowEnergyEventRouter::Status status)624 void BluetoothLowEnergyStartCharacteristicNotificationsFunction::ErrorCallback(
625     BluetoothLowEnergyEventRouter::Status status) {
626   SetError(StatusToString(status));
627   SendResponse(false);
628 }
629 
DoWork()630 bool BluetoothLowEnergyStopCharacteristicNotificationsFunction::DoWork() {
631   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
632 
633   BluetoothLowEnergyEventRouter* event_router =
634       GetEventRouter(browser_context());
635 
636   // The adapter must be initialized at this point, but return an error instead
637   // of asserting.
638   if (!event_router->HasAdapter()) {
639     SetError(kErrorAdapterNotInitialized);
640     SendResponse(false);
641     return false;
642   }
643 
644   scoped_ptr<apibtle::StopCharacteristicNotifications::Params> params(
645       apibtle::StopCharacteristicNotifications::Params::Create(*args_));
646   EXTENSION_FUNCTION_VALIDATE(params.get() != NULL);
647 
648   event_router->StopCharacteristicNotifications(
649       GetExtension(),
650       params->characteristic_id,
651       base::Bind(&BluetoothLowEnergyStopCharacteristicNotificationsFunction::
652                      SuccessCallback,
653                  this),
654       base::Bind(&BluetoothLowEnergyStopCharacteristicNotificationsFunction::
655                      ErrorCallback,
656                  this));
657 
658   return true;
659 }
660 
661 void
SuccessCallback()662 BluetoothLowEnergyStopCharacteristicNotificationsFunction::SuccessCallback() {
663   SendResponse(true);
664 }
665 
ErrorCallback(BluetoothLowEnergyEventRouter::Status status)666 void BluetoothLowEnergyStopCharacteristicNotificationsFunction::ErrorCallback(
667     BluetoothLowEnergyEventRouter::Status status) {
668   SetError(StatusToString(status));
669   SendResponse(false);
670 }
671 
DoWork()672 bool BluetoothLowEnergyReadDescriptorValueFunction::DoWork() {
673   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
674 
675   BluetoothLowEnergyEventRouter* event_router =
676       GetEventRouter(browser_context());
677 
678   // The adapter must be initialized at this point, but return an error instead
679   // of asserting.
680   if (!event_router->HasAdapter()) {
681     SetError(kErrorAdapterNotInitialized);
682     SendResponse(false);
683     return false;
684   }
685 
686   scoped_ptr<apibtle::ReadDescriptorValue::Params> params(
687       apibtle::ReadDescriptorValue::Params::Create(*args_));
688   EXTENSION_FUNCTION_VALIDATE(params.get() != NULL);
689 
690   instance_id_ = params->descriptor_id;
691   event_router->ReadDescriptorValue(
692       GetExtension(),
693       instance_id_,
694       base::Bind(
695           &BluetoothLowEnergyReadDescriptorValueFunction::SuccessCallback,
696           this),
697       base::Bind(&BluetoothLowEnergyReadDescriptorValueFunction::ErrorCallback,
698                  this));
699 
700   return true;
701 }
702 
SuccessCallback()703 void BluetoothLowEnergyReadDescriptorValueFunction::SuccessCallback() {
704   // Obtain info on the descriptor and see whether or not the descriptor is
705   // still around.
706   apibtle::Descriptor descriptor;
707   BluetoothLowEnergyEventRouter::Status status =
708       GetEventRouter(browser_context())
709           ->GetDescriptor(GetExtension(), instance_id_, &descriptor);
710   if (status != BluetoothLowEnergyEventRouter::kStatusSuccess) {
711     SetError(StatusToString(status));
712     SendResponse(false);
713     return;
714   }
715 
716   // Manually construct the result instead of using
717   // apibtle::GetDescriptor::Results::Create as it doesn't convert lists of
718   // enums correctly.
719   SetResult(apibtle::DescriptorToValue(&descriptor).release());
720   SendResponse(true);
721 }
722 
ErrorCallback(BluetoothLowEnergyEventRouter::Status status)723 void BluetoothLowEnergyReadDescriptorValueFunction::ErrorCallback(
724     BluetoothLowEnergyEventRouter::Status status) {
725   SetError(StatusToString(status));
726   SendResponse(false);
727 }
728 
DoWork()729 bool BluetoothLowEnergyWriteDescriptorValueFunction::DoWork() {
730   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
731 
732   BluetoothLowEnergyEventRouter* event_router =
733       GetEventRouter(browser_context());
734 
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;
741   }
742 
743   scoped_ptr<apibtle::WriteDescriptorValue::Params> params(
744       apibtle::WriteDescriptorValue::Params::Create(*args_));
745   EXTENSION_FUNCTION_VALIDATE(params.get() != NULL);
746 
747   std::vector<uint8> value(params->value.begin(), params->value.end());
748   event_router->WriteDescriptorValue(
749       GetExtension(),
750       params->descriptor_id,
751       value,
752       base::Bind(
753           &BluetoothLowEnergyWriteDescriptorValueFunction::SuccessCallback,
754           this),
755       base::Bind(&BluetoothLowEnergyWriteDescriptorValueFunction::ErrorCallback,
756                  this));
757 
758   return true;
759 }
760 
SuccessCallback()761 void BluetoothLowEnergyWriteDescriptorValueFunction::SuccessCallback() {
762   results_ = apibtle::WriteDescriptorValue::Results::Create();
763   SendResponse(true);
764 }
765 
ErrorCallback(BluetoothLowEnergyEventRouter::Status status)766 void BluetoothLowEnergyWriteDescriptorValueFunction::ErrorCallback(
767     BluetoothLowEnergyEventRouter::Status status) {
768   SetError(StatusToString(status));
769   SendResponse(false);
770 }
771 
772 }  // namespace api
773 }  // namespace extensions
774