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/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::SocketInfo;
22 using extensions::api::bluetooth_socket::SocketProperties;
26 const char kDeviceNotFoundError[] = "Device not found";
27 const char kInvalidUuidError[] = "Invalid UUID";
28 const char kPermissionDeniedError[] = "Permission denied";
29 const char kSocketNotFoundError[] = "Socket not found";
31 linked_ptr<SocketInfo> CreateSocketInfo(int socket_id,
32 BluetoothApiSocket* socket) {
33 DCHECK(BrowserThread::CurrentlyOn(BluetoothApiSocket::kThreadId));
34 linked_ptr<SocketInfo> socket_info(new SocketInfo());
35 // This represents what we know about the socket, and does not call through
37 socket_info->socket_id = socket_id;
38 if (!socket->name().empty()) {
39 socket_info->name.reset(new std::string(socket->name()));
41 socket_info->persistent = socket->persistent();
42 if (socket->buffer_size() > 0) {
43 socket_info->buffer_size.reset(new int(socket->buffer_size()));
45 socket_info->paused = socket->paused();
46 socket_info->connected = socket->IsConnected();
48 // TODO(keybuk): These should not be present if socket isn't connected or
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 manager_ = ApiResourceManager<BluetoothApiSocket>::Get(browser_context());
103 << "There is no socket manager. "
104 "If this assertion is failing during a test, then it is likely that "
105 "TestExtensionSystem is failing to provide an instance of "
106 "ApiResourceManager<BluetoothApiSocket>.";
107 return manager_ != NULL;
110 bool BluetoothSocketAsyncApiFunction::Respond() { return error_.empty(); }
112 void BluetoothSocketAsyncApiFunction::AsyncWorkCompleted() {
113 SendResponse(Respond());
116 void BluetoothSocketAsyncApiFunction::Work() {}
118 void BluetoothSocketAsyncApiFunction::AsyncWorkStart() {
120 AsyncWorkCompleted();
123 int BluetoothSocketAsyncApiFunction::AddSocket(BluetoothApiSocket* socket) {
124 return manager_->Add(socket);
127 content::BrowserThread::ID
128 BluetoothSocketAsyncApiFunction::work_thread_id() const {
129 return BluetoothApiSocket::kThreadId;
132 BluetoothApiSocket* BluetoothSocketAsyncApiFunction::GetSocket(
133 int api_resource_id) {
134 return manager_->Get(extension_id(), api_resource_id);
137 void BluetoothSocketAsyncApiFunction::RemoveSocket(int api_resource_id) {
138 manager_->Remove(extension_id(), api_resource_id);
141 base::hash_set<int>* BluetoothSocketAsyncApiFunction::GetSocketIds() {
142 return manager_->GetResourceIds(extension_id());
145 BluetoothSocketCreateFunction::BluetoothSocketCreateFunction() {}
147 BluetoothSocketCreateFunction::~BluetoothSocketCreateFunction() {}
149 bool BluetoothSocketCreateFunction::Prepare() {
150 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
152 params_ = bluetooth_socket::Create::Params::Create(*args_);
153 EXTENSION_FUNCTION_VALIDATE(params_.get());
157 void BluetoothSocketCreateFunction::Work() {
158 DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
160 BluetoothApiSocket* socket = new BluetoothApiSocket(extension_id());
162 bluetooth_socket::SocketProperties* properties =
163 params_.get()->properties.get();
165 SetSocketProperties(socket, properties);
168 bluetooth_socket::CreateInfo create_info;
169 create_info.socket_id = AddSocket(socket);
170 results_ = bluetooth_socket::Create::Results::Create(create_info);
171 AsyncWorkCompleted();
174 BluetoothSocketUpdateFunction::BluetoothSocketUpdateFunction() {}
176 BluetoothSocketUpdateFunction::~BluetoothSocketUpdateFunction() {}
178 bool BluetoothSocketUpdateFunction::Prepare() {
179 params_ = bluetooth_socket::Update::Params::Create(*args_);
180 EXTENSION_FUNCTION_VALIDATE(params_.get());
184 void BluetoothSocketUpdateFunction::Work() {
185 BluetoothApiSocket* socket = GetSocket(params_->socket_id);
187 error_ = kSocketNotFoundError;
191 SetSocketProperties(socket, ¶ms_.get()->properties);
192 results_ = bluetooth_socket::Update::Results::Create();
195 BluetoothSocketSetPausedFunction::BluetoothSocketSetPausedFunction()
196 : socket_event_dispatcher_(NULL) {}
198 BluetoothSocketSetPausedFunction::~BluetoothSocketSetPausedFunction() {}
200 bool BluetoothSocketSetPausedFunction::Prepare() {
201 params_ = bluetooth_socket::SetPaused::Params::Create(*args_);
202 EXTENSION_FUNCTION_VALIDATE(params_.get());
204 socket_event_dispatcher_ = GetSocketEventDispatcher(browser_context());
205 return socket_event_dispatcher_ != NULL;
208 void BluetoothSocketSetPausedFunction::Work() {
209 BluetoothApiSocket* socket = GetSocket(params_->socket_id);
211 error_ = kSocketNotFoundError;
215 if (socket->paused() != params_->paused) {
216 socket->set_paused(params_->paused);
217 if (!params_->paused) {
218 socket_event_dispatcher_->OnSocketResume(extension_id(),
223 results_ = bluetooth_socket::SetPaused::Results::Create();
226 bool BluetoothSocketListenUsingRfcommFunction::RunAsync() {
227 // TODO(keybuk): Implement.
228 SetError("Not yet implemented.");
232 bool BluetoothSocketListenUsingInsecureRfcommFunction::RunAsync() {
233 // TODO(keybuk): Implement.
234 SetError("Not yet implemented.");
238 bool BluetoothSocketListenUsingL2capFunction::RunAsync() {
239 // TODO(keybuk): Implement.
240 SetError("Not yet implemented.");
244 BluetoothSocketConnectFunction::BluetoothSocketConnectFunction() {}
246 BluetoothSocketConnectFunction::~BluetoothSocketConnectFunction() {}
248 bool BluetoothSocketConnectFunction::Prepare() {
249 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
250 params_ = bluetooth_socket::Connect::Params::Create(*args_);
251 EXTENSION_FUNCTION_VALIDATE(params_.get());
253 socket_event_dispatcher_ = GetSocketEventDispatcher(browser_context());
254 return socket_event_dispatcher_ != NULL;
257 void BluetoothSocketConnectFunction::AsyncWorkStart() {
258 DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
259 device::BluetoothAdapterFactory::GetAdapter(
260 base::Bind(&BluetoothSocketConnectFunction::OnGetAdapter, this));
263 void BluetoothSocketConnectFunction::OnGetAdapter(
264 scoped_refptr<device::BluetoothAdapter> adapter) {
265 DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
266 BluetoothApiSocket* socket = GetSocket(params_->socket_id);
268 error_ = kSocketNotFoundError;
269 AsyncWorkCompleted();
273 device::BluetoothDevice* device = adapter->GetDevice(params_->address);
275 error_ = kDeviceNotFoundError;
276 AsyncWorkCompleted();
280 device::BluetoothUUID uuid(params_->uuid);
281 if (!uuid.IsValid()) {
282 error_ = kInvalidUuidError;
283 AsyncWorkCompleted();
287 BluetoothPermissionRequest param(params_->uuid);
288 if (!BluetoothManifestData::CheckRequest(GetExtension(), param)) {
289 error_ = kPermissionDeniedError;
290 AsyncWorkCompleted();
294 device->ConnectToService(
296 base::Bind(&BluetoothSocketConnectFunction::OnConnect, this),
297 base::Bind(&BluetoothSocketConnectFunction::OnConnectError, this));
300 void BluetoothSocketConnectFunction::OnConnect(
301 scoped_refptr<device::BluetoothSocket> socket) {
302 DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
304 // Fetch the socket again since this is not a reference-counted object, and
305 // it may have gone away in the meantime (we check earlier to avoid making
306 // a connection in the case of an obvious programming error).
307 BluetoothApiSocket* api_socket = GetSocket(params_->socket_id);
309 error_ = kSocketNotFoundError;
310 AsyncWorkCompleted();
314 api_socket->AdoptConnectedSocket(socket,
316 device::BluetoothUUID(params_->uuid));
317 socket_event_dispatcher_->OnSocketConnect(extension_id(),
320 results_ = bluetooth_socket::Connect::Results::Create();
321 AsyncWorkCompleted();
324 void BluetoothSocketConnectFunction::OnConnectError(
325 const std::string& message) {
326 DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
328 AsyncWorkCompleted();
331 BluetoothSocketDisconnectFunction::BluetoothSocketDisconnectFunction() {}
333 BluetoothSocketDisconnectFunction::~BluetoothSocketDisconnectFunction() {}
335 bool BluetoothSocketDisconnectFunction::Prepare() {
336 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
337 params_ = bluetooth_socket::Disconnect::Params::Create(*args_);
338 EXTENSION_FUNCTION_VALIDATE(params_.get());
342 void BluetoothSocketDisconnectFunction::AsyncWorkStart() {
343 DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
344 BluetoothApiSocket* socket = GetSocket(params_->socket_id);
346 error_ = kSocketNotFoundError;
347 AsyncWorkCompleted();
351 socket->Disconnect(base::Bind(&BluetoothSocketDisconnectFunction::OnSuccess,
355 void BluetoothSocketDisconnectFunction::OnSuccess() {
356 DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
357 results_ = bluetooth_socket::Disconnect::Results::Create();
358 AsyncWorkCompleted();
361 BluetoothSocketCloseFunction::BluetoothSocketCloseFunction() {}
363 BluetoothSocketCloseFunction::~BluetoothSocketCloseFunction() {}
365 bool BluetoothSocketCloseFunction::Prepare() {
366 params_ = bluetooth_socket::Close::Params::Create(*args_);
367 EXTENSION_FUNCTION_VALIDATE(params_.get());
371 void BluetoothSocketCloseFunction::Work() {
372 BluetoothApiSocket* socket = GetSocket(params_->socket_id);
374 error_ = kSocketNotFoundError;
378 RemoveSocket(params_->socket_id);
379 results_ = bluetooth_socket::Close::Results::Create();
382 BluetoothSocketSendFunction::BluetoothSocketSendFunction()
383 : io_buffer_size_(0) {}
385 BluetoothSocketSendFunction::~BluetoothSocketSendFunction() {}
387 bool BluetoothSocketSendFunction::Prepare() {
388 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
389 params_ = bluetooth_socket::Send::Params::Create(*args_);
390 EXTENSION_FUNCTION_VALIDATE(params_.get());
392 io_buffer_size_ = params_->data.size();
393 io_buffer_ = new net::WrappedIOBuffer(params_->data.data());
397 void BluetoothSocketSendFunction::AsyncWorkStart() {
398 DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
399 BluetoothApiSocket* socket = GetSocket(params_->socket_id);
401 error_ = kSocketNotFoundError;
405 socket->Send(io_buffer_,
407 base::Bind(&BluetoothSocketSendFunction::OnSuccess, this),
408 base::Bind(&BluetoothSocketSendFunction::OnError, this));
411 void BluetoothSocketSendFunction::OnSuccess(int bytes_sent) {
412 DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
413 results_ = bluetooth_socket::Send::Results::Create(bytes_sent);
414 AsyncWorkCompleted();
417 void BluetoothSocketSendFunction::OnError(
418 BluetoothApiSocket::ErrorReason reason,
419 const std::string& message) {
420 DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
422 AsyncWorkCompleted();
425 BluetoothSocketGetInfoFunction::BluetoothSocketGetInfoFunction() {}
427 BluetoothSocketGetInfoFunction::~BluetoothSocketGetInfoFunction() {}
429 bool BluetoothSocketGetInfoFunction::Prepare() {
430 params_ = bluetooth_socket::GetInfo::Params::Create(*args_);
431 EXTENSION_FUNCTION_VALIDATE(params_.get());
435 void BluetoothSocketGetInfoFunction::Work() {
436 BluetoothApiSocket* socket = GetSocket(params_->socket_id);
438 error_ = kSocketNotFoundError;
442 linked_ptr<bluetooth_socket::SocketInfo> socket_info =
443 CreateSocketInfo(params_->socket_id, socket);
444 results_ = bluetooth_socket::GetInfo::Results::Create(*socket_info);
447 BluetoothSocketGetSocketsFunction::BluetoothSocketGetSocketsFunction() {}
449 BluetoothSocketGetSocketsFunction::~BluetoothSocketGetSocketsFunction() {}
451 bool BluetoothSocketGetSocketsFunction::Prepare() { return true; }
453 void BluetoothSocketGetSocketsFunction::Work() {
454 std::vector<linked_ptr<bluetooth_socket::SocketInfo> > socket_infos;
455 base::hash_set<int>* resource_ids = GetSocketIds();
456 if (resource_ids != NULL) {
457 for (base::hash_set<int>::iterator it = resource_ids->begin();
458 it != resource_ids->end();
461 BluetoothApiSocket* socket = GetSocket(socket_id);
463 socket_infos.push_back(CreateSocketInfo(socket_id, socket));
467 results_ = bluetooth_socket::GetSockets::Results::Create(socket_infos);
471 } // namespace extensions