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 | |
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
23 files changed, 317 insertions, 22 deletions
diff --git a/chrome/browser/browser.scons b/chrome/browser/browser.scons index 6949384..52dada2 100644 --- a/chrome/browser/browser.scons +++ b/chrome/browser/browser.scons @@ -533,6 +533,8 @@ input_files = ChromeFileList([ 'renderer_host/download_resource_handler.h', 'renderer_host/download_throttling_resource_handler.cc', 'renderer_host/download_throttling_resource_handler.h', + 'renderer_host/media_resource_handler.cc', + 'renderer_host/media_resource_handler.h', 'renderer_host/render_process_host.cc', 'renderer_host/render_process_host.h', 'renderer_host/render_view_host.cc', diff --git a/chrome/browser/browser.vcproj b/chrome/browser/browser.vcproj index eeff546..2880e43 100644 --- a/chrome/browser/browser.vcproj +++ b/chrome/browser/browser.vcproj @@ -2022,6 +2022,14 @@ > </File> <File + RelativePath=".\renderer_host\media_resource_handler.cc" + > + </File> + <File + RelativePath=".\renderer_host\media_resource_handler.h" + > + </File> + <File RelativePath=".\renderer_host\render_process_host.cc" > </File> diff --git a/chrome/browser/profile.cc b/chrome/browser/profile.cc index 526e528..352d96582 100644 --- a/chrome/browser/profile.cc +++ b/chrome/browser/profile.cc @@ -99,6 +99,7 @@ class OffTheRecordProfileImpl : public Profile, public: explicit OffTheRecordProfileImpl(Profile* real_profile) : profile_(real_profile), + media_request_context_(NULL), start_time_(Time::Now()) { request_context_ = ChromeURLRequestContext::CreateOffTheRecord(this); request_context_->AddRef(); @@ -352,6 +353,7 @@ ProfileImpl::ProfileImpl(const FilePath& path) personalization_(NULL), #endif request_context_(NULL), + media_request_context_(NULL), history_service_created_(false), created_web_data_service_(false), created_download_manager_(false), 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 diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp index 0068bf6..dc0d55f 100644 --- a/chrome/chrome.gyp +++ b/chrome/chrome.gyp @@ -839,6 +839,8 @@ 'browser/renderer_host/download_resource_handler.h', 'browser/renderer_host/download_throttling_resource_handler.cc', 'browser/renderer_host/download_throttling_resource_handler.h', + 'browser/renderer_host/media_resource_handler.cc', + 'browser/renderer_host/media_resource_handler.h', 'browser/renderer_host/render_process_host.cc', 'browser/renderer_host/render_process_host.h', 'browser/renderer_host/render_view_host.cc', diff --git a/chrome/common/render_messages.h b/chrome/common/render_messages.h index 462d853..048a0a6 100755..100644 --- a/chrome/common/render_messages.h +++ b/chrome/common/render_messages.h @@ -377,6 +377,9 @@ struct ParamTraits<ResourceType::Type> { case ResourceType::OBJECT: type = L"OBJECT"; break; + case ResourceType::MEDIA: + type = L"MEDIA"; + break; default: type = L"UNKNOWN"; break; @@ -1334,6 +1337,7 @@ struct ParamTraits<ResourceResponseHead> { ParamTraits<webkit_glue::ResourceLoaderBridge::ResponseInfo>::Write(m, p); WriteParam(m, p.status); WriteParam(m, p.filter_policy); + WriteParam(m, p.response_data_file); } static bool Read(const Message* m, void** iter, param_type* r) { return @@ -1341,7 +1345,8 @@ struct ParamTraits<ResourceResponseHead> { iter, r) && ReadParam(m, iter, &r->status) && - ReadParam(m, iter, &r->filter_policy); + ReadParam(m, iter, &r->filter_policy) && + ReadParam(m, iter, &r->response_data_file); } static void Log(const param_type& p, std::wstring* l) { // log more? diff --git a/chrome/common/render_messages_internal.h b/chrome/common/render_messages_internal.h index 6416a4b..5ebe6e9 100644 --- a/chrome/common/render_messages_internal.h +++ b/chrome/common/render_messages_internal.h @@ -168,7 +168,14 @@ IPC_BEGIN_MESSAGES(View) int /* request_id */, ResourceResponseHead) - // Sent as upload progress is being made + // Sent as download progress is being made, size of the resource may be + // unknown, in that case |size| is -1. + IPC_MESSAGE_ROUTED3(ViewMsg_Resource_DownloadProgress, + int /* request_id */, + int64 /* position */, + int64 /* size */) + + // Sent as upload progress is being made. IPC_MESSAGE_ROUTED3(ViewMsg_Resource_UploadProgress, int /* request_id */, int64 /* position */, @@ -1104,8 +1111,13 @@ IPC_BEGIN_MESSAGES(ViewHost) GURL /* last url */, GURL /* url redirected to */) - // Sent when the renderer process to acknowlege receipt of and UploadProgress - // message. + // Sent by the renderer process to acknowledge receipt of a + // DownloadProgress message. + IPC_MESSAGE_ROUTED1(ViewHostMsg_DownloadProgress_ACK, + int /* request_id */) + + // Sent by the renderer process to acknowledge receipt of a + // UploadProgress message. IPC_MESSAGE_ROUTED1(ViewHostMsg_UploadProgress_ACK, int /* request_id */) diff --git a/chrome/common/resource_dispatcher.cc b/chrome/common/resource_dispatcher.cc index 61c5013..32f15b1 100644 --- a/chrome/common/resource_dispatcher.cc +++ b/chrome/common/resource_dispatcher.cc @@ -275,6 +275,13 @@ bool ResourceDispatcher::OnMessageReceived(const IPC::Message& message) { return true; } +void ResourceDispatcher::OnDownloadProgress( + int request_id, int64 position, int64 size) { + // TODO(hclam): delegate this message to + // ResourceLoaderBridge::Peer::OnDownloadProgress and send an ACK message + // back to ResourceDispatcherHost. +} + void ResourceDispatcher::OnUploadProgress( const IPC::Message& message, int request_id, int64 position, int64 size) { PendingRequestList::iterator it = pending_requests_.find(request_id); @@ -453,6 +460,7 @@ void ResourceDispatcher::SetDefersLoading(int request_id, bool value) { void ResourceDispatcher::DispatchMessage(const IPC::Message& message) { IPC_BEGIN_MESSAGE_MAP(ResourceDispatcher, message) IPC_MESSAGE_HANDLER(ViewMsg_Resource_UploadProgress, OnUploadProgress) + IPC_MESSAGE_HANDLER(ViewMsg_Resource_DownloadProgress, OnDownloadProgress) IPC_MESSAGE_HANDLER(ViewMsg_Resource_ReceivedResponse, OnReceivedResponse) IPC_MESSAGE_HANDLER(ViewMsg_Resource_ReceivedRedirect, OnReceivedRedirect) IPC_MESSAGE_HANDLER(ViewMsg_Resource_DataReceived, OnReceivedData) @@ -502,6 +510,7 @@ webkit_glue::ResourceLoaderBridge* ResourceDispatcher::CreateBridge( bool ResourceDispatcher::IsResourceMessage(const IPC::Message& message) const { switch (message.type()) { + case ViewMsg_Resource_DownloadProgress::ID: case ViewMsg_Resource_UploadProgress::ID: case ViewMsg_Resource_ReceivedResponse::ID: case ViewMsg_Resource_ReceivedRedirect::ID: diff --git a/chrome/common/resource_dispatcher.h b/chrome/common/resource_dispatcher.h index 3cdf1ee..04db7a1 100644 --- a/chrome/common/resource_dispatcher.h +++ b/chrome/common/resource_dispatcher.h @@ -98,6 +98,7 @@ class ResourceDispatcher { int request_id, int64 position, int64 size); + void OnDownloadProgress(int request_id, int64 position, int64 size); void OnReceivedResponse(int request_id, const ResourceResponseHead&); void OnReceivedRedirect(int request_id, const GURL& new_url); void OnReceivedData(const IPC::Message& message, diff --git a/net/base/load_flags.h b/net/base/load_flags.h index 8557126..354980c 100644 --- a/net/base/load_flags.h +++ b/net/base/load_flags.h @@ -37,6 +37,9 @@ enum { // If present, upload progress messages should be provided to initiator. LOAD_ENABLE_UPLOAD_PROGRESS = 1 << 6, + // If present, try to download the resource to a standalone file. + LOAD_ENABLE_DOWNLOAD_FILE = 1 << 7, + // If present, ignores certificate mismatches with the domain name. // (The default behavior is to trigger an OnSSLCertificateError callback.) LOAD_IGNORE_CERT_COMMON_NAME_INVALID = 1 << 8, diff --git a/net/disk_cache/disk_cache.h b/net/disk_cache/disk_cache.h index 48b7ba5..3ea3b25 100644 --- a/net/disk_cache/disk_cache.h +++ b/net/disk_cache/disk_cache.h @@ -160,9 +160,8 @@ class Entry { // not base::kInvalidPlatformFileValue), there is no guarantee that the file // is truncated. Implementor can always return base::kInvalidPlatformFileValue // if external file is not available in that particular implementation. - // Caller should never close the file handle returned by this method, since - // the handle should be managed by the implementor of this class. Caller - // should never save the handle for future use. + // The caller should close the file handle returned by this method or there + // will be a leak. // With a stream prepared as an external file, the stream would always be // kept in an external file since creation, even if the stream has 0 bytes. // So we need to be cautious about using this option for preparing a stream or @@ -171,10 +170,10 @@ class Entry { // directly *without* buffering. virtual base::PlatformFile UseExternalFile(int index) = 0; - // Returns a read file handle for the cache stream referenced by |index|. - // Caller should never close the handle returned by this method and should - // not save it for future use. The lifetime of the base::PlatformFile handle - // is managed by the implementor of this class. + // Returns an asynchronous read file handle for the cache stream referenced by + // |index|. Values other than base::kInvalidPlatformFileValue are successful + // and the file handle should be managed by the caller, i.e. caller should + // close the handle after use or there will be a leak. virtual base::PlatformFile GetPlatformFile(int index) = 0; protected: diff --git a/net/disk_cache/entry_impl.cc b/net/disk_cache/entry_impl.cc index 361a7ee..446138e 100644 --- a/net/disk_cache/entry_impl.cc +++ b/net/disk_cache/entry_impl.cc @@ -379,11 +379,11 @@ base::PlatformFile EntryImpl::GetPlatformFile(int index) { if (!address.is_initialized() || !address.is_separate_file()) return base::kInvalidPlatformFileValue; - File* cache_file = GetExternalFile(address, index); - if (!cache_file) - return base::kInvalidPlatformFileValue; - - return cache_file->platform_file(); + return base::CreatePlatformFile(backend_->GetFileName(address), + base::PLATFORM_FILE_OPEN | + base::PLATFORM_FILE_READ | + base::PLATFORM_FILE_ASYNC, + NULL); } uint32 EntryImpl::GetHash() { diff --git a/net/http/http_cache.cc b/net/http/http_cache.cc index 75f0256..8637f2d 100644 --- a/net/http/http_cache.cc +++ b/net/http/http_cache.cc @@ -7,6 +7,11 @@ #include <algorithm> #include "base/compiler_specific.h" + +#if defined(OS_POSIX) +#include <unistd.h> +#endif + #include "base/message_loop.h" #include "base/pickle.h" #include "base/ref_counted.h" @@ -607,6 +612,15 @@ void HttpCache::Transaction::SetRequest(const HttpRequestInfo* request) { if (cache_->mode() == RECORD) effective_load_flags_ |= LOAD_BYPASS_CACHE; + // If HttpCache has type MEDIA make sure LOAD_ENABLE_DOWNLOAD_FILE is set, + // otherwise make sure LOAD_ENABLE_DOWNLOAD_FILE is not set when HttpCache + // has type other than MEDIA. + if (cache_->type() == HttpCache::MEDIA) { + DCHECK(effective_load_flags_ & LOAD_ENABLE_DOWNLOAD_FILE); + } else { + DCHECK(!(effective_load_flags_ & LOAD_ENABLE_DOWNLOAD_FILE)); + } + // Some headers imply load flags. The order here is significant. // // LOAD_DISABLE_CACHE : no cache read or write @@ -796,9 +810,10 @@ int HttpCache::Transaction::ReadResponseInfoFromEntry() { // If the cache object is used for media file, we want the file handle of // response data. - if (cache_->type() == HttpCache::MEDIA) + if (cache_->type() == HttpCache::MEDIA) { response_.response_data_file = entry_->disk_entry->GetPlatformFile(kResponseContentIndex); + } return OK; } @@ -869,9 +884,10 @@ void HttpCache::Transaction::TruncateResponseData() { // if we get a valid response from server, i.e. 200. We don't want empty // cache files for redirection or external files for erroneous requests. response_.response_data_file = base::kInvalidPlatformFileValue; - if (cache_->type() == HttpCache::MEDIA) + if (cache_->type() == HttpCache::MEDIA) { response_.response_data_file = entry_->disk_entry->UseExternalFile(kResponseContentIndex); + } // Truncate the stream. WriteToEntry(kResponseContentIndex, 0, NULL, 0); diff --git a/net/http/http_cache_unittest.cc b/net/http/http_cache_unittest.cc index 92980e1..61c2908 100644 --- a/net/http/http_cache_unittest.cc +++ b/net/http/http_cache_unittest.cc @@ -1227,6 +1227,7 @@ TEST(HttpCache, SimpleGET_MediaCache) { #endif ScopedMockTransaction trans_info(kSimpleGET_Transaction); + trans_info.load_flags |= net::LOAD_ENABLE_DOWNLOAD_FILE; TestCompletionCallback callback; { diff --git a/net/http/http_response_info.cc b/net/http/http_response_info.cc index ad6ef87..536d42b 100644 --- a/net/http/http_response_info.cc +++ b/net/http/http_response_info.cc @@ -3,12 +3,12 @@ // found in the LICENSE file. #include "net/http/http_response_info.h" - #include "net/http/http_response_headers.h" namespace net { -HttpResponseInfo::HttpResponseInfo() { +HttpResponseInfo::HttpResponseInfo() + : response_data_file(base::kInvalidPlatformFileValue) { } HttpResponseInfo::~HttpResponseInfo() { diff --git a/net/url_request/url_request.h b/net/url_request/url_request.h index 4309689..dcc999e 100644 --- a/net/url_request/url_request.h +++ b/net/url_request/url_request.h @@ -307,6 +307,13 @@ class URLRequest { return response_info_.ssl_info; } + // Returns the platform specific file handle for the standalone file that + // contains response data. base::kInvalidPlatformFileValue is returned if + // such file is not available. + base::PlatformFile response_data_file() { + return response_info_.response_data_file; + } + // Returns the cookie values included in the response, if the request is one // that can have cookies. Returns true if the request is a cookie-bearing // type, false otherwise. This method may only be called once the diff --git a/webkit/glue/resource_loader_bridge.h b/webkit/glue/resource_loader_bridge.h index 8d32f0c..bd5ad42 100644 --- a/webkit/glue/resource_loader_bridge.h +++ b/webkit/glue/resource_loader_bridge.h @@ -91,6 +91,13 @@ class ResourceLoaderBridge { public: virtual ~Peer() {} + // Called as download progress is made. + // note: only for requests with LOAD_ENABLE_DOWNLOAD_FILE set and the + // resource is downloaded to a standalone file and the file handle to it is + // passed in ResponseInfo during OnReceivedResponse. Note that size may be + // unknown and |size| will be kuint64max in that case. + virtual void OnDownloadProgress(uint64 position, uint64 size) {} + // Called as upload progress is made. // note: only for requests with LOAD_ENABLE_UPLOAD_PROGRESS set virtual void OnUploadProgress(uint64 position, uint64 size) = 0; @@ -105,7 +112,7 @@ class ResourceLoaderBridge { virtual void OnReceivedResponse(const ResponseInfo& info, bool content_filtered) = 0; - // Called when a chunk of response data is available. This method may + // Called when a chunk of response data is available. This method may // be called multiple times or not at all if an error occurs. virtual void OnReceivedData(const char* data, int len) = 0; |