Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(62)

Side by Side Diff: chrome/browser/extensions/api/bluetooth_socket/bluetooth_socket_event_dispatcher.cc

Issue 278663002: Implement chrome.bluetoothSocket.listenUsing*() (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix BluetoothAdapterMac include typo Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/extensions/api/bluetooth_socket/bluetooth_socket_event_ dispatcher.h" 5 #include "chrome/browser/extensions/api/bluetooth_socket/bluetooth_socket_event_ dispatcher.h"
6 6
7 #include "chrome/browser/browser_process.h" 7 #include "chrome/browser/browser_process.h"
8 #include "chrome/browser/extensions/api/bluetooth/bluetooth_api_socket.h" 8 #include "chrome/browser/extensions/api/bluetooth/bluetooth_api_socket.h"
9 #include "chrome/common/extensions/api/bluetooth_socket.h" 9 #include "chrome/common/extensions/api/bluetooth_socket.h"
10 #include "device/bluetooth/bluetooth_device.h"
11 #include "device/bluetooth/bluetooth_socket.h"
10 #include "extensions/browser/event_router.h" 12 #include "extensions/browser/event_router.h"
11 #include "net/base/io_buffer.h" 13 #include "net/base/io_buffer.h"
12 #include "net/base/net_errors.h" 14 #include "net/base/net_errors.h"
13 15
14 namespace { 16 namespace {
15 17
16 namespace bluetooth_socket = extensions::api::bluetooth_socket; 18 namespace bluetooth_socket = extensions::api::bluetooth_socket;
17 using extensions::BluetoothApiSocket; 19 using extensions::BluetoothApiSocket;
18 20
19 int kDefaultBufferSize = 4096; 21 int kDefaultBufferSize = 4096;
20 22
21 bluetooth_socket::ReceiveError MapErrorReason( 23 bluetooth_socket::ReceiveError MapReceiveErrorReason(
22 BluetoothApiSocket::ErrorReason value) { 24 BluetoothApiSocket::ErrorReason value) {
23 switch (value) { 25 switch (value) {
24 case BluetoothApiSocket::kDisconnected: 26 case BluetoothApiSocket::kDisconnected:
25 return bluetooth_socket::RECEIVE_ERROR_DISCONNECTED; 27 return bluetooth_socket::RECEIVE_ERROR_DISCONNECTED;
26 case BluetoothApiSocket::kNotConnected: 28 case BluetoothApiSocket::kNotConnected:
27 // kNotConnected is impossible since a socket has to be connected to be 29 // kNotConnected is impossible since a socket has to be connected to be
28 // able to call Receive() on it. 30 // able to call Receive() on it.
29 // fallthrough 31 // fallthrough
30 case BluetoothApiSocket::kIOPending: 32 case BluetoothApiSocket::kIOPending:
31 // kIOPending is not relevant to apps, as BluetoothSocketEventDispatcher 33 // kIOPending is not relevant to apps, as BluetoothSocketEventDispatcher
32 // handles this specific error. 34 // handles this specific error.
33 // fallthrough 35 // fallthrough
34 default: 36 default:
35 return bluetooth_socket::RECEIVE_ERROR_SYSTEM_ERROR; 37 return bluetooth_socket::RECEIVE_ERROR_SYSTEM_ERROR;
36 } 38 }
37 } 39 }
38 40
41 bluetooth_socket::AcceptError MapAcceptErrorReason(
42 BluetoothApiSocket::ErrorReason value) {
43 // TODO(keybuk): All values are system error, we may want to seperate these
44 // out to more discrete reasons.
45 switch (value) {
46 case BluetoothApiSocket::kNotListening:
47 // kNotListening is impossible since a socket has to be listening to be
48 // able to call Accept() on it.
49 // fallthrough
50 default:
51 return bluetooth_socket::ACCEPT_ERROR_SYSTEM_ERROR;
52 }
53 }
54
39 } // namespace 55 } // namespace
40 56
41 namespace extensions { 57 namespace extensions {
42 namespace api { 58 namespace api {
43 59
44 using content::BrowserThread; 60 using content::BrowserThread;
45 61
46 static base::LazyInstance< 62 static base::LazyInstance<
47 BrowserContextKeyedAPIFactory<BluetoothSocketEventDispatcher> > g_factory = 63 BrowserContextKeyedAPIFactory<BluetoothSocketEventDispatcher> > g_factory =
48 LAZY_INSTANCE_INITIALIZER; 64 LAZY_INSTANCE_INITIALIZER;
(...skipping 22 matching lines...) Expand all
71 DCHECK(manager) 87 DCHECK(manager)
72 << "There is no socket manager. " 88 << "There is no socket manager. "
73 "If this assertion is failing during a test, then it is likely that " 89 "If this assertion is failing during a test, then it is likely that "
74 "TestExtensionSystem is failing to provide an instance of " 90 "TestExtensionSystem is failing to provide an instance of "
75 "ApiResourceManager<BluetoothApiSocket>."; 91 "ApiResourceManager<BluetoothApiSocket>.";
76 sockets_ = manager->data_; 92 sockets_ = manager->data_;
77 } 93 }
78 94
79 BluetoothSocketEventDispatcher::~BluetoothSocketEventDispatcher() {} 95 BluetoothSocketEventDispatcher::~BluetoothSocketEventDispatcher() {}
80 96
81 BluetoothSocketEventDispatcher::ReceiveParams::ReceiveParams() {} 97 BluetoothSocketEventDispatcher::SocketParams::SocketParams() {}
82 98
83 BluetoothSocketEventDispatcher::ReceiveParams::~ReceiveParams() {} 99 BluetoothSocketEventDispatcher::SocketParams::~SocketParams() {}
84 100
85 void BluetoothSocketEventDispatcher::OnSocketConnect( 101 void BluetoothSocketEventDispatcher::OnSocketConnect(
86 const std::string& extension_id, 102 const std::string& extension_id,
87 int socket_id) { 103 int socket_id) {
88 DCHECK(BrowserThread::CurrentlyOn(thread_id_)); 104 DCHECK(BrowserThread::CurrentlyOn(thread_id_));
89 105
90 StartSocketReceive(extension_id, socket_id); 106 SocketParams params;
91 }
92
93 void BluetoothSocketEventDispatcher::OnSocketResume(
94 const std::string& extension_id,
95 int socket_id) {
96 DCHECK(BrowserThread::CurrentlyOn(thread_id_));
97
98 StartSocketReceive(extension_id, socket_id);
99 }
100
101 void BluetoothSocketEventDispatcher::StartSocketReceive(
102 const std::string& extension_id,
103 int socket_id) {
104 DCHECK(BrowserThread::CurrentlyOn(thread_id_));
105
106 ReceiveParams params;
107 params.thread_id = thread_id_; 107 params.thread_id = thread_id_;
108 params.browser_context_id = browser_context_; 108 params.browser_context_id = browser_context_;
109 params.extension_id = extension_id; 109 params.extension_id = extension_id;
110 params.sockets = sockets_; 110 params.sockets = sockets_;
111 params.socket_id = socket_id; 111 params.socket_id = socket_id;
112 112
113 StartReceive(params); 113 StartReceive(params);
114 } 114 }
115 115
116 void BluetoothSocketEventDispatcher::OnSocketListen(
117 const std::string& extension_id,
118 int socket_id) {
119 DCHECK(BrowserThread::CurrentlyOn(thread_id_));
120
121 SocketParams params;
122 params.thread_id = thread_id_;
123 params.browser_context_id = browser_context_;
124 params.extension_id = extension_id;
125 params.sockets = sockets_;
126 params.socket_id = socket_id;
127
128 StartAccept(params);
129 }
130
131 void BluetoothSocketEventDispatcher::OnSocketResume(
132 const std::string& extension_id,
133 int socket_id) {
134 DCHECK(BrowserThread::CurrentlyOn(thread_id_));
135
136 SocketParams params;
137 params.thread_id = thread_id_;
138 params.browser_context_id = browser_context_;
139 params.extension_id = extension_id;
140 params.sockets = sockets_;
141 params.socket_id = socket_id;
142
143 BluetoothApiSocket* socket =
144 params.sockets->Get(params.extension_id, params.socket_id);
145 if (!socket) {
146 // This can happen if the socket is closed while our callback is active.
147 return;
148 }
149
150 if (socket->IsConnected()) {
151 StartReceive(params);
152 } else {
153 StartAccept(params);
154 }
155 }
156
116 // static 157 // static
117 void BluetoothSocketEventDispatcher::StartReceive(const ReceiveParams& params) { 158 void BluetoothSocketEventDispatcher::StartReceive(const SocketParams& params) {
118 DCHECK(BrowserThread::CurrentlyOn(params.thread_id)); 159 DCHECK(BrowserThread::CurrentlyOn(params.thread_id));
119 160
120 BluetoothApiSocket* socket = 161 BluetoothApiSocket* socket =
121 params.sockets->Get(params.extension_id, params.socket_id); 162 params.sockets->Get(params.extension_id, params.socket_id);
122 if (!socket) { 163 if (!socket) {
123 // This can happen if the socket is closed while our callback is active. 164 // This can happen if the socket is closed while our callback is active.
124 return; 165 return;
125 } 166 }
126 DCHECK(params.extension_id == socket->owner_extension_id()) 167 DCHECK(params.extension_id == socket->owner_extension_id())
127 << "Socket has wrong owner."; 168 << "Socket has wrong owner.";
128 169
129 // Don't start another read if the socket has been paused. 170 // Don't start another read if the socket has been paused.
130 if (socket->paused()) 171 if (socket->paused())
131 return; 172 return;
132 173
133 int buffer_size = socket->buffer_size(); 174 int buffer_size = socket->buffer_size();
134 if (buffer_size <= 0) 175 if (buffer_size <= 0)
135 buffer_size = kDefaultBufferSize; 176 buffer_size = kDefaultBufferSize;
136 socket->Receive( 177 socket->Receive(
137 buffer_size, 178 buffer_size,
138 base::Bind( 179 base::Bind(
139 &BluetoothSocketEventDispatcher::ReceiveCallback, params), 180 &BluetoothSocketEventDispatcher::ReceiveCallback, params),
140 base::Bind( 181 base::Bind(
141 &BluetoothSocketEventDispatcher::ReceiveErrorCallback, params)); 182 &BluetoothSocketEventDispatcher::ReceiveErrorCallback, params));
142 } 183 }
143 184
144 // static 185 // static
145 void BluetoothSocketEventDispatcher::ReceiveCallback( 186 void BluetoothSocketEventDispatcher::ReceiveCallback(
146 const ReceiveParams& params, 187 const SocketParams& params,
147 int bytes_read, 188 int bytes_read,
148 scoped_refptr<net::IOBuffer> io_buffer) { 189 scoped_refptr<net::IOBuffer> io_buffer) {
149 DCHECK(BrowserThread::CurrentlyOn(params.thread_id)); 190 DCHECK(BrowserThread::CurrentlyOn(params.thread_id));
150 191
151 // Dispatch "onReceive" event. 192 // Dispatch "onReceive" event.
152 bluetooth_socket::ReceiveInfo receive_info; 193 bluetooth_socket::ReceiveInfo receive_info;
153 receive_info.socket_id = params.socket_id; 194 receive_info.socket_id = params.socket_id;
154 receive_info.data = std::string(io_buffer->data(), bytes_read); 195 receive_info.data = std::string(io_buffer->data(), bytes_read);
155 scoped_ptr<base::ListValue> args = 196 scoped_ptr<base::ListValue> args =
156 bluetooth_socket::OnReceive::Create(receive_info); 197 bluetooth_socket::OnReceive::Create(receive_info);
157 scoped_ptr<Event> event( 198 scoped_ptr<Event> event(
158 new Event(bluetooth_socket::OnReceive::kEventName, args.Pass())); 199 new Event(bluetooth_socket::OnReceive::kEventName, args.Pass()));
159 PostEvent(params, event.Pass()); 200 PostEvent(params, event.Pass());
160 201
161 // Post a task to delay the read until the socket is available, as 202 // Post a task to delay the read until the socket is available, as
162 // calling StartReceive at this point would error with ERR_IO_PENDING. 203 // calling StartReceive at this point would error with ERR_IO_PENDING.
163 BrowserThread::PostTask( 204 BrowserThread::PostTask(
164 params.thread_id, 205 params.thread_id,
165 FROM_HERE, 206 FROM_HERE,
166 base::Bind(&BluetoothSocketEventDispatcher::StartReceive, params)); 207 base::Bind(&BluetoothSocketEventDispatcher::StartReceive, params));
167 } 208 }
168 209
169 // static 210 // static
170 void BluetoothSocketEventDispatcher::ReceiveErrorCallback( 211 void BluetoothSocketEventDispatcher::ReceiveErrorCallback(
171 const ReceiveParams& params, 212 const SocketParams& params,
172 BluetoothApiSocket::ErrorReason error_reason, 213 BluetoothApiSocket::ErrorReason error_reason,
173 const std::string& error) { 214 const std::string& error) {
174 DCHECK(BrowserThread::CurrentlyOn(params.thread_id)); 215 DCHECK(BrowserThread::CurrentlyOn(params.thread_id));
175 216
176 if (error_reason == BluetoothApiSocket::kIOPending) { 217 if (error_reason == BluetoothApiSocket::kIOPending) {
177 // This happens when resuming a socket which already had an active "read" 218 // This happens when resuming a socket which already had an active "read"
178 // callback. We can safely ignore this error, as the application should not 219 // callback. We can safely ignore this error, as the application should not
179 // care. 220 // care.
180 return; 221 return;
181 } 222 }
182 223
183 // Dispatch "onReceiveError" event but don't start another read to avoid 224 // Dispatch "onReceiveError" event but don't start another read to avoid
184 // potential infinite reads if we have a persistent network error. 225 // potential infinite reads if we have a persistent network error.
185 bluetooth_socket::ReceiveErrorInfo receive_error_info; 226 bluetooth_socket::ReceiveErrorInfo receive_error_info;
186 receive_error_info.socket_id = params.socket_id; 227 receive_error_info.socket_id = params.socket_id;
187 receive_error_info.error_message = error; 228 receive_error_info.error_message = error;
188 receive_error_info.error = MapErrorReason(error_reason); 229 receive_error_info.error = MapReceiveErrorReason(error_reason);
189 scoped_ptr<base::ListValue> args = 230 scoped_ptr<base::ListValue> args =
190 bluetooth_socket::OnReceiveError::Create(receive_error_info); 231 bluetooth_socket::OnReceiveError::Create(receive_error_info);
191 scoped_ptr<Event> event( 232 scoped_ptr<Event> event(
192 new Event(bluetooth_socket::OnReceiveError::kEventName, args.Pass())); 233 new Event(bluetooth_socket::OnReceiveError::kEventName, args.Pass()));
193 PostEvent(params, event.Pass()); 234 PostEvent(params, event.Pass());
194 235
195 // Since we got an error, the socket is now "paused" until the application 236 // Since we got an error, the socket is now "paused" until the application
196 // "resumes" it. 237 // "resumes" it.
197 BluetoothApiSocket* socket = 238 BluetoothApiSocket* socket =
198 params.sockets->Get(params.extension_id, params.socket_id); 239 params.sockets->Get(params.extension_id, params.socket_id);
199 if (socket) { 240 if (socket) {
200 socket->set_paused(true); 241 socket->set_paused(true);
201 } 242 }
202 } 243 }
203 244
204 // static 245 // static
205 void BluetoothSocketEventDispatcher::PostEvent(const ReceiveParams& params, 246 void BluetoothSocketEventDispatcher::StartAccept(const SocketParams& params) {
247 DCHECK(BrowserThread::CurrentlyOn(params.thread_id));
248
249 BluetoothApiSocket* socket =
250 params.sockets->Get(params.extension_id, params.socket_id);
251 if (!socket) {
252 // This can happen if the socket is closed while our callback is active.
253 return;
254 }
255 DCHECK(params.extension_id == socket->owner_extension_id())
256 << "Socket has wrong owner.";
257
258 // Don't start another accept if the socket has been paused.
259 if (socket->paused())
260 return;
261
262 socket->Accept(
263 base::Bind(
264 &BluetoothSocketEventDispatcher::AcceptCallback, params),
265 base::Bind(
266 &BluetoothSocketEventDispatcher::AcceptErrorCallback, params));
267 }
268
269 // static
270 void BluetoothSocketEventDispatcher::AcceptCallback(
271 const SocketParams& params,
272 const device::BluetoothDevice* device,
273 scoped_refptr<device::BluetoothSocket> socket) {
274 DCHECK(BrowserThread::CurrentlyOn(params.thread_id));
275
276 BluetoothApiSocket* server_api_socket =
277 params.sockets->Get(params.extension_id, params.socket_id);
278 DCHECK(server_api_socket);
279
280 BluetoothApiSocket* client_api_socket = new BluetoothApiSocket(
281 params.extension_id,
282 socket,
283 device->GetAddress(),
284 server_api_socket->uuid());
285 int client_socket_id = params.sockets->Add(client_api_socket);
286
287 // Dispatch "onAccept" event.
288 bluetooth_socket::AcceptInfo accept_info;
289 accept_info.socket_id = params.socket_id;
290 accept_info.client_socket_id = client_socket_id;
291 scoped_ptr<base::ListValue> args =
292 bluetooth_socket::OnAccept::Create(accept_info);
293 scoped_ptr<Event> event(
294 new Event(bluetooth_socket::OnAccept::kEventName, args.Pass()));
295 PostEvent(params, event.Pass());
296
297 // Post a task to delay the accept until the socket is available, as
298 // calling StartAccept at this point would error with ERR_IO_PENDING.
299 BrowserThread::PostTask(
300 params.thread_id,
301 FROM_HERE,
302 base::Bind(&BluetoothSocketEventDispatcher::StartAccept, params));
303 }
304
305 // static
306 void BluetoothSocketEventDispatcher::AcceptErrorCallback(
307 const SocketParams& params,
308 BluetoothApiSocket::ErrorReason error_reason,
309 const std::string& error) {
310 DCHECK(BrowserThread::CurrentlyOn(params.thread_id));
311
312 if (error_reason == BluetoothApiSocket::kIOPending) {
313 // This happens when resuming a socket which already had an active "accept"
314 // callback. We can safely ignore this error, as the application should not
315 // care.
316 return;
317 }
318
319 // Dispatch "onAcceptError" event but don't start another accept to avoid
320 // potential infinite accepts if we have a persistent network error.
321 bluetooth_socket::AcceptErrorInfo accept_error_info;
322 accept_error_info.socket_id = params.socket_id;
323 accept_error_info.error_message = error;
324 accept_error_info.error = MapAcceptErrorReason(error_reason);
325 scoped_ptr<base::ListValue> args =
326 bluetooth_socket::OnAcceptError::Create(accept_error_info);
327 scoped_ptr<Event> event(
328 new Event(bluetooth_socket::OnAcceptError::kEventName, args.Pass()));
329 PostEvent(params, event.Pass());
330
331 // Since we got an error, the socket is now "paused" until the application
332 // "resumes" it.
333 BluetoothApiSocket* socket =
334 params.sockets->Get(params.extension_id, params.socket_id);
335 if (socket) {
336 socket->set_paused(true);
337 }
338 }
339
340 // static
341 void BluetoothSocketEventDispatcher::PostEvent(const SocketParams& params,
206 scoped_ptr<Event> event) { 342 scoped_ptr<Event> event) {
207 DCHECK(BrowserThread::CurrentlyOn(params.thread_id)); 343 DCHECK(BrowserThread::CurrentlyOn(params.thread_id));
208 344
209 BrowserThread::PostTask( 345 BrowserThread::PostTask(
210 BrowserThread::UI, 346 BrowserThread::UI,
211 FROM_HERE, 347 FROM_HERE,
212 base::Bind(&DispatchEvent, 348 base::Bind(&DispatchEvent,
213 params.browser_context_id, 349 params.browser_context_id,
214 params.extension_id, 350 params.extension_id,
215 base::Passed(event.Pass()))); 351 base::Passed(event.Pass())));
(...skipping 11 matching lines...) Expand all
227 if (!extensions::ExtensionsBrowserClient::Get()->IsValidContext(context)) 363 if (!extensions::ExtensionsBrowserClient::Get()->IsValidContext(context))
228 return; 364 return;
229 365
230 EventRouter* router = EventRouter::Get(context); 366 EventRouter* router = EventRouter::Get(context);
231 if (router) 367 if (router)
232 router->DispatchEventToExtension(extension_id, event.Pass()); 368 router->DispatchEventToExtension(extension_id, event.Pass());
233 } 369 }
234 370
235 } // namespace api 371 } // namespace api
236 } // namespace extensions 372 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698