| 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 |