Upstream version 7.36.149.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/bluetooth_low_energy_event_router.h"
11 #include "chrome/browser/extensions/api/bluetooth_low_energy/utils.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
16 using content::BrowserContext;
17 using content::BrowserThread;
18
19 namespace apibtle = extensions::api::bluetooth_low_energy;
20
21 namespace {
22
23 const char kErrorAdapterNotInitialized[] =
24     "Could not initialize Bluetooth adapter.";
25 const char kErrorCharacteristicNotFoundFormat[] =
26     "Characteristic with ID \"%s\" not found.";
27 const char kErrorDeviceNotFoundFormat[] =
28     "Device with address \"%s\" not found.";
29 const char kErrorReadCharacteristicValueFailedFormat[] =
30     "Failed to read value of characteristic with ID \"%s\".";
31 const char kErrorServiceNotFoundFormat[] = "Service with ID \"%s\" not found.";
32 const char kErrorPlatformNotSupported[] =
33     "This operation is not supported on the current platform";
34
35 extensions::BluetoothLowEnergyEventRouter* GetEventRouter(
36     BrowserContext* context) {
37   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
38   return extensions::BluetoothLowEnergyAPI::Get(context)->event_router();
39 }
40
41 void DoWorkCallback(const base::Callback<bool()>& callback) {
42   DCHECK(!callback.is_null());
43   callback.Run();
44 }
45
46 }  // namespace
47
48 namespace extensions {
49
50 static base::LazyInstance<BrowserContextKeyedAPIFactory<BluetoothLowEnergyAPI> >
51     g_factory = LAZY_INSTANCE_INITIALIZER;
52
53 // static
54 BrowserContextKeyedAPIFactory<BluetoothLowEnergyAPI>*
55 BluetoothLowEnergyAPI::GetFactoryInstance() {
56   return g_factory.Pointer();
57 }
58
59 // static
60 BluetoothLowEnergyAPI* BluetoothLowEnergyAPI::Get(BrowserContext* context) {
61   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
62   return GetFactoryInstance()->Get(context);
63 }
64
65 BluetoothLowEnergyAPI::BluetoothLowEnergyAPI(BrowserContext* context)
66     : event_router_(new BluetoothLowEnergyEventRouter(context)),
67       browser_context_(context) {
68   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
69 }
70
71 BluetoothLowEnergyAPI::~BluetoothLowEnergyAPI() {
72 }
73
74 void BluetoothLowEnergyAPI::Shutdown() {
75   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
76 }
77
78 namespace api {
79
80 BluetoothLowEnergyExtensionFunction::BluetoothLowEnergyExtensionFunction() {
81 }
82
83 BluetoothLowEnergyExtensionFunction::~BluetoothLowEnergyExtensionFunction() {
84 }
85
86 bool BluetoothLowEnergyExtensionFunction::RunAsync() {
87   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
88
89   BluetoothLowEnergyEventRouter* event_router =
90       GetEventRouter(browser_context());
91   if (!event_router->IsBluetoothSupported()) {
92     SetError(kErrorPlatformNotSupported);
93     return false;
94   }
95
96   // It is safe to pass |this| here as ExtensionFunction is refcounted.
97   if (!event_router->InitializeAdapterAndInvokeCallback(base::Bind(
98           &DoWorkCallback,
99           base::Bind(&BluetoothLowEnergyExtensionFunction::DoWork, this)))) {
100     SetError(kErrorAdapterNotInitialized);
101     return false;
102   }
103
104   return true;
105 }
106
107 bool BluetoothLowEnergyGetServiceFunction::DoWork() {
108   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
109
110   BluetoothLowEnergyEventRouter* event_router =
111       GetEventRouter(browser_context());
112
113   // The adapter must be initialized at this point, but return an error instead
114   // of asserting.
115   if (!event_router->HasAdapter()) {
116     SetError(kErrorAdapterNotInitialized);
117     SendResponse(false);
118     return false;
119   }
120
121   scoped_ptr<apibtle::GetService::Params> params(
122       apibtle::GetService::Params::Create(*args_));
123   EXTENSION_FUNCTION_VALIDATE(params.get() != NULL);
124
125   std::string service_id = params->service_id;
126
127   apibtle::Service service;
128   if (!event_router->GetService(service_id, &service)) {
129     SetError(
130         base::StringPrintf(kErrorServiceNotFoundFormat, service_id.c_str()));
131     SendResponse(false);
132     return false;
133   }
134
135   results_ = apibtle::GetService::Results::Create(service);
136   SendResponse(true);
137
138   return true;
139 }
140
141 bool BluetoothLowEnergyGetServicesFunction::DoWork() {
142   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
143
144   BluetoothLowEnergyEventRouter* event_router =
145       GetEventRouter(browser_context());
146
147   // The adapter must be initialized at this point, but return an error instead
148   // of asserting.
149   if (!event_router->HasAdapter()) {
150     SetError(kErrorAdapterNotInitialized);
151     SendResponse(false);
152     return false;
153   }
154
155   scoped_ptr<apibtle::GetServices::Params> params(
156       apibtle::GetServices::Params::Create(*args_));
157   EXTENSION_FUNCTION_VALIDATE(params.get() != NULL);
158
159   std::string device_address = params->device_address;
160
161   BluetoothLowEnergyEventRouter::ServiceList service_list;
162   if (!event_router->GetServices(device_address, &service_list)) {
163     SetError(
164         base::StringPrintf(kErrorDeviceNotFoundFormat, device_address.c_str()));
165     SendResponse(false);
166     return false;
167   }
168
169   results_ = apibtle::GetServices::Results::Create(service_list);
170   SendResponse(true);
171
172   return true;
173 }
174
175 bool BluetoothLowEnergyGetCharacteristicFunction::DoWork() {
176   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
177
178   BluetoothLowEnergyEventRouter* event_router =
179       GetEventRouter(browser_context());
180
181   // The adapter must be initialized at this point, but return an error instead
182   // of asserting.
183   if (!event_router->HasAdapter()) {
184     SetError(kErrorAdapterNotInitialized);
185     SendResponse(false);
186     return false;
187   }
188
189   scoped_ptr<apibtle::GetCharacteristic::Params> params(
190       apibtle::GetCharacteristic::Params::Create(*args_));
191   EXTENSION_FUNCTION_VALIDATE(params.get() != NULL);
192
193   std::string characteristic_id = params->characteristic_id;
194
195   apibtle::Characteristic characteristic;
196   if (!event_router->GetCharacteristic(characteristic_id, &characteristic)) {
197     SetError(base::StringPrintf(kErrorCharacteristicNotFoundFormat,
198                                 characteristic_id.c_str()));
199     SendResponse(false);
200     return false;
201   }
202
203   // Manually construct the result instead of using
204   // apibtle::GetCharacteristic::Result::Create as it doesn't convert lists of
205   // enums correctly.
206   SetResult(apibtle::CharacteristicToValue(&characteristic).release());
207   SendResponse(true);
208
209   return true;
210 }
211
212 bool BluetoothLowEnergyGetCharacteristicsFunction::DoWork() {
213   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
214
215   BluetoothLowEnergyEventRouter* event_router =
216       GetEventRouter(browser_context());
217
218   // The adapter must be initialized at this point, but return an error instead
219   // of asserting.
220   if (!event_router->HasAdapter()) {
221     SetError(kErrorAdapterNotInitialized);
222     SendResponse(false);
223     return false;
224   }
225
226   scoped_ptr<apibtle::GetCharacteristics::Params> params(
227       apibtle::GetCharacteristics::Params::Create(*args_));
228   EXTENSION_FUNCTION_VALIDATE(params.get() != NULL);
229
230   std::string service_id = params->service_id;
231
232   BluetoothLowEnergyEventRouter::CharacteristicList characteristic_list;
233   if (!event_router->GetCharacteristics(service_id, &characteristic_list)) {
234     SetError(
235         base::StringPrintf(kErrorServiceNotFoundFormat, service_id.c_str()));
236
237     SendResponse(false);
238     return false;
239   }
240
241   // Manually construct the result instead of using
242   // apibtle::GetCharacteristics::Result::Create as it doesn't convert lists of
243   // enums correctly.
244   scoped_ptr<base::ListValue> result(new base::ListValue());
245   for (BluetoothLowEnergyEventRouter::CharacteristicList::iterator iter =
246            characteristic_list.begin();
247        iter != characteristic_list.end();
248        ++iter)
249     result->Append(apibtle::CharacteristicToValue(iter->get()).release());
250
251   SetResult(result.release());
252   SendResponse(true);
253
254   return true;
255 }
256
257 bool BluetoothLowEnergyGetIncludedServicesFunction::DoWork() {
258   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
259
260   BluetoothLowEnergyEventRouter* event_router =
261       GetEventRouter(browser_context());
262
263   // The adapter must be initialized at this point, but return an error instead
264   // of asserting.
265   if (!event_router->HasAdapter()) {
266     SetError(kErrorAdapterNotInitialized);
267     SendResponse(false);
268     return false;
269   }
270
271   scoped_ptr<apibtle::GetIncludedServices::Params> params(
272       apibtle::GetIncludedServices::Params::Create(*args_));
273   EXTENSION_FUNCTION_VALIDATE(params.get() != NULL);
274
275   std::string service_id = params->service_id;
276
277   BluetoothLowEnergyEventRouter::ServiceList service_list;
278   if (!event_router->GetIncludedServices(service_id, &service_list)) {
279     SetError(
280         base::StringPrintf(kErrorServiceNotFoundFormat, service_id.c_str()));
281     SendResponse(false);
282     return false;
283   }
284
285   results_ = apibtle::GetIncludedServices::Results::Create(service_list);
286   SendResponse(true);
287
288   return true;
289 }
290
291 bool BluetoothLowEnergyGetDescriptorFunction::DoWork() {
292   // TODO(armansito): Implement.
293   SetError("Call not supported.");
294   SendResponse(false);
295   return false;
296 }
297
298 bool BluetoothLowEnergyGetDescriptorsFunction::DoWork() {
299   // TODO(armansito): Implement.
300   SetError("Call not supported.");
301   SendResponse(false);
302   return false;
303 }
304
305 bool BluetoothLowEnergyReadCharacteristicValueFunction::DoWork() {
306   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
307
308   BluetoothLowEnergyEventRouter* event_router =
309       GetEventRouter(browser_context());
310
311   // The adapter must be initialized at this point, but return an error instead
312   // of asserting.
313   if (!event_router->HasAdapter()) {
314     SetError(kErrorAdapterNotInitialized);
315     SendResponse(false);
316     return false;
317   }
318
319   scoped_ptr<apibtle::ReadCharacteristicValue::Params> params(
320       apibtle::ReadCharacteristicValue::Params::Create(*args_));
321   EXTENSION_FUNCTION_VALIDATE(params.get() != NULL);
322
323   instance_id_ = params->characteristic_id;
324
325   if (!event_router->ReadCharacteristicValue(
326           instance_id_,
327           base::Bind(&BluetoothLowEnergyReadCharacteristicValueFunction::
328                          SuccessCallback,
329                      this),
330           base::Bind(
331               &BluetoothLowEnergyReadCharacteristicValueFunction::ErrorCallback,
332               this))) {
333     SetError(base::StringPrintf(kErrorCharacteristicNotFoundFormat,
334                                 instance_id_.c_str()));
335     SendResponse(false);
336     return false;
337   }
338
339   return true;
340 }
341
342 void BluetoothLowEnergyReadCharacteristicValueFunction::SuccessCallback() {
343   // Obtain info on the characteristic and see whether or not the characteristic
344   // is still around.
345   apibtle::Characteristic characteristic;
346   if (!GetEventRouter(browser_context())
347            ->GetCharacteristic(instance_id_, &characteristic)) {
348     SetError(base::StringPrintf(kErrorCharacteristicNotFoundFormat,
349                                 instance_id_.c_str()));
350     SendResponse(false);
351     return;
352   }
353
354   // Manually construct the result instead of using
355   // apibtle::GetCharacteristic::Result::Create as it doesn't convert lists of
356   // enums correctly.
357   SetResult(apibtle::CharacteristicToValue(&characteristic).release());
358   SendResponse(true);
359 }
360
361 void BluetoothLowEnergyReadCharacteristicValueFunction::ErrorCallback() {
362   SetError(base::StringPrintf(kErrorReadCharacteristicValueFailedFormat,
363                               instance_id_.c_str()));
364   SendResponse(false);
365 }
366
367 bool BluetoothLowEnergyWriteCharacteristicValueFunction::DoWork() {
368   // TODO(armansito): Implement.
369   SetError("Call not supported.");
370   SendResponse(false);
371   return false;
372 }
373
374 bool BluetoothLowEnergyReadDescriptorValueFunction::DoWork() {
375   // TODO(armansito): Implement.
376   SetError("Call not supported.");
377   SendResponse(false);
378   return false;
379 }
380
381 bool BluetoothLowEnergyWriteDescriptorValueFunction::DoWork() {
382   // TODO(armansito): Implement.
383   SetError("Call not supported.");
384   SendResponse(false);
385   return false;
386 }
387
388 }  // namespace api
389 }  // namespace extensions