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 "extensions/browser/api/sockets_tcp/tcp_socket_event_dispatcher.h" | 5 #include "extensions/browser/api/sockets_tcp/tcp_socket_event_dispatcher.h" |
6 | 6 |
7 #include "base/lazy_instance.h" | 7 #include "base/lazy_instance.h" |
8 #include "extensions/browser/api/socket/tcp_socket.h" | 8 #include "extensions/browser/api/socket/tcp_socket.h" |
9 #include "extensions/browser/event_router.h" | 9 #include "extensions/browser/event_router.h" |
10 #include "extensions/browser/extension_system.h" | 10 #include "extensions/browser/extension_system.h" |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
108 socket->Read(buffer_size, | 108 socket->Read(buffer_size, |
109 base::Bind(&TCPSocketEventDispatcher::ReadCallback, params)); | 109 base::Bind(&TCPSocketEventDispatcher::ReadCallback, params)); |
110 } | 110 } |
111 | 111 |
112 // static | 112 // static |
113 void TCPSocketEventDispatcher::ReadCallback( | 113 void TCPSocketEventDispatcher::ReadCallback( |
114 const ReadParams& params, | 114 const ReadParams& params, |
115 int bytes_read, | 115 int bytes_read, |
116 scoped_refptr<net::IOBuffer> io_buffer) { | 116 scoped_refptr<net::IOBuffer> io_buffer) { |
117 DCHECK_CURRENTLY_ON(params.thread_id); | 117 DCHECK_CURRENTLY_ON(params.thread_id); |
| 118 ResumableTCPSocket* socket = |
| 119 params.sockets->Get(params.extension_id, params.socket_id); |
| 120 bool socket_paused = socket != NULL && socket->paused(); |
118 | 121 |
119 // If |bytes_read| == 0, the connection has been closed by the peer. | 122 // If |bytes_read| == 0, the connection has been closed by the peer. |
120 // If |bytes_read| < 0, there was a network error, and |bytes_read| is a value | 123 // If |bytes_read| < 0, there was a network error, and |bytes_read| is a value |
121 // from "net::ERR_". | 124 // from "net::ERR_". |
122 | 125 |
123 if (bytes_read == 0) { | 126 if (bytes_read == 0) { |
124 bytes_read = net::ERR_CONNECTION_CLOSED; | 127 bytes_read = net::ERR_CONNECTION_CLOSED; |
125 } | 128 } |
126 | 129 |
127 if (bytes_read > 0) { | 130 if (bytes_read > 0) { |
(...skipping 10 matching lines...) Expand all Loading... |
138 | 141 |
139 // Post a task to delay the read until the socket is available, as | 142 // Post a task to delay the read until the socket is available, as |
140 // calling StartReceive at this point would error with ERR_IO_PENDING. | 143 // calling StartReceive at this point would error with ERR_IO_PENDING. |
141 BrowserThread::PostTask( | 144 BrowserThread::PostTask( |
142 params.thread_id, | 145 params.thread_id, |
143 FROM_HERE, | 146 FROM_HERE, |
144 base::Bind(&TCPSocketEventDispatcher::StartRead, params)); | 147 base::Bind(&TCPSocketEventDispatcher::StartRead, params)); |
145 } else if (bytes_read == net::ERR_IO_PENDING) { | 148 } else if (bytes_read == net::ERR_IO_PENDING) { |
146 // This happens when resuming a socket which already had an | 149 // This happens when resuming a socket which already had an |
147 // active "read" callback. | 150 // active "read" callback. |
| 151 } else if (bytes_read == net::ERR_ABORTED && socket_paused) { |
| 152 // This happens when a socket has been paused by the |
| 153 // sockets_tcp.setPaused() API. The Read() was canceled on purpose. Let |
| 154 // the socket know that the API-invoked pause process has completed. Do |
| 155 // not dispatch an "onReceiveError" as there was no real error. |
| 156 socket->ApiPauseComplete(); |
148 } else { | 157 } else { |
149 // Dispatch "onReceiveError" event but don't start another read to avoid | 158 // Dispatch "onReceiveError" event but don't start another read to avoid |
150 // potential infinite reads if we have a persistent network error. | 159 // potential infinite reads if we have a persistent network error. |
151 sockets_tcp::ReceiveErrorInfo receive_error_info; | 160 sockets_tcp::ReceiveErrorInfo receive_error_info; |
152 receive_error_info.socket_id = params.socket_id; | 161 receive_error_info.socket_id = params.socket_id; |
153 receive_error_info.result_code = bytes_read; | 162 receive_error_info.result_code = bytes_read; |
154 scoped_ptr<base::ListValue> args = | 163 scoped_ptr<base::ListValue> args = |
155 sockets_tcp::OnReceiveError::Create(receive_error_info); | 164 sockets_tcp::OnReceiveError::Create(receive_error_info); |
156 scoped_ptr<Event> event(new Event(events::SOCKETS_TCP_ON_RECEIVE_ERROR, | 165 scoped_ptr<Event> event(new Event(events::SOCKETS_TCP_ON_RECEIVE_ERROR, |
157 sockets_tcp::OnReceiveError::kEventName, | 166 sockets_tcp::OnReceiveError::kEventName, |
158 args.Pass())); | 167 args.Pass())); |
159 PostEvent(params, event.Pass()); | 168 PostEvent(params, event.Pass()); |
160 | |
161 // Since we got an error, the socket is now "paused" until the application | 169 // Since we got an error, the socket is now "paused" until the application |
162 // "resumes" it. | 170 // "resumes" it. |
163 ResumableTCPSocket* socket = | 171 ResumableTCPSocket* socket = |
164 params.sockets->Get(params.extension_id, params.socket_id); | 172 params.sockets->Get(params.extension_id, params.socket_id); |
165 if (socket) { | 173 if (socket) { |
166 socket->set_paused(true); | 174 socket->set_paused(true); |
167 } | 175 } |
168 } | 176 } |
169 } | 177 } |
170 | 178 |
171 // static | 179 // static |
172 void TCPSocketEventDispatcher::PostEvent(const ReadParams& params, | 180 void TCPSocketEventDispatcher::PostEvent(const ReadParams& params, |
173 scoped_ptr<Event> event) { | 181 scoped_ptr<Event> event) { |
174 DCHECK_CURRENTLY_ON(params.thread_id); | 182 DCHECK_CURRENTLY_ON(params.thread_id); |
175 | 183 BrowserThread::PostTask( |
176 BrowserThread::PostTask(BrowserThread::UI, | 184 BrowserThread::UI, FROM_HERE, |
177 FROM_HERE, | 185 base::Bind(&DispatchEvent, params.browser_context_id, params.extension_id, |
178 base::Bind(&DispatchEvent, | 186 base::Passed(event.Pass()))); |
179 params.browser_context_id, | |
180 params.extension_id, | |
181 base::Passed(event.Pass()))); | |
182 } | 187 } |
183 | 188 |
184 // static | 189 // static |
185 void TCPSocketEventDispatcher::DispatchEvent(void* browser_context_id, | 190 void TCPSocketEventDispatcher::DispatchEvent(void* browser_context_id, |
186 const std::string& extension_id, | 191 const std::string& extension_id, |
187 scoped_ptr<Event> event) { | 192 scoped_ptr<Event> event) { |
188 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 193 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
189 | 194 |
190 content::BrowserContext* context = | 195 content::BrowserContext* context = |
191 reinterpret_cast<content::BrowserContext*>(browser_context_id); | 196 reinterpret_cast<content::BrowserContext*>(browser_context_id); |
192 if (!extensions::ExtensionsBrowserClient::Get()->IsValidContext(context)) | 197 if (!extensions::ExtensionsBrowserClient::Get()->IsValidContext(context)) { |
193 return; | 198 return; |
| 199 } |
194 | 200 |
195 EventRouter* event_router = EventRouter::Get(context); | 201 EventRouter* event_router = EventRouter::Get(context); |
196 if (event_router) | 202 if (event_router) { |
197 event_router->DispatchEventToExtension(extension_id, event.Pass()); | 203 event_router->DispatchEventToExtension(extension_id, event.Pass()); |
| 204 } |
198 } | 205 } |
199 | 206 |
200 } // namespace api | 207 } // namespace api |
201 } // namespace extensions | 208 } // namespace extensions |
OLD | NEW |