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
21using content::BrowserThread;
22using extensions::BluetoothApiSocket;
23using extensions::core_api::bluetooth_socket::ListenOptions;
24using extensions::core_api::bluetooth_socket::SocketInfo;
25using extensions::core_api::bluetooth_socket::SocketProperties;
26
27namespace extensions {
28namespace core_api {
29
30namespace {
31
32const char kDeviceNotFoundError[] = "Device not found";
33const char kInvalidPsmError[] = "Invalid PSM";
34const char kInvalidUuidError[] = "Invalid UUID";
35const char kPermissionDeniedError[] = "Permission denied";
36const char kSocketNotFoundError[] = "Socket not found";
37
38linked_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
62void 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
77BluetoothSocketEventDispatcher* 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'.
93bool 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
119BluetoothSocketAsyncApiFunction::BluetoothSocketAsyncApiFunction() {}
120
121BluetoothSocketAsyncApiFunction::~BluetoothSocketAsyncApiFunction() {}
122
123bool BluetoothSocketAsyncApiFunction::RunAsync() {
124  if (!PrePrepare() || !Prepare()) {
125    return false;
126  }
127  AsyncWorkStart();
128  return true;
129}
130
131bool 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
146bool BluetoothSocketAsyncApiFunction::Respond() { return error_.empty(); }
147
148void BluetoothSocketAsyncApiFunction::AsyncWorkCompleted() {
149  SendResponse(Respond());
150}
151
152void BluetoothSocketAsyncApiFunction::Work() {}
153
154void BluetoothSocketAsyncApiFunction::AsyncWorkStart() {
155  Work();
156  AsyncWorkCompleted();
157}
158
159int BluetoothSocketAsyncApiFunction::AddSocket(BluetoothApiSocket* socket) {
160  return manager_->Add(socket);
161}
162
163content::BrowserThread::ID
164BluetoothSocketAsyncApiFunction::work_thread_id() const {
165  return BluetoothApiSocket::kThreadId;
166}
167
168BluetoothApiSocket* BluetoothSocketAsyncApiFunction::GetSocket(
169    int api_resource_id) {
170  return manager_->Get(extension_id(), api_resource_id);
171}
172
173void BluetoothSocketAsyncApiFunction::RemoveSocket(int api_resource_id) {
174  manager_->Remove(extension_id(), api_resource_id);
175}
176
177base::hash_set<int>* BluetoothSocketAsyncApiFunction::GetSocketIds() {
178  return manager_->GetResourceIds(extension_id());
179}
180
181BluetoothSocketCreateFunction::BluetoothSocketCreateFunction() {}
182
183BluetoothSocketCreateFunction::~BluetoothSocketCreateFunction() {}
184
185bool 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
193void 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
210BluetoothSocketUpdateFunction::BluetoothSocketUpdateFunction() {}
211
212BluetoothSocketUpdateFunction::~BluetoothSocketUpdateFunction() {}
213
214bool BluetoothSocketUpdateFunction::Prepare() {
215  params_ = bluetooth_socket::Update::Params::Create(*args_);
216  EXTENSION_FUNCTION_VALIDATE(params_.get());
217  return true;
218}
219
220void 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
231BluetoothSocketSetPausedFunction::BluetoothSocketSetPausedFunction()
232    : socket_event_dispatcher_(NULL) {}
233
234BluetoothSocketSetPausedFunction::~BluetoothSocketSetPausedFunction() {}
235
236bool 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
244void 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
262BluetoothSocketListenFunction::BluetoothSocketListenFunction() {}
263
264BluetoothSocketListenFunction::~BluetoothSocketListenFunction() {}
265
266bool 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
274void BluetoothSocketListenFunction::AsyncWorkStart() {
275  DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
276  device::BluetoothAdapterFactory::GetAdapter(
277      base::Bind(&BluetoothSocketListenFunction::OnGetAdapter, this));
278}
279
280void 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
317void 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
339void BluetoothSocketListenFunction::OnCreateServiceError(
340    const std::string& message) {
341  DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
342  error_ = message;
343  AsyncWorkCompleted();
344}
345
346BluetoothSocketListenUsingRfcommFunction::
347    BluetoothSocketListenUsingRfcommFunction() {}
348
349BluetoothSocketListenUsingRfcommFunction::
350    ~BluetoothSocketListenUsingRfcommFunction() {}
351
352int BluetoothSocketListenUsingRfcommFunction::socket_id() const {
353  return params_->socket_id;
354}
355
356const std::string& BluetoothSocketListenUsingRfcommFunction::uuid() const {
357  return params_->uuid;
358}
359
360bool BluetoothSocketListenUsingRfcommFunction::CreateParams() {
361  params_ = bluetooth_socket::ListenUsingRfcomm::Params::Create(*args_);
362  EXTENSION_FUNCTION_VALIDATE(params_.get());
363  return true;
364}
365
366void 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
385void BluetoothSocketListenUsingRfcommFunction::CreateResults() {
386  results_ = bluetooth_socket::ListenUsingRfcomm::Results::Create();
387}
388
389BluetoothSocketListenUsingL2capFunction::
390    BluetoothSocketListenUsingL2capFunction() {}
391
392BluetoothSocketListenUsingL2capFunction::
393    ~BluetoothSocketListenUsingL2capFunction() {}
394
395int BluetoothSocketListenUsingL2capFunction::socket_id() const {
396  return params_->socket_id;
397}
398
399const std::string& BluetoothSocketListenUsingL2capFunction::uuid() const {
400  return params_->uuid;
401}
402
403bool BluetoothSocketListenUsingL2capFunction::CreateParams() {
404  params_ = bluetooth_socket::ListenUsingL2cap::Params::Create(*args_);
405  EXTENSION_FUNCTION_VALIDATE(params_.get());
406  return true;
407}
408
409void 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
435void BluetoothSocketListenUsingL2capFunction::CreateResults() {
436  results_ = bluetooth_socket::ListenUsingL2cap::Results::Create();
437}
438
439BluetoothSocketAbstractConnectFunction::
440    BluetoothSocketAbstractConnectFunction() {}
441
442BluetoothSocketAbstractConnectFunction::
443    ~BluetoothSocketAbstractConnectFunction() {}
444
445bool 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
454void BluetoothSocketAbstractConnectFunction::AsyncWorkStart() {
455  DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
456  device::BluetoothAdapterFactory::GetAdapter(
457      base::Bind(&BluetoothSocketAbstractConnectFunction::OnGetAdapter, this));
458}
459
460void 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
494void 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
518void BluetoothSocketAbstractConnectFunction::OnConnectError(
519    const std::string& message) {
520  DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
521  error_ = message;
522  AsyncWorkCompleted();
523}
524
525BluetoothSocketConnectFunction::BluetoothSocketConnectFunction() {}
526
527BluetoothSocketConnectFunction::~BluetoothSocketConnectFunction() {}
528
529void 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
538BluetoothSocketDisconnectFunction::BluetoothSocketDisconnectFunction() {}
539
540BluetoothSocketDisconnectFunction::~BluetoothSocketDisconnectFunction() {}
541
542bool 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
549void 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
562void BluetoothSocketDisconnectFunction::OnSuccess() {
563  DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
564  results_ = bluetooth_socket::Disconnect::Results::Create();
565  AsyncWorkCompleted();
566}
567
568BluetoothSocketCloseFunction::BluetoothSocketCloseFunction() {}
569
570BluetoothSocketCloseFunction::~BluetoothSocketCloseFunction() {}
571
572bool BluetoothSocketCloseFunction::Prepare() {
573  params_ = bluetooth_socket::Close::Params::Create(*args_);
574  EXTENSION_FUNCTION_VALIDATE(params_.get());
575  return true;
576}
577
578void 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
589BluetoothSocketSendFunction::BluetoothSocketSendFunction()
590    : io_buffer_size_(0) {}
591
592BluetoothSocketSendFunction::~BluetoothSocketSendFunction() {}
593
594bool 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
604void 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
618void 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
624void 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
632BluetoothSocketGetInfoFunction::BluetoothSocketGetInfoFunction() {}
633
634BluetoothSocketGetInfoFunction::~BluetoothSocketGetInfoFunction() {}
635
636bool BluetoothSocketGetInfoFunction::Prepare() {
637  params_ = bluetooth_socket::GetInfo::Params::Create(*args_);
638  EXTENSION_FUNCTION_VALIDATE(params_.get());
639  return true;
640}
641
642void 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
654BluetoothSocketGetSocketsFunction::BluetoothSocketGetSocketsFunction() {}
655
656BluetoothSocketGetSocketsFunction::~BluetoothSocketGetSocketsFunction() {}
657
658bool BluetoothSocketGetSocketsFunction::Prepare() { return true; }
659
660void 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