OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/buffered_resource_handler.h" | 5 #include "content/browser/renderer_host/buffered_resource_handler.h" |
6 | 6 |
7 #include <vector> | 7 #include <vector> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
11 #include "base/metrics/histogram.h" | 11 #include "base/metrics/histogram.h" |
12 #include "base/string_util.h" | 12 #include "base/string_util.h" |
13 #include "content/browser/download/download_resource_handler.h" | 13 #include "content/browser/download/download_resource_handler.h" |
14 #include "content/browser/download/download_stats.h" | 14 #include "content/browser/download/download_stats.h" |
15 #include "content/browser/download/download_types.h" | 15 #include "content/browser/download/download_types.h" |
16 #include "content/browser/plugin_service_impl.h" | 16 #include "content/browser/plugin_service_impl.h" |
17 #include "content/browser/renderer_host/resource_dispatcher_host.h" | 17 #include "content/browser/renderer_host/resource_dispatcher_host.h" |
18 #include "content/browser/renderer_host/resource_dispatcher_host_request_info.h" | 18 #include "content/browser/renderer_host/resource_request_info_impl.h" |
19 #include "content/browser/renderer_host/x509_user_cert_resource_handler.h" | 19 #include "content/browser/renderer_host/x509_user_cert_resource_handler.h" |
20 #include "content/public/browser/browser_thread.h" | 20 #include "content/public/browser/browser_thread.h" |
21 #include "content/public/browser/content_browser_client.h" | 21 #include "content/public/browser/content_browser_client.h" |
22 #include "content/public/browser/resource_context.h" | 22 #include "content/public/browser/resource_context.h" |
23 #include "content/public/browser/resource_dispatcher_host_delegate.h" | 23 #include "content/public/browser/resource_dispatcher_host_delegate.h" |
24 #include "content/public/common/resource_response.h" | 24 #include "content/public/common/resource_response.h" |
25 #include "net/base/io_buffer.h" | 25 #include "net/base/io_buffer.h" |
26 #include "net/base/mime_sniffer.h" | 26 #include "net/base/mime_sniffer.h" |
27 #include "net/base/mime_util.h" | 27 #include "net/base/mime_util.h" |
28 #include "net/base/net_errors.h" | 28 #include "net/base/net_errors.h" |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
110 return false; | 110 return false; |
111 } | 111 } |
112 read_buffer_ = *buf; | 112 read_buffer_ = *buf; |
113 read_buffer_size_ = *buf_size; | 113 read_buffer_size_ = *buf_size; |
114 DCHECK_GE(read_buffer_size_, net::kMaxBytesToSniff * 2); | 114 DCHECK_GE(read_buffer_size_, net::kMaxBytesToSniff * 2); |
115 bytes_read_ = 0; | 115 bytes_read_ = 0; |
116 return true; | 116 return true; |
117 } | 117 } |
118 | 118 |
119 bool BufferedResourceHandler::OnReadCompleted(int request_id, int* bytes_read) { | 119 bool BufferedResourceHandler::OnReadCompleted(int request_id, int* bytes_read) { |
120 ResourceDispatcherHostRequestInfo* info = | 120 ResourceRequestInfoImpl* info = |
121 ResourceDispatcherHost::InfoForRequest(request_); | 121 ResourceDispatcherHost::InfoForRequest(request_); |
122 | 122 |
123 if (sniff_content_) { | 123 if (sniff_content_) { |
124 if (KeepBuffering(*bytes_read)) | 124 if (KeepBuffering(*bytes_read)) |
125 return true; | 125 return true; |
126 | 126 |
127 *bytes_read = bytes_read_; | 127 *bytes_read = bytes_read_; |
128 | 128 |
129 // Done buffering, send the pending ResponseStarted event. | 129 // Done buffering, send the pending ResponseStarted event. |
130 if (!CompleteResponseStarted(request_id)) | 130 if (!CompleteResponseStarted(request_id)) |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
249 | 249 |
250 buffering_ = false; | 250 buffering_ = false; |
251 | 251 |
252 if (wait_for_plugins_) | 252 if (wait_for_plugins_) |
253 return true; | 253 return true; |
254 | 254 |
255 return false; | 255 return false; |
256 } | 256 } |
257 | 257 |
258 bool BufferedResourceHandler::CompleteResponseStarted(int request_id) { | 258 bool BufferedResourceHandler::CompleteResponseStarted(int request_id) { |
259 ResourceDispatcherHostRequestInfo* info = | 259 ResourceRequestInfoImpl* info = |
260 ResourceDispatcherHost::InfoForRequest(request_); | 260 ResourceDispatcherHost::InfoForRequest(request_); |
261 std::string mime_type; | 261 std::string mime_type; |
262 request_->GetMimeType(&mime_type); | 262 request_->GetMimeType(&mime_type); |
263 | 263 |
264 // Check if this is an X.509 certificate, if yes, let it be handled | 264 // Check if this is an X.509 certificate, if yes, let it be handled |
265 // by X509UserCertResourceHandler. | 265 // by X509UserCertResourceHandler. |
266 if (mime_type == "application/x-x509-user-cert") { | 266 if (mime_type == "application/x-x509-user-cert") { |
267 // This is entirely similar to how DownloadResourceThrottle works except we | 267 // This is entirely similar to how DownloadResourceThrottle works except we |
268 // are doing it for an X.509 client certificates. | 268 // are doing it for an X.509 client certificates. |
269 // TODO(darin): This does not belong here! | 269 // TODO(darin): This does not belong here! |
270 | 270 |
271 if (response_->headers && // Can be NULL if FTP. | 271 if (response_->headers && // Can be NULL if FTP. |
272 response_->headers->response_code() / 100 != 2) { | 272 response_->headers->response_code() / 100 != 2) { |
273 // The response code indicates that this is an error page, but we are | 273 // The response code indicates that this is an error page, but we are |
274 // expecting an X.509 user certificate. We follow Firefox here and show | 274 // expecting an X.509 user certificate. We follow Firefox here and show |
275 // our own error page instead of handling the error page as a | 275 // our own error page instead of handling the error page as a |
276 // certificate. | 276 // certificate. |
277 // TODO(abarth): We should abstract the response_code test, but this kind | 277 // TODO(abarth): We should abstract the response_code test, but this kind |
278 // of check is scattered throughout our codebase. | 278 // of check is scattered throughout our codebase. |
279 request_->SimulateError(net::ERR_FILE_NOT_FOUND); | 279 request_->SimulateError(net::ERR_FILE_NOT_FOUND); |
280 return false; | 280 return false; |
281 } | 281 } |
282 | 282 |
283 X509UserCertResourceHandler* x509_cert_handler = | 283 X509UserCertResourceHandler* x509_cert_handler = |
284 new X509UserCertResourceHandler(host_, request_, | 284 new X509UserCertResourceHandler(host_, request_, |
285 info->child_id(), info->route_id()); | 285 info->GetChildID(), info->GetRouteID()); |
286 if (!UseAlternateResourceHandler(request_id, x509_cert_handler)) | 286 if (!UseAlternateResourceHandler(request_id, x509_cert_handler)) |
287 return false; | 287 return false; |
288 } | 288 } |
289 | 289 |
290 // Check to see if we should forward the data from this request to the | 290 // Check to see if we should forward the data from this request to the |
291 // download thread. | 291 // download thread. |
292 // TODO(paulg): Only download if the context from the renderer allows it. | 292 // TODO(paulg): Only download if the context from the renderer allows it. |
293 if (info->allow_download() && ShouldDownload(NULL)) { | 293 if (info->allow_download() && ShouldDownload(NULL)) { |
294 if (response_->headers && // Can be NULL if FTP. | 294 if (response_->headers && // Can be NULL if FTP. |
295 response_->headers->response_code() / 100 != 2) { | 295 response_->headers->response_code() / 100 != 2) { |
296 // The response code indicates that this is an error page, but we don't | 296 // The response code indicates that this is an error page, but we don't |
297 // know how to display the content. We follow Firefox here and show our | 297 // know how to display the content. We follow Firefox here and show our |
298 // own error page instead of triggering a download. | 298 // own error page instead of triggering a download. |
299 // TODO(abarth): We should abstract the response_code test, but this kind | 299 // TODO(abarth): We should abstract the response_code test, but this kind |
300 // of check is scattered throughout our codebase. | 300 // of check is scattered throughout our codebase. |
301 request_->SimulateError(net::ERR_FILE_NOT_FOUND); | 301 request_->SimulateError(net::ERR_FILE_NOT_FOUND); |
302 return false; | 302 return false; |
303 } | 303 } |
304 | 304 |
305 info->set_is_download(true); | 305 info->set_is_download(true); |
306 | 306 |
307 scoped_refptr<ResourceHandler> handler( | 307 scoped_refptr<ResourceHandler> handler( |
308 host_->CreateResourceHandlerForDownload( | 308 host_->CreateResourceHandlerForDownload( |
309 request_, | 309 request_, |
310 info->context(), | 310 info->GetContext(), |
311 info->child_id(), | 311 info->GetChildID(), |
312 info->route_id(), | 312 info->GetRouteID(), |
313 info->request_id(), | 313 info->GetRequestID(), |
314 DownloadSaveInfo(), | 314 DownloadSaveInfo(), |
315 DownloadResourceHandler::OnStartedCallback())); | 315 DownloadResourceHandler::OnStartedCallback())); |
316 | 316 |
317 if (!UseAlternateResourceHandler(request_id, handler)) | 317 if (!UseAlternateResourceHandler(request_id, handler)) |
318 return false; | 318 return false; |
319 } | 319 } |
320 | 320 |
321 if (info->pause_count()) | 321 if (info->pause_count()) |
322 return true; | 322 return true; |
323 | 323 |
324 return next_handler_->OnResponseStarted(request_id, response_); | 324 return next_handler_->OnResponseStarted(request_id, response_); |
325 } | 325 } |
326 | 326 |
327 bool BufferedResourceHandler::ShouldWaitForPlugins() { | 327 bool BufferedResourceHandler::ShouldWaitForPlugins() { |
328 bool need_plugin_list; | 328 bool need_plugin_list; |
329 if (!ShouldDownload(&need_plugin_list) || !need_plugin_list) | 329 if (!ShouldDownload(&need_plugin_list) || !need_plugin_list) |
330 return false; | 330 return false; |
331 | 331 |
332 // We don't want to keep buffering as our buffer will fill up. | 332 // We don't want to keep buffering as our buffer will fill up. |
333 ResourceDispatcherHostRequestInfo* info = | 333 ResourceRequestInfoImpl* info = |
334 ResourceDispatcherHost::InfoForRequest(request_); | 334 ResourceDispatcherHost::InfoForRequest(request_); |
335 host_->PauseRequest(info->child_id(), info->request_id(), true); | 335 host_->PauseRequest(info->GetChildID(), info->GetRequestID(), true); |
336 | 336 |
337 // Get the plugins asynchronously. | 337 // Get the plugins asynchronously. |
338 PluginServiceImpl::GetInstance()->GetPlugins( | 338 PluginServiceImpl::GetInstance()->GetPlugins( |
339 base::Bind(&BufferedResourceHandler::OnPluginsLoaded, this)); | 339 base::Bind(&BufferedResourceHandler::OnPluginsLoaded, this)); |
340 return true; | 340 return true; |
341 } | 341 } |
342 | 342 |
343 // This test mirrors the decision that WebKit makes in | 343 // This test mirrors the decision that WebKit makes in |
344 // WebFrameLoaderClient::dispatchDecidePolicyForMIMEType. | 344 // WebFrameLoaderClient::dispatchDecidePolicyForMIMEType. |
345 bool BufferedResourceHandler::ShouldDownload(bool* need_plugin_list) { | 345 bool BufferedResourceHandler::ShouldDownload(bool* need_plugin_list) { |
(...skipping 13 matching lines...) Expand all Loading... |
359 if (host_->delegate() && | 359 if (host_->delegate() && |
360 host_->delegate()->ShouldForceDownloadResource(request_->url(), type)) | 360 host_->delegate()->ShouldForceDownloadResource(request_->url(), type)) |
361 return true; | 361 return true; |
362 | 362 |
363 // MIME type checking. | 363 // MIME type checking. |
364 if (net::IsSupportedMimeType(type)) | 364 if (net::IsSupportedMimeType(type)) |
365 return false; | 365 return false; |
366 | 366 |
367 // Finally, check the plugin list. | 367 // Finally, check the plugin list. |
368 bool allow_wildcard = false; | 368 bool allow_wildcard = false; |
369 ResourceDispatcherHostRequestInfo* info = | 369 ResourceRequestInfoImpl* info = |
370 ResourceDispatcherHost::InfoForRequest(request_); | 370 ResourceDispatcherHost::InfoForRequest(request_); |
371 bool stale = false; | 371 bool stale = false; |
372 webkit::WebPluginInfo plugin; | 372 webkit::WebPluginInfo plugin; |
373 bool found = PluginServiceImpl::GetInstance()->GetPluginInfo( | 373 bool found = PluginServiceImpl::GetInstance()->GetPluginInfo( |
374 info->child_id(), info->route_id(), info->context(), | 374 info->GetChildID(), info->GetRouteID(), info->GetContext(), |
375 request_->url(), GURL(), type, allow_wildcard, | 375 request_->url(), GURL(), type, allow_wildcard, |
376 &stale, &plugin, NULL); | 376 &stale, &plugin, NULL); |
377 | 377 |
378 if (need_plugin_list) { | 378 if (need_plugin_list) { |
379 if (stale) { | 379 if (stale) { |
380 *need_plugin_list = true; | 380 *need_plugin_list = true; |
381 return true; | 381 return true; |
382 } | 382 } |
383 } else { | 383 } else { |
384 DCHECK(!stale); | 384 DCHECK(!stale); |
385 } | 385 } |
386 | 386 |
387 return !found; | 387 return !found; |
388 } | 388 } |
389 | 389 |
390 bool BufferedResourceHandler::UseAlternateResourceHandler( | 390 bool BufferedResourceHandler::UseAlternateResourceHandler( |
391 int request_id, | 391 int request_id, |
392 ResourceHandler* handler) { | 392 ResourceHandler* handler) { |
393 // Inform the original ResourceHandler that this will be handled entirely by | 393 // Inform the original ResourceHandler that this will be handled entirely by |
394 // the new ResourceHandler. | 394 // the new ResourceHandler. |
395 // TODO(darin): We should probably check the return values of these. | 395 // TODO(darin): We should probably check the return values of these. |
396 next_handler_->OnResponseStarted(request_id, response_); | 396 next_handler_->OnResponseStarted(request_id, response_); |
397 net::URLRequestStatus status(net::URLRequestStatus::HANDLED_EXTERNALLY, 0); | 397 net::URLRequestStatus status(net::URLRequestStatus::HANDLED_EXTERNALLY, 0); |
398 next_handler_->OnResponseCompleted(request_id, status, std::string()); | 398 next_handler_->OnResponseCompleted(request_id, status, std::string()); |
399 | 399 |
400 // Remove the non-owning pointer to the CrossSiteResourceHandler, if any, | 400 // Remove the non-owning pointer to the CrossSiteResourceHandler, if any, |
401 // from the extra request info because the CrossSiteResourceHandler (part of | 401 // from the extra request info because the CrossSiteResourceHandler (part of |
402 // the original ResourceHandler chain) will be deleted by the next statement. | 402 // the original ResourceHandler chain) will be deleted by the next statement. |
403 ResourceDispatcherHostRequestInfo* info = | 403 ResourceRequestInfoImpl* info = |
404 ResourceDispatcherHost::InfoForRequest(request_); | 404 ResourceDispatcherHost::InfoForRequest(request_); |
405 info->set_cross_site_handler(NULL); | 405 info->set_cross_site_handler(NULL); |
406 | 406 |
407 // This is handled entirely within the new ResourceHandler, so just reset the | 407 // This is handled entirely within the new ResourceHandler, so just reset the |
408 // original ResourceHandler. | 408 // original ResourceHandler. |
409 next_handler_ = handler; | 409 next_handler_ = handler; |
410 | 410 |
411 next_handler_needs_response_started_ = true; | 411 next_handler_needs_response_started_ = true; |
412 next_handler_needs_will_read_ = true; | 412 next_handler_needs_will_read_ = true; |
413 | 413 |
414 return ForwardPendingEventsToNextHandler(request_id); | 414 return ForwardPendingEventsToNextHandler(request_id); |
415 } | 415 } |
416 | 416 |
417 bool BufferedResourceHandler::ForwardPendingEventsToNextHandler( | 417 bool BufferedResourceHandler::ForwardPendingEventsToNextHandler( |
418 int request_id) { | 418 int request_id) { |
419 ResourceDispatcherHostRequestInfo* info = | 419 ResourceRequestInfoImpl* info = |
420 ResourceDispatcherHost::InfoForRequest(request_); | 420 ResourceDispatcherHost::InfoForRequest(request_); |
421 if (info->pause_count()) | 421 if (info->pause_count()) |
422 return true; | 422 return true; |
423 | 423 |
424 if (next_handler_needs_response_started_) { | 424 if (next_handler_needs_response_started_) { |
425 if (!next_handler_->OnResponseStarted(request_id, response_)) | 425 if (!next_handler_->OnResponseStarted(request_id, response_)) |
426 return false; | 426 return false; |
427 // If the request was paused during OnResponseStarted, we need to avoid | 427 // If the request was paused during OnResponseStarted, we need to avoid |
428 // calling OnResponseStarted again. | 428 // calling OnResponseStarted again. |
429 next_handler_needs_response_started_ = false; | 429 next_handler_needs_response_started_ = false; |
(...skipping 23 matching lines...) Expand all Loading... |
453 memcpy(buf->data(), read_buffer_->data(), bytes_read_); | 453 memcpy(buf->data(), read_buffer_->data(), bytes_read_); |
454 } | 454 } |
455 } | 455 } |
456 | 456 |
457 void BufferedResourceHandler::OnPluginsLoaded( | 457 void BufferedResourceHandler::OnPluginsLoaded( |
458 const std::vector<webkit::WebPluginInfo>& plugins) { | 458 const std::vector<webkit::WebPluginInfo>& plugins) { |
459 wait_for_plugins_ = false; | 459 wait_for_plugins_ = false; |
460 if (!request_) | 460 if (!request_) |
461 return; | 461 return; |
462 | 462 |
463 ResourceDispatcherHostRequestInfo* info = | 463 ResourceRequestInfoImpl* info = |
464 ResourceDispatcherHost::InfoForRequest(request_); | 464 ResourceDispatcherHost::InfoForRequest(request_); |
465 host_->PauseRequest(info->child_id(), info->request_id(), false); | 465 int child_id = info->GetChildID(); |
466 if (!CompleteResponseStarted(info->request_id())) | 466 int request_id = info->GetRequestID(); |
467 host_->CancelRequest(info->child_id(), info->request_id(), false); | 467 |
| 468 host_->PauseRequest(child_id, request_id, false); |
| 469 if (!CompleteResponseStarted(request_id)) |
| 470 host_->CancelRequest(child_id, request_id, false); |
468 } | 471 } |
469 | 472 |
470 } // namespace content | 473 } // namespace content |
OLD | NEW |