15c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// Copyright 2014 The Chromium Authors. All rights reserved.
25c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// Use of this source code is governed by a BSD-style license that can be
35c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// found in the LICENSE file.
45c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
51320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "extensions/browser/api/bluetooth_socket/bluetooth_socket_api.h"
65c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
7116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include <stdint.h>
8116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
95c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "content/public/browser/browser_context.h"
105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "content/public/browser/browser_thread.h"
11010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "device/bluetooth/bluetooth_adapter.h"
12010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "device/bluetooth/bluetooth_adapter_factory.h"
13010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "device/bluetooth/bluetooth_device.h"
14010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "device/bluetooth/bluetooth_socket.h"
151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "extensions/browser/api/bluetooth_socket/bluetooth_api_socket.h"
161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "extensions/browser/api/bluetooth_socket/bluetooth_socket_event_dispatcher.h"
171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "extensions/common/api/bluetooth/bluetooth_manifest_data.h"
18010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "extensions/common/permissions/permissions_data.h"
195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "net/base/io_buffer.h"
205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuusing content::BrowserThread;
225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuusing extensions::BluetoothApiSocket;
231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciusing extensions::core_api::bluetooth_socket::ListenOptions;
241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciusing extensions::core_api::bluetooth_socket::SocketInfo;
251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciusing extensions::core_api::bluetooth_socket::SocketProperties;
261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccinamespace extensions {
281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccinamespace core_api {
295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liunamespace {
315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
32010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)const char kDeviceNotFoundError[] = "Device not found";
33116680a4aac90f2aa7413d9095a592090648e557Ben Murdochconst char kInvalidPsmError[] = "Invalid PSM";
34010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)const char kInvalidUuidError[] = "Invalid UUID";
35010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)const char kPermissionDeniedError[] = "Permission denied";
365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuconst char kSocketNotFoundError[] = "Socket not found";
375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liulinked_ptr<SocketInfo> CreateSocketInfo(int socket_id,
395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                        BluetoothApiSocket* socket) {
405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  DCHECK(BrowserThread::CurrentlyOn(BluetoothApiSocket::kThreadId));
415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  linked_ptr<SocketInfo> socket_info(new SocketInfo());
425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // This represents what we know about the socket, and does not call through
435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // to the system.
445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  socket_info->socket_id = socket_id;
45116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (socket->name()) {
46116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    socket_info->name.reset(new std::string(*socket->name()));
475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  socket_info->persistent = socket->persistent();
495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (socket->buffer_size() > 0) {
505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    socket_info->buffer_size.reset(new int(socket->buffer_size()));
515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  socket_info->paused = socket->paused();
535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  socket_info->connected = socket->IsConnected();
545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
55cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (socket->IsConnected())
56cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    socket_info->address.reset(new std::string(socket->device_address()));
575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  socket_info->uuid.reset(new std::string(socket->uuid().canonical_value()));
585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  return socket_info;
605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid SetSocketProperties(BluetoothApiSocket* socket,
635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                         SocketProperties* properties) {
645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (properties->name.get()) {
655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    socket->set_name(*properties->name.get());
665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (properties->persistent.get()) {
685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    socket->set_persistent(*properties->persistent.get());
695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (properties->buffer_size.get()) {
715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    // buffer size is validated when issuing the actual Recv operation
725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    // on the socket.
735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    socket->set_buffer_size(*properties->buffer_size.get());
745c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
755c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
765c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciBluetoothSocketEventDispatcher* GetSocketEventDispatcher(
78010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    content::BrowserContext* browser_context) {
791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  BluetoothSocketEventDispatcher* socket_event_dispatcher =
801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      BluetoothSocketEventDispatcher::Get(browser_context);
81010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DCHECK(socket_event_dispatcher)
82010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      << "There is no socket event dispatcher. "
83010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)         "If this assertion is failing during a test, then it is likely that "
84010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)         "TestExtensionSystem is failing to provide an instance of "
85010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)         "BluetoothSocketEventDispatcher.";
86010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  return socket_event_dispatcher;
87010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
88010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
89116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// Returns |true| if |psm| is a valid PSM.
90116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// Per the Bluetooth specification, the PSM field must be at least two octets in
91116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// length, with least significant bit of the least significant octet equal to
92116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// '1' and the least significant bit of the most significant octet equal to '0'.
93116680a4aac90f2aa7413d9095a592090648e557Ben Murdochbool IsValidPsm(int psm) {
94116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (psm <= 0)
95116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return false;
96116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
97116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  std::vector<int16_t> octets;
98116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  while (psm > 0) {
99116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch     octets.push_back(psm & 0xFF);
100116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch     psm = psm >> 8;
101116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
102116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
103116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (octets.size() < 2U)
104116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return false;
105116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
106116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // The least significant bit of the least significant octet must be '1'.
107116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if ((octets.front() & 0x01) != 1)
108116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return false;
109116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
110116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // The least significant bit of the most significant octet must be '0'.
111116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if ((octets.back() & 0x01) != 0)
112116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return false;
113116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
114116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return true;
115116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
116116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
1175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}  // namespace
1185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuBluetoothSocketAsyncApiFunction::BluetoothSocketAsyncApiFunction() {}
1205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuBluetoothSocketAsyncApiFunction::~BluetoothSocketAsyncApiFunction() {}
1225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
123010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)bool BluetoothSocketAsyncApiFunction::RunAsync() {
1245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (!PrePrepare() || !Prepare()) {
1255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return false;
1265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
1275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  AsyncWorkStart();
1285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  return true;
1295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
1305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liubool BluetoothSocketAsyncApiFunction::PrePrepare() {
1325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!BluetoothManifestData::CheckSocketPermitted(extension())) {
133f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    error_ = kPermissionDeniedError;
134f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return false;
135f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
136f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
1375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  manager_ = ApiResourceManager<BluetoothApiSocket>::Get(browser_context());
1385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  DCHECK(manager_)
1395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      << "There is no socket manager. "
1405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu         "If this assertion is failing during a test, then it is likely that "
1415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu         "TestExtensionSystem is failing to provide an instance of "
1425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu         "ApiResourceManager<BluetoothApiSocket>.";
1435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  return manager_ != NULL;
1445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
1455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liubool BluetoothSocketAsyncApiFunction::Respond() { return error_.empty(); }
1475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid BluetoothSocketAsyncApiFunction::AsyncWorkCompleted() {
1495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  SendResponse(Respond());
1505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
1515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid BluetoothSocketAsyncApiFunction::Work() {}
1535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid BluetoothSocketAsyncApiFunction::AsyncWorkStart() {
1555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  Work();
1565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  AsyncWorkCompleted();
1575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
1585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuint BluetoothSocketAsyncApiFunction::AddSocket(BluetoothApiSocket* socket) {
1605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  return manager_->Add(socket);
1615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
1625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liucontent::BrowserThread::ID
1645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuBluetoothSocketAsyncApiFunction::work_thread_id() const {
1655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  return BluetoothApiSocket::kThreadId;
1665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
1675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuBluetoothApiSocket* BluetoothSocketAsyncApiFunction::GetSocket(
1695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    int api_resource_id) {
1705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  return manager_->Get(extension_id(), api_resource_id);
1715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
1725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid BluetoothSocketAsyncApiFunction::RemoveSocket(int api_resource_id) {
1745c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  manager_->Remove(extension_id(), api_resource_id);
1755c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
1765c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1775c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liubase::hash_set<int>* BluetoothSocketAsyncApiFunction::GetSocketIds() {
1785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  return manager_->GetResourceIds(extension_id());
1795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
1805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1815c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuBluetoothSocketCreateFunction::BluetoothSocketCreateFunction() {}
1825c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1835c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuBluetoothSocketCreateFunction::~BluetoothSocketCreateFunction() {}
1845c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1855c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liubool BluetoothSocketCreateFunction::Prepare() {
1865c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1875c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1885c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  params_ = bluetooth_socket::Create::Params::Create(*args_);
1895c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXTENSION_FUNCTION_VALIDATE(params_.get());
1905c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  return true;
1915c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
1925c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1935c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid BluetoothSocketCreateFunction::Work() {
1945c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
1955c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1965c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  BluetoothApiSocket* socket = new BluetoothApiSocket(extension_id());
1975c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1985c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  bluetooth_socket::SocketProperties* properties =
1995c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      params_.get()->properties.get();
2005c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (properties) {
2015c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    SetSocketProperties(socket, properties);
2025c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
2035c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
2045c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  bluetooth_socket::CreateInfo create_info;
2055c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  create_info.socket_id = AddSocket(socket);
2065c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  results_ = bluetooth_socket::Create::Results::Create(create_info);
2075c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  AsyncWorkCompleted();
2085c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
2095c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
2105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuBluetoothSocketUpdateFunction::BluetoothSocketUpdateFunction() {}
2115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
2125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuBluetoothSocketUpdateFunction::~BluetoothSocketUpdateFunction() {}
2135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
2145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liubool BluetoothSocketUpdateFunction::Prepare() {
2155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  params_ = bluetooth_socket::Update::Params::Create(*args_);
2165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXTENSION_FUNCTION_VALIDATE(params_.get());
2175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  return true;
2185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
2195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
2205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid BluetoothSocketUpdateFunction::Work() {
2215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  BluetoothApiSocket* socket = GetSocket(params_->socket_id);
2225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (!socket) {
2235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    error_ = kSocketNotFoundError;
2245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return;
2255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
2265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
2275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  SetSocketProperties(socket, &params_.get()->properties);
2285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  results_ = bluetooth_socket::Update::Results::Create();
2295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
2305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
2315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuBluetoothSocketSetPausedFunction::BluetoothSocketSetPausedFunction()
2325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    : socket_event_dispatcher_(NULL) {}
2335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
2345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuBluetoothSocketSetPausedFunction::~BluetoothSocketSetPausedFunction() {}
2355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
2365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liubool BluetoothSocketSetPausedFunction::Prepare() {
2375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  params_ = bluetooth_socket::SetPaused::Params::Create(*args_);
2385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXTENSION_FUNCTION_VALIDATE(params_.get());
2395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
240010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  socket_event_dispatcher_ = GetSocketEventDispatcher(browser_context());
2415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  return socket_event_dispatcher_ != NULL;
2425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
2435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
2445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid BluetoothSocketSetPausedFunction::Work() {
2455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  BluetoothApiSocket* socket = GetSocket(params_->socket_id);
2465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (!socket) {
2475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    error_ = kSocketNotFoundError;
2485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return;
2495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
2505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
2515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (socket->paused() != params_->paused) {
2525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    socket->set_paused(params_->paused);
2535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    if (!params_->paused) {
2545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      socket_event_dispatcher_->OnSocketResume(extension_id(),
2555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                               params_->socket_id);
2565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    }
2575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
2585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
2595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  results_ = bluetooth_socket::SetPaused::Results::Create();
2605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
2615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
262cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)BluetoothSocketListenFunction::BluetoothSocketListenFunction() {}
263cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
264cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)BluetoothSocketListenFunction::~BluetoothSocketListenFunction() {}
265cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
266cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool BluetoothSocketListenFunction::Prepare() {
267cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
268cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!CreateParams())
269cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return false;
270cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  socket_event_dispatcher_ = GetSocketEventDispatcher(browser_context());
271cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return socket_event_dispatcher_ != NULL;
272cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
273cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
274cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void BluetoothSocketListenFunction::AsyncWorkStart() {
275cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
276cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  device::BluetoothAdapterFactory::GetAdapter(
277cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      base::Bind(&BluetoothSocketListenFunction::OnGetAdapter, this));
278cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
279cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
280cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void BluetoothSocketListenFunction::OnGetAdapter(
281cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    scoped_refptr<device::BluetoothAdapter> adapter) {
282cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
283cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  BluetoothApiSocket* socket = GetSocket(socket_id());
284cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!socket) {
285cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    error_ = kSocketNotFoundError;
286cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    AsyncWorkCompleted();
287cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return;
288cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
289cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
290cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  device::BluetoothUUID bluetooth_uuid(uuid());
291cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!bluetooth_uuid.IsValid()) {
292cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    error_ = kInvalidUuidError;
293cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    AsyncWorkCompleted();
294cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return;
295cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
296cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
297cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  BluetoothPermissionRequest param(uuid());
2985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!BluetoothManifestData::CheckRequest(extension(), param)) {
299cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    error_ = kPermissionDeniedError;
300cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    AsyncWorkCompleted();
301cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return;
302cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
303cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
304116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  scoped_ptr<std::string> name;
305116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (socket->name())
306116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    name.reset(new std::string(*socket->name()));
307116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
308cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  CreateService(
309cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      adapter,
310cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      bluetooth_uuid,
311116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      name.Pass(),
312cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      base::Bind(&BluetoothSocketListenFunction::OnCreateService, this),
313cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      base::Bind(&BluetoothSocketListenFunction::OnCreateServiceError, this));
314cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
315cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
316cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
317cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void BluetoothSocketListenFunction::OnCreateService(
318cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    scoped_refptr<device::BluetoothSocket> socket) {
319cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
320cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
321cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Fetch the socket again since this is not a reference-counted object, and
322cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // it may have gone away in the meantime (we check earlier to avoid making
323cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // a connection in the case of an obvious programming error).
324cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  BluetoothApiSocket* api_socket = GetSocket(socket_id());
325cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!api_socket) {
326cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    error_ = kSocketNotFoundError;
327cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    AsyncWorkCompleted();
328cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return;
329cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
330cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
331cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  api_socket->AdoptListeningSocket(socket,
332cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                   device::BluetoothUUID(uuid()));
333cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  socket_event_dispatcher_->OnSocketListen(extension_id(), socket_id());
334cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
335cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  CreateResults();
336cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  AsyncWorkCompleted();
337cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
338cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
339cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void BluetoothSocketListenFunction::OnCreateServiceError(
340cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const std::string& message) {
341cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
342cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  error_ = message;
343cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  AsyncWorkCompleted();
344cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
345cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
346cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)BluetoothSocketListenUsingRfcommFunction::
347cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    BluetoothSocketListenUsingRfcommFunction() {}
348cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
349cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)BluetoothSocketListenUsingRfcommFunction::
350cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    ~BluetoothSocketListenUsingRfcommFunction() {}
351cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
352cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)int BluetoothSocketListenUsingRfcommFunction::socket_id() const {
353cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return params_->socket_id;
354cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
355cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
356cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)const std::string& BluetoothSocketListenUsingRfcommFunction::uuid() const {
357cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return params_->uuid;
358cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
359cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
360cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool BluetoothSocketListenUsingRfcommFunction::CreateParams() {
361cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  params_ = bluetooth_socket::ListenUsingRfcomm::Params::Create(*args_);
362cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXTENSION_FUNCTION_VALIDATE(params_.get());
363cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return true;
364cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
365cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
366cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void BluetoothSocketListenUsingRfcommFunction::CreateService(
367cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    scoped_refptr<device::BluetoothAdapter> adapter,
368cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const device::BluetoothUUID& uuid,
369116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    scoped_ptr<std::string> name,
370cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const device::BluetoothAdapter::CreateServiceCallback& callback,
371cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const device::BluetoothAdapter::CreateServiceErrorCallback&
372cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        error_callback) {
373116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  device::BluetoothAdapter::ServiceOptions service_options;
374116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  service_options.name = name.Pass();
375cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
376f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  ListenOptions* options = params_->options.get();
377f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (options) {
378f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (options->channel.get())
379116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      service_options.channel.reset(new int(*(options->channel)));
380f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
381f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
382116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  adapter->CreateRfcommService(uuid, service_options, callback, error_callback);
383cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
384cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
385cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void BluetoothSocketListenUsingRfcommFunction::CreateResults() {
386cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  results_ = bluetooth_socket::ListenUsingRfcomm::Results::Create();
387cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
388cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
389cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)BluetoothSocketListenUsingL2capFunction::
390cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    BluetoothSocketListenUsingL2capFunction() {}
391cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
392cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)BluetoothSocketListenUsingL2capFunction::
393cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    ~BluetoothSocketListenUsingL2capFunction() {}
394cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
395cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)int BluetoothSocketListenUsingL2capFunction::socket_id() const {
396cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return params_->socket_id;
397cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
398cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
399cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)const std::string& BluetoothSocketListenUsingL2capFunction::uuid() const {
400cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return params_->uuid;
401cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
402cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
403cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool BluetoothSocketListenUsingL2capFunction::CreateParams() {
404cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  params_ = bluetooth_socket::ListenUsingL2cap::Params::Create(*args_);
405cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXTENSION_FUNCTION_VALIDATE(params_.get());
406cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return true;
4075c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
4085c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
409cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void BluetoothSocketListenUsingL2capFunction::CreateService(
410cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    scoped_refptr<device::BluetoothAdapter> adapter,
411cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const device::BluetoothUUID& uuid,
412116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    scoped_ptr<std::string> name,
413cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const device::BluetoothAdapter::CreateServiceCallback& callback,
414cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const device::BluetoothAdapter::CreateServiceErrorCallback&
415cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        error_callback) {
416116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  device::BluetoothAdapter::ServiceOptions service_options;
417116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  service_options.name = name.Pass();
418f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
419f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  ListenOptions* options = params_->options.get();
420f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (options) {
421116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (options->psm) {
422116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      int psm = *options->psm;
423116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      if (!IsValidPsm(psm)) {
424116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        error_callback.Run(kInvalidPsmError);
425116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        return;
426116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      }
427116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
428116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      service_options.psm.reset(new int(psm));
429116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    }
430f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
431cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
432116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  adapter->CreateL2capService(uuid, service_options, callback, error_callback);
4335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
4345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
435cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void BluetoothSocketListenUsingL2capFunction::CreateResults() {
436cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  results_ = bluetooth_socket::ListenUsingL2cap::Results::Create();
4375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
4385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
43903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)BluetoothSocketAbstractConnectFunction::
44003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    BluetoothSocketAbstractConnectFunction() {}
441010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
44203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)BluetoothSocketAbstractConnectFunction::
44303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    ~BluetoothSocketAbstractConnectFunction() {}
444010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
44503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)bool BluetoothSocketAbstractConnectFunction::Prepare() {
446010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
447010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  params_ = bluetooth_socket::Connect::Params::Create(*args_);
448010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  EXTENSION_FUNCTION_VALIDATE(params_.get());
449010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
450010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  socket_event_dispatcher_ = GetSocketEventDispatcher(browser_context());
451010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  return socket_event_dispatcher_ != NULL;
452010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
453010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
45403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void BluetoothSocketAbstractConnectFunction::AsyncWorkStart() {
455010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
456010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  device::BluetoothAdapterFactory::GetAdapter(
45703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      base::Bind(&BluetoothSocketAbstractConnectFunction::OnGetAdapter, this));
458010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
459010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
46003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void BluetoothSocketAbstractConnectFunction::OnGetAdapter(
461010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    scoped_refptr<device::BluetoothAdapter> adapter) {
462010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
463010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  BluetoothApiSocket* socket = GetSocket(params_->socket_id);
464010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!socket) {
465010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    error_ = kSocketNotFoundError;
466010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    AsyncWorkCompleted();
467010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return;
468010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
469010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
470010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  device::BluetoothDevice* device = adapter->GetDevice(params_->address);
471010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!device) {
472010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    error_ = kDeviceNotFoundError;
473010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    AsyncWorkCompleted();
474010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return;
475010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
476010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
477010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  device::BluetoothUUID uuid(params_->uuid);
478010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!uuid.IsValid()) {
479010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    error_ = kInvalidUuidError;
480010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    AsyncWorkCompleted();
481010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return;
482010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
483010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
484010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  BluetoothPermissionRequest param(params_->uuid);
4855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!BluetoothManifestData::CheckRequest(extension(), param)) {
486010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    error_ = kPermissionDeniedError;
487010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    AsyncWorkCompleted();
488010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return;
489010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
490010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
49103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  ConnectToService(device, uuid);
492010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
493010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
49403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void BluetoothSocketAbstractConnectFunction::OnConnect(
495010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    scoped_refptr<device::BluetoothSocket> socket) {
496010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
497010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
498010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // Fetch the socket again since this is not a reference-counted object, and
499010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // it may have gone away in the meantime (we check earlier to avoid making
500010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // a connection in the case of an obvious programming error).
501010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  BluetoothApiSocket* api_socket = GetSocket(params_->socket_id);
502010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!api_socket) {
503010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    error_ = kSocketNotFoundError;
504010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    AsyncWorkCompleted();
505010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return;
506010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
507010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
508010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  api_socket->AdoptConnectedSocket(socket,
509010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                   params_->address,
510010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                   device::BluetoothUUID(params_->uuid));
511010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  socket_event_dispatcher_->OnSocketConnect(extension_id(),
512010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                            params_->socket_id);
513010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
514010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  results_ = bluetooth_socket::Connect::Results::Create();
515010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  AsyncWorkCompleted();
516010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
517010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
51803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void BluetoothSocketAbstractConnectFunction::OnConnectError(
519010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const std::string& message) {
520010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
521010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  error_ = message;
522010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  AsyncWorkCompleted();
5235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
5245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
52503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)BluetoothSocketConnectFunction::BluetoothSocketConnectFunction() {}
52603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
52703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)BluetoothSocketConnectFunction::~BluetoothSocketConnectFunction() {}
52803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
52903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void BluetoothSocketConnectFunction::ConnectToService(
53003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    device::BluetoothDevice* device,
53103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    const device::BluetoothUUID& uuid) {
53203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  device->ConnectToService(
53303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      uuid,
53403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      base::Bind(&BluetoothSocketConnectFunction::OnConnect, this),
53503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      base::Bind(&BluetoothSocketConnectFunction::OnConnectError, this));
53603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
53703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
5385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuBluetoothSocketDisconnectFunction::BluetoothSocketDisconnectFunction() {}
5395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
5405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuBluetoothSocketDisconnectFunction::~BluetoothSocketDisconnectFunction() {}
5415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
5425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liubool BluetoothSocketDisconnectFunction::Prepare() {
5435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
5445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  params_ = bluetooth_socket::Disconnect::Params::Create(*args_);
5455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXTENSION_FUNCTION_VALIDATE(params_.get());
5465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  return true;
5475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
5485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
5495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid BluetoothSocketDisconnectFunction::AsyncWorkStart() {
5505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
5515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  BluetoothApiSocket* socket = GetSocket(params_->socket_id);
5525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (!socket) {
5535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    error_ = kSocketNotFoundError;
554010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    AsyncWorkCompleted();
5555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return;
5565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
5575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
5585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  socket->Disconnect(base::Bind(&BluetoothSocketDisconnectFunction::OnSuccess,
5595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                this));
5605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
5615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
5625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid BluetoothSocketDisconnectFunction::OnSuccess() {
5635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
5645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  results_ = bluetooth_socket::Disconnect::Results::Create();
5655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  AsyncWorkCompleted();
5665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
5675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
5685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuBluetoothSocketCloseFunction::BluetoothSocketCloseFunction() {}
5695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
5705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuBluetoothSocketCloseFunction::~BluetoothSocketCloseFunction() {}
5715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
5725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liubool BluetoothSocketCloseFunction::Prepare() {
5735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  params_ = bluetooth_socket::Close::Params::Create(*args_);
5745c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXTENSION_FUNCTION_VALIDATE(params_.get());
5755c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  return true;
5765c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
5775c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
5785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid BluetoothSocketCloseFunction::Work() {
5795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  BluetoothApiSocket* socket = GetSocket(params_->socket_id);
5805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (!socket) {
5815c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    error_ = kSocketNotFoundError;
5825c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return;
5835c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
5845c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
5855c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  RemoveSocket(params_->socket_id);
5865c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  results_ = bluetooth_socket::Close::Results::Create();
5875c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
5885c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
5895c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuBluetoothSocketSendFunction::BluetoothSocketSendFunction()
5905c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    : io_buffer_size_(0) {}
5915c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
5925c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuBluetoothSocketSendFunction::~BluetoothSocketSendFunction() {}
5935c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
5945c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liubool BluetoothSocketSendFunction::Prepare() {
5955c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
5965c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  params_ = bluetooth_socket::Send::Params::Create(*args_);
5975c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXTENSION_FUNCTION_VALIDATE(params_.get());
5985c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
5995c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  io_buffer_size_ = params_->data.size();
6005c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  io_buffer_ = new net::WrappedIOBuffer(params_->data.data());
6015c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  return true;
6025c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
6035c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
6045c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid BluetoothSocketSendFunction::AsyncWorkStart() {
6055c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
6065c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  BluetoothApiSocket* socket = GetSocket(params_->socket_id);
6075c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (!socket) {
6085c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    error_ = kSocketNotFoundError;
6095c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return;
6105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
6115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
6125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  socket->Send(io_buffer_,
6135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu               io_buffer_size_,
6145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu               base::Bind(&BluetoothSocketSendFunction::OnSuccess, this),
6155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu               base::Bind(&BluetoothSocketSendFunction::OnError, this));
6165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
6175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
6185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid BluetoothSocketSendFunction::OnSuccess(int bytes_sent) {
6195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
6205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  results_ = bluetooth_socket::Send::Results::Create(bytes_sent);
6215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  AsyncWorkCompleted();
6225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
6235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
6245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid BluetoothSocketSendFunction::OnError(
6255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    BluetoothApiSocket::ErrorReason reason,
6265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    const std::string& message) {
6275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
6285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  error_ = message;
6295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  AsyncWorkCompleted();
6305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
6315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
6325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuBluetoothSocketGetInfoFunction::BluetoothSocketGetInfoFunction() {}
6335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
6345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuBluetoothSocketGetInfoFunction::~BluetoothSocketGetInfoFunction() {}
6355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
6365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liubool BluetoothSocketGetInfoFunction::Prepare() {
6375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  params_ = bluetooth_socket::GetInfo::Params::Create(*args_);
6385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXTENSION_FUNCTION_VALIDATE(params_.get());
6395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  return true;
6405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
6415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
6425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid BluetoothSocketGetInfoFunction::Work() {
6435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  BluetoothApiSocket* socket = GetSocket(params_->socket_id);
6445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (!socket) {
6455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    error_ = kSocketNotFoundError;
6465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return;
6475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
6485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
6495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  linked_ptr<bluetooth_socket::SocketInfo> socket_info =
6505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      CreateSocketInfo(params_->socket_id, socket);
6515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  results_ = bluetooth_socket::GetInfo::Results::Create(*socket_info);
6525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
6535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
6545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuBluetoothSocketGetSocketsFunction::BluetoothSocketGetSocketsFunction() {}
6555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
6565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuBluetoothSocketGetSocketsFunction::~BluetoothSocketGetSocketsFunction() {}
6575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
6585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liubool BluetoothSocketGetSocketsFunction::Prepare() { return true; }
6595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
6605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid BluetoothSocketGetSocketsFunction::Work() {
6615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  std::vector<linked_ptr<bluetooth_socket::SocketInfo> > socket_infos;
6625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  base::hash_set<int>* resource_ids = GetSocketIds();
6635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (resource_ids != NULL) {
6645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    for (base::hash_set<int>::iterator it = resource_ids->begin();
6655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu         it != resource_ids->end();
6665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu         ++it) {
6675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      int socket_id = *it;
6685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      BluetoothApiSocket* socket = GetSocket(socket_id);
6695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      if (socket) {
6705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        socket_infos.push_back(CreateSocketInfo(socket_id, socket));
6715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      }
6725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    }
6735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
6745c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  results_ = bluetooth_socket::GetSockets::Results::Create(socket_infos);
6755c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
6765c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
6771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}  // namespace core_api
6785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}  // namespace extensions
679