Home | History | Annotate | Download | only in bluetooth_socket
      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 "extensions/browser/api/bluetooth_socket/bluetooth_socket_api.h"
      6 
      7 #include <stdint.h>
      8 
      9 #include "content/public/browser/browser_context.h"
     10 #include "content/public/browser/browser_thread.h"
     11 #include "device/bluetooth/bluetooth_adapter.h"
     12 #include "device/bluetooth/bluetooth_adapter_factory.h"
     13 #include "device/bluetooth/bluetooth_device.h"
     14 #include "device/bluetooth/bluetooth_socket.h"
     15 #include "extensions/browser/api/bluetooth_socket/bluetooth_api_socket.h"
     16 #include "extensions/browser/api/bluetooth_socket/bluetooth_socket_event_dispatcher.h"
     17 #include "extensions/common/api/bluetooth/bluetooth_manifest_data.h"
     18 #include "extensions/common/permissions/permissions_data.h"
     19 #include "net/base/io_buffer.h"
     20 
     21 using content::BrowserThread;
     22 using extensions::BluetoothApiSocket;
     23 using extensions::core_api::bluetooth_socket::ListenOptions;
     24 using extensions::core_api::bluetooth_socket::SocketInfo;
     25 using extensions::core_api::bluetooth_socket::SocketProperties;
     26 
     27 namespace extensions {
     28 namespace core_api {
     29 
     30 namespace {
     31 
     32 const char kDeviceNotFoundError[] = "Device not found";
     33 const char kInvalidPsmError[] = "Invalid PSM";
     34 const char kInvalidUuidError[] = "Invalid UUID";
     35 const char kPermissionDeniedError[] = "Permission denied";
     36 const char kSocketNotFoundError[] = "Socket not found";
     37 
     38 linked_ptr<SocketInfo> CreateSocketInfo(int socket_id,
     39                                         BluetoothApiSocket* socket) {
     40   DCHECK(BrowserThread::CurrentlyOn(BluetoothApiSocket::kThreadId));
     41   linked_ptr<SocketInfo> socket_info(new SocketInfo());
     42   // This represents what we know about the socket, and does not call through
     43   // to the system.
     44   socket_info->socket_id = socket_id;
     45   if (socket->name()) {
     46     socket_info->name.reset(new std::string(*socket->name()));
     47   }
     48   socket_info->persistent = socket->persistent();
     49   if (socket->buffer_size() > 0) {
     50     socket_info->buffer_size.reset(new int(socket->buffer_size()));
     51   }
     52   socket_info->paused = socket->paused();
     53   socket_info->connected = socket->IsConnected();
     54 
     55   if (socket->IsConnected())
     56     socket_info->address.reset(new std::string(socket->device_address()));
     57   socket_info->uuid.reset(new std::string(socket->uuid().canonical_value()));
     58 
     59   return socket_info;
     60 }
     61 
     62 void SetSocketProperties(BluetoothApiSocket* socket,
     63                          SocketProperties* properties) {
     64   if (properties->name.get()) {
     65     socket->set_name(*properties->name.get());
     66   }
     67   if (properties->persistent.get()) {
     68     socket->set_persistent(*properties->persistent.get());
     69   }
     70   if (properties->buffer_size.get()) {
     71     // buffer size is validated when issuing the actual Recv operation
     72     // on the socket.
     73     socket->set_buffer_size(*properties->buffer_size.get());
     74   }
     75 }
     76 
     77 BluetoothSocketEventDispatcher* GetSocketEventDispatcher(
     78     content::BrowserContext* browser_context) {
     79   BluetoothSocketEventDispatcher* socket_event_dispatcher =
     80       BluetoothSocketEventDispatcher::Get(browser_context);
     81   DCHECK(socket_event_dispatcher)
     82       << "There is no socket event dispatcher. "
     83          "If this assertion is failing during a test, then it is likely that "
     84          "TestExtensionSystem is failing to provide an instance of "
     85          "BluetoothSocketEventDispatcher.";
     86   return socket_event_dispatcher;
     87 }
     88 
     89 // Returns |true| if |psm| is a valid PSM.
     90 // Per the Bluetooth specification, the PSM field must be at least two octets in
     91 // length, with least significant bit of the least significant octet equal to
     92 // '1' and the least significant bit of the most significant octet equal to '0'.
     93 bool IsValidPsm(int psm) {
     94   if (psm <= 0)
     95     return false;
     96 
     97   std::vector<int16_t> octets;
     98   while (psm > 0) {
     99      octets.push_back(psm & 0xFF);
    100      psm = psm >> 8;
    101   }
    102 
    103   if (octets.size() < 2U)
    104     return false;
    105 
    106   // The least significant bit of the least significant octet must be '1'.
    107   if ((octets.front() & 0x01) != 1)
    108     return false;
    109 
    110   // The least significant bit of the most significant octet must be '0'.
    111   if ((octets.back() & 0x01) != 0)
    112     return false;
    113 
    114   return true;
    115 }
    116 
    117 }  // namespace
    118 
    119 BluetoothSocketAsyncApiFunction::BluetoothSocketAsyncApiFunction() {}
    120 
    121 BluetoothSocketAsyncApiFunction::~BluetoothSocketAsyncApiFunction() {}
    122 
    123 bool BluetoothSocketAsyncApiFunction::RunAsync() {
    124   if (!PrePrepare() || !Prepare()) {
    125     return false;
    126   }
    127   AsyncWorkStart();
    128   return true;
    129 }
    130 
    131 bool BluetoothSocketAsyncApiFunction::PrePrepare() {
    132   if (!BluetoothManifestData::CheckSocketPermitted(extension())) {
    133     error_ = kPermissionDeniedError;
    134     return false;
    135   }
    136 
    137   manager_ = ApiResourceManager<BluetoothApiSocket>::Get(browser_context());
    138   DCHECK(manager_)
    139       << "There is no socket manager. "
    140          "If this assertion is failing during a test, then it is likely that "
    141          "TestExtensionSystem is failing to provide an instance of "
    142          "ApiResourceManager<BluetoothApiSocket>.";
    143   return manager_ != NULL;
    144 }
    145 
    146 bool BluetoothSocketAsyncApiFunction::Respond() { return error_.empty(); }
    147 
    148 void BluetoothSocketAsyncApiFunction::AsyncWorkCompleted() {
    149   SendResponse(Respond());
    150 }
    151 
    152 void BluetoothSocketAsyncApiFunction::Work() {}
    153 
    154 void BluetoothSocketAsyncApiFunction::AsyncWorkStart() {
    155   Work();
    156   AsyncWorkCompleted();
    157 }
    158 
    159 int BluetoothSocketAsyncApiFunction::AddSocket(BluetoothApiSocket* socket) {
    160   return manager_->Add(socket);
    161 }
    162 
    163 content::BrowserThread::ID
    164 BluetoothSocketAsyncApiFunction::work_thread_id() const {
    165   return BluetoothApiSocket::kThreadId;
    166 }
    167 
    168 BluetoothApiSocket* BluetoothSocketAsyncApiFunction::GetSocket(
    169     int api_resource_id) {
    170   return manager_->Get(extension_id(), api_resource_id);
    171 }
    172 
    173 void BluetoothSocketAsyncApiFunction::RemoveSocket(int api_resource_id) {
    174   manager_->Remove(extension_id(), api_resource_id);
    175 }
    176 
    177 base::hash_set<int>* BluetoothSocketAsyncApiFunction::GetSocketIds() {
    178   return manager_->GetResourceIds(extension_id());
    179 }
    180 
    181 BluetoothSocketCreateFunction::BluetoothSocketCreateFunction() {}
    182 
    183 BluetoothSocketCreateFunction::~BluetoothSocketCreateFunction() {}
    184 
    185 bool BluetoothSocketCreateFunction::Prepare() {
    186   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    187 
    188   params_ = bluetooth_socket::Create::Params::Create(*args_);
    189   EXTENSION_FUNCTION_VALIDATE(params_.get());
    190   return true;
    191 }
    192 
    193 void BluetoothSocketCreateFunction::Work() {
    194   DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
    195 
    196   BluetoothApiSocket* socket = new BluetoothApiSocket(extension_id());
    197 
    198   bluetooth_socket::SocketProperties* properties =
    199       params_.get()->properties.get();
    200   if (properties) {
    201     SetSocketProperties(socket, properties);
    202   }
    203 
    204   bluetooth_socket::CreateInfo create_info;
    205   create_info.socket_id = AddSocket(socket);
    206   results_ = bluetooth_socket::Create::Results::Create(create_info);
    207   AsyncWorkCompleted();
    208 }
    209 
    210 BluetoothSocketUpdateFunction::BluetoothSocketUpdateFunction() {}
    211 
    212 BluetoothSocketUpdateFunction::~BluetoothSocketUpdateFunction() {}
    213 
    214 bool BluetoothSocketUpdateFunction::Prepare() {
    215   params_ = bluetooth_socket::Update::Params::Create(*args_);
    216   EXTENSION_FUNCTION_VALIDATE(params_.get());
    217   return true;
    218 }
    219 
    220 void BluetoothSocketUpdateFunction::Work() {
    221   BluetoothApiSocket* socket = GetSocket(params_->socket_id);
    222   if (!socket) {
    223     error_ = kSocketNotFoundError;
    224     return;
    225   }
    226 
    227   SetSocketProperties(socket, &params_.get()->properties);
    228   results_ = bluetooth_socket::Update::Results::Create();
    229 }
    230 
    231 BluetoothSocketSetPausedFunction::BluetoothSocketSetPausedFunction()
    232     : socket_event_dispatcher_(NULL) {}
    233 
    234 BluetoothSocketSetPausedFunction::~BluetoothSocketSetPausedFunction() {}
    235 
    236 bool BluetoothSocketSetPausedFunction::Prepare() {
    237   params_ = bluetooth_socket::SetPaused::Params::Create(*args_);
    238   EXTENSION_FUNCTION_VALIDATE(params_.get());
    239 
    240   socket_event_dispatcher_ = GetSocketEventDispatcher(browser_context());
    241   return socket_event_dispatcher_ != NULL;
    242 }
    243 
    244 void BluetoothSocketSetPausedFunction::Work() {
    245   BluetoothApiSocket* socket = GetSocket(params_->socket_id);
    246   if (!socket) {
    247     error_ = kSocketNotFoundError;
    248     return;
    249   }
    250 
    251   if (socket->paused() != params_->paused) {
    252     socket->set_paused(params_->paused);
    253     if (!params_->paused) {
    254       socket_event_dispatcher_->OnSocketResume(extension_id(),
    255                                                params_->socket_id);
    256     }
    257   }
    258 
    259   results_ = bluetooth_socket::SetPaused::Results::Create();
    260 }
    261 
    262 BluetoothSocketListenFunction::BluetoothSocketListenFunction() {}
    263 
    264 BluetoothSocketListenFunction::~BluetoothSocketListenFunction() {}
    265 
    266 bool BluetoothSocketListenFunction::Prepare() {
    267   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    268   if (!CreateParams())
    269     return false;
    270   socket_event_dispatcher_ = GetSocketEventDispatcher(browser_context());
    271   return socket_event_dispatcher_ != NULL;
    272 }
    273 
    274 void BluetoothSocketListenFunction::AsyncWorkStart() {
    275   DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
    276   device::BluetoothAdapterFactory::GetAdapter(
    277       base::Bind(&BluetoothSocketListenFunction::OnGetAdapter, this));
    278 }
    279 
    280 void BluetoothSocketListenFunction::OnGetAdapter(
    281     scoped_refptr<device::BluetoothAdapter> adapter) {
    282   DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
    283   BluetoothApiSocket* socket = GetSocket(socket_id());
    284   if (!socket) {
    285     error_ = kSocketNotFoundError;
    286     AsyncWorkCompleted();
    287     return;
    288   }
    289 
    290   device::BluetoothUUID bluetooth_uuid(uuid());
    291   if (!bluetooth_uuid.IsValid()) {
    292     error_ = kInvalidUuidError;
    293     AsyncWorkCompleted();
    294     return;
    295   }
    296 
    297   BluetoothPermissionRequest param(uuid());
    298   if (!BluetoothManifestData::CheckRequest(extension(), param)) {
    299     error_ = kPermissionDeniedError;
    300     AsyncWorkCompleted();
    301     return;
    302   }
    303 
    304   scoped_ptr<std::string> name;
    305   if (socket->name())
    306     name.reset(new std::string(*socket->name()));
    307 
    308   CreateService(
    309       adapter,
    310       bluetooth_uuid,
    311       name.Pass(),
    312       base::Bind(&BluetoothSocketListenFunction::OnCreateService, this),
    313       base::Bind(&BluetoothSocketListenFunction::OnCreateServiceError, this));
    314 }
    315 
    316 
    317 void BluetoothSocketListenFunction::OnCreateService(
    318     scoped_refptr<device::BluetoothSocket> socket) {
    319   DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
    320 
    321   // Fetch the socket again since this is not a reference-counted object, and
    322   // it may have gone away in the meantime (we check earlier to avoid making
    323   // a connection in the case of an obvious programming error).
    324   BluetoothApiSocket* api_socket = GetSocket(socket_id());
    325   if (!api_socket) {
    326     error_ = kSocketNotFoundError;
    327     AsyncWorkCompleted();
    328     return;
    329   }
    330 
    331   api_socket->AdoptListeningSocket(socket,
    332                                    device::BluetoothUUID(uuid()));
    333   socket_event_dispatcher_->OnSocketListen(extension_id(), socket_id());
    334 
    335   CreateResults();
    336   AsyncWorkCompleted();
    337 }
    338 
    339 void BluetoothSocketListenFunction::OnCreateServiceError(
    340     const std::string& message) {
    341   DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
    342   error_ = message;
    343   AsyncWorkCompleted();
    344 }
    345 
    346 BluetoothSocketListenUsingRfcommFunction::
    347     BluetoothSocketListenUsingRfcommFunction() {}
    348 
    349 BluetoothSocketListenUsingRfcommFunction::
    350     ~BluetoothSocketListenUsingRfcommFunction() {}
    351 
    352 int BluetoothSocketListenUsingRfcommFunction::socket_id() const {
    353   return params_->socket_id;
    354 }
    355 
    356 const std::string& BluetoothSocketListenUsingRfcommFunction::uuid() const {
    357   return params_->uuid;
    358 }
    359 
    360 bool BluetoothSocketListenUsingRfcommFunction::CreateParams() {
    361   params_ = bluetooth_socket::ListenUsingRfcomm::Params::Create(*args_);
    362   EXTENSION_FUNCTION_VALIDATE(params_.get());
    363   return true;
    364 }
    365 
    366 void BluetoothSocketListenUsingRfcommFunction::CreateService(
    367     scoped_refptr<device::BluetoothAdapter> adapter,
    368     const device::BluetoothUUID& uuid,
    369     scoped_ptr<std::string> name,
    370     const device::BluetoothAdapter::CreateServiceCallback& callback,
    371     const device::BluetoothAdapter::CreateServiceErrorCallback&
    372         error_callback) {
    373   device::BluetoothAdapter::ServiceOptions service_options;
    374   service_options.name = name.Pass();
    375 
    376   ListenOptions* options = params_->options.get();
    377   if (options) {
    378     if (options->channel.get())
    379       service_options.channel.reset(new int(*(options->channel)));
    380   }
    381 
    382   adapter->CreateRfcommService(uuid, service_options, callback, error_callback);
    383 }
    384 
    385 void BluetoothSocketListenUsingRfcommFunction::CreateResults() {
    386   results_ = bluetooth_socket::ListenUsingRfcomm::Results::Create();
    387 }
    388 
    389 BluetoothSocketListenUsingL2capFunction::
    390     BluetoothSocketListenUsingL2capFunction() {}
    391 
    392 BluetoothSocketListenUsingL2capFunction::
    393     ~BluetoothSocketListenUsingL2capFunction() {}
    394 
    395 int BluetoothSocketListenUsingL2capFunction::socket_id() const {
    396   return params_->socket_id;
    397 }
    398 
    399 const std::string& BluetoothSocketListenUsingL2capFunction::uuid() const {
    400   return params_->uuid;
    401 }
    402 
    403 bool BluetoothSocketListenUsingL2capFunction::CreateParams() {
    404   params_ = bluetooth_socket::ListenUsingL2cap::Params::Create(*args_);
    405   EXTENSION_FUNCTION_VALIDATE(params_.get());
    406   return true;
    407 }
    408 
    409 void BluetoothSocketListenUsingL2capFunction::CreateService(
    410     scoped_refptr<device::BluetoothAdapter> adapter,
    411     const device::BluetoothUUID& uuid,
    412     scoped_ptr<std::string> name,
    413     const device::BluetoothAdapter::CreateServiceCallback& callback,
    414     const device::BluetoothAdapter::CreateServiceErrorCallback&
    415         error_callback) {
    416   device::BluetoothAdapter::ServiceOptions service_options;
    417   service_options.name = name.Pass();
    418 
    419   ListenOptions* options = params_->options.get();
    420   if (options) {
    421     if (options->psm) {
    422       int psm = *options->psm;
    423       if (!IsValidPsm(psm)) {
    424         error_callback.Run(kInvalidPsmError);
    425         return;
    426       }
    427 
    428       service_options.psm.reset(new int(psm));
    429     }
    430   }
    431 
    432   adapter->CreateL2capService(uuid, service_options, callback, error_callback);
    433 }
    434 
    435 void BluetoothSocketListenUsingL2capFunction::CreateResults() {
    436   results_ = bluetooth_socket::ListenUsingL2cap::Results::Create();
    437 }
    438 
    439 BluetoothSocketAbstractConnectFunction::
    440     BluetoothSocketAbstractConnectFunction() {}
    441 
    442 BluetoothSocketAbstractConnectFunction::
    443     ~BluetoothSocketAbstractConnectFunction() {}
    444 
    445 bool BluetoothSocketAbstractConnectFunction::Prepare() {
    446   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    447   params_ = bluetooth_socket::Connect::Params::Create(*args_);
    448   EXTENSION_FUNCTION_VALIDATE(params_.get());
    449 
    450   socket_event_dispatcher_ = GetSocketEventDispatcher(browser_context());
    451   return socket_event_dispatcher_ != NULL;
    452 }
    453 
    454 void BluetoothSocketAbstractConnectFunction::AsyncWorkStart() {
    455   DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
    456   device::BluetoothAdapterFactory::GetAdapter(
    457       base::Bind(&BluetoothSocketAbstractConnectFunction::OnGetAdapter, this));
    458 }
    459 
    460 void BluetoothSocketAbstractConnectFunction::OnGetAdapter(
    461     scoped_refptr<device::BluetoothAdapter> adapter) {
    462   DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
    463   BluetoothApiSocket* socket = GetSocket(params_->socket_id);
    464   if (!socket) {
    465     error_ = kSocketNotFoundError;
    466     AsyncWorkCompleted();
    467     return;
    468   }
    469 
    470   device::BluetoothDevice* device = adapter->GetDevice(params_->address);
    471   if (!device) {
    472     error_ = kDeviceNotFoundError;
    473     AsyncWorkCompleted();
    474     return;
    475   }
    476 
    477   device::BluetoothUUID uuid(params_->uuid);
    478   if (!uuid.IsValid()) {
    479     error_ = kInvalidUuidError;
    480     AsyncWorkCompleted();
    481     return;
    482   }
    483 
    484   BluetoothPermissionRequest param(params_->uuid);
    485   if (!BluetoothManifestData::CheckRequest(extension(), param)) {
    486     error_ = kPermissionDeniedError;
    487     AsyncWorkCompleted();
    488     return;
    489   }
    490 
    491   ConnectToService(device, uuid);
    492 }
    493 
    494 void BluetoothSocketAbstractConnectFunction::OnConnect(
    495     scoped_refptr<device::BluetoothSocket> socket) {
    496   DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
    497 
    498   // Fetch the socket again since this is not a reference-counted object, and
    499   // it may have gone away in the meantime (we check earlier to avoid making
    500   // a connection in the case of an obvious programming error).
    501   BluetoothApiSocket* api_socket = GetSocket(params_->socket_id);
    502   if (!api_socket) {
    503     error_ = kSocketNotFoundError;
    504     AsyncWorkCompleted();
    505     return;
    506   }
    507 
    508   api_socket->AdoptConnectedSocket(socket,
    509                                    params_->address,
    510                                    device::BluetoothUUID(params_->uuid));
    511   socket_event_dispatcher_->OnSocketConnect(extension_id(),
    512                                             params_->socket_id);
    513 
    514   results_ = bluetooth_socket::Connect::Results::Create();
    515   AsyncWorkCompleted();
    516 }
    517 
    518 void BluetoothSocketAbstractConnectFunction::OnConnectError(
    519     const std::string& message) {
    520   DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
    521   error_ = message;
    522   AsyncWorkCompleted();
    523 }
    524 
    525 BluetoothSocketConnectFunction::BluetoothSocketConnectFunction() {}
    526 
    527 BluetoothSocketConnectFunction::~BluetoothSocketConnectFunction() {}
    528 
    529 void BluetoothSocketConnectFunction::ConnectToService(
    530     device::BluetoothDevice* device,
    531     const device::BluetoothUUID& uuid) {
    532   device->ConnectToService(
    533       uuid,
    534       base::Bind(&BluetoothSocketConnectFunction::OnConnect, this),
    535       base::Bind(&BluetoothSocketConnectFunction::OnConnectError, this));
    536 }
    537 
    538 BluetoothSocketDisconnectFunction::BluetoothSocketDisconnectFunction() {}
    539 
    540 BluetoothSocketDisconnectFunction::~BluetoothSocketDisconnectFunction() {}
    541 
    542 bool BluetoothSocketDisconnectFunction::Prepare() {
    543   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    544   params_ = bluetooth_socket::Disconnect::Params::Create(*args_);
    545   EXTENSION_FUNCTION_VALIDATE(params_.get());
    546   return true;
    547 }
    548 
    549 void BluetoothSocketDisconnectFunction::AsyncWorkStart() {
    550   DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
    551   BluetoothApiSocket* socket = GetSocket(params_->socket_id);
    552   if (!socket) {
    553     error_ = kSocketNotFoundError;
    554     AsyncWorkCompleted();
    555     return;
    556   }
    557 
    558   socket->Disconnect(base::Bind(&BluetoothSocketDisconnectFunction::OnSuccess,
    559                                 this));
    560 }
    561 
    562 void BluetoothSocketDisconnectFunction::OnSuccess() {
    563   DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
    564   results_ = bluetooth_socket::Disconnect::Results::Create();
    565   AsyncWorkCompleted();
    566 }
    567 
    568 BluetoothSocketCloseFunction::BluetoothSocketCloseFunction() {}
    569 
    570 BluetoothSocketCloseFunction::~BluetoothSocketCloseFunction() {}
    571 
    572 bool BluetoothSocketCloseFunction::Prepare() {
    573   params_ = bluetooth_socket::Close::Params::Create(*args_);
    574   EXTENSION_FUNCTION_VALIDATE(params_.get());
    575   return true;
    576 }
    577 
    578 void BluetoothSocketCloseFunction::Work() {
    579   BluetoothApiSocket* socket = GetSocket(params_->socket_id);
    580   if (!socket) {
    581     error_ = kSocketNotFoundError;
    582     return;
    583   }
    584 
    585   RemoveSocket(params_->socket_id);
    586   results_ = bluetooth_socket::Close::Results::Create();
    587 }
    588 
    589 BluetoothSocketSendFunction::BluetoothSocketSendFunction()
    590     : io_buffer_size_(0) {}
    591 
    592 BluetoothSocketSendFunction::~BluetoothSocketSendFunction() {}
    593 
    594 bool BluetoothSocketSendFunction::Prepare() {
    595   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    596   params_ = bluetooth_socket::Send::Params::Create(*args_);
    597   EXTENSION_FUNCTION_VALIDATE(params_.get());
    598 
    599   io_buffer_size_ = params_->data.size();
    600   io_buffer_ = new net::WrappedIOBuffer(params_->data.data());
    601   return true;
    602 }
    603 
    604 void BluetoothSocketSendFunction::AsyncWorkStart() {
    605   DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
    606   BluetoothApiSocket* socket = GetSocket(params_->socket_id);
    607   if (!socket) {
    608     error_ = kSocketNotFoundError;
    609     return;
    610   }
    611 
    612   socket->Send(io_buffer_,
    613                io_buffer_size_,
    614                base::Bind(&BluetoothSocketSendFunction::OnSuccess, this),
    615                base::Bind(&BluetoothSocketSendFunction::OnError, this));
    616 }
    617 
    618 void BluetoothSocketSendFunction::OnSuccess(int bytes_sent) {
    619   DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
    620   results_ = bluetooth_socket::Send::Results::Create(bytes_sent);
    621   AsyncWorkCompleted();
    622 }
    623 
    624 void BluetoothSocketSendFunction::OnError(
    625     BluetoothApiSocket::ErrorReason reason,
    626     const std::string& message) {
    627   DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
    628   error_ = message;
    629   AsyncWorkCompleted();
    630 }
    631 
    632 BluetoothSocketGetInfoFunction::BluetoothSocketGetInfoFunction() {}
    633 
    634 BluetoothSocketGetInfoFunction::~BluetoothSocketGetInfoFunction() {}
    635 
    636 bool BluetoothSocketGetInfoFunction::Prepare() {
    637   params_ = bluetooth_socket::GetInfo::Params::Create(*args_);
    638   EXTENSION_FUNCTION_VALIDATE(params_.get());
    639   return true;
    640 }
    641 
    642 void BluetoothSocketGetInfoFunction::Work() {
    643   BluetoothApiSocket* socket = GetSocket(params_->socket_id);
    644   if (!socket) {
    645     error_ = kSocketNotFoundError;
    646     return;
    647   }
    648 
    649   linked_ptr<bluetooth_socket::SocketInfo> socket_info =
    650       CreateSocketInfo(params_->socket_id, socket);
    651   results_ = bluetooth_socket::GetInfo::Results::Create(*socket_info);
    652 }
    653 
    654 BluetoothSocketGetSocketsFunction::BluetoothSocketGetSocketsFunction() {}
    655 
    656 BluetoothSocketGetSocketsFunction::~BluetoothSocketGetSocketsFunction() {}
    657 
    658 bool BluetoothSocketGetSocketsFunction::Prepare() { return true; }
    659 
    660 void BluetoothSocketGetSocketsFunction::Work() {
    661   std::vector<linked_ptr<bluetooth_socket::SocketInfo> > socket_infos;
    662   base::hash_set<int>* resource_ids = GetSocketIds();
    663   if (resource_ids != NULL) {
    664     for (base::hash_set<int>::iterator it = resource_ids->begin();
    665          it != resource_ids->end();
    666          ++it) {
    667       int socket_id = *it;
    668       BluetoothApiSocket* socket = GetSocket(socket_id);
    669       if (socket) {
    670         socket_infos.push_back(CreateSocketInfo(socket_id, socket));
    671       }
    672     }
    673   }
    674   results_ = bluetooth_socket::GetSockets::Results::Create(socket_infos);
    675 }
    676 
    677 }  // namespace core_api
    678 }  // namespace extensions
    679