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/event_router.h"
     15 #include "chrome/browser/extensions/extension_system.h"
     16 #include "chrome/browser/profiles/profile.h"
     17 #include "chrome/common/extensions/api/bluetooth.h"
     18 #include "chrome/common/extensions/permissions/bluetooth_permission.h"
     19 #include "chrome/common/extensions/permissions/permissions_data.h"
     20 #include "content/public/browser/browser_thread.h"
     21 #include "device/bluetooth/bluetooth_adapter.h"
     22 #include "device/bluetooth/bluetooth_device.h"
     23 #include "device/bluetooth/bluetooth_out_of_band_pairing_data.h"
     24 #include "device/bluetooth/bluetooth_profile.h"
     25 #include "device/bluetooth/bluetooth_service_record.h"
     26 #include "device/bluetooth/bluetooth_socket.h"
     27 #include "device/bluetooth/bluetooth_utils.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 kPlatformNotSupported[] =
     55     "This operation is not supported on your platform";
     56 const char kProfileAlreadyRegistered[] =
     57     "This profile has already been registered";
     58 const char kProfileNotFound[] = "Profile not found: invalid uuid";
     59 const char kProfileRegistrationFailed[] = "Profile registration failed";
     60 const char kServiceDiscoveryFailed[] = "Service discovery failed";
     61 const char kSocketNotFoundError[] = "Socket not found: invalid socket id";
     62 const char kStartDiscoveryFailed[] = "Starting discovery failed";
     63 const char kStopDiscoveryFailed[] = "Failed to stop discovery";
     64 
     65 }  // namespace
     66 
     67 namespace AddProfile = extensions::api::bluetooth::AddProfile;
     68 namespace Connect = extensions::api::bluetooth::Connect;
     69 namespace Disconnect = extensions::api::bluetooth::Disconnect;
     70 namespace GetDevices = extensions::api::bluetooth::GetDevices;
     71 namespace GetProfiles = extensions::api::bluetooth::GetProfiles;
     72 namespace GetServices = extensions::api::bluetooth::GetServices;
     73 namespace Read = extensions::api::bluetooth::Read;
     74 namespace RemoveProfile = extensions::api::bluetooth::RemoveProfile;
     75 namespace SetOutOfBandPairingData =
     76     extensions::api::bluetooth::SetOutOfBandPairingData;
     77 namespace Write = extensions::api::bluetooth::Write;
     78 
     79 namespace extensions {
     80 
     81 // static
     82 BluetoothAPI* BluetoothAPI::Get(Profile* profile) {
     83   return BluetoothAPIFactory::GetForProfile(profile);
     84 }
     85 
     86 BluetoothAPI::BluetoothAPI(Profile* profile) : profile_(profile) {
     87   ExtensionSystem::Get(profile_)->event_router()->RegisterObserver(
     88       this, extensions::event_names::kBluetoothOnAdapterStateChanged);
     89 }
     90 
     91 BluetoothAPI::~BluetoothAPI() {
     92 }
     93 
     94 ExtensionBluetoothEventRouter* BluetoothAPI::bluetooth_event_router() {
     95   if (!bluetooth_event_router_)
     96     bluetooth_event_router_.reset(new ExtensionBluetoothEventRouter(profile_));
     97 
     98   return bluetooth_event_router_.get();
     99 }
    100 
    101 void BluetoothAPI::Shutdown() {
    102   ExtensionSystem::Get(profile_)->event_router()->UnregisterObserver(this);
    103 }
    104 
    105 void BluetoothAPI::OnListenerAdded(const EventListenerInfo& details) {
    106   if (bluetooth_event_router()->IsBluetoothSupported())
    107     bluetooth_event_router()->OnListenerAdded();
    108 }
    109 
    110 void BluetoothAPI::OnListenerRemoved(const EventListenerInfo& details) {
    111   if (bluetooth_event_router()->IsBluetoothSupported())
    112     bluetooth_event_router()->OnListenerRemoved();
    113 }
    114 
    115 namespace api {
    116 
    117 BluetoothAddProfileFunction::BluetoothAddProfileFunction() {
    118 }
    119 
    120 bool BluetoothAddProfileFunction::RunImpl() {
    121   scoped_ptr<AddProfile::Params> params(AddProfile::Params::Create(*args_));
    122   EXTENSION_FUNCTION_VALIDATE(params.get() != NULL);
    123 
    124   if (!BluetoothDevice::IsUUIDValid(params->profile.uuid)) {
    125     SetError(kInvalidUuid);
    126     return false;
    127   }
    128 
    129   BluetoothPermission::CheckParam param(params->profile.uuid);
    130   if (!PermissionsData::CheckAPIPermissionWithParam(
    131           GetExtension(), APIPermission::kBluetooth, &param)) {
    132     SetError(kPermissionDenied);
    133     return false;
    134   }
    135 
    136   uuid_ = device::bluetooth_utils::CanonicalUuid(params->profile.uuid);
    137 
    138   if (GetEventRouter(profile())->HasProfile(uuid_)) {
    139     SetError(kProfileAlreadyRegistered);
    140     return false;
    141   }
    142 
    143   BluetoothProfile::Options options;
    144   if (params->profile.name.get())
    145     options.name = *params->profile.name.get();
    146   if (params->profile.channel.get())
    147     options.channel = *params->profile.channel.get();
    148   if (params->profile.psm.get())
    149     options.psm = *params->profile.psm.get();
    150   if (params->profile.require_authentication.get()) {
    151     options.require_authentication =
    152         *params->profile.require_authentication.get();
    153   }
    154   if (params->profile.require_authorization.get()) {
    155     options.require_authorization =
    156         *params->profile.require_authorization.get();
    157   }
    158   if (params->profile.auto_connect.get())
    159     options.auto_connect = *params->profile.auto_connect.get();
    160   if (params->profile.version.get())
    161     options.version = *params->profile.version.get();
    162   if (params->profile.features.get())
    163     options.features = *params->profile.features.get();
    164 
    165   RegisterProfile(
    166       options,
    167       base::Bind(&BluetoothAddProfileFunction::OnProfileRegistered, this));
    168 
    169   return true;
    170 }
    171 
    172 void BluetoothAddProfileFunction::RegisterProfile(
    173     const BluetoothProfile::Options& options,
    174     const BluetoothProfile::ProfileCallback& callback) {
    175   BluetoothProfile::Register(uuid_, options, callback);
    176 }
    177 
    178 void BluetoothAddProfileFunction::OnProfileRegistered(
    179     BluetoothProfile* bluetooth_profile) {
    180   if (!bluetooth_profile) {
    181     SetError(kProfileRegistrationFailed);
    182     SendResponse(false);
    183     return;
    184   }
    185 
    186   if (GetEventRouter(profile())->HasProfile(uuid_)) {
    187     bluetooth_profile->Unregister();
    188     SetError(kProfileAlreadyRegistered);
    189     SendResponse(false);
    190     return;
    191   }
    192 
    193   bluetooth_profile->SetConnectionCallback(
    194       base::Bind(&ExtensionBluetoothEventRouter::DispatchConnectionEvent,
    195                  base::Unretained(GetEventRouter(profile())),
    196                  extension_id(),
    197                  uuid_));
    198   GetEventRouter(profile())->AddProfile(uuid_, bluetooth_profile);
    199   SendResponse(true);
    200 }
    201 
    202 bool BluetoothRemoveProfileFunction::RunImpl() {
    203   scoped_ptr<RemoveProfile::Params> params(
    204       RemoveProfile::Params::Create(*args_));
    205 
    206   if (!BluetoothDevice::IsUUIDValid(params->profile.uuid)) {
    207     SetError(kInvalidUuid);
    208     return false;
    209   }
    210 
    211   std::string uuid =
    212       device::bluetooth_utils::CanonicalUuid(params->profile.uuid);
    213 
    214   if (!GetEventRouter(profile())->HasProfile(uuid)) {
    215     SetError(kProfileNotFound);
    216     return false;
    217   }
    218 
    219   GetEventRouter(profile())->RemoveProfile(uuid);
    220   return true;
    221 }
    222 
    223 // TODO(youngki): Implement.
    224 bool BluetoothGetProfilesFunction::DoWork(
    225     scoped_refptr<device::BluetoothAdapter> adapter) {
    226   scoped_ptr<GetProfiles::Params> params(GetProfiles::Params::Create(*args_));
    227   EXTENSION_FUNCTION_VALIDATE(params.get() != NULL);
    228   const bluetooth::GetProfilesOptions& options = params->options;
    229 
    230   BluetoothDevice* device = adapter->GetDevice(options.device.address);
    231   if (!device) {
    232     SetError(kInvalidDevice);
    233     SendResponse(false);
    234     return false;
    235   }
    236 
    237   BluetoothDevice::ServiceList service_list = device->GetServices();
    238 
    239   base::ListValue* profiles = new base::ListValue;
    240   for (BluetoothDevice::ServiceList::const_iterator iter = service_list.begin();
    241        iter != service_list.end();
    242        ++iter) {
    243     bluetooth::Profile api_profile;
    244     api_profile.uuid = *iter;
    245     profiles->Append(api_profile.ToValue().release());
    246   }
    247 
    248   SetResult(profiles);
    249   SendResponse(true);
    250 
    251   return true;
    252 }
    253 
    254 bool BluetoothGetAdapterStateFunction::DoWork(
    255     scoped_refptr<BluetoothAdapter> adapter) {
    256   bluetooth::AdapterState state;
    257   PopulateAdapterState(*adapter.get(), &state);
    258   SetResult(state.ToValue().release());
    259   SendResponse(true);
    260   return true;
    261 }
    262 
    263 BluetoothGetDevicesFunction::BluetoothGetDevicesFunction()
    264     : device_events_sent_(0) {}
    265 
    266 void BluetoothGetDevicesFunction::DispatchDeviceSearchResult(
    267     const BluetoothDevice& device) {
    268   bluetooth::Device extension_device;
    269   bluetooth::BluetoothDeviceToApiDevice(device, &extension_device);
    270   GetEventRouter(profile())->DispatchDeviceEvent(
    271       extensions::event_names::kBluetoothOnDeviceSearchResult,
    272       extension_device);
    273 
    274   device_events_sent_++;
    275 }
    276 
    277 void BluetoothGetDevicesFunction::FinishDeviceSearch() {
    278   scoped_ptr<base::ListValue> args(new base::ListValue());
    279   scoped_ptr<base::DictionaryValue> info(new base::DictionaryValue());
    280   info->SetInteger("expectedEventCount", device_events_sent_);
    281   args->Append(info.release());
    282 
    283   scoped_ptr<extensions::Event> event(new extensions::Event(
    284       extensions::event_names::kBluetoothOnDeviceSearchFinished, args.Pass()));
    285   extensions::ExtensionSystem::Get(profile())->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(profile())->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(profile())->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(profile())->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(profile())->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(base::Value::CreateIntegerValue(
    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(profile())->SetResponsibleForDiscovery(false);
    627   SendResponse(false);
    628   GetEventRouter(profile())->OnListenerRemoved();
    629 }
    630 
    631 bool BluetoothStartDiscoveryFunction::DoWork(
    632     scoped_refptr<BluetoothAdapter> adapter) {
    633   GetEventRouter(profile())->SetSendDiscoveryEvents(true);
    634 
    635   // If this profile is already discovering devices, there should be nothing
    636   // else to do.
    637   if (!GetEventRouter(profile())->IsResponsibleForDiscovery()) {
    638     GetEventRouter(profile())->SetResponsibleForDiscovery(true);
    639     GetEventRouter(profile())->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(profile())->OnListenerRemoved();
    651 }
    652 
    653 void BluetoothStopDiscoveryFunction::OnErrorCallback() {
    654   SetError(kStopDiscoveryFailed);
    655   GetEventRouter(profile())->SetResponsibleForDiscovery(true);
    656   SendResponse(false);
    657   GetEventRouter(profile())->OnListenerRemoved();
    658 }
    659 
    660 bool BluetoothStopDiscoveryFunction::DoWork(
    661     scoped_refptr<BluetoothAdapter> adapter) {
    662   GetEventRouter(profile())->SetSendDiscoveryEvents(false);
    663   if (GetEventRouter(profile())->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