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