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.
5 #include "chrome/browser/extensions/api/bluetooth_socket/bluetooth_socket_api.h"
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"
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;
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";
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
38 socket_info->socket_id = socket_id;
39 if (!socket->name().empty()) {
40 socket_info->name.reset(new std::string(socket->name()));
42 socket_info->persistent = socket->persistent();
43 if (socket->buffer_size() > 0) {
44 socket_info->buffer_size.reset(new int(socket->buffer_size()));
46 socket_info->paused = socket->paused();
47 socket_info->connected = socket->IsConnected();
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()));
56 void SetSocketProperties(BluetoothApiSocket* socket,
57 SocketProperties* properties) {
58 if (properties->name.get()) {
59 socket->set_name(*properties->name.get());
61 if (properties->persistent.get()) {
62 socket->set_persistent(*properties->persistent.get());
64 if (properties->buffer_size.get()) {
65 // buffer size is validated when issuing the actual Recv operation
67 socket->set_buffer_size(*properties->buffer_size.get());
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;
85 namespace extensions {
88 BluetoothSocketAsyncApiFunction::BluetoothSocketAsyncApiFunction() {}
90 BluetoothSocketAsyncApiFunction::~BluetoothSocketAsyncApiFunction() {}
92 bool BluetoothSocketAsyncApiFunction::RunAsync() {
93 if (!PrePrepare() || !Prepare()) {
100 bool BluetoothSocketAsyncApiFunction::PrePrepare() {
101 if (!BluetoothManifestData::CheckSocketPermitted(GetExtension())) {
102 error_ = kPermissionDeniedError;
106 manager_ = ApiResourceManager<BluetoothApiSocket>::Get(browser_context());
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;
115 bool BluetoothSocketAsyncApiFunction::Respond() { return error_.empty(); }
117 void BluetoothSocketAsyncApiFunction::AsyncWorkCompleted() {
118 SendResponse(Respond());
121 void BluetoothSocketAsyncApiFunction::Work() {}
123 void BluetoothSocketAsyncApiFunction::AsyncWorkStart() {
125 AsyncWorkCompleted();
128 int BluetoothSocketAsyncApiFunction::AddSocket(BluetoothApiSocket* socket) {
129 return manager_->Add(socket);
132 content::BrowserThread::ID
133 BluetoothSocketAsyncApiFunction::work_thread_id() const {
134 return BluetoothApiSocket::kThreadId;
137 BluetoothApiSocket* BluetoothSocketAsyncApiFunction::GetSocket(
138 int api_resource_id) {
139 return manager_->Get(extension_id(), api_resource_id);
142 void BluetoothSocketAsyncApiFunction::RemoveSocket(int api_resource_id) {
143 manager_->Remove(extension_id(), api_resource_id);
146 base::hash_set<int>* BluetoothSocketAsyncApiFunction::GetSocketIds() {
147 return manager_->GetResourceIds(extension_id());
150 BluetoothSocketCreateFunction::BluetoothSocketCreateFunction() {}
152 BluetoothSocketCreateFunction::~BluetoothSocketCreateFunction() {}
154 bool BluetoothSocketCreateFunction::Prepare() {
155 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
157 params_ = bluetooth_socket::Create::Params::Create(*args_);
158 EXTENSION_FUNCTION_VALIDATE(params_.get());
162 void BluetoothSocketCreateFunction::Work() {
163 DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
165 BluetoothApiSocket* socket = new BluetoothApiSocket(extension_id());
167 bluetooth_socket::SocketProperties* properties =
168 params_.get()->properties.get();
170 SetSocketProperties(socket, properties);
173 bluetooth_socket::CreateInfo create_info;
174 create_info.socket_id = AddSocket(socket);
175 results_ = bluetooth_socket::Create::Results::Create(create_info);
176 AsyncWorkCompleted();
179 BluetoothSocketUpdateFunction::BluetoothSocketUpdateFunction() {}
181 BluetoothSocketUpdateFunction::~BluetoothSocketUpdateFunction() {}
183 bool BluetoothSocketUpdateFunction::Prepare() {
184 params_ = bluetooth_socket::Update::Params::Create(*args_);
185 EXTENSION_FUNCTION_VALIDATE(params_.get());
189 void BluetoothSocketUpdateFunction::Work() {
190 BluetoothApiSocket* socket = GetSocket(params_->socket_id);
192 error_ = kSocketNotFoundError;
196 SetSocketProperties(socket, ¶ms_.get()->properties);
197 results_ = bluetooth_socket::Update::Results::Create();
200 BluetoothSocketSetPausedFunction::BluetoothSocketSetPausedFunction()
201 : socket_event_dispatcher_(NULL) {}
203 BluetoothSocketSetPausedFunction::~BluetoothSocketSetPausedFunction() {}
205 bool BluetoothSocketSetPausedFunction::Prepare() {
206 params_ = bluetooth_socket::SetPaused::Params::Create(*args_);
207 EXTENSION_FUNCTION_VALIDATE(params_.get());
209 socket_event_dispatcher_ = GetSocketEventDispatcher(browser_context());
210 return socket_event_dispatcher_ != NULL;
213 void BluetoothSocketSetPausedFunction::Work() {
214 BluetoothApiSocket* socket = GetSocket(params_->socket_id);
216 error_ = kSocketNotFoundError;
220 if (socket->paused() != params_->paused) {
221 socket->set_paused(params_->paused);
222 if (!params_->paused) {
223 socket_event_dispatcher_->OnSocketResume(extension_id(),
228 results_ = bluetooth_socket::SetPaused::Results::Create();
231 BluetoothSocketListenFunction::BluetoothSocketListenFunction() {}
233 BluetoothSocketListenFunction::~BluetoothSocketListenFunction() {}
235 bool BluetoothSocketListenFunction::Prepare() {
236 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
239 socket_event_dispatcher_ = GetSocketEventDispatcher(browser_context());
240 return socket_event_dispatcher_ != NULL;
243 void BluetoothSocketListenFunction::AsyncWorkStart() {
244 DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
245 device::BluetoothAdapterFactory::GetAdapter(
246 base::Bind(&BluetoothSocketListenFunction::OnGetAdapter, this));
249 void BluetoothSocketListenFunction::OnGetAdapter(
250 scoped_refptr<device::BluetoothAdapter> adapter) {
251 DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
252 BluetoothApiSocket* socket = GetSocket(socket_id());
254 error_ = kSocketNotFoundError;
255 AsyncWorkCompleted();
259 device::BluetoothUUID bluetooth_uuid(uuid());
260 if (!bluetooth_uuid.IsValid()) {
261 error_ = kInvalidUuidError;
262 AsyncWorkCompleted();
266 BluetoothPermissionRequest param(uuid());
267 if (!BluetoothManifestData::CheckRequest(GetExtension(), param)) {
268 error_ = kPermissionDeniedError;
269 AsyncWorkCompleted();
276 base::Bind(&BluetoothSocketListenFunction::OnCreateService, this),
277 base::Bind(&BluetoothSocketListenFunction::OnCreateServiceError, this));
281 void BluetoothSocketListenFunction::OnCreateService(
282 scoped_refptr<device::BluetoothSocket> socket) {
283 DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
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());
290 error_ = kSocketNotFoundError;
291 AsyncWorkCompleted();
295 api_socket->AdoptListeningSocket(socket,
296 device::BluetoothUUID(uuid()));
297 socket_event_dispatcher_->OnSocketListen(extension_id(), socket_id());
300 AsyncWorkCompleted();
303 void BluetoothSocketListenFunction::OnCreateServiceError(
304 const std::string& message) {
305 DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
307 AsyncWorkCompleted();
310 BluetoothSocketListenUsingRfcommFunction::
311 BluetoothSocketListenUsingRfcommFunction() {}
313 BluetoothSocketListenUsingRfcommFunction::
314 ~BluetoothSocketListenUsingRfcommFunction() {}
316 int BluetoothSocketListenUsingRfcommFunction::socket_id() const {
317 return params_->socket_id;
320 const std::string& BluetoothSocketListenUsingRfcommFunction::uuid() const {
321 return params_->uuid;
324 bool BluetoothSocketListenUsingRfcommFunction::CreateParams() {
325 params_ = bluetooth_socket::ListenUsingRfcomm::Params::Create(*args_);
326 EXTENSION_FUNCTION_VALIDATE(params_.get());
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&
336 int channel = device::BluetoothAdapter::kChannelAuto;
338 ListenOptions* options = params_->options.get();
340 if (options->channel.get())
341 channel = *(options->channel);
344 adapter->CreateRfcommService(uuid, channel, callback, error_callback);
347 void BluetoothSocketListenUsingRfcommFunction::CreateResults() {
348 results_ = bluetooth_socket::ListenUsingRfcomm::Results::Create();
351 BluetoothSocketListenUsingL2capFunction::
352 BluetoothSocketListenUsingL2capFunction() {}
354 BluetoothSocketListenUsingL2capFunction::
355 ~BluetoothSocketListenUsingL2capFunction() {}
357 int BluetoothSocketListenUsingL2capFunction::socket_id() const {
358 return params_->socket_id;
361 const std::string& BluetoothSocketListenUsingL2capFunction::uuid() const {
362 return params_->uuid;
365 bool BluetoothSocketListenUsingL2capFunction::CreateParams() {
366 params_ = bluetooth_socket::ListenUsingL2cap::Params::Create(*args_);
367 EXTENSION_FUNCTION_VALIDATE(params_.get());
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&
377 int psm = device::BluetoothAdapter::kPsmAuto;
379 ListenOptions* options = params_->options.get();
381 if (options->psm.get())
382 psm = *(options->psm);
385 adapter->CreateL2capService(uuid, psm, callback, error_callback);
388 void BluetoothSocketListenUsingL2capFunction::CreateResults() {
389 results_ = bluetooth_socket::ListenUsingL2cap::Results::Create();
392 BluetoothSocketConnectFunction::BluetoothSocketConnectFunction() {}
394 BluetoothSocketConnectFunction::~BluetoothSocketConnectFunction() {}
396 bool BluetoothSocketConnectFunction::Prepare() {
397 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
398 params_ = bluetooth_socket::Connect::Params::Create(*args_);
399 EXTENSION_FUNCTION_VALIDATE(params_.get());
401 socket_event_dispatcher_ = GetSocketEventDispatcher(browser_context());
402 return socket_event_dispatcher_ != NULL;
405 void BluetoothSocketConnectFunction::AsyncWorkStart() {
406 DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
407 device::BluetoothAdapterFactory::GetAdapter(
408 base::Bind(&BluetoothSocketConnectFunction::OnGetAdapter, this));
411 void BluetoothSocketConnectFunction::OnGetAdapter(
412 scoped_refptr<device::BluetoothAdapter> adapter) {
413 DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
414 BluetoothApiSocket* socket = GetSocket(params_->socket_id);
416 error_ = kSocketNotFoundError;
417 AsyncWorkCompleted();
421 device::BluetoothDevice* device = adapter->GetDevice(params_->address);
423 error_ = kDeviceNotFoundError;
424 AsyncWorkCompleted();
428 device::BluetoothUUID uuid(params_->uuid);
429 if (!uuid.IsValid()) {
430 error_ = kInvalidUuidError;
431 AsyncWorkCompleted();
435 BluetoothPermissionRequest param(params_->uuid);
436 if (!BluetoothManifestData::CheckRequest(GetExtension(), param)) {
437 error_ = kPermissionDeniedError;
438 AsyncWorkCompleted();
442 device->ConnectToService(
444 base::Bind(&BluetoothSocketConnectFunction::OnConnect, this),
445 base::Bind(&BluetoothSocketConnectFunction::OnConnectError, this));
448 void BluetoothSocketConnectFunction::OnConnect(
449 scoped_refptr<device::BluetoothSocket> socket) {
450 DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
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);
457 error_ = kSocketNotFoundError;
458 AsyncWorkCompleted();
462 api_socket->AdoptConnectedSocket(socket,
464 device::BluetoothUUID(params_->uuid));
465 socket_event_dispatcher_->OnSocketConnect(extension_id(),
468 results_ = bluetooth_socket::Connect::Results::Create();
469 AsyncWorkCompleted();
472 void BluetoothSocketConnectFunction::OnConnectError(
473 const std::string& message) {
474 DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
476 AsyncWorkCompleted();
479 BluetoothSocketDisconnectFunction::BluetoothSocketDisconnectFunction() {}
481 BluetoothSocketDisconnectFunction::~BluetoothSocketDisconnectFunction() {}
483 bool BluetoothSocketDisconnectFunction::Prepare() {
484 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
485 params_ = bluetooth_socket::Disconnect::Params::Create(*args_);
486 EXTENSION_FUNCTION_VALIDATE(params_.get());
490 void BluetoothSocketDisconnectFunction::AsyncWorkStart() {
491 DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
492 BluetoothApiSocket* socket = GetSocket(params_->socket_id);
494 error_ = kSocketNotFoundError;
495 AsyncWorkCompleted();
499 socket->Disconnect(base::Bind(&BluetoothSocketDisconnectFunction::OnSuccess,
503 void BluetoothSocketDisconnectFunction::OnSuccess() {
504 DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
505 results_ = bluetooth_socket::Disconnect::Results::Create();
506 AsyncWorkCompleted();
509 BluetoothSocketCloseFunction::BluetoothSocketCloseFunction() {}
511 BluetoothSocketCloseFunction::~BluetoothSocketCloseFunction() {}
513 bool BluetoothSocketCloseFunction::Prepare() {
514 params_ = bluetooth_socket::Close::Params::Create(*args_);
515 EXTENSION_FUNCTION_VALIDATE(params_.get());
519 void BluetoothSocketCloseFunction::Work() {
520 BluetoothApiSocket* socket = GetSocket(params_->socket_id);
522 error_ = kSocketNotFoundError;
526 RemoveSocket(params_->socket_id);
527 results_ = bluetooth_socket::Close::Results::Create();
530 BluetoothSocketSendFunction::BluetoothSocketSendFunction()
531 : io_buffer_size_(0) {}
533 BluetoothSocketSendFunction::~BluetoothSocketSendFunction() {}
535 bool BluetoothSocketSendFunction::Prepare() {
536 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
537 params_ = bluetooth_socket::Send::Params::Create(*args_);
538 EXTENSION_FUNCTION_VALIDATE(params_.get());
540 io_buffer_size_ = params_->data.size();
541 io_buffer_ = new net::WrappedIOBuffer(params_->data.data());
545 void BluetoothSocketSendFunction::AsyncWorkStart() {
546 DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
547 BluetoothApiSocket* socket = GetSocket(params_->socket_id);
549 error_ = kSocketNotFoundError;
553 socket->Send(io_buffer_,
555 base::Bind(&BluetoothSocketSendFunction::OnSuccess, this),
556 base::Bind(&BluetoothSocketSendFunction::OnError, this));
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();
565 void BluetoothSocketSendFunction::OnError(
566 BluetoothApiSocket::ErrorReason reason,
567 const std::string& message) {
568 DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
570 AsyncWorkCompleted();
573 BluetoothSocketGetInfoFunction::BluetoothSocketGetInfoFunction() {}
575 BluetoothSocketGetInfoFunction::~BluetoothSocketGetInfoFunction() {}
577 bool BluetoothSocketGetInfoFunction::Prepare() {
578 params_ = bluetooth_socket::GetInfo::Params::Create(*args_);
579 EXTENSION_FUNCTION_VALIDATE(params_.get());
583 void BluetoothSocketGetInfoFunction::Work() {
584 BluetoothApiSocket* socket = GetSocket(params_->socket_id);
586 error_ = kSocketNotFoundError;
590 linked_ptr<bluetooth_socket::SocketInfo> socket_info =
591 CreateSocketInfo(params_->socket_id, socket);
592 results_ = bluetooth_socket::GetInfo::Results::Create(*socket_info);
595 BluetoothSocketGetSocketsFunction::BluetoothSocketGetSocketsFunction() {}
597 BluetoothSocketGetSocketsFunction::~BluetoothSocketGetSocketsFunction() {}
599 bool BluetoothSocketGetSocketsFunction::Prepare() { return true; }
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();
609 BluetoothApiSocket* socket = GetSocket(socket_id);
611 socket_infos.push_back(CreateSocketInfo(socket_id, socket));
615 results_ = bluetooth_socket::GetSockets::Results::Create(socket_infos);
619 } // namespace extensions