OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |