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