Home | History | Annotate | Download | only in bluetooth
      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/extensions/extension_system.h"
     15 #include "chrome/browser/profiles/profile.h"
     16 #include "chrome/common/extensions/api/bluetooth.h"
     17 #include "chrome/common/extensions/permissions/bluetooth_permission.h"
     18 #include "content/public/browser/browser_thread.h"
     19 #include "device/bluetooth/bluetooth_adapter.h"
     20 #include "device/bluetooth/bluetooth_device.h"
     21 #include "device/bluetooth/bluetooth_out_of_band_pairing_data.h"
     22 #include "device/bluetooth/bluetooth_profile.h"
     23 #include "device/bluetooth/bluetooth_service_record.h"
     24 #include "device/bluetooth/bluetooth_socket.h"
     25 #include "device/bluetooth/bluetooth_utils.h"
     26 #include "extensions/browser/event_router.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   BluetoothPermission::CheckParam param(params->profile.uuid);
    129   if (!PermissionsData::CheckAPIPermissionWithParam(
    130           GetExtension(), APIPermission::kBluetooth, &param)) {
    131     SetError(kPermissionDenied);
    132     return false;
    133   }
    134 
    135   uuid_ = device::bluetooth_utils::CanonicalUuid(params->profile.uuid);
    136 
    137   if (GetEventRouter(GetProfile())->HasProfile(uuid_)) {
    138     SetError(kProfileAlreadyRegistered);
    139     return false;
    140   }
    141 
    142   BluetoothProfile::Options options;
    143   if (params->profile.name.get())
    144     options.name = *params->profile.name.get();
    145   if (params->profile.channel.get())
    146     options.channel = *params->profile.channel.get();
    147   if (params->profile.psm.get())
    148     options.psm = *params->profile.psm.get();
    149   if (params->profile.require_authentication.get()) {
    150     options.require_authentication =
    151         *params->profile.require_authentication.get();
    152   }
    153   if (params->profile.require_authorization.get()) {
    154     options.require_authorization =
    155         *params->profile.require_authorization.get();
    156   }
    157   if (params->profile.auto_connect.get())
    158     options.auto_connect = *params->profile.auto_connect.get();
    159   if (params->profile.version.get())
    160     options.version = *params->profile.version.get();
    161   if (params->profile.features.get())
    162     options.features = *params->profile.features.get();
    163 
    164   RegisterProfile(
    165       options,
    166       base::Bind(&BluetoothAddProfileFunction::OnProfileRegistered, this));
    167 
    168   return true;
    169 }
    170 
    171 void BluetoothAddProfileFunction::RegisterProfile(
    172     const BluetoothProfile::Options& options,
    173     const BluetoothProfile::ProfileCallback& callback) {
    174   BluetoothProfile::Register(uuid_, options, callback);
    175 }
    176 
    177 void BluetoothAddProfileFunction::OnProfileRegistered(
    178     BluetoothProfile* bluetooth_profile) {
    179   if (!bluetooth_profile) {
    180     SetError(kProfileRegistrationFailed);
    181     SendResponse(false);
    182     return;
    183   }
    184 
    185   if (GetEventRouter(GetProfile())->HasProfile(uuid_)) {
    186     bluetooth_profile->Unregister();
    187     SetError(kProfileAlreadyRegistered);
    188     SendResponse(false);
    189     return;
    190   }
    191 
    192   bluetooth_profile->SetConnectionCallback(
    193       base::Bind(&ExtensionBluetoothEventRouter::DispatchConnectionEvent,
    194                  base::Unretained(GetEventRouter(GetProfile())),
    195                  extension_id(),
    196                  uuid_));
    197   GetEventRouter(GetProfile())->AddProfile(uuid_, 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
    674