eefdbbf00f9d40e073b1a295e2394d61c06b41c8
[platform/framework/web/crosswalk.git] / src / chrome / browser / extensions / api / bluetooth_socket / bluetooth_socket_api.cc
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 <stdint.h>
8
9 #include "chrome/browser/extensions/api/bluetooth_socket/bluetooth_api_socket.h"
10 #include "chrome/browser/extensions/api/bluetooth_socket/bluetooth_socket_event_dispatcher.h"
11 #include "chrome/common/extensions/api/bluetooth/bluetooth_manifest_data.h"
12 #include "content/public/browser/browser_context.h"
13 #include "content/public/browser/browser_thread.h"
14 #include "device/bluetooth/bluetooth_adapter.h"
15 #include "device/bluetooth/bluetooth_adapter_factory.h"
16 #include "device/bluetooth/bluetooth_device.h"
17 #include "device/bluetooth/bluetooth_socket.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::api::bluetooth_socket::ListenOptions;
24 using extensions::api::bluetooth_socket::SocketInfo;
25 using extensions::api::bluetooth_socket::SocketProperties;
26
27 namespace {
28
29 const char kDeviceNotFoundError[] = "Device not found";
30 const char kInvalidPsmError[] = "Invalid PSM";
31 const char kInvalidUuidError[] = "Invalid UUID";
32 const char kPermissionDeniedError[] = "Permission denied";
33 const char kSocketNotFoundError[] = "Socket not found";
34
35 linked_ptr<SocketInfo> CreateSocketInfo(int socket_id,
36                                         BluetoothApiSocket* socket) {
37   DCHECK(BrowserThread::CurrentlyOn(BluetoothApiSocket::kThreadId));
38   linked_ptr<SocketInfo> socket_info(new SocketInfo());
39   // This represents what we know about the socket, and does not call through
40   // to the system.
41   socket_info->socket_id = socket_id;
42   if (socket->name()) {
43     socket_info->name.reset(new std::string(*socket->name()));
44   }
45   socket_info->persistent = socket->persistent();
46   if (socket->buffer_size() > 0) {
47     socket_info->buffer_size.reset(new int(socket->buffer_size()));
48   }
49   socket_info->paused = socket->paused();
50   socket_info->connected = socket->IsConnected();
51
52   if (socket->IsConnected())
53     socket_info->address.reset(new std::string(socket->device_address()));
54   socket_info->uuid.reset(new std::string(socket->uuid().canonical_value()));
55
56   return socket_info;
57 }
58
59 void SetSocketProperties(BluetoothApiSocket* socket,
60                          SocketProperties* properties) {
61   if (properties->name.get()) {
62     socket->set_name(*properties->name.get());
63   }
64   if (properties->persistent.get()) {
65     socket->set_persistent(*properties->persistent.get());
66   }
67   if (properties->buffer_size.get()) {
68     // buffer size is validated when issuing the actual Recv operation
69     // on the socket.
70     socket->set_buffer_size(*properties->buffer_size.get());
71   }
72 }
73
74 extensions::api::BluetoothSocketEventDispatcher* GetSocketEventDispatcher(
75     content::BrowserContext* browser_context) {
76   extensions::api::BluetoothSocketEventDispatcher* socket_event_dispatcher =
77       extensions::api::BluetoothSocketEventDispatcher::Get(browser_context);
78   DCHECK(socket_event_dispatcher)
79       << "There is no socket event dispatcher. "
80          "If this assertion is failing during a test, then it is likely that "
81          "TestExtensionSystem is failing to provide an instance of "
82          "BluetoothSocketEventDispatcher.";
83   return socket_event_dispatcher;
84 }
85
86 // Returns |true| if |psm| is a valid PSM.
87 // Per the Bluetooth specification, the PSM field must be at least two octets in
88 // length, with least significant bit of the least significant octet equal to
89 // '1' and the least significant bit of the most significant octet equal to '0'.
90 bool IsValidPsm(int psm) {
91   if (psm <= 0)
92     return false;
93
94   std::vector<int16_t> octets;
95   while (psm > 0) {
96      octets.push_back(psm & 0xFF);
97      psm = psm >> 8;
98   }
99
100   if (octets.size() < 2U)
101     return false;
102
103   // The least significant bit of the least significant octet must be '1'.
104   if ((octets.front() & 0x01) != 1)
105     return false;
106
107   // The least significant bit of the most significant octet must be '0'.
108   if ((octets.back() & 0x01) != 0)
109     return false;
110
111   return true;
112 }
113
114 }  // namespace
115
116 namespace extensions {
117 namespace api {
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 BluetoothSocketConnectFunction::BluetoothSocketConnectFunction() {}
440
441 BluetoothSocketConnectFunction::~BluetoothSocketConnectFunction() {}
442
443 bool BluetoothSocketConnectFunction::Prepare() {
444   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
445   params_ = bluetooth_socket::Connect::Params::Create(*args_);
446   EXTENSION_FUNCTION_VALIDATE(params_.get());
447
448   socket_event_dispatcher_ = GetSocketEventDispatcher(browser_context());
449   return socket_event_dispatcher_ != NULL;
450 }
451
452 void BluetoothSocketConnectFunction::AsyncWorkStart() {
453   DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
454   device::BluetoothAdapterFactory::GetAdapter(
455       base::Bind(&BluetoothSocketConnectFunction::OnGetAdapter, this));
456 }
457
458 void BluetoothSocketConnectFunction::OnGetAdapter(
459     scoped_refptr<device::BluetoothAdapter> adapter) {
460   DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
461   BluetoothApiSocket* socket = GetSocket(params_->socket_id);
462   if (!socket) {
463     error_ = kSocketNotFoundError;
464     AsyncWorkCompleted();
465     return;
466   }
467
468   device::BluetoothDevice* device = adapter->GetDevice(params_->address);
469   if (!device) {
470     error_ = kDeviceNotFoundError;
471     AsyncWorkCompleted();
472     return;
473   }
474
475   device::BluetoothUUID uuid(params_->uuid);
476   if (!uuid.IsValid()) {
477     error_ = kInvalidUuidError;
478     AsyncWorkCompleted();
479     return;
480   }
481
482   BluetoothPermissionRequest param(params_->uuid);
483   if (!BluetoothManifestData::CheckRequest(extension(), param)) {
484     error_ = kPermissionDeniedError;
485     AsyncWorkCompleted();
486     return;
487   }
488
489   device->ConnectToService(
490       uuid,
491       base::Bind(&BluetoothSocketConnectFunction::OnConnect, this),
492       base::Bind(&BluetoothSocketConnectFunction::OnConnectError, this));
493 }
494
495 void BluetoothSocketConnectFunction::OnConnect(
496     scoped_refptr<device::BluetoothSocket> socket) {
497   DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
498
499   // Fetch the socket again since this is not a reference-counted object, and
500   // it may have gone away in the meantime (we check earlier to avoid making
501   // a connection in the case of an obvious programming error).
502   BluetoothApiSocket* api_socket = GetSocket(params_->socket_id);
503   if (!api_socket) {
504     error_ = kSocketNotFoundError;
505     AsyncWorkCompleted();
506     return;
507   }
508
509   api_socket->AdoptConnectedSocket(socket,
510                                    params_->address,
511                                    device::BluetoothUUID(params_->uuid));
512   socket_event_dispatcher_->OnSocketConnect(extension_id(),
513                                             params_->socket_id);
514
515   results_ = bluetooth_socket::Connect::Results::Create();
516   AsyncWorkCompleted();
517 }
518
519 void BluetoothSocketConnectFunction::OnConnectError(
520     const std::string& message) {
521   DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
522   error_ = message;
523   AsyncWorkCompleted();
524 }
525
526 BluetoothSocketDisconnectFunction::BluetoothSocketDisconnectFunction() {}
527
528 BluetoothSocketDisconnectFunction::~BluetoothSocketDisconnectFunction() {}
529
530 bool BluetoothSocketDisconnectFunction::Prepare() {
531   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
532   params_ = bluetooth_socket::Disconnect::Params::Create(*args_);
533   EXTENSION_FUNCTION_VALIDATE(params_.get());
534   return true;
535 }
536
537 void BluetoothSocketDisconnectFunction::AsyncWorkStart() {
538   DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
539   BluetoothApiSocket* socket = GetSocket(params_->socket_id);
540   if (!socket) {
541     error_ = kSocketNotFoundError;
542     AsyncWorkCompleted();
543     return;
544   }
545
546   socket->Disconnect(base::Bind(&BluetoothSocketDisconnectFunction::OnSuccess,
547                                 this));
548 }
549
550 void BluetoothSocketDisconnectFunction::OnSuccess() {
551   DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
552   results_ = bluetooth_socket::Disconnect::Results::Create();
553   AsyncWorkCompleted();
554 }
555
556 BluetoothSocketCloseFunction::BluetoothSocketCloseFunction() {}
557
558 BluetoothSocketCloseFunction::~BluetoothSocketCloseFunction() {}
559
560 bool BluetoothSocketCloseFunction::Prepare() {
561   params_ = bluetooth_socket::Close::Params::Create(*args_);
562   EXTENSION_FUNCTION_VALIDATE(params_.get());
563   return true;
564 }
565
566 void BluetoothSocketCloseFunction::Work() {
567   BluetoothApiSocket* socket = GetSocket(params_->socket_id);
568   if (!socket) {
569     error_ = kSocketNotFoundError;
570     return;
571   }
572
573   RemoveSocket(params_->socket_id);
574   results_ = bluetooth_socket::Close::Results::Create();
575 }
576
577 BluetoothSocketSendFunction::BluetoothSocketSendFunction()
578     : io_buffer_size_(0) {}
579
580 BluetoothSocketSendFunction::~BluetoothSocketSendFunction() {}
581
582 bool BluetoothSocketSendFunction::Prepare() {
583   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
584   params_ = bluetooth_socket::Send::Params::Create(*args_);
585   EXTENSION_FUNCTION_VALIDATE(params_.get());
586
587   io_buffer_size_ = params_->data.size();
588   io_buffer_ = new net::WrappedIOBuffer(params_->data.data());
589   return true;
590 }
591
592 void BluetoothSocketSendFunction::AsyncWorkStart() {
593   DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
594   BluetoothApiSocket* socket = GetSocket(params_->socket_id);
595   if (!socket) {
596     error_ = kSocketNotFoundError;
597     return;
598   }
599
600   socket->Send(io_buffer_,
601                io_buffer_size_,
602                base::Bind(&BluetoothSocketSendFunction::OnSuccess, this),
603                base::Bind(&BluetoothSocketSendFunction::OnError, this));
604 }
605
606 void BluetoothSocketSendFunction::OnSuccess(int bytes_sent) {
607   DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
608   results_ = bluetooth_socket::Send::Results::Create(bytes_sent);
609   AsyncWorkCompleted();
610 }
611
612 void BluetoothSocketSendFunction::OnError(
613     BluetoothApiSocket::ErrorReason reason,
614     const std::string& message) {
615   DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
616   error_ = message;
617   AsyncWorkCompleted();
618 }
619
620 BluetoothSocketGetInfoFunction::BluetoothSocketGetInfoFunction() {}
621
622 BluetoothSocketGetInfoFunction::~BluetoothSocketGetInfoFunction() {}
623
624 bool BluetoothSocketGetInfoFunction::Prepare() {
625   params_ = bluetooth_socket::GetInfo::Params::Create(*args_);
626   EXTENSION_FUNCTION_VALIDATE(params_.get());
627   return true;
628 }
629
630 void BluetoothSocketGetInfoFunction::Work() {
631   BluetoothApiSocket* socket = GetSocket(params_->socket_id);
632   if (!socket) {
633     error_ = kSocketNotFoundError;
634     return;
635   }
636
637   linked_ptr<bluetooth_socket::SocketInfo> socket_info =
638       CreateSocketInfo(params_->socket_id, socket);
639   results_ = bluetooth_socket::GetInfo::Results::Create(*socket_info);
640 }
641
642 BluetoothSocketGetSocketsFunction::BluetoothSocketGetSocketsFunction() {}
643
644 BluetoothSocketGetSocketsFunction::~BluetoothSocketGetSocketsFunction() {}
645
646 bool BluetoothSocketGetSocketsFunction::Prepare() { return true; }
647
648 void BluetoothSocketGetSocketsFunction::Work() {
649   std::vector<linked_ptr<bluetooth_socket::SocketInfo> > socket_infos;
650   base::hash_set<int>* resource_ids = GetSocketIds();
651   if (resource_ids != NULL) {
652     for (base::hash_set<int>::iterator it = resource_ids->begin();
653          it != resource_ids->end();
654          ++it) {
655       int socket_id = *it;
656       BluetoothApiSocket* socket = GetSocket(socket_id);
657       if (socket) {
658         socket_infos.push_back(CreateSocketInfo(socket_id, socket));
659       }
660     }
661   }
662   results_ = bluetooth_socket::GetSockets::Results::Create(socket_infos);
663 }
664
665 }  // namespace api
666 }  // namespace extensions