OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 "content/browser/renderer_host/websocket_host.h" | 5 #include "content/browser/renderer_host/websocket_host.h" |
6 | 6 |
7 #include <utility> | 7 #include <utility> |
8 | 8 |
9 #include "base/location.h" | 9 #include "base/location.h" |
10 #include "base/macros.h" | 10 #include "base/macros.h" |
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
146 | 146 |
147 DISALLOW_COPY_AND_ASSIGN(WebSocketEventHandler); | 147 DISALLOW_COPY_AND_ASSIGN(WebSocketEventHandler); |
148 }; | 148 }; |
149 | 149 |
150 WebSocketEventHandler::WebSocketEventHandler( | 150 WebSocketEventHandler::WebSocketEventHandler( |
151 WebSocketDispatcherHost* dispatcher, | 151 WebSocketDispatcherHost* dispatcher, |
152 int routing_id, | 152 int routing_id, |
153 int render_frame_id) | 153 int render_frame_id) |
154 : dispatcher_(dispatcher), | 154 : dispatcher_(dispatcher), |
155 routing_id_(routing_id), | 155 routing_id_(routing_id), |
156 render_frame_id_(render_frame_id) { | 156 render_frame_id_(render_frame_id) {} |
157 } | |
158 | 157 |
159 WebSocketEventHandler::~WebSocketEventHandler() { | 158 WebSocketEventHandler::~WebSocketEventHandler() { |
160 DVLOG(1) << "WebSocketEventHandler destroyed routing_id=" << routing_id_; | 159 DVLOG(1) << "WebSocketEventHandler destroyed routing_id=" << routing_id_; |
161 } | 160 } |
162 | 161 |
163 ChannelState WebSocketEventHandler::OnAddChannelResponse( | 162 ChannelState WebSocketEventHandler::OnAddChannelResponse( |
164 const std::string& selected_protocol, | 163 const std::string& selected_protocol, |
165 const std::string& extensions) { | 164 const std::string& extensions) { |
166 DVLOG(3) << "WebSocketEventHandler::OnAddChannelResponse" | 165 DVLOG(3) << "WebSocketEventHandler::OnAddChannelResponse" |
167 << " routing_id=" << routing_id_ | 166 << " routing_id=" << routing_id_ << " selected_protocol=\"" |
168 << " selected_protocol=\"" << selected_protocol << "\"" | 167 << selected_protocol << "\"" |
169 << " extensions=\"" << extensions << "\""; | 168 << " extensions=\"" << extensions << "\""; |
170 | 169 |
171 return StateCast(dispatcher_->SendAddChannelResponse( | 170 return StateCast(dispatcher_->SendAddChannelResponse( |
172 routing_id_, selected_protocol, extensions)); | 171 routing_id_, selected_protocol, extensions)); |
173 } | 172 } |
174 | 173 |
175 ChannelState WebSocketEventHandler::OnDataFrame( | 174 ChannelState WebSocketEventHandler::OnDataFrame( |
176 bool fin, | 175 bool fin, |
177 net::WebSocketFrameHeader::OpCode type, | 176 net::WebSocketFrameHeader::OpCode type, |
178 const std::vector<char>& data) { | 177 const std::vector<char>& data) { |
179 DVLOG(3) << "WebSocketEventHandler::OnDataFrame" | 178 DVLOG(3) << "WebSocketEventHandler::OnDataFrame" |
180 << " routing_id=" << routing_id_ << " fin=" << fin | 179 << " routing_id=" << routing_id_ << " fin=" << fin |
181 << " type=" << type << " data is " << data.size() << " bytes"; | 180 << " type=" << type << " data is " << data.size() << " bytes"; |
182 | 181 |
183 return StateCast(dispatcher_->SendFrame( | 182 return StateCast(dispatcher_->SendFrame(routing_id_, fin, |
184 routing_id_, fin, OpCodeToMessageType(type), data)); | 183 OpCodeToMessageType(type), data)); |
185 } | 184 } |
186 | 185 |
187 ChannelState WebSocketEventHandler::OnClosingHandshake() { | 186 ChannelState WebSocketEventHandler::OnClosingHandshake() { |
188 DVLOG(3) << "WebSocketEventHandler::OnClosingHandshake" | 187 DVLOG(3) << "WebSocketEventHandler::OnClosingHandshake" |
189 << " routing_id=" << routing_id_; | 188 << " routing_id=" << routing_id_; |
190 | 189 |
191 return StateCast(dispatcher_->NotifyClosingHandshake(routing_id_)); | 190 return StateCast(dispatcher_->NotifyClosingHandshake(routing_id_)); |
192 } | 191 } |
193 | 192 |
194 ChannelState WebSocketEventHandler::OnFlowControl(int64_t quota) { | 193 ChannelState WebSocketEventHandler::OnFlowControl(int64_t quota) { |
195 DVLOG(3) << "WebSocketEventHandler::OnFlowControl" | 194 DVLOG(3) << "WebSocketEventHandler::OnFlowControl" |
196 << " routing_id=" << routing_id_ << " quota=" << quota; | 195 << " routing_id=" << routing_id_ << " quota=" << quota; |
197 | 196 |
198 return StateCast(dispatcher_->SendFlowControl(routing_id_, quota)); | 197 return StateCast(dispatcher_->SendFlowControl(routing_id_, quota)); |
199 } | 198 } |
200 | 199 |
201 ChannelState WebSocketEventHandler::OnDropChannel(bool was_clean, | 200 ChannelState WebSocketEventHandler::OnDropChannel(bool was_clean, |
202 uint16_t code, | 201 uint16_t code, |
203 const std::string& reason) { | 202 const std::string& reason) { |
204 DVLOG(3) << "WebSocketEventHandler::OnDropChannel" | 203 DVLOG(3) << "WebSocketEventHandler::OnDropChannel" |
205 << " routing_id=" << routing_id_ << " was_clean=" << was_clean | 204 << " routing_id=" << routing_id_ << " was_clean=" << was_clean |
206 << " code=" << code << " reason=\"" << reason << "\""; | 205 << " code=" << code << " reason=\"" << reason << "\""; |
207 | 206 |
208 return StateCast( | 207 return StateCast( |
209 dispatcher_->DoDropChannel(routing_id_, was_clean, code, reason)); | 208 dispatcher_->DoDropChannel(routing_id_, was_clean, code, reason)); |
210 } | 209 } |
211 | 210 |
212 ChannelState WebSocketEventHandler::OnFailChannel(const std::string& message) { | 211 ChannelState WebSocketEventHandler::OnFailChannel(const std::string& message) { |
213 DVLOG(3) << "WebSocketEventHandler::OnFailChannel" | 212 DVLOG(3) << "WebSocketEventHandler::OnFailChannel" |
214 << " routing_id=" << routing_id_ | 213 << " routing_id=" << routing_id_ << " message=\"" << message << "\""; |
215 << " message=\"" << message << "\""; | |
216 | 214 |
217 return StateCast(dispatcher_->NotifyFailure(routing_id_, message)); | 215 return StateCast(dispatcher_->NotifyFailure(routing_id_, message)); |
218 } | 216 } |
219 | 217 |
220 ChannelState WebSocketEventHandler::OnStartOpeningHandshake( | 218 ChannelState WebSocketEventHandler::OnStartOpeningHandshake( |
221 scoped_ptr<net::WebSocketHandshakeRequestInfo> request) { | 219 scoped_ptr<net::WebSocketHandshakeRequestInfo> request) { |
222 bool should_send = dispatcher_->CanReadRawCookies(); | 220 bool should_send = dispatcher_->CanReadRawCookies(); |
223 DVLOG(3) << "WebSocketEventHandler::OnStartOpeningHandshake " | 221 DVLOG(3) << "WebSocketEventHandler::OnStartOpeningHandshake " |
224 << "should_send=" << should_send; | 222 << "should_send=" << should_send; |
225 | 223 |
226 if (!should_send) | 224 if (!should_send) |
227 return WebSocketEventInterface::CHANNEL_ALIVE; | 225 return WebSocketEventInterface::CHANNEL_ALIVE; |
228 | 226 |
229 WebSocketHandshakeRequest request_to_pass; | 227 WebSocketHandshakeRequest request_to_pass; |
230 request_to_pass.url.Swap(&request->url); | 228 request_to_pass.url.Swap(&request->url); |
231 net::HttpRequestHeaders::Iterator it(request->headers); | 229 net::HttpRequestHeaders::Iterator it(request->headers); |
232 while (it.GetNext()) | 230 while (it.GetNext()) |
233 request_to_pass.headers.push_back(std::make_pair(it.name(), it.value())); | 231 request_to_pass.headers.push_back(std::make_pair(it.name(), it.value())); |
234 request_to_pass.headers_text = | 232 request_to_pass.headers_text = |
235 base::StringPrintf("GET %s HTTP/1.1\r\n", | 233 base::StringPrintf("GET %s HTTP/1.1\r\n", |
236 request_to_pass.url.spec().c_str()) + | 234 request_to_pass.url.spec().c_str()) + |
237 request->headers.ToString(); | 235 request->headers.ToString(); |
238 request_to_pass.request_time = request->request_time; | 236 request_to_pass.request_time = request->request_time; |
239 | 237 |
240 return StateCast(dispatcher_->NotifyStartOpeningHandshake(routing_id_, | 238 return StateCast( |
241 request_to_pass)); | 239 dispatcher_->NotifyStartOpeningHandshake(routing_id_, request_to_pass)); |
242 } | 240 } |
243 | 241 |
244 ChannelState WebSocketEventHandler::OnFinishOpeningHandshake( | 242 ChannelState WebSocketEventHandler::OnFinishOpeningHandshake( |
245 scoped_ptr<net::WebSocketHandshakeResponseInfo> response) { | 243 scoped_ptr<net::WebSocketHandshakeResponseInfo> response) { |
246 bool should_send = dispatcher_->CanReadRawCookies(); | 244 bool should_send = dispatcher_->CanReadRawCookies(); |
247 DVLOG(3) << "WebSocketEventHandler::OnFinishOpeningHandshake " | 245 DVLOG(3) << "WebSocketEventHandler::OnFinishOpeningHandshake " |
248 << "should_send=" << should_send; | 246 << "should_send=" << should_send; |
249 | 247 |
250 if (!should_send) | 248 if (!should_send) |
251 return WebSocketEventInterface::CHANNEL_ALIVE; | 249 return WebSocketEventInterface::CHANNEL_ALIVE; |
252 | 250 |
253 WebSocketHandshakeResponse response_to_pass; | 251 WebSocketHandshakeResponse response_to_pass; |
254 response_to_pass.url.Swap(&response->url); | 252 response_to_pass.url.Swap(&response->url); |
255 response_to_pass.status_code = response->status_code; | 253 response_to_pass.status_code = response->status_code; |
256 response_to_pass.status_text.swap(response->status_text); | 254 response_to_pass.status_text.swap(response->status_text); |
257 void* iter = NULL; | 255 void* iter = NULL; |
258 std::string name, value; | 256 std::string name, value; |
259 while (response->headers->EnumerateHeaderLines(&iter, &name, &value)) | 257 while (response->headers->EnumerateHeaderLines(&iter, &name, &value)) |
260 response_to_pass.headers.push_back(std::make_pair(name, value)); | 258 response_to_pass.headers.push_back(std::make_pair(name, value)); |
261 response_to_pass.headers_text = | 259 response_to_pass.headers_text = |
262 net::HttpUtil::ConvertHeadersBackToHTTPResponse( | 260 net::HttpUtil::ConvertHeadersBackToHTTPResponse( |
263 response->headers->raw_headers()); | 261 response->headers->raw_headers()); |
264 response_to_pass.response_time = response->response_time; | 262 response_to_pass.response_time = response->response_time; |
265 | 263 |
266 return StateCast(dispatcher_->NotifyFinishOpeningHandshake(routing_id_, | 264 return StateCast( |
267 response_to_pass)); | 265 dispatcher_->NotifyFinishOpeningHandshake(routing_id_, response_to_pass)); |
268 } | 266 } |
269 | 267 |
270 ChannelState WebSocketEventHandler::OnSSLCertificateError( | 268 ChannelState WebSocketEventHandler::OnSSLCertificateError( |
271 scoped_ptr<net::WebSocketEventInterface::SSLErrorCallbacks> callbacks, | 269 scoped_ptr<net::WebSocketEventInterface::SSLErrorCallbacks> callbacks, |
272 const GURL& url, | 270 const GURL& url, |
273 const net::SSLInfo& ssl_info, | 271 const net::SSLInfo& ssl_info, |
274 bool fatal) { | 272 bool fatal) { |
275 DVLOG(3) << "WebSocketEventHandler::OnSSLCertificateError" | 273 DVLOG(3) << "WebSocketEventHandler::OnSSLCertificateError" |
276 << " routing_id=" << routing_id_ << " url=" << url.spec() | 274 << " routing_id=" << routing_id_ << " url=" << url.spec() |
277 << " cert_status=" << ssl_info.cert_status << " fatal=" << fatal; | 275 << " cert_status=" << ssl_info.cert_status << " fatal=" << fatal; |
278 ssl_error_handler_delegate_.reset( | 276 ssl_error_handler_delegate_.reset( |
279 new SSLErrorHandlerDelegate(std::move(callbacks))); | 277 new SSLErrorHandlerDelegate(std::move(callbacks))); |
280 SSLManager::OnSSLCertificateSubresourceError( | 278 SSLManager::OnSSLCertificateSubresourceError( |
281 ssl_error_handler_delegate_->GetWeakPtr(), url, | 279 ssl_error_handler_delegate_->GetWeakPtr(), url, |
282 dispatcher_->render_process_id(), render_frame_id_, ssl_info, fatal); | 280 dispatcher_->render_process_id(), render_frame_id_, ssl_info, fatal); |
283 // The above method is always asynchronous. | 281 // The above method is always asynchronous. |
284 return WebSocketEventInterface::CHANNEL_ALIVE; | 282 return WebSocketEventInterface::CHANNEL_ALIVE; |
285 } | 283 } |
286 | 284 |
287 WebSocketEventHandler::SSLErrorHandlerDelegate::SSLErrorHandlerDelegate( | 285 WebSocketEventHandler::SSLErrorHandlerDelegate::SSLErrorHandlerDelegate( |
288 scoped_ptr<net::WebSocketEventInterface::SSLErrorCallbacks> callbacks) | 286 scoped_ptr<net::WebSocketEventInterface::SSLErrorCallbacks> callbacks) |
289 : callbacks_(std::move(callbacks)), weak_ptr_factory_(this) {} | 287 : callbacks_(std::move(callbacks)), weak_ptr_factory_(this) {} |
290 | 288 |
291 WebSocketEventHandler::SSLErrorHandlerDelegate::~SSLErrorHandlerDelegate() {} | 289 WebSocketEventHandler::SSLErrorHandlerDelegate::~SSLErrorHandlerDelegate() {} |
292 | 290 |
293 base::WeakPtr<SSLErrorHandler::Delegate> | 291 base::WeakPtr<SSLErrorHandler::Delegate> |
294 WebSocketEventHandler::SSLErrorHandlerDelegate::GetWeakPtr() { | 292 WebSocketEventHandler::SSLErrorHandlerDelegate::GetWeakPtr() { |
(...skipping 10 matching lines...) Expand all Loading... |
305 callbacks_->CancelSSLRequest(error, ssl_info); | 303 callbacks_->CancelSSLRequest(error, ssl_info); |
306 } | 304 } |
307 | 305 |
308 void WebSocketEventHandler::SSLErrorHandlerDelegate::ContinueSSLRequest() { | 306 void WebSocketEventHandler::SSLErrorHandlerDelegate::ContinueSSLRequest() { |
309 DVLOG(3) << "SSLErrorHandlerDelegate::ContinueSSLRequest"; | 307 DVLOG(3) << "SSLErrorHandlerDelegate::ContinueSSLRequest"; |
310 callbacks_->ContinueSSLRequest(); | 308 callbacks_->ContinueSSLRequest(); |
311 } | 309 } |
312 | 310 |
313 } // namespace | 311 } // namespace |
314 | 312 |
| 313 WebSocketHost::ReceiveQuotaMultiplexer::ReceiveQuotaMultiplexer() |
| 314 : channel_(nullptr), published_quota_(0), current_consumer_(nullptr) {} |
| 315 |
| 316 // Quota can be added to any consumer at any time. |
| 317 bool WebSocketHost::ReceiveQuotaMultiplexer::AddQuota( |
| 318 ReceiveQuotaProvider* provider, |
| 319 int64_t quota) { |
| 320 DCHECK(channel_); |
| 321 DCHECK_GE(quota, 0); |
| 322 *provider += quota; |
| 323 if (provider == current_consumer_) { |
| 324 PublishMoreQuotaIfNeeded(); |
| 325 return true; |
| 326 } |
| 327 return false; |
| 328 } |
| 329 |
| 330 // Quota can only be used from the current consumer. |
| 331 int64_t WebSocketHost::ReceiveQuotaMultiplexer::AvailableQuota() const { |
| 332 DCHECK(current_consumer_); |
| 333 return *current_consumer_; |
| 334 } |
| 335 |
| 336 // Quota is only consumed by the current consumer. |
| 337 void WebSocketHost::ReceiveQuotaMultiplexer::ConsumedQuota(int64_t quota) { |
| 338 DCHECK_GE(quota, 0); |
| 339 DCHECK_GE(*current_consumer_, quota); |
| 340 DCHECK_GE(published_quota_, *current_consumer_); |
| 341 *current_consumer_ -= quota; |
| 342 published_quota_ -= quota; |
| 343 } |
| 344 |
| 345 // Changing the current consumer may result in more quota being published. |
| 346 void WebSocketHost::ReceiveQuotaMultiplexer::SetConsumer( |
| 347 ReceiveQuotaConsumer* consumer) { |
| 348 DCHECK(channel_); |
| 349 DCHECK(consumer); |
| 350 current_consumer_ = consumer; |
| 351 PublishMoreQuotaIfNeeded(); |
| 352 } |
| 353 |
| 354 void WebSocketHost::ReceiveQuotaMultiplexer::PublishMoreQuotaIfNeeded() { |
| 355 DCHECK(channel_); |
| 356 DCHECK(current_consumer_); |
| 357 if (*current_consumer_ > published_quota_) { |
| 358 channel_->SendFlowControl(published_quota_ - *current_consumer_); |
| 359 published_quota_ = *current_consumer_; |
| 360 } |
| 361 } |
| 362 |
315 WebSocketHost::WebSocketHost(int routing_id, | 363 WebSocketHost::WebSocketHost(int routing_id, |
316 WebSocketDispatcherHost* dispatcher, | 364 WebSocketDispatcherHost* dispatcher, |
317 net::URLRequestContext* url_request_context, | 365 net::URLRequestContext* url_request_context, |
318 base::TimeDelta delay) | 366 base::TimeDelta delay) |
319 : dispatcher_(dispatcher), | 367 : dispatcher_(dispatcher), |
320 url_request_context_(url_request_context), | 368 url_request_context_(url_request_context), |
321 routing_id_(routing_id), | 369 routing_id_(routing_id), |
322 delay_(delay), | 370 delay_(delay), |
323 pending_flow_control_quota_(0), | 371 pending_flow_control_quota_(0), |
324 handshake_succeeded_(false), | 372 handshake_succeeded_(false), |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
447 ""); | 495 ""); |
448 DCHECK_EQ(WebSocketDispatcherHost::WEBSOCKET_HOST_DELETED, result); | 496 DCHECK_EQ(WebSocketDispatcherHost::WEBSOCKET_HOST_DELETED, result); |
449 return; | 497 return; |
450 } | 498 } |
451 | 499 |
452 // TODO(yhirano): Handle |was_clean| appropriately. | 500 // TODO(yhirano): Handle |was_clean| appropriately. |
453 channel_->StartClosingHandshake(code, reason); | 501 channel_->StartClosingHandshake(code, reason); |
454 } | 502 } |
455 | 503 |
456 } // namespace content | 504 } // namespace content |
OLD | NEW |