Upstream version 7.36.149.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/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::SocketInfo;
22 using extensions::api::bluetooth_socket::SocketProperties;
23
24 namespace {
25
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";
30
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
36   // to the system.
37   socket_info->socket_id = socket_id;
38   if (!socket->name().empty()) {
39     socket_info->name.reset(new std::string(socket->name()));
40   }
41   socket_info->persistent = socket->persistent();
42   if (socket->buffer_size() > 0) {
43     socket_info->buffer_size.reset(new int(socket->buffer_size()));
44   }
45   socket_info->paused = socket->paused();
46   socket_info->connected = socket->IsConnected();
47
48   // TODO(keybuk): These should not be present if socket isn't connected or
49   // listening.
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   manager_ = ApiResourceManager<BluetoothApiSocket>::Get(browser_context());
102   DCHECK(manager_)
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;
108 }
109
110 bool BluetoothSocketAsyncApiFunction::Respond() { return error_.empty(); }
111
112 void BluetoothSocketAsyncApiFunction::AsyncWorkCompleted() {
113   SendResponse(Respond());
114 }
115
116 void BluetoothSocketAsyncApiFunction::Work() {}
117
118 void BluetoothSocketAsyncApiFunction::AsyncWorkStart() {
119   Work();
120   AsyncWorkCompleted();
121 }
122
123 int BluetoothSocketAsyncApiFunction::AddSocket(BluetoothApiSocket* socket) {
124   return manager_->Add(socket);
125 }
126
127 content::BrowserThread::ID
128 BluetoothSocketAsyncApiFunction::work_thread_id() const {
129   return BluetoothApiSocket::kThreadId;
130 }
131
132 BluetoothApiSocket* BluetoothSocketAsyncApiFunction::GetSocket(
133     int api_resource_id) {
134   return manager_->Get(extension_id(), api_resource_id);
135 }
136
137 void BluetoothSocketAsyncApiFunction::RemoveSocket(int api_resource_id) {
138   manager_->Remove(extension_id(), api_resource_id);
139 }
140
141 base::hash_set<int>* BluetoothSocketAsyncApiFunction::GetSocketIds() {
142   return manager_->GetResourceIds(extension_id());
143 }
144
145 BluetoothSocketCreateFunction::BluetoothSocketCreateFunction() {}
146
147 BluetoothSocketCreateFunction::~BluetoothSocketCreateFunction() {}
148
149 bool BluetoothSocketCreateFunction::Prepare() {
150   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
151
152   params_ = bluetooth_socket::Create::Params::Create(*args_);
153   EXTENSION_FUNCTION_VALIDATE(params_.get());
154   return true;
155 }
156
157 void BluetoothSocketCreateFunction::Work() {
158   DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
159
160   BluetoothApiSocket* socket = new BluetoothApiSocket(extension_id());
161
162   bluetooth_socket::SocketProperties* properties =
163       params_.get()->properties.get();
164   if (properties) {
165     SetSocketProperties(socket, properties);
166   }
167
168   bluetooth_socket::CreateInfo create_info;
169   create_info.socket_id = AddSocket(socket);
170   results_ = bluetooth_socket::Create::Results::Create(create_info);
171   AsyncWorkCompleted();
172 }
173
174 BluetoothSocketUpdateFunction::BluetoothSocketUpdateFunction() {}
175
176 BluetoothSocketUpdateFunction::~BluetoothSocketUpdateFunction() {}
177
178 bool BluetoothSocketUpdateFunction::Prepare() {
179   params_ = bluetooth_socket::Update::Params::Create(*args_);
180   EXTENSION_FUNCTION_VALIDATE(params_.get());
181   return true;
182 }
183
184 void BluetoothSocketUpdateFunction::Work() {
185   BluetoothApiSocket* socket = GetSocket(params_->socket_id);
186   if (!socket) {
187     error_ = kSocketNotFoundError;
188     return;
189   }
190
191   SetSocketProperties(socket, &params_.get()->properties);
192   results_ = bluetooth_socket::Update::Results::Create();
193 }
194
195 BluetoothSocketSetPausedFunction::BluetoothSocketSetPausedFunction()
196     : socket_event_dispatcher_(NULL) {}
197
198 BluetoothSocketSetPausedFunction::~BluetoothSocketSetPausedFunction() {}
199
200 bool BluetoothSocketSetPausedFunction::Prepare() {
201   params_ = bluetooth_socket::SetPaused::Params::Create(*args_);
202   EXTENSION_FUNCTION_VALIDATE(params_.get());
203
204   socket_event_dispatcher_ = GetSocketEventDispatcher(browser_context());
205   return socket_event_dispatcher_ != NULL;
206 }
207
208 void BluetoothSocketSetPausedFunction::Work() {
209   BluetoothApiSocket* socket = GetSocket(params_->socket_id);
210   if (!socket) {
211     error_ = kSocketNotFoundError;
212     return;
213   }
214
215   if (socket->paused() != params_->paused) {
216     socket->set_paused(params_->paused);
217     if (!params_->paused) {
218       socket_event_dispatcher_->OnSocketResume(extension_id(),
219                                                params_->socket_id);
220     }
221   }
222
223   results_ = bluetooth_socket::SetPaused::Results::Create();
224 }
225
226 bool BluetoothSocketListenUsingRfcommFunction::RunAsync() {
227   // TODO(keybuk): Implement.
228   SetError("Not yet implemented.");
229   return false;
230 }
231
232 bool BluetoothSocketListenUsingInsecureRfcommFunction::RunAsync() {
233   // TODO(keybuk): Implement.
234   SetError("Not yet implemented.");
235   return false;
236 }
237
238 bool BluetoothSocketListenUsingL2capFunction::RunAsync() {
239   // TODO(keybuk): Implement.
240   SetError("Not yet implemented.");
241   return false;
242 }
243
244 BluetoothSocketConnectFunction::BluetoothSocketConnectFunction() {}
245
246 BluetoothSocketConnectFunction::~BluetoothSocketConnectFunction() {}
247
248 bool BluetoothSocketConnectFunction::Prepare() {
249   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
250   params_ = bluetooth_socket::Connect::Params::Create(*args_);
251   EXTENSION_FUNCTION_VALIDATE(params_.get());
252
253   socket_event_dispatcher_ = GetSocketEventDispatcher(browser_context());
254   return socket_event_dispatcher_ != NULL;
255 }
256
257 void BluetoothSocketConnectFunction::AsyncWorkStart() {
258   DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
259   device::BluetoothAdapterFactory::GetAdapter(
260       base::Bind(&BluetoothSocketConnectFunction::OnGetAdapter, this));
261 }
262
263 void BluetoothSocketConnectFunction::OnGetAdapter(
264     scoped_refptr<device::BluetoothAdapter> adapter) {
265   DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
266   BluetoothApiSocket* socket = GetSocket(params_->socket_id);
267   if (!socket) {
268     error_ = kSocketNotFoundError;
269     AsyncWorkCompleted();
270     return;
271   }
272
273   device::BluetoothDevice* device = adapter->GetDevice(params_->address);
274   if (!device) {
275     error_ = kDeviceNotFoundError;
276     AsyncWorkCompleted();
277     return;
278   }
279
280   device::BluetoothUUID uuid(params_->uuid);
281   if (!uuid.IsValid()) {
282     error_ = kInvalidUuidError;
283     AsyncWorkCompleted();
284     return;
285   }
286
287   BluetoothPermissionRequest param(params_->uuid);
288   if (!BluetoothManifestData::CheckRequest(GetExtension(), param)) {
289     error_ = kPermissionDeniedError;
290     AsyncWorkCompleted();
291     return;
292   }
293
294   device->ConnectToService(
295       uuid,
296       base::Bind(&BluetoothSocketConnectFunction::OnConnect, this),
297       base::Bind(&BluetoothSocketConnectFunction::OnConnectError, this));
298 }
299
300 void BluetoothSocketConnectFunction::OnConnect(
301     scoped_refptr<device::BluetoothSocket> socket) {
302   DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
303
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);
308   if (!api_socket) {
309     error_ = kSocketNotFoundError;
310     AsyncWorkCompleted();
311     return;
312   }
313
314   api_socket->AdoptConnectedSocket(socket,
315                                    params_->address,
316                                    device::BluetoothUUID(params_->uuid));
317   socket_event_dispatcher_->OnSocketConnect(extension_id(),
318                                             params_->socket_id);
319
320   results_ = bluetooth_socket::Connect::Results::Create();
321   AsyncWorkCompleted();
322 }
323
324 void BluetoothSocketConnectFunction::OnConnectError(
325     const std::string& message) {
326   DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
327   error_ = message;
328   AsyncWorkCompleted();
329 }
330
331 BluetoothSocketDisconnectFunction::BluetoothSocketDisconnectFunction() {}
332
333 BluetoothSocketDisconnectFunction::~BluetoothSocketDisconnectFunction() {}
334
335 bool BluetoothSocketDisconnectFunction::Prepare() {
336   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
337   params_ = bluetooth_socket::Disconnect::Params::Create(*args_);
338   EXTENSION_FUNCTION_VALIDATE(params_.get());
339   return true;
340 }
341
342 void BluetoothSocketDisconnectFunction::AsyncWorkStart() {
343   DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
344   BluetoothApiSocket* socket = GetSocket(params_->socket_id);
345   if (!socket) {
346     error_ = kSocketNotFoundError;
347     AsyncWorkCompleted();
348     return;
349   }
350
351   socket->Disconnect(base::Bind(&BluetoothSocketDisconnectFunction::OnSuccess,
352                                 this));
353 }
354
355 void BluetoothSocketDisconnectFunction::OnSuccess() {
356   DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
357   results_ = bluetooth_socket::Disconnect::Results::Create();
358   AsyncWorkCompleted();
359 }
360
361 BluetoothSocketCloseFunction::BluetoothSocketCloseFunction() {}
362
363 BluetoothSocketCloseFunction::~BluetoothSocketCloseFunction() {}
364
365 bool BluetoothSocketCloseFunction::Prepare() {
366   params_ = bluetooth_socket::Close::Params::Create(*args_);
367   EXTENSION_FUNCTION_VALIDATE(params_.get());
368   return true;
369 }
370
371 void BluetoothSocketCloseFunction::Work() {
372   BluetoothApiSocket* socket = GetSocket(params_->socket_id);
373   if (!socket) {
374     error_ = kSocketNotFoundError;
375     return;
376   }
377
378   RemoveSocket(params_->socket_id);
379   results_ = bluetooth_socket::Close::Results::Create();
380 }
381
382 BluetoothSocketSendFunction::BluetoothSocketSendFunction()
383     : io_buffer_size_(0) {}
384
385 BluetoothSocketSendFunction::~BluetoothSocketSendFunction() {}
386
387 bool BluetoothSocketSendFunction::Prepare() {
388   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
389   params_ = bluetooth_socket::Send::Params::Create(*args_);
390   EXTENSION_FUNCTION_VALIDATE(params_.get());
391
392   io_buffer_size_ = params_->data.size();
393   io_buffer_ = new net::WrappedIOBuffer(params_->data.data());
394   return true;
395 }
396
397 void BluetoothSocketSendFunction::AsyncWorkStart() {
398   DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
399   BluetoothApiSocket* socket = GetSocket(params_->socket_id);
400   if (!socket) {
401     error_ = kSocketNotFoundError;
402     return;
403   }
404
405   socket->Send(io_buffer_,
406                io_buffer_size_,
407                base::Bind(&BluetoothSocketSendFunction::OnSuccess, this),
408                base::Bind(&BluetoothSocketSendFunction::OnError, this));
409 }
410
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();
415 }
416
417 void BluetoothSocketSendFunction::OnError(
418     BluetoothApiSocket::ErrorReason reason,
419     const std::string& message) {
420   DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
421   error_ = message;
422   AsyncWorkCompleted();
423 }
424
425 BluetoothSocketGetInfoFunction::BluetoothSocketGetInfoFunction() {}
426
427 BluetoothSocketGetInfoFunction::~BluetoothSocketGetInfoFunction() {}
428
429 bool BluetoothSocketGetInfoFunction::Prepare() {
430   params_ = bluetooth_socket::GetInfo::Params::Create(*args_);
431   EXTENSION_FUNCTION_VALIDATE(params_.get());
432   return true;
433 }
434
435 void BluetoothSocketGetInfoFunction::Work() {
436   BluetoothApiSocket* socket = GetSocket(params_->socket_id);
437   if (!socket) {
438     error_ = kSocketNotFoundError;
439     return;
440   }
441
442   linked_ptr<bluetooth_socket::SocketInfo> socket_info =
443       CreateSocketInfo(params_->socket_id, socket);
444   results_ = bluetooth_socket::GetInfo::Results::Create(*socket_info);
445 }
446
447 BluetoothSocketGetSocketsFunction::BluetoothSocketGetSocketsFunction() {}
448
449 BluetoothSocketGetSocketsFunction::~BluetoothSocketGetSocketsFunction() {}
450
451 bool BluetoothSocketGetSocketsFunction::Prepare() { return true; }
452
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();
459          ++it) {
460       int socket_id = *it;
461       BluetoothApiSocket* socket = GetSocket(socket_id);
462       if (socket) {
463         socket_infos.push_back(CreateSocketInfo(socket_id, socket));
464       }
465     }
466   }
467   results_ = bluetooth_socket::GetSockets::Results::Create(socket_infos);
468 }
469
470 }  // namespace api
471 }  // namespace extensions