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