Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / extensions / api / bluetooth / bluetooth_api.cc
1 // Copyright (c) 2012 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/bluetooth_api.h"
6
7 #include <string>
8
9 #include "base/memory/ref_counted.h"
10 #include "chrome/browser/extensions/api/bluetooth/bluetooth_api_factory.h"
11 #include "chrome/browser/extensions/api/bluetooth/bluetooth_api_utils.h"
12 #include "chrome/browser/extensions/api/bluetooth/bluetooth_event_router.h"
13 #include "chrome/browser/extensions/event_names.h"
14 #include "chrome/browser/profiles/profile.h"
15 #include "chrome/common/extensions/api/bluetooth.h"
16 #include "chrome/common/extensions/api/bluetooth/bluetooth_manifest_data.h"
17 #include "content/public/browser/browser_thread.h"
18 #include "device/bluetooth/bluetooth_adapter.h"
19 #include "device/bluetooth/bluetooth_device.h"
20 #include "device/bluetooth/bluetooth_out_of_band_pairing_data.h"
21 #include "device/bluetooth/bluetooth_profile.h"
22 #include "device/bluetooth/bluetooth_service_record.h"
23 #include "device/bluetooth/bluetooth_socket.h"
24 #include "device/bluetooth/bluetooth_utils.h"
25 #include "extensions/browser/event_router.h"
26 #include "extensions/browser/extension_system.h"
27 #include "extensions/common/permissions/permissions_data.h"
28 #include "net/base/io_buffer.h"
29
30 using device::BluetoothAdapter;
31 using device::BluetoothDevice;
32 using device::BluetoothProfile;
33 using device::BluetoothServiceRecord;
34 using device::BluetoothSocket;
35
36 namespace {
37
38 extensions::ExtensionBluetoothEventRouter* GetEventRouter(Profile* profile) {
39   return extensions::BluetoothAPI::Get(profile)->bluetooth_event_router();
40 }
41
42 }  // namespace
43
44 namespace {
45
46 const char kCouldNotGetLocalOutOfBandPairingData[] =
47     "Could not get local Out Of Band Pairing Data";
48 const char kCouldNotSetOutOfBandPairingData[] =
49     "Could not set Out Of Band Pairing Data";
50 const char kFailedToConnect[] = "Connection failed";
51 const char kInvalidDevice[] = "Invalid device";
52 const char kInvalidUuid[] = "Invalid UUID";
53 const char kPermissionDenied[] = "Permission to add profile denied.";
54 const char kProfileAlreadyRegistered[] =
55     "This profile has already been registered";
56 const char kProfileNotFound[] = "Profile not found: invalid uuid";
57 const char kProfileRegistrationFailed[] = "Profile registration failed";
58 const char kServiceDiscoveryFailed[] = "Service discovery failed";
59 const char kSocketNotFoundError[] = "Socket not found: invalid socket id";
60 const char kStartDiscoveryFailed[] = "Starting discovery failed";
61 const char kStopDiscoveryFailed[] = "Failed to stop discovery";
62
63 }  // namespace
64
65 namespace AddProfile = extensions::api::bluetooth::AddProfile;
66 namespace bluetooth = extensions::api::bluetooth;
67 namespace Connect = extensions::api::bluetooth::Connect;
68 namespace Disconnect = extensions::api::bluetooth::Disconnect;
69 namespace GetDevices = extensions::api::bluetooth::GetDevices;
70 namespace GetProfiles = extensions::api::bluetooth::GetProfiles;
71 namespace GetServices = extensions::api::bluetooth::GetServices;
72 namespace Read = extensions::api::bluetooth::Read;
73 namespace RemoveProfile = extensions::api::bluetooth::RemoveProfile;
74 namespace SetOutOfBandPairingData =
75     extensions::api::bluetooth::SetOutOfBandPairingData;
76 namespace Write = extensions::api::bluetooth::Write;
77
78 namespace extensions {
79
80 // static
81 BluetoothAPI* BluetoothAPI::Get(Profile* profile) {
82   return BluetoothAPIFactory::GetForProfile(profile);
83 }
84
85 BluetoothAPI::BluetoothAPI(Profile* profile) : profile_(profile) {
86   ExtensionSystem::Get(profile_)->event_router()->RegisterObserver(
87       this, bluetooth::OnAdapterStateChanged::kEventName);
88 }
89
90 BluetoothAPI::~BluetoothAPI() {
91 }
92
93 ExtensionBluetoothEventRouter* BluetoothAPI::bluetooth_event_router() {
94   if (!bluetooth_event_router_)
95     bluetooth_event_router_.reset(new ExtensionBluetoothEventRouter(profile_));
96
97   return bluetooth_event_router_.get();
98 }
99
100 void BluetoothAPI::Shutdown() {
101   ExtensionSystem::Get(profile_)->event_router()->UnregisterObserver(this);
102 }
103
104 void BluetoothAPI::OnListenerAdded(const EventListenerInfo& details) {
105   if (bluetooth_event_router()->IsBluetoothSupported())
106     bluetooth_event_router()->OnListenerAdded();
107 }
108
109 void BluetoothAPI::OnListenerRemoved(const EventListenerInfo& details) {
110   if (bluetooth_event_router()->IsBluetoothSupported())
111     bluetooth_event_router()->OnListenerRemoved();
112 }
113
114 namespace api {
115
116 BluetoothAddProfileFunction::BluetoothAddProfileFunction() {
117 }
118
119 bool BluetoothAddProfileFunction::RunImpl() {
120   scoped_ptr<AddProfile::Params> params(AddProfile::Params::Create(*args_));
121   EXTENSION_FUNCTION_VALIDATE(params.get() != NULL);
122
123   if (!BluetoothDevice::IsUUIDValid(params->profile.uuid)) {
124     SetError(kInvalidUuid);
125     return false;
126   }
127
128   BluetoothPermissionRequest param(params->profile.uuid);
129   if (!BluetoothManifestData::CheckRequest(GetExtension(), param)) {
130     error_ = kPermissionDenied;
131     return false;
132   }
133
134   uuid_ = device::bluetooth_utils::CanonicalUuid(params->profile.uuid);
135
136   if (GetEventRouter(GetProfile())->HasProfile(uuid_)) {
137     SetError(kProfileAlreadyRegistered);
138     return false;
139   }
140
141   BluetoothProfile::Options options;
142   if (params->profile.name.get())
143     options.name = *params->profile.name.get();
144   if (params->profile.channel.get())
145     options.channel = *params->profile.channel.get();
146   if (params->profile.psm.get())
147     options.psm = *params->profile.psm.get();
148   if (params->profile.require_authentication.get()) {
149     options.require_authentication =
150         *params->profile.require_authentication.get();
151   }
152   if (params->profile.require_authorization.get()) {
153     options.require_authorization =
154         *params->profile.require_authorization.get();
155   }
156   if (params->profile.auto_connect.get())
157     options.auto_connect = *params->profile.auto_connect.get();
158   if (params->profile.version.get())
159     options.version = *params->profile.version.get();
160   if (params->profile.features.get())
161     options.features = *params->profile.features.get();
162
163   RegisterProfile(
164       options,
165       base::Bind(&BluetoothAddProfileFunction::OnProfileRegistered, this));
166
167   return true;
168 }
169
170 void BluetoothAddProfileFunction::RegisterProfile(
171     const BluetoothProfile::Options& options,
172     const BluetoothProfile::ProfileCallback& callback) {
173   BluetoothProfile::Register(uuid_, options, callback);
174 }
175
176 void BluetoothAddProfileFunction::OnProfileRegistered(
177     BluetoothProfile* bluetooth_profile) {
178   if (!bluetooth_profile) {
179     SetError(kProfileRegistrationFailed);
180     SendResponse(false);
181     return;
182   }
183
184   if (GetEventRouter(GetProfile())->HasProfile(uuid_)) {
185     bluetooth_profile->Unregister();
186     SetError(kProfileAlreadyRegistered);
187     SendResponse(false);
188     return;
189   }
190
191   bluetooth_profile->SetConnectionCallback(
192       base::Bind(&ExtensionBluetoothEventRouter::DispatchConnectionEvent,
193                  base::Unretained(GetEventRouter(GetProfile())),
194                  extension_id(),
195                  uuid_));
196   GetEventRouter(GetProfile())->AddProfile(
197       uuid_, extension_id(), bluetooth_profile);
198   SendResponse(true);
199 }
200
201 bool BluetoothRemoveProfileFunction::RunImpl() {
202   scoped_ptr<RemoveProfile::Params> params(
203       RemoveProfile::Params::Create(*args_));
204
205   if (!BluetoothDevice::IsUUIDValid(params->profile.uuid)) {
206     SetError(kInvalidUuid);
207     return false;
208   }
209
210   std::string uuid =
211       device::bluetooth_utils::CanonicalUuid(params->profile.uuid);
212
213   if (!GetEventRouter(GetProfile())->HasProfile(uuid)) {
214     SetError(kProfileNotFound);
215     return false;
216   }
217
218   GetEventRouter(GetProfile())->RemoveProfile(uuid);
219   return true;
220 }
221
222 // TODO(youngki): Implement.
223 bool BluetoothGetProfilesFunction::DoWork(
224     scoped_refptr<device::BluetoothAdapter> adapter) {
225   scoped_ptr<GetProfiles::Params> params(GetProfiles::Params::Create(*args_));
226   EXTENSION_FUNCTION_VALIDATE(params.get() != NULL);
227   const bluetooth::GetProfilesOptions& options = params->options;
228
229   BluetoothDevice* device = adapter->GetDevice(options.device.address);
230   if (!device) {
231     SetError(kInvalidDevice);
232     SendResponse(false);
233     return false;
234   }
235
236   BluetoothDevice::ServiceList service_list = device->GetServices();
237
238   base::ListValue* profiles = new base::ListValue;
239   for (BluetoothDevice::ServiceList::const_iterator iter = service_list.begin();
240        iter != service_list.end();
241        ++iter) {
242     bluetooth::Profile api_profile;
243     api_profile.uuid = *iter;
244     profiles->Append(api_profile.ToValue().release());
245   }
246
247   SetResult(profiles);
248   SendResponse(true);
249
250   return true;
251 }
252
253 bool BluetoothGetAdapterStateFunction::DoWork(
254     scoped_refptr<BluetoothAdapter> adapter) {
255   bluetooth::AdapterState state;
256   PopulateAdapterState(*adapter.get(), &state);
257   SetResult(state.ToValue().release());
258   SendResponse(true);
259   return true;
260 }
261
262 BluetoothGetDevicesFunction::BluetoothGetDevicesFunction()
263     : device_events_sent_(0) {}
264
265 void BluetoothGetDevicesFunction::DispatchDeviceSearchResult(
266     const BluetoothDevice& device) {
267   bluetooth::Device extension_device;
268   bluetooth::BluetoothDeviceToApiDevice(device, &extension_device);
269   GetEventRouter(GetProfile())->DispatchDeviceEvent(
270       extensions::event_names::kBluetoothOnDeviceSearchResult,
271       extension_device);
272
273   device_events_sent_++;
274 }
275
276 void BluetoothGetDevicesFunction::FinishDeviceSearch() {
277   scoped_ptr<base::ListValue> args(new base::ListValue());
278   scoped_ptr<base::DictionaryValue> info(new base::DictionaryValue());
279   info->SetInteger("expectedEventCount", device_events_sent_);
280   args->Append(info.release());
281
282   scoped_ptr<extensions::Event> event(new extensions::Event(
283       extensions::event_names::kBluetoothOnDeviceSearchFinished, args.Pass()));
284   extensions::ExtensionSystem::Get(GetProfile())
285       ->event_router()
286       ->BroadcastEvent(event.Pass());
287
288   SendResponse(true);
289 }
290
291 bool BluetoothGetDevicesFunction::DoWork(
292     scoped_refptr<BluetoothAdapter> adapter) {
293   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
294
295   scoped_ptr<GetDevices::Params> params(GetDevices::Params::Create(*args_));
296   EXTENSION_FUNCTION_VALIDATE(params.get() != NULL);
297   const bluetooth::GetDevicesOptions& options = params->options;
298
299   std::string uuid;
300   if (options.profile.get() != NULL) {
301     uuid = options.profile->uuid;
302     if (!BluetoothDevice::IsUUIDValid(uuid)) {
303       SetError(kInvalidUuid);
304       SendResponse(false);
305       return false;
306     }
307   }
308
309   BluetoothAdapter::DeviceList devices = adapter->GetDevices();
310   for (BluetoothAdapter::DeviceList::const_iterator iter = devices.begin();
311        iter != devices.end();
312        ++iter) {
313     const BluetoothDevice* device = *iter;
314     DCHECK(device);
315     if (uuid.empty() || device->ProvidesServiceWithUUID(uuid))
316       DispatchDeviceSearchResult(*device);
317   }
318
319   FinishDeviceSearch();
320
321   return true;
322 }
323
324 void BluetoothGetServicesFunction::GetServiceRecordsCallback(
325     base::ListValue* services,
326     const BluetoothDevice::ServiceRecordList& records) {
327   for (BluetoothDevice::ServiceRecordList::const_iterator i = records.begin();
328       i != records.end(); ++i) {
329     const BluetoothServiceRecord& record = **i;
330     bluetooth::ServiceRecord api_record;
331     api_record.name = record.name();
332     if (!record.uuid().empty())
333       api_record.uuid.reset(new std::string(record.uuid()));
334     services->Append(api_record.ToValue().release());
335   }
336
337   SendResponse(true);
338 }
339
340 void BluetoothGetServicesFunction::OnErrorCallback() {
341   SetError(kServiceDiscoveryFailed);
342   SendResponse(false);
343 }
344
345 bool BluetoothGetServicesFunction::DoWork(
346     scoped_refptr<BluetoothAdapter> adapter) {
347   scoped_ptr<GetServices::Params> params(GetServices::Params::Create(*args_));
348   EXTENSION_FUNCTION_VALIDATE(params.get() != NULL);
349   const bluetooth::GetServicesOptions& options = params->options;
350
351   BluetoothDevice* device = adapter->GetDevice(options.device_address);
352   if (!device) {
353     SetError(kInvalidDevice);
354     SendResponse(false);
355     return false;
356   }
357
358   base::ListValue* services = new base::ListValue;
359   SetResult(services);
360
361   device->GetServiceRecords(
362       base::Bind(&BluetoothGetServicesFunction::GetServiceRecordsCallback,
363                  this,
364                  services),
365       base::Bind(&BluetoothGetServicesFunction::OnErrorCallback,
366                  this));
367
368   return true;
369 }
370
371 void BluetoothConnectFunction::OnSuccessCallback() {
372   SendResponse(true);
373 }
374
375 void BluetoothConnectFunction::OnErrorCallback() {
376   SetError(kFailedToConnect);
377   SendResponse(false);
378 }
379
380 bool BluetoothConnectFunction::DoWork(scoped_refptr<BluetoothAdapter> adapter) {
381   scoped_ptr<Connect::Params> params(Connect::Params::Create(*args_));
382   EXTENSION_FUNCTION_VALIDATE(params.get() != NULL);
383   const bluetooth::ConnectOptions& options = params->options;
384
385   if (!BluetoothDevice::IsUUIDValid(options.profile.uuid)) {
386     SetError(kInvalidUuid);
387     SendResponse(false);
388     return false;
389   }
390
391   BluetoothDevice* device = adapter->GetDevice(options.device.address);
392   if (!device) {
393     SetError(kInvalidDevice);
394     SendResponse(false);
395     return false;
396   }
397
398   std::string uuid = device::bluetooth_utils::CanonicalUuid(
399       options.profile.uuid);
400
401   BluetoothProfile* bluetooth_profile =
402       GetEventRouter(GetProfile())->GetProfile(uuid);
403   if (!bluetooth_profile) {
404     SetError(kProfileNotFound);
405     SendResponse(false);
406     return false;
407   }
408
409   device->ConnectToProfile(
410       bluetooth_profile,
411       base::Bind(&BluetoothConnectFunction::OnSuccessCallback, this),
412       base::Bind(&BluetoothConnectFunction::OnErrorCallback, this));
413
414   return true;
415 }
416
417 bool BluetoothDisconnectFunction::RunImpl() {
418   scoped_ptr<Disconnect::Params> params(Disconnect::Params::Create(*args_));
419   EXTENSION_FUNCTION_VALIDATE(params.get() != NULL);
420   const bluetooth::DisconnectOptions& options = params->options;
421   return GetEventRouter(GetProfile())->ReleaseSocket(options.socket.id);
422 }
423
424 BluetoothReadFunction::BluetoothReadFunction() : success_(false) {}
425 BluetoothReadFunction::~BluetoothReadFunction() {}
426
427 bool BluetoothReadFunction::Prepare() {
428   scoped_ptr<Read::Params> params(Read::Params::Create(*args_));
429   EXTENSION_FUNCTION_VALIDATE(params.get() != NULL);
430   const bluetooth::ReadOptions& options = params->options;
431
432   socket_ = GetEventRouter(GetProfile())->GetSocket(options.socket.id);
433   if (socket_.get() == NULL) {
434     SetError(kSocketNotFoundError);
435     return false;
436   }
437
438   success_ = false;
439   return true;
440 }
441
442 void BluetoothReadFunction::Work() {
443   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
444
445   if (!socket_.get())
446     return;
447
448   scoped_refptr<net::GrowableIOBuffer> buffer(new net::GrowableIOBuffer);
449   success_ = socket_->Receive(buffer.get());
450   if (success_)
451     SetResult(base::BinaryValue::CreateWithCopiedBuffer(buffer->StartOfBuffer(),
452                                                         buffer->offset()));
453   else
454     SetError(socket_->GetLastErrorMessage());
455 }
456
457 bool BluetoothReadFunction::Respond() {
458   return success_;
459 }
460
461 BluetoothWriteFunction::BluetoothWriteFunction()
462     : success_(false),
463       data_to_write_(NULL) {
464 }
465
466 BluetoothWriteFunction::~BluetoothWriteFunction() {}
467
468 bool BluetoothWriteFunction::Prepare() {
469   // TODO(bryeung): update to new-style parameter passing when ArrayBuffer
470   // support is added
471   base::DictionaryValue* options;
472   EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &options));
473
474   base::DictionaryValue* socket;
475   EXTENSION_FUNCTION_VALIDATE(options->GetDictionary("socket", &socket));
476
477   int socket_id;
478   EXTENSION_FUNCTION_VALIDATE(socket->GetInteger("id", &socket_id));
479
480   socket_ = GetEventRouter(GetProfile())->GetSocket(socket_id);
481   if (socket_.get() == NULL) {
482     SetError(kSocketNotFoundError);
483     return false;
484   }
485
486   base::BinaryValue* tmp_data;
487   EXTENSION_FUNCTION_VALIDATE(options->GetBinary("data", &tmp_data));
488   data_to_write_ = tmp_data;
489
490   success_ = false;
491   return socket_.get() != NULL;
492 }
493
494 void BluetoothWriteFunction::Work() {
495   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
496
497   if (socket_.get() == NULL)
498     return;
499
500   scoped_refptr<net::WrappedIOBuffer> wrapped_io_buffer(
501       new net::WrappedIOBuffer(data_to_write_->GetBuffer()));
502   scoped_refptr<net::DrainableIOBuffer> drainable_io_buffer(
503       new net::DrainableIOBuffer(wrapped_io_buffer.get(),
504                                  data_to_write_->GetSize()));
505   success_ = socket_->Send(drainable_io_buffer.get());
506   if (success_) {
507     if (drainable_io_buffer->BytesConsumed() > 0)
508       SetResult(new base::FundamentalValue(
509           drainable_io_buffer->BytesConsumed()));
510     else
511       results_.reset();
512   } else {
513     SetError(socket_->GetLastErrorMessage());
514   }
515 }
516
517 bool BluetoothWriteFunction::Respond() {
518   return success_;
519 }
520
521 void BluetoothSetOutOfBandPairingDataFunction::OnSuccessCallback() {
522   SendResponse(true);
523 }
524
525 void BluetoothSetOutOfBandPairingDataFunction::OnErrorCallback() {
526   SetError(kCouldNotSetOutOfBandPairingData);
527   SendResponse(false);
528 }
529
530 bool BluetoothSetOutOfBandPairingDataFunction::DoWork(
531     scoped_refptr<BluetoothAdapter> adapter) {
532   // TODO(bryeung): update to new-style parameter passing when ArrayBuffer
533   // support is added
534   base::DictionaryValue* options;
535   EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &options));
536   std::string address;
537   EXTENSION_FUNCTION_VALIDATE(options->GetString("deviceAddress", &address));
538
539   BluetoothDevice* device = adapter->GetDevice(address);
540   if (!device) {
541     SetError(kInvalidDevice);
542     SendResponse(false);
543     return false;
544   }
545
546   if (options->HasKey("data")) {
547     base::DictionaryValue* data_in;
548     EXTENSION_FUNCTION_VALIDATE(options->GetDictionary("data", &data_in));
549
550     device::BluetoothOutOfBandPairingData data_out;
551
552     base::BinaryValue* tmp_data;
553     EXTENSION_FUNCTION_VALIDATE(data_in->GetBinary("hash", &tmp_data));
554     EXTENSION_FUNCTION_VALIDATE(
555         tmp_data->GetSize() == device::kBluetoothOutOfBandPairingDataSize);
556     memcpy(data_out.hash,
557         reinterpret_cast<uint8_t*>(tmp_data->GetBuffer()),
558         device::kBluetoothOutOfBandPairingDataSize);
559
560     EXTENSION_FUNCTION_VALIDATE(data_in->GetBinary("randomizer", &tmp_data));
561     EXTENSION_FUNCTION_VALIDATE(
562         tmp_data->GetSize() == device::kBluetoothOutOfBandPairingDataSize);
563     memcpy(data_out.randomizer,
564         reinterpret_cast<uint8_t*>(tmp_data->GetBuffer()),
565         device::kBluetoothOutOfBandPairingDataSize);
566
567     device->SetOutOfBandPairingData(
568         data_out,
569         base::Bind(&BluetoothSetOutOfBandPairingDataFunction::OnSuccessCallback,
570             this),
571         base::Bind(&BluetoothSetOutOfBandPairingDataFunction::OnErrorCallback,
572             this));
573   } else {
574     device->ClearOutOfBandPairingData(
575         base::Bind(&BluetoothSetOutOfBandPairingDataFunction::OnSuccessCallback,
576             this),
577         base::Bind(&BluetoothSetOutOfBandPairingDataFunction::OnErrorCallback,
578             this));
579   }
580
581   return true;
582 }
583
584 void BluetoothGetLocalOutOfBandPairingDataFunction::ReadCallback(
585     const device::BluetoothOutOfBandPairingData& data) {
586   base::BinaryValue* hash = base::BinaryValue::CreateWithCopiedBuffer(
587       reinterpret_cast<const char*>(data.hash),
588       device::kBluetoothOutOfBandPairingDataSize);
589   base::BinaryValue* randomizer = base::BinaryValue::CreateWithCopiedBuffer(
590       reinterpret_cast<const char*>(data.randomizer),
591       device::kBluetoothOutOfBandPairingDataSize);
592
593   // TODO(bryeung): convert to bluetooth::OutOfBandPairingData
594   // when ArrayBuffer support within objects is completed.
595   base::DictionaryValue* result = new base::DictionaryValue();
596   result->Set("hash", hash);
597   result->Set("randomizer", randomizer);
598
599   SetResult(result);
600
601   SendResponse(true);
602 }
603
604 void BluetoothGetLocalOutOfBandPairingDataFunction::ErrorCallback() {
605   SetError(kCouldNotGetLocalOutOfBandPairingData);
606   SendResponse(false);
607 }
608
609 bool BluetoothGetLocalOutOfBandPairingDataFunction::DoWork(
610     scoped_refptr<BluetoothAdapter> adapter) {
611   adapter->ReadLocalOutOfBandPairingData(
612       base::Bind(&BluetoothGetLocalOutOfBandPairingDataFunction::ReadCallback,
613           this),
614       base::Bind(&BluetoothGetLocalOutOfBandPairingDataFunction::ErrorCallback,
615           this));
616
617   return true;
618 }
619
620 void BluetoothStartDiscoveryFunction::OnSuccessCallback() {
621   SendResponse(true);
622 }
623
624 void BluetoothStartDiscoveryFunction::OnErrorCallback() {
625   SetError(kStartDiscoveryFailed);
626   GetEventRouter(GetProfile())->SetResponsibleForDiscovery(false);
627   SendResponse(false);
628   GetEventRouter(GetProfile())->OnListenerRemoved();
629 }
630
631 bool BluetoothStartDiscoveryFunction::DoWork(
632     scoped_refptr<BluetoothAdapter> adapter) {
633   GetEventRouter(GetProfile())->SetSendDiscoveryEvents(true);
634
635   // If this profile is already discovering devices, there should be nothing
636   // else to do.
637   if (!GetEventRouter(GetProfile())->IsResponsibleForDiscovery()) {
638     GetEventRouter(GetProfile())->SetResponsibleForDiscovery(true);
639     GetEventRouter(GetProfile())->OnListenerAdded();
640     adapter->StartDiscovering(
641         base::Bind(&BluetoothStartDiscoveryFunction::OnSuccessCallback, this),
642         base::Bind(&BluetoothStartDiscoveryFunction::OnErrorCallback, this));
643   }
644
645   return true;
646 }
647
648 void BluetoothStopDiscoveryFunction::OnSuccessCallback() {
649   SendResponse(true);
650   GetEventRouter(GetProfile())->OnListenerRemoved();
651 }
652
653 void BluetoothStopDiscoveryFunction::OnErrorCallback() {
654   SetError(kStopDiscoveryFailed);
655   GetEventRouter(GetProfile())->SetResponsibleForDiscovery(true);
656   SendResponse(false);
657   GetEventRouter(GetProfile())->OnListenerRemoved();
658 }
659
660 bool BluetoothStopDiscoveryFunction::DoWork(
661     scoped_refptr<BluetoothAdapter> adapter) {
662   GetEventRouter(GetProfile())->SetSendDiscoveryEvents(false);
663   if (GetEventRouter(GetProfile())->IsResponsibleForDiscovery()) {
664     adapter->StopDiscovering(
665         base::Bind(&BluetoothStopDiscoveryFunction::OnSuccessCallback, this),
666         base::Bind(&BluetoothStopDiscoveryFunction::OnErrorCallback, this));
667   }
668
669   return true;
670 }
671
672 }  // namespace api
673 }  // namespace extensions