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
CreateSocketInfo(int socket_id,BluetoothApiSocket * socket)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
SetSocketProperties(BluetoothApiSocket * socket,SocketProperties * properties)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
GetSocketEventDispatcher(content::BrowserContext * browser_context)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
BluetoothSocketAsyncApiFunction()88 BluetoothSocketAsyncApiFunction::BluetoothSocketAsyncApiFunction() {}
89
~BluetoothSocketAsyncApiFunction()90 BluetoothSocketAsyncApiFunction::~BluetoothSocketAsyncApiFunction() {}
91
RunAsync()92 bool BluetoothSocketAsyncApiFunction::RunAsync() {
93 if (!PrePrepare() || !Prepare()) {
94 return false;
95 }
96 AsyncWorkStart();
97 return true;
98 }
99
PrePrepare()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
Respond()115 bool BluetoothSocketAsyncApiFunction::Respond() { return error_.empty(); }
116
AsyncWorkCompleted()117 void BluetoothSocketAsyncApiFunction::AsyncWorkCompleted() {
118 SendResponse(Respond());
119 }
120
Work()121 void BluetoothSocketAsyncApiFunction::Work() {}
122
AsyncWorkStart()123 void BluetoothSocketAsyncApiFunction::AsyncWorkStart() {
124 Work();
125 AsyncWorkCompleted();
126 }
127
AddSocket(BluetoothApiSocket * socket)128 int BluetoothSocketAsyncApiFunction::AddSocket(BluetoothApiSocket* socket) {
129 return manager_->Add(socket);
130 }
131
132 content::BrowserThread::ID
work_thread_id() const133 BluetoothSocketAsyncApiFunction::work_thread_id() const {
134 return BluetoothApiSocket::kThreadId;
135 }
136
GetSocket(int api_resource_id)137 BluetoothApiSocket* BluetoothSocketAsyncApiFunction::GetSocket(
138 int api_resource_id) {
139 return manager_->Get(extension_id(), api_resource_id);
140 }
141
RemoveSocket(int api_resource_id)142 void BluetoothSocketAsyncApiFunction::RemoveSocket(int api_resource_id) {
143 manager_->Remove(extension_id(), api_resource_id);
144 }
145
GetSocketIds()146 base::hash_set<int>* BluetoothSocketAsyncApiFunction::GetSocketIds() {
147 return manager_->GetResourceIds(extension_id());
148 }
149
BluetoothSocketCreateFunction()150 BluetoothSocketCreateFunction::BluetoothSocketCreateFunction() {}
151
~BluetoothSocketCreateFunction()152 BluetoothSocketCreateFunction::~BluetoothSocketCreateFunction() {}
153
Prepare()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
Work()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
BluetoothSocketUpdateFunction()179 BluetoothSocketUpdateFunction::BluetoothSocketUpdateFunction() {}
180
~BluetoothSocketUpdateFunction()181 BluetoothSocketUpdateFunction::~BluetoothSocketUpdateFunction() {}
182
Prepare()183 bool BluetoothSocketUpdateFunction::Prepare() {
184 params_ = bluetooth_socket::Update::Params::Create(*args_);
185 EXTENSION_FUNCTION_VALIDATE(params_.get());
186 return true;
187 }
188
Work()189 void BluetoothSocketUpdateFunction::Work() {
190 BluetoothApiSocket* socket = GetSocket(params_->socket_id);
191 if (!socket) {
192 error_ = kSocketNotFoundError;
193 return;
194 }
195
196 SetSocketProperties(socket, ¶ms_.get()->properties);
197 results_ = bluetooth_socket::Update::Results::Create();
198 }
199
BluetoothSocketSetPausedFunction()200 BluetoothSocketSetPausedFunction::BluetoothSocketSetPausedFunction()
201 : socket_event_dispatcher_(NULL) {}
202
~BluetoothSocketSetPausedFunction()203 BluetoothSocketSetPausedFunction::~BluetoothSocketSetPausedFunction() {}
204
Prepare()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
Work()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
BluetoothSocketListenFunction()231 BluetoothSocketListenFunction::BluetoothSocketListenFunction() {}
232
~BluetoothSocketListenFunction()233 BluetoothSocketListenFunction::~BluetoothSocketListenFunction() {}
234
Prepare()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
AsyncWorkStart()243 void BluetoothSocketListenFunction::AsyncWorkStart() {
244 DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
245 device::BluetoothAdapterFactory::GetAdapter(
246 base::Bind(&BluetoothSocketListenFunction::OnGetAdapter, this));
247 }
248
OnGetAdapter(scoped_refptr<device::BluetoothAdapter> adapter)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
OnCreateService(scoped_refptr<device::BluetoothSocket> socket)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
OnCreateServiceError(const std::string & message)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::
BluetoothSocketListenUsingRfcommFunction()311 BluetoothSocketListenUsingRfcommFunction() {}
312
313 BluetoothSocketListenUsingRfcommFunction::
~BluetoothSocketListenUsingRfcommFunction()314 ~BluetoothSocketListenUsingRfcommFunction() {}
315
socket_id() const316 int BluetoothSocketListenUsingRfcommFunction::socket_id() const {
317 return params_->socket_id;
318 }
319
uuid() const320 const std::string& BluetoothSocketListenUsingRfcommFunction::uuid() const {
321 return params_->uuid;
322 }
323
CreateParams()324 bool BluetoothSocketListenUsingRfcommFunction::CreateParams() {
325 params_ = bluetooth_socket::ListenUsingRfcomm::Params::Create(*args_);
326 EXTENSION_FUNCTION_VALIDATE(params_.get());
327 return true;
328 }
329
CreateService(scoped_refptr<device::BluetoothAdapter> adapter,const device::BluetoothUUID & uuid,const device::BluetoothAdapter::CreateServiceCallback & callback,const device::BluetoothAdapter::CreateServiceErrorCallback & error_callback)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
CreateResults()347 void BluetoothSocketListenUsingRfcommFunction::CreateResults() {
348 results_ = bluetooth_socket::ListenUsingRfcomm::Results::Create();
349 }
350
351 BluetoothSocketListenUsingL2capFunction::
BluetoothSocketListenUsingL2capFunction()352 BluetoothSocketListenUsingL2capFunction() {}
353
354 BluetoothSocketListenUsingL2capFunction::
~BluetoothSocketListenUsingL2capFunction()355 ~BluetoothSocketListenUsingL2capFunction() {}
356
socket_id() const357 int BluetoothSocketListenUsingL2capFunction::socket_id() const {
358 return params_->socket_id;
359 }
360
uuid() const361 const std::string& BluetoothSocketListenUsingL2capFunction::uuid() const {
362 return params_->uuid;
363 }
364
CreateParams()365 bool BluetoothSocketListenUsingL2capFunction::CreateParams() {
366 params_ = bluetooth_socket::ListenUsingL2cap::Params::Create(*args_);
367 EXTENSION_FUNCTION_VALIDATE(params_.get());
368 return true;
369 }
370
CreateService(scoped_refptr<device::BluetoothAdapter> adapter,const device::BluetoothUUID & uuid,const device::BluetoothAdapter::CreateServiceCallback & callback,const device::BluetoothAdapter::CreateServiceErrorCallback & error_callback)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
CreateResults()388 void BluetoothSocketListenUsingL2capFunction::CreateResults() {
389 results_ = bluetooth_socket::ListenUsingL2cap::Results::Create();
390 }
391
BluetoothSocketConnectFunction()392 BluetoothSocketConnectFunction::BluetoothSocketConnectFunction() {}
393
~BluetoothSocketConnectFunction()394 BluetoothSocketConnectFunction::~BluetoothSocketConnectFunction() {}
395
Prepare()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
AsyncWorkStart()405 void BluetoothSocketConnectFunction::AsyncWorkStart() {
406 DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
407 device::BluetoothAdapterFactory::GetAdapter(
408 base::Bind(&BluetoothSocketConnectFunction::OnGetAdapter, this));
409 }
410
OnGetAdapter(scoped_refptr<device::BluetoothAdapter> adapter)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
OnConnect(scoped_refptr<device::BluetoothSocket> socket)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
OnConnectError(const std::string & message)472 void BluetoothSocketConnectFunction::OnConnectError(
473 const std::string& message) {
474 DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
475 error_ = message;
476 AsyncWorkCompleted();
477 }
478
BluetoothSocketDisconnectFunction()479 BluetoothSocketDisconnectFunction::BluetoothSocketDisconnectFunction() {}
480
~BluetoothSocketDisconnectFunction()481 BluetoothSocketDisconnectFunction::~BluetoothSocketDisconnectFunction() {}
482
Prepare()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
AsyncWorkStart()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
OnSuccess()503 void BluetoothSocketDisconnectFunction::OnSuccess() {
504 DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
505 results_ = bluetooth_socket::Disconnect::Results::Create();
506 AsyncWorkCompleted();
507 }
508
BluetoothSocketCloseFunction()509 BluetoothSocketCloseFunction::BluetoothSocketCloseFunction() {}
510
~BluetoothSocketCloseFunction()511 BluetoothSocketCloseFunction::~BluetoothSocketCloseFunction() {}
512
Prepare()513 bool BluetoothSocketCloseFunction::Prepare() {
514 params_ = bluetooth_socket::Close::Params::Create(*args_);
515 EXTENSION_FUNCTION_VALIDATE(params_.get());
516 return true;
517 }
518
Work()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
BluetoothSocketSendFunction()530 BluetoothSocketSendFunction::BluetoothSocketSendFunction()
531 : io_buffer_size_(0) {}
532
~BluetoothSocketSendFunction()533 BluetoothSocketSendFunction::~BluetoothSocketSendFunction() {}
534
Prepare()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
AsyncWorkStart()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
OnSuccess(int bytes_sent)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
OnError(BluetoothApiSocket::ErrorReason reason,const std::string & message)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
BluetoothSocketGetInfoFunction()573 BluetoothSocketGetInfoFunction::BluetoothSocketGetInfoFunction() {}
574
~BluetoothSocketGetInfoFunction()575 BluetoothSocketGetInfoFunction::~BluetoothSocketGetInfoFunction() {}
576
Prepare()577 bool BluetoothSocketGetInfoFunction::Prepare() {
578 params_ = bluetooth_socket::GetInfo::Params::Create(*args_);
579 EXTENSION_FUNCTION_VALIDATE(params_.get());
580 return true;
581 }
582
Work()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
BluetoothSocketGetSocketsFunction()595 BluetoothSocketGetSocketsFunction::BluetoothSocketGetSocketsFunction() {}
596
~BluetoothSocketGetSocketsFunction()597 BluetoothSocketGetSocketsFunction::~BluetoothSocketGetSocketsFunction() {}
598
Prepare()599 bool BluetoothSocketGetSocketsFunction::Prepare() { return true; }
600
Work()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