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

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: 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 } else if (socket->IsConnected()) {
armansito 2014/05/08 22:00:16 nit: No need for else since the previous block ret
149 StartReceive(params);
150 } else {
151 StartAccept(params);
152 }
153 }
154
116 // static 155 // static
117 void BluetoothSocketEventDispatcher::StartReceive(const ReceiveParams& params) { 156 void BluetoothSocketEventDispatcher::StartReceive(const SocketParams& params) {
118 DCHECK(BrowserThread::CurrentlyOn(params.thread_id)); 157 DCHECK(BrowserThread::CurrentlyOn(params.thread_id));
119 158
120 BluetoothApiSocket* socket = 159 BluetoothApiSocket* socket =
121 params.sockets->Get(params.extension_id, params.socket_id); 160 params.sockets->Get(params.extension_id, params.socket_id);
122 if (!socket) { 161 if (!socket) {
123 // This can happen if the socket is closed while our callback is active. 162 // This can happen if the socket is closed while our callback is active.
124 return; 163 return;
125 } 164 }
126 DCHECK(params.extension_id == socket->owner_extension_id()) 165 DCHECK(params.extension_id == socket->owner_extension_id())
127 << "Socket has wrong owner."; 166 << "Socket has wrong owner.";
128 167
129 // Don't start another read if the socket has been paused. 168 // Don't start another read if the socket has been paused.
130 if (socket->paused()) 169 if (socket->paused())
131 return; 170 return;
132 171
133 int buffer_size = socket->buffer_size(); 172 int buffer_size = socket->buffer_size();
134 if (buffer_size <= 0) 173 if (buffer_size <= 0)
135 buffer_size = kDefaultBufferSize; 174 buffer_size = kDefaultBufferSize;
136 socket->Receive( 175 socket->Receive(
137 buffer_size, 176 buffer_size,
138 base::Bind( 177 base::Bind(
139 &BluetoothSocketEventDispatcher::ReceiveCallback, params), 178 &BluetoothSocketEventDispatcher::ReceiveCallback, params),
140 base::Bind( 179 base::Bind(
141 &BluetoothSocketEventDispatcher::ReceiveErrorCallback, params)); 180 &BluetoothSocketEventDispatcher::ReceiveErrorCallback, params));
142 } 181 }
143 182
144 // static 183 // static
145 void BluetoothSocketEventDispatcher::ReceiveCallback( 184 void BluetoothSocketEventDispatcher::ReceiveCallback(
146 const ReceiveParams& params, 185 const SocketParams& params,
147 int bytes_read, 186 int bytes_read,
148 scoped_refptr<net::IOBuffer> io_buffer) { 187 scoped_refptr<net::IOBuffer> io_buffer) {
149 DCHECK(BrowserThread::CurrentlyOn(params.thread_id)); 188 DCHECK(BrowserThread::CurrentlyOn(params.thread_id));
150 189
151 // Dispatch "onReceive" event. 190 // Dispatch "onReceive" event.
152 bluetooth_socket::ReceiveInfo receive_info; 191 bluetooth_socket::ReceiveInfo receive_info;
153 receive_info.socket_id = params.socket_id; 192 receive_info.socket_id = params.socket_id;
154 receive_info.data = std::string(io_buffer->data(), bytes_read); 193 receive_info.data = std::string(io_buffer->data(), bytes_read);
155 scoped_ptr<base::ListValue> args = 194 scoped_ptr<base::ListValue> args =
156 bluetooth_socket::OnReceive::Create(receive_info); 195 bluetooth_socket::OnReceive::Create(receive_info);
157 scoped_ptr<Event> event( 196 scoped_ptr<Event> event(
158 new Event(bluetooth_socket::OnReceive::kEventName, args.Pass())); 197 new Event(bluetooth_socket::OnReceive::kEventName, args.Pass()));
159 PostEvent(params, event.Pass()); 198 PostEvent(params, event.Pass());
160 199
161 // Post a task to delay the read until the socket is available, as 200 // 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. 201 // calling StartReceive at this point would error with ERR_IO_PENDING.
163 BrowserThread::PostTask( 202 BrowserThread::PostTask(
164 params.thread_id, 203 params.thread_id,
165 FROM_HERE, 204 FROM_HERE,
166 base::Bind(&BluetoothSocketEventDispatcher::StartReceive, params)); 205 base::Bind(&BluetoothSocketEventDispatcher::StartReceive, params));
167 } 206 }
168 207
169 // static 208 // static
170 void BluetoothSocketEventDispatcher::ReceiveErrorCallback( 209 void BluetoothSocketEventDispatcher::ReceiveErrorCallback(
171 const ReceiveParams& params, 210 const SocketParams& params,
172 BluetoothApiSocket::ErrorReason error_reason, 211 BluetoothApiSocket::ErrorReason error_reason,
173 const std::string& error) { 212 const std::string& error) {
174 DCHECK(BrowserThread::CurrentlyOn(params.thread_id)); 213 DCHECK(BrowserThread::CurrentlyOn(params.thread_id));
175 214
176 if (error_reason == BluetoothApiSocket::kIOPending) { 215 if (error_reason == BluetoothApiSocket::kIOPending) {
177 // This happens when resuming a socket which already had an active "read" 216 // 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 217 // callback. We can safely ignore this error, as the application should not
179 // care. 218 // care.
180 return; 219 return;
181 } 220 }
182 221
183 // Dispatch "onReceiveError" event but don't start another read to avoid 222 // Dispatch "onReceiveError" event but don't start another read to avoid
184 // potential infinite reads if we have a persistent network error. 223 // potential infinite reads if we have a persistent network error.
185 bluetooth_socket::ReceiveErrorInfo receive_error_info; 224 bluetooth_socket::ReceiveErrorInfo receive_error_info;
186 receive_error_info.socket_id = params.socket_id; 225 receive_error_info.socket_id = params.socket_id;
187 receive_error_info.error_message = error; 226 receive_error_info.error_message = error;
188 receive_error_info.error = MapErrorReason(error_reason); 227 receive_error_info.error = MapReceiveErrorReason(error_reason);
189 scoped_ptr<base::ListValue> args = 228 scoped_ptr<base::ListValue> args =
190 bluetooth_socket::OnReceiveError::Create(receive_error_info); 229 bluetooth_socket::OnReceiveError::Create(receive_error_info);
191 scoped_ptr<Event> event( 230 scoped_ptr<Event> event(
192 new Event(bluetooth_socket::OnReceiveError::kEventName, args.Pass())); 231 new Event(bluetooth_socket::OnReceiveError::kEventName, args.Pass()));
193 PostEvent(params, event.Pass()); 232 PostEvent(params, event.Pass());
194 233
195 // Since we got an error, the socket is now "paused" until the application 234 // Since we got an error, the socket is now "paused" until the application
196 // "resumes" it. 235 // "resumes" it.
197 BluetoothApiSocket* socket = 236 BluetoothApiSocket* socket =
198 params.sockets->Get(params.extension_id, params.socket_id); 237 params.sockets->Get(params.extension_id, params.socket_id);
199 if (socket) { 238 if (socket) {
200 socket->set_paused(true); 239 socket->set_paused(true);
201 } 240 }
202 } 241 }
203 242
204 // static 243 // static
205 void BluetoothSocketEventDispatcher::PostEvent(const ReceiveParams& params, 244 void BluetoothSocketEventDispatcher::StartAccept(const SocketParams& params) {
245 DCHECK(BrowserThread::CurrentlyOn(params.thread_id));
246
247 BluetoothApiSocket* socket =
248 params.sockets->Get(params.extension_id, params.socket_id);
249 if (!socket) {
250 // This can happen if the socket is closed while our callback is active.
251 return;
252 }
253 DCHECK(params.extension_id == socket->owner_extension_id())
254 << "Socket has wrong owner.";
255
256 // Don't start another accept if the socket has been paused.
257 if (socket->paused())
258 return;
259
260 socket->Accept(
261 base::Bind(
262 &BluetoothSocketEventDispatcher::AcceptCallback, params),
263 base::Bind(
264 &BluetoothSocketEventDispatcher::AcceptErrorCallback, params));
265 }
266
267 // static
268 void BluetoothSocketEventDispatcher::AcceptCallback(
269 const SocketParams& params,
270 const device::BluetoothDevice* device,
271 scoped_refptr<device::BluetoothSocket> socket) {
272 DCHECK(BrowserThread::CurrentlyOn(params.thread_id));
273
274 BluetoothApiSocket* server_api_socket =
275 params.sockets->Get(params.extension_id, params.socket_id);
276 DCHECK(server_api_socket);
277
278 BluetoothApiSocket* client_api_socket = new BluetoothApiSocket(
279 params.extension_id,
280 socket,
281 device->GetAddress(),
282 server_api_socket->uuid());
283 int client_socket_id = params.sockets->Add(client_api_socket);
284
285 // Dispatch "onAccept" event.
286 bluetooth_socket::AcceptInfo accept_info;
287 accept_info.socket_id = params.socket_id;
288 accept_info.client_socket_id = client_socket_id;
289 scoped_ptr<base::ListValue> args =
290 bluetooth_socket::OnAccept::Create(accept_info);
291 scoped_ptr<Event> event(
292 new Event(bluetooth_socket::OnAccept::kEventName, args.Pass()));
293 PostEvent(params, event.Pass());
294
295 // Post a task to delay the accept until the socket is available, as
296 // calling StartAccept at this point would error with ERR_IO_PENDING.
297 BrowserThread::PostTask(
298 params.thread_id,
299 FROM_HERE,
300 base::Bind(&BluetoothSocketEventDispatcher::StartAccept, params));
301 }
302
303 // static
304 void BluetoothSocketEventDispatcher::AcceptErrorCallback(
305 const SocketParams& params,
306 BluetoothApiSocket::ErrorReason error_reason,
307 const std::string& error) {
308 DCHECK(BrowserThread::CurrentlyOn(params.thread_id));
309
310 if (error_reason == BluetoothApiSocket::kIOPending) {
311 // This happens when resuming a socket which already had an active "acce0t"
rpaquay 2014/05/09 16:09:53 accept?
keybuk 2014/05/09 18:28:24 Done.
312 // callback. We can safely ignore this error, as the application should not
313 // care.
314 return;
315 }
316
317 // Dispatch "onAcceptError" event but don't start another read to avoid
rpaquay 2014/05/09 16:09:53 read => accept
keybuk 2014/05/09 18:28:24 Done.
318 // potential infinite reads if we have a persistent network error.
rpaquay 2014/05/09 16:09:53 reads => accepts
keybuk 2014/05/09 18:28:24 Done.
319 bluetooth_socket::AcceptErrorInfo accept_error_info;
320 accept_error_info.socket_id = params.socket_id;
321 accept_error_info.error_message = error;
322 accept_error_info.error = MapAcceptErrorReason(error_reason);
323 scoped_ptr<base::ListValue> args =
324 bluetooth_socket::OnAcceptError::Create(accept_error_info);
325 scoped_ptr<Event> event(
326 new Event(bluetooth_socket::OnAcceptError::kEventName, args.Pass()));
327 PostEvent(params, event.Pass());
328
329 // Since we got an error, the socket is now "paused" until the application
330 // "resumes" it.
331 BluetoothApiSocket* socket =
332 params.sockets->Get(params.extension_id, params.socket_id);
333 if (socket) {
334 socket->set_paused(true);
335 }
336 }
337
338 // static
339 void BluetoothSocketEventDispatcher::PostEvent(const SocketParams& params,
206 scoped_ptr<Event> event) { 340 scoped_ptr<Event> event) {
207 DCHECK(BrowserThread::CurrentlyOn(params.thread_id)); 341 DCHECK(BrowserThread::CurrentlyOn(params.thread_id));
208 342
209 BrowserThread::PostTask( 343 BrowserThread::PostTask(
210 BrowserThread::UI, 344 BrowserThread::UI,
211 FROM_HERE, 345 FROM_HERE,
212 base::Bind(&DispatchEvent, 346 base::Bind(&DispatchEvent,
213 params.browser_context_id, 347 params.browser_context_id,
214 params.extension_id, 348 params.extension_id,
215 base::Passed(event.Pass()))); 349 base::Passed(event.Pass())));
(...skipping 11 matching lines...) Expand all
227 if (!extensions::ExtensionsBrowserClient::Get()->IsValidContext(context)) 361 if (!extensions::ExtensionsBrowserClient::Get()->IsValidContext(context))
228 return; 362 return;
229 363
230 EventRouter* router = EventRouter::Get(context); 364 EventRouter* router = EventRouter::Get(context);
231 if (router) 365 if (router)
232 router->DispatchEventToExtension(extension_id, event.Pass()); 366 router->DispatchEventToExtension(extension_id, event.Pass());
233 } 367 }
234 368
235 } // namespace api 369 } // namespace api
236 } // namespace extensions 370 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698