diff options
author | hclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-03-13 20:06:57 +0000 |
---|---|---|
committer | hclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-03-13 20:06:57 +0000 |
commit | 363347b61871d82d0f84d14d5a24288ac79eddc3 (patch) | |
tree | 5cfc6dc4c874e9d23d3fc66ae4b9294bf549921b /chrome/browser/renderer_host | |
parent | cc7948aeb5fe21af08a2d5e868c0087ded0d244a (diff) | |
download | chromium_src-363347b61871d82d0f84d14d5a24288ac79eddc3.zip chromium_src-363347b61871d82d0f84d14d5a24288ac79eddc3.tar.gz chromium_src-363347b61871d82d0f84d14d5a24288ac79eddc3.tar.bz2 |
Highlights of changes:
1. Added entry to ResourceResponseHead so that it contains
either a base::PlatformFile (OS_WIN) or
base::FileDescriptor (OS_POSIX) for passing the file
handle from browser to renderer process.
2. Also added IPC messages for reporting download progress
and ACK message for it. ResourceLoaderBridge::Peer::OnDownloadProgress
is added so that the peer is notified of the download
progress in the renderer process.
3. Load flag to kick start the resource loading for media
files. LOAD_MEDIA_RESOURCE is added so that
ResourceDispatcherHost knows how to use a different
ResourceHandler for handling media resource request.
Review URL: http://codereview.chromium.org/27168
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@11661 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/renderer_host')
7 files changed, 222 insertions, 1 deletions
diff --git a/chrome/browser/renderer_host/media_resource_handler.cc b/chrome/browser/renderer_host/media_resource_handler.cc new file mode 100644 index 0000000..ca79b0d --- /dev/null +++ b/chrome/browser/renderer_host/media_resource_handler.cc @@ -0,0 +1,98 @@ +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/renderer_host/media_resource_handler.h" + +#include "base/process.h" +#include "chrome/common/render_messages.h" +#include "net/base/load_flags.h" + +MediaResourceHandler::MediaResourceHandler( + ResourceHandler* resource_handler, + ResourceDispatcherHost::Receiver* receiver, + int render_process_host_id, + int routing_id, + base::ProcessHandle render_process, + ResourceDispatcherHost* resource_dispatcher_host) + : receiver_(receiver), + render_process_host_id_(render_process_host_id), + routing_id_(routing_id), + render_process_(render_process), + handler_(resource_handler), + rdh_(resource_dispatcher_host), + has_file_handle_(false), + position_(0), + size_(-1) { +} + +bool MediaResourceHandler::OnUploadProgress(int request_id, + uint64 position, + uint64 size) { + return handler_->OnUploadProgress(request_id, position, size); +} + +bool MediaResourceHandler::OnRequestRedirected(int request_id, + const GURL& new_url) { + return handler_->OnRequestRedirected(request_id, new_url); +} + +bool MediaResourceHandler::OnResponseStarted(int request_id, + ResourceResponse* response) { +#if defined(OS_POSIX) + if (response->response_head.response_data_file.fd != + base::kInvalidPlatformFileValue) { + // On POSIX, we will just set auto_close to true, and the IPC infrastructure + // will send this file handle through and close it automatically. + response->response_head.response_data_file.auto_close = true; + has_file_handle_ = true; + } +#elif defined(OS_WIN) + if (response->response_head.response_data_file != + base::kInvalidPlatformFileValue) { + // On Windows, we duplicate the file handle for the renderer process and + // close the original manually. + base::PlatformFile foreign_handle; + if (DuplicateHandle(GetCurrentProcess(), + response->response_head.response_data_file, + render_process_, + &foreign_handle, + FILE_READ_DATA, // Only allow read access to data. + false, // Foreign handle is not inheritable. + // Close the file handle after duplication. + DUPLICATE_CLOSE_SOURCE)){ + response->response_head.response_data_file = foreign_handle; + has_file_handle_ = true; + } else { + has_file_handle_ = false; + } + } +#endif + size_ = response->response_head.content_length; + return handler_->OnResponseStarted(request_id, response); +} + +bool MediaResourceHandler::OnWillRead(int request_id, + net::IOBuffer** buf, int* buf_size, + int min_size) { + return handler_->OnWillRead(request_id, buf, buf_size, min_size); +} + +bool MediaResourceHandler::OnReadCompleted(int request_id, int* bytes_read) { + if (has_file_handle_) { + // If we have received a file handle before we will be sending a progress + // update for download. + // TODO(hclam): rate limit this message so we won't be sending too much to + // the renderer process. + receiver_->Send( + new ViewMsg_Resource_DownloadProgress(routing_id_, request_id, + position_, size_)); + position_ += *bytes_read; + } + return handler_->OnReadCompleted(request_id, bytes_read); +} + +bool MediaResourceHandler::OnResponseCompleted(int request_id, + const URLRequestStatus& status, const std::string& security_info) { + return handler_->OnResponseCompleted(request_id, status, security_info); +} diff --git a/chrome/browser/renderer_host/media_resource_handler.h b/chrome/browser/renderer_host/media_resource_handler.h new file mode 100644 index 0000000..93be6d706 --- /dev/null +++ b/chrome/browser/renderer_host/media_resource_handler.h @@ -0,0 +1,50 @@ +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_RENDERER_HOST_MEDIA_RESOURCE_HANDLER_H_ +#define CHROME_BROWSER_RENDERER_HOST_MEDIA_RESOURCE_HANDLER_H_ + +#include "base/process.h" +#include "base/platform_file.h" +#include "chrome/browser/renderer_host/resource_dispatcher_host.h" +#include "chrome/browser/renderer_host/resource_handler.h" + +// Used to complete a media resource request in response to resource load events +// from the resource dispatcher host. This handler only works asynchronously and +// tries to work with file for response data if possible. If a response data +// file is not available, it redirects calls to underlying handler. +class MediaResourceHandler : public ResourceHandler { + public: + MediaResourceHandler(ResourceHandler* resource_handler, + ResourceDispatcherHost::Receiver* receiver, + int render_process_host_id, + int routing_id, + base::ProcessHandle render_process, + ResourceDispatcherHost* resource_dispatcher_host); + + // ResourceHandler implementation: + bool OnUploadProgress(int request_id, uint64 position, uint64 size); + bool OnRequestRedirected(int request_id, const GURL& new_url); + bool OnResponseStarted(int request_id, ResourceResponse* response); + bool OnWillRead(int request_id, net::IOBuffer** buf, int* buf_size, + int min_size); + bool OnReadCompleted(int request_id, int* bytes_read); + bool OnResponseCompleted(int request_id, const URLRequestStatus& status, + const std::string& security_info); + + private: + ResourceDispatcherHost::Receiver* receiver_; + int render_process_host_id_; + int routing_id_; + base::ProcessHandle render_process_; + scoped_refptr<ResourceHandler> handler_; + ResourceDispatcherHost* rdh_; + bool has_file_handle_; + int64 position_; + int64 size_; + + DISALLOW_COPY_AND_ASSIGN(MediaResourceHandler); +}; + +#endif // CHROME_BROWSER_RENDERER_HOST_MEDIA_RESOURCE_HANDLER_H_ diff --git a/chrome/browser/renderer_host/resource_dispatcher_host.cc b/chrome/browser/renderer_host/resource_dispatcher_host.cc index b4535ca..057343d 100644 --- a/chrome/browser/renderer_host/resource_dispatcher_host.cc +++ b/chrome/browser/renderer_host/resource_dispatcher_host.cc @@ -22,6 +22,7 @@ #include "chrome/browser/renderer_host/buffered_resource_handler.h" #include "chrome/browser/renderer_host/cross_site_resource_handler.h" #include "chrome/browser/renderer_host/download_resource_handler.h" +#include "chrome/browser/renderer_host/media_resource_handler.h" #include "chrome/browser/renderer_host/render_view_host.h" #include "chrome/browser/renderer_host/renderer_security_policy.h" #include "chrome/browser/renderer_host/resource_request_details.h" @@ -248,6 +249,17 @@ void ResourceDispatcherHost::BeginRequest( process_handle, request_data.url, this); + // If the resource type is ResourceType::MEDIA and LOAD_ENABLE_DOWNLOAD_FILE + // is enabled we insert a media resource handler. + if (request_data.resource_type == ResourceType::MEDIA && + (request_data.load_flags & net::LOAD_ENABLE_DOWNLOAD_FILE)) { + handler = new MediaResourceHandler(handler, + receiver, + process_id, + route_id, + process_handle, + this); + } } if (HandleExternalProtocol(request_id, process_id, route_id, @@ -513,6 +525,11 @@ void ResourceDispatcherHost::OnDataReceivedACK(int process_id, } } +void ResourceDispatcherHost::OnDownloadProgressACK(int process_id, + int request_id) { + // TODO(hclam): do something to help rate limiting the message. +} + void ResourceDispatcherHost::OnUploadProgressACK(int process_id, int request_id) { PendingRequestList::iterator i = pending_requests_.find( @@ -811,6 +828,15 @@ bool ResourceDispatcherHost::CompleteResponseStarted(URLRequest* request) { response->response_head.content_length = request->GetExpectedContentSize(); request->GetMimeType(&response->response_head.mime_type); + // Make sure we don't get a file handle if LOAD_ENABLE_FILE is not set. + DCHECK((request->load_flags() & net::LOAD_ENABLE_DOWNLOAD_FILE) || + request->response_data_file() == base::kInvalidPlatformFileValue); +#if defined(OS_POSIX) + response->response_head.response_data_file.fd = request->response_data_file(); +#elif defined(OS_WIN) + response->response_head.response_data_file = request->response_data_file(); +#endif + if (request->ssl_info().cert) { int cert_id = CertStore::GetSharedInstance()->StoreCert( diff --git a/chrome/browser/renderer_host/resource_dispatcher_host.h b/chrome/browser/renderer_host/resource_dispatcher_host.h index 931401e..3d14213 100644 --- a/chrome/browser/renderer_host/resource_dispatcher_host.h +++ b/chrome/browser/renderer_host/resource_dispatcher_host.h @@ -237,6 +237,10 @@ class ResourceDispatcherHost : public URLRequest::Delegate { // messages sent. void OnDataReceivedACK(int process_id, int request_id); + // Called when the renderer process confirms the reception of a download + // progress message. + void OnDownloadProgressACK(int process_id, int request_id); + // Resets the waiting_for_upload_progress_ack flag. void OnUploadProgressACK(int process_id, int request_id); diff --git a/chrome/browser/renderer_host/resource_handler.h b/chrome/browser/renderer_host/resource_handler.h index 2b843f9..e0713d9 100644 --- a/chrome/browser/renderer_host/resource_handler.h +++ b/chrome/browser/renderer_host/resource_handler.h @@ -14,6 +14,11 @@ #include <string> +#include "build/build_config.h" +#if defined(OS_POSIX) +#include "base/file_descriptor_posix.h" +#endif +#include "base/platform_file.h" #include "chrome/common/filter_policy.h" #include "net/url_request/url_request_status.h" #include "webkit/glue/resource_loader_bridge.h" @@ -31,6 +36,20 @@ struct ResourceResponseHead // Specifies if the resource should be filtered before being displayed // (insecure resources can be filtered to keep the page secure). FilterPolicy::Type filter_policy; + + // A platform specific handle for a file that carries response data. This + // entry is used if the resource request is of type ResourceType::MEDIA and + // the underlying cache layer keeps the response data in a standalone file. +#if defined(OS_POSIX) + // If the response data file is available, the file handle is stored in + // response_data_file.fd, its value is base::kInvalidPlatformFileValue + // otherwise. + base::FileDescriptor response_data_file; +#elif defined(OS_WIN) + // An asynchronous file handle to the response data file, its value is + // base::kInvalidPlatformFileValue if the file is not available. + base::PlatformFile response_data_file; +#endif }; // Parameters for a synchronous resource response. diff --git a/chrome/browser/renderer_host/resource_message_filter.cc b/chrome/browser/renderer_host/resource_message_filter.cc index 02ae30a..404e68b 100644 --- a/chrome/browser/renderer_host/resource_message_filter.cc +++ b/chrome/browser/renderer_host/resource_message_filter.cc @@ -32,6 +32,7 @@ #include "chrome/common/render_messages.h" #include "net/base/cookie_monster.h" #include "net/base/mime_util.h" +#include "net/base/load_flags.h" #include "net/url_request/url_request_context.h" #include "webkit/glue/webkit_glue.h" #include "webkit/glue/webplugin.h" @@ -114,11 +115,14 @@ ResourceMessageFilter::ResourceMessageFilter( ALLOW_THIS_IN_INITIALIZER_LIST(resolve_proxy_msg_helper_(this, NULL)), render_handle_(NULL), request_context_(profile->GetRequestContext()), + media_request_context_(profile->GetRequestContextForMedia()), profile_(profile), render_widget_helper_(render_widget_helper), audio_renderer_host_(audio_renderer_host) { DCHECK(request_context_.get()); DCHECK(request_context_->cookie_store()); + DCHECK(media_request_context_.get()); + DCHECK(media_request_context_->cookie_store()); DCHECK(audio_renderer_host_.get()); } @@ -188,6 +192,7 @@ bool ResourceMessageFilter::OnMessageReceived(const IPC::Message& message) { IPC_MESSAGE_HANDLER(ViewHostMsg_CancelRequest, OnCancelRequest) IPC_MESSAGE_HANDLER(ViewHostMsg_ClosePage_ACK, OnClosePageACK) IPC_MESSAGE_HANDLER(ViewHostMsg_DataReceived_ACK, OnDataReceivedACK) + IPC_MESSAGE_HANDLER(ViewHostMsg_DownloadProgress_ACK, OnDownloadProgressACK) IPC_MESSAGE_HANDLER(ViewHostMsg_UploadProgress_ACK, OnUploadProgressACK) IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_SyncLoad, OnSyncLoad) @@ -333,6 +338,16 @@ void ResourceMessageFilter::OnRequestResource( const IPC::Message& message, int request_id, const ViewHostMsg_Resource_Request& request) { + URLRequestContext* request_context = request_context_; + // If the request has resource type of ResourceType::MEDIA and + // LOAD_ENABLE_DOWNLOAD_FILE is set as a load flag, we use a request context + // specific to media for handling it because these resources have specific + // needs for caching and data passing. + if (request.resource_type == ResourceType::MEDIA && + (request.load_flags & net::LOAD_ENABLE_DOWNLOAD_FILE)) { + request_context = media_request_context_; + } + resource_dispatcher_host_->BeginRequest(this, ChildProcessInfo::RENDER_PROCESS, render_handle_, @@ -340,7 +355,7 @@ void ResourceMessageFilter::OnRequestResource( message.routing_id(), request_id, request, - request_context_, + request_context, NULL); } @@ -348,6 +363,11 @@ void ResourceMessageFilter::OnDataReceivedACK(int request_id) { resource_dispatcher_host_->OnDataReceivedACK(render_process_id_, request_id); } +void ResourceMessageFilter::OnDownloadProgressACK(int request_id) { + resource_dispatcher_host_->OnDownloadProgressACK(render_process_id_, + request_id); +} + void ResourceMessageFilter::OnUploadProgressACK(int request_id) { resource_dispatcher_host_->OnUploadProgressACK(render_process_id_, request_id); diff --git a/chrome/browser/renderer_host/resource_message_filter.h b/chrome/browser/renderer_host/resource_message_filter.h index 10a12ed..3269c89 100644 --- a/chrome/browser/renderer_host/resource_message_filter.h +++ b/chrome/browser/renderer_host/resource_message_filter.h @@ -101,6 +101,7 @@ class ResourceMessageFilter : public IPC::ChannelProxy::MessageFilter, void OnCancelRequest(int request_id); void OnClosePageACK(int new_render_process_host_id, int new_request_id); void OnDataReceivedACK(int request_id); + void OnDownloadProgressACK(int request_id); void OnUploadProgressACK(int request_id); void OnSyncLoad(int request_id, const ViewHostMsg_Resource_Request& request, @@ -251,6 +252,9 @@ class ResourceMessageFilter : public IPC::ChannelProxy::MessageFilter, // Contextual information to be used for requests created here. scoped_refptr<URLRequestContext> request_context_; + // A request context specific for media resources. + scoped_refptr<URLRequestContext> media_request_context_; + // A pointer to the profile associated with this filter. // // DANGER! Do not dereference this pointer! This class lives on the I/O thread |