Home | History | Annotate | Download | only in bluetooth_socket
      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 "extensions/browser/api/bluetooth_socket/bluetooth_api_socket.h"
      6 
      7 #include "base/lazy_instance.h"
      8 #include "device/bluetooth/bluetooth_socket.h"
      9 #include "net/base/io_buffer.h"
     10 
     11 namespace {
     12 
     13 const char kSocketNotConnectedError[] = "Socket not connected";
     14 const char kSocketNotListeningError[] = "Socket not listening";
     15 
     16 }  // namespace
     17 
     18 namespace extensions {
     19 
     20 // static
     21 static base::LazyInstance<
     22     BrowserContextKeyedAPIFactory<ApiResourceManager<BluetoothApiSocket> > >
     23     g_server_factory = LAZY_INSTANCE_INITIALIZER;
     24 
     25 // static
     26 template <>
     27 BrowserContextKeyedAPIFactory<ApiResourceManager<BluetoothApiSocket> >*
     28 ApiResourceManager<BluetoothApiSocket>::GetFactoryInstance() {
     29   return g_server_factory.Pointer();
     30 }
     31 
     32 BluetoothApiSocket::BluetoothApiSocket(const std::string& owner_extension_id)
     33     : ApiResource(owner_extension_id),
     34       persistent_(false),
     35       buffer_size_(0),
     36       paused_(false),
     37       connected_(false) {
     38   DCHECK(content::BrowserThread::CurrentlyOn(kThreadId));
     39 }
     40 
     41 BluetoothApiSocket::BluetoothApiSocket(
     42     const std::string& owner_extension_id,
     43     scoped_refptr<device::BluetoothSocket> socket,
     44     const std::string& device_address,
     45     const device::BluetoothUUID& uuid)
     46     : ApiResource(owner_extension_id),
     47       socket_(socket),
     48       device_address_(device_address),
     49       uuid_(uuid),
     50       persistent_(false),
     51       buffer_size_(0),
     52       paused_(true),
     53       connected_(true) {
     54   DCHECK(content::BrowserThread::CurrentlyOn(kThreadId));
     55 }
     56 
     57 BluetoothApiSocket::~BluetoothApiSocket() {
     58   DCHECK(content::BrowserThread::CurrentlyOn(kThreadId));
     59   if (socket_.get())
     60     socket_->Close();
     61 }
     62 
     63 void BluetoothApiSocket::AdoptConnectedSocket(
     64     scoped_refptr<device::BluetoothSocket> socket,
     65     const std::string& device_address,
     66     const device::BluetoothUUID& uuid) {
     67   DCHECK(content::BrowserThread::CurrentlyOn(kThreadId));
     68 
     69   if (socket_.get())
     70     socket_->Close();
     71 
     72   socket_ = socket;
     73   device_address_ = device_address;
     74   uuid_ = uuid;
     75   connected_ = true;
     76 }
     77 
     78 void BluetoothApiSocket::AdoptListeningSocket(
     79     scoped_refptr<device::BluetoothSocket> socket,
     80     const device::BluetoothUUID& uuid) {
     81   DCHECK(content::BrowserThread::CurrentlyOn(kThreadId));
     82 
     83   if (socket_.get())
     84     socket_->Close();
     85 
     86   socket_ = socket;
     87   device_address_ = "";
     88   uuid_ = uuid;
     89   connected_ = false;
     90 }
     91 
     92 void BluetoothApiSocket::Disconnect(const base::Closure& callback) {
     93   DCHECK(content::BrowserThread::CurrentlyOn(kThreadId));
     94 
     95   if (!socket_.get()) {
     96     callback.Run();
     97     return;
     98   }
     99 
    100   connected_ = false;
    101   socket_->Disconnect(callback);
    102 }
    103 
    104 bool BluetoothApiSocket::IsPersistent() const {
    105   DCHECK(content::BrowserThread::CurrentlyOn(kThreadId));
    106   return persistent_;
    107 }
    108 
    109 void BluetoothApiSocket::Receive(
    110     int count,
    111     const ReceiveCompletionCallback& success_callback,
    112     const ErrorCompletionCallback& error_callback) {
    113   DCHECK(content::BrowserThread::CurrentlyOn(kThreadId));
    114 
    115   if (!socket_.get() || !IsConnected()) {
    116     error_callback.Run(BluetoothApiSocket::kNotConnected,
    117                        kSocketNotConnectedError);
    118     return;
    119   }
    120 
    121   socket_->Receive(count,
    122                    success_callback,
    123                    base::Bind(&OnSocketReceiveError, error_callback));
    124 }
    125 
    126 // static
    127 void BluetoothApiSocket::OnSocketReceiveError(
    128     const ErrorCompletionCallback& error_callback,
    129     device::BluetoothSocket::ErrorReason reason,
    130     const std::string& message) {
    131   DCHECK(content::BrowserThread::CurrentlyOn(kThreadId));
    132   BluetoothApiSocket::ErrorReason error_reason;
    133   switch (reason) {
    134     case device::BluetoothSocket::kIOPending:
    135       error_reason = BluetoothApiSocket::kIOPending;
    136       break;
    137     case device::BluetoothSocket::kDisconnected:
    138       error_reason = BluetoothApiSocket::kDisconnected;
    139       break;
    140     case device::BluetoothSocket::kSystemError:
    141       error_reason = BluetoothApiSocket::kSystemError;
    142       break;
    143   }
    144   error_callback.Run(error_reason, message);
    145 }
    146 
    147 void BluetoothApiSocket::Send(scoped_refptr<net::IOBuffer> buffer,
    148                               int buffer_size,
    149                               const SendCompletionCallback& success_callback,
    150                               const ErrorCompletionCallback& error_callback) {
    151   DCHECK(content::BrowserThread::CurrentlyOn(kThreadId));
    152 
    153   if (!socket_.get() || !IsConnected()) {
    154     error_callback.Run(BluetoothApiSocket::kNotConnected,
    155                        kSocketNotConnectedError);
    156     return;
    157   }
    158 
    159   socket_->Send(buffer,
    160                 buffer_size,
    161                 success_callback,
    162                 base::Bind(&OnSocketSendError, error_callback));
    163 }
    164 
    165 // static
    166 void BluetoothApiSocket::OnSocketSendError(
    167     const ErrorCompletionCallback& error_callback,
    168     const std::string& message) {
    169   DCHECK(content::BrowserThread::CurrentlyOn(kThreadId));
    170   error_callback.Run(BluetoothApiSocket::kSystemError, message);
    171 }
    172 
    173 void BluetoothApiSocket::Accept(
    174     const AcceptCompletionCallback& success_callback,
    175     const ErrorCompletionCallback& error_callback) {
    176   DCHECK(content::BrowserThread::CurrentlyOn(kThreadId));
    177 
    178   if (!socket_.get() || IsConnected()) {
    179     error_callback.Run(BluetoothApiSocket::kNotListening,
    180                        kSocketNotListeningError);
    181     return;
    182   }
    183 
    184   socket_->Accept(success_callback,
    185                   base::Bind(&OnSocketAcceptError, error_callback));
    186 }
    187 
    188 // static
    189 void BluetoothApiSocket::OnSocketAcceptError(
    190     const ErrorCompletionCallback& error_callback,
    191     const std::string& message) {
    192   DCHECK(content::BrowserThread::CurrentlyOn(kThreadId));
    193   error_callback.Run(BluetoothApiSocket::kSystemError, message);
    194 }
    195 
    196 }  // namespace extensions
    197