Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / extensions / api / bluetooth_low_energy / bluetooth_low_energy_api.cc
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|.
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
67 extensions::BluetoothLowEnergyEventRouter* GetEventRouter(
68     BrowserContext* context) {
69   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
70   return extensions::BluetoothLowEnergyAPI::Get(context)->event_router();
71 }
72
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>*
86 BluetoothLowEnergyAPI::GetFactoryInstance() {
87   return g_factory.Pointer();
88 }
89
90 // static
91 BluetoothLowEnergyAPI* BluetoothLowEnergyAPI::Get(BrowserContext* context) {
92   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
93   return GetFactoryInstance()->Get(context);
94 }
95
96 BluetoothLowEnergyAPI::BluetoothLowEnergyAPI(BrowserContext* context)
97     : event_router_(new BluetoothLowEnergyEventRouter(context)),
98       browser_context_(context) {
99   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
100 }
101
102 BluetoothLowEnergyAPI::~BluetoothLowEnergyAPI() {
103 }
104
105 void BluetoothLowEnergyAPI::Shutdown() {
106   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
107 }
108
109 namespace api {
110
111 BluetoothLowEnergyExtensionFunction::BluetoothLowEnergyExtensionFunction() {
112 }
113
114 BluetoothLowEnergyExtensionFunction::~BluetoothLowEnergyExtensionFunction() {
115 }
116
117 bool BluetoothLowEnergyExtensionFunction::RunAsync() {
118   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
119
120   if (!BluetoothManifestData::CheckLowEnergyPermitted(extension())) {
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
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       extension(),
169       params->device_address,
170       base::Bind(&BluetoothLowEnergyConnectFunction::SuccessCallback, this),
171       base::Bind(&BluetoothLowEnergyConnectFunction::ErrorCallback, this));
172
173   return true;
174 }
175
176 void BluetoothLowEnergyConnectFunction::SuccessCallback() {
177   SendResponse(true);
178 }
179
180 void BluetoothLowEnergyConnectFunction::ErrorCallback(
181     BluetoothLowEnergyEventRouter::Status status) {
182   SetError(StatusToString(status));
183   SendResponse(false);
184 }
185
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       extension(),
206       params->device_address,
207       base::Bind(&BluetoothLowEnergyDisconnectFunction::SuccessCallback, this),
208       base::Bind(&BluetoothLowEnergyDisconnectFunction::ErrorCallback, this));
209
210   return true;
211 }
212
213 void BluetoothLowEnergyDisconnectFunction::SuccessCallback() {
214   SendResponse(true);
215 }
216
217 void BluetoothLowEnergyDisconnectFunction::ErrorCallback(
218     BluetoothLowEnergyEventRouter::Status status) {
219   SetError(StatusToString(status));
220   SendResponse(false);
221 }
222
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
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
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           extension(), 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
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           extension(), 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
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
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       extension(), 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
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       extension(), 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
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       extension(),
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
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(extension(), 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
532 void BluetoothLowEnergyReadCharacteristicValueFunction::ErrorCallback(
533     BluetoothLowEnergyEventRouter::Status status) {
534   SetError(StatusToString(status));
535   SendResponse(false);
536 }
537
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       extension(),
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
571 void BluetoothLowEnergyWriteCharacteristicValueFunction::SuccessCallback() {
572   results_ = apibtle::WriteCharacteristicValue::Results::Create();
573   SendResponse(true);
574 }
575
576 void BluetoothLowEnergyWriteCharacteristicValueFunction::ErrorCallback(
577     BluetoothLowEnergyEventRouter::Status status) {
578   SetError(StatusToString(status));
579   SendResponse(false);
580 }
581
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       extension(),
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
620 BluetoothLowEnergyStartCharacteristicNotificationsFunction::SuccessCallback() {
621   SendResponse(true);
622 }
623
624 void BluetoothLowEnergyStartCharacteristicNotificationsFunction::ErrorCallback(
625     BluetoothLowEnergyEventRouter::Status status) {
626   SetError(StatusToString(status));
627   SendResponse(false);
628 }
629
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       extension(),
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
662 BluetoothLowEnergyStopCharacteristicNotificationsFunction::SuccessCallback() {
663   SendResponse(true);
664 }
665
666 void BluetoothLowEnergyStopCharacteristicNotificationsFunction::ErrorCallback(
667     BluetoothLowEnergyEventRouter::Status status) {
668   SetError(StatusToString(status));
669   SendResponse(false);
670 }
671
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       extension(),
693       instance_id_,
694       base::Bind(
695           &BluetoothLowEnergyReadDescriptorValueFunction::SuccessCallback,
696           this),
697       base::Bind(&BluetoothLowEnergyReadDescriptorValueFunction::ErrorCallback,
698                  this));
699
700   return true;
701 }
702
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(extension(), 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
723 void BluetoothLowEnergyReadDescriptorValueFunction::ErrorCallback(
724     BluetoothLowEnergyEventRouter::Status status) {
725   SetError(StatusToString(status));
726   SendResponse(false);
727 }
728
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       extension(),
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
761 void BluetoothLowEnergyWriteDescriptorValueFunction::SuccessCallback() {
762   results_ = apibtle::WriteDescriptorValue::Results::Create();
763   SendResponse(true);
764 }
765
766 void BluetoothLowEnergyWriteDescriptorValueFunction::ErrorCallback(
767     BluetoothLowEnergyEventRouter::Status status) {
768   SetError(StatusToString(status));
769   SendResponse(false);
770 }
771
772 }  // namespace api
773 }  // namespace extensions