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