diff options
author | michaeln@google.com <michaeln@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-10-17 23:00:51 +0000 |
---|---|---|
committer | michaeln@google.com <michaeln@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-10-17 23:00:51 +0000 |
commit | a3c71e8edf494687af2e67bc8fe8b013577bcbb6 (patch) | |
tree | ee46aaaf7a90f4b57065f6af59c2b6a647d92c00 /content | |
parent | 378429dc295cf26b11d20f9e52bc568e4dbf3b4e (diff) | |
download | chromium_src-a3c71e8edf494687af2e67bc8fe8b013577bcbb6.zip chromium_src-a3c71e8edf494687af2e67bc8fe8b013577bcbb6.tar.gz chromium_src-a3c71e8edf494687af2e67bc8fe8b013577bcbb6.tar.bz2 |
A few improvements to Blob handling.
* Break large blobs into multiple ipcs during creation.
* Use shared memory blocks for the xfer.
* Rename some methods and IPCs for readability.
* Cap memory usage in the browser process at 1G.
BUG=97221
Review URL: http://codereview.chromium.org/7974011
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@105950 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content')
-rw-r--r-- | content/browser/renderer_host/blob_message_filter.cc | 78 | ||||
-rw-r--r-- | content/browser/renderer_host/blob_message_filter.h | 20 | ||||
-rw-r--r-- | content/common/webblob_messages.h | 44 | ||||
-rw-r--r-- | content/common/webblobregistry_impl.cc | 73 | ||||
-rw-r--r-- | content/common/webblobregistry_impl.h | 14 | ||||
-rw-r--r-- | content/common/webkit_param_traits.cc | 100 | ||||
-rw-r--r-- | content/common/webkit_param_traits.h | 8 | ||||
-rw-r--r-- | content/renderer/renderer_webkitplatformsupport_impl.cc | 6 |
8 files changed, 175 insertions, 168 deletions
diff --git a/content/browser/renderer_host/blob_message_filter.cc b/content/browser/renderer_host/blob_message_filter.cc index 829c025..6c09451 100644 --- a/content/browser/renderer_host/blob_message_filter.cc +++ b/content/browser/renderer_host/blob_message_filter.cc @@ -11,6 +11,8 @@ #include "webkit/blob/blob_data.h" #include "webkit/blob/blob_storage_controller.h" +using webkit_blob::BlobData; + BlobMessageFilter::BlobMessageFilter( int process_id, ChromeBlobStorageContext* blob_storage_context) @@ -28,7 +30,7 @@ void BlobMessageFilter::OnChannelClosing() { // process. for (base::hash_set<std::string>::const_iterator iter = blob_urls_.begin(); iter != blob_urls_.end(); ++iter) { - blob_storage_context_->controller()->UnregisterBlobUrl(GURL(*iter)); + blob_storage_context_->controller()->RemoveBlob(GURL(*iter)); } } @@ -38,48 +40,70 @@ bool BlobMessageFilter::OnMessageReceived(const IPC::Message& message, bool handled = true; IPC_BEGIN_MESSAGE_MAP_EX(BlobMessageFilter, message, *message_was_ok) - IPC_MESSAGE_HANDLER(BlobHostMsg_RegisterBlobUrl, OnRegisterBlobUrl) - IPC_MESSAGE_HANDLER(BlobHostMsg_RegisterBlobUrlFrom, OnRegisterBlobUrlFrom) - IPC_MESSAGE_HANDLER(BlobHostMsg_UnregisterBlobUrl, OnUnregisterBlobUrl) + IPC_MESSAGE_HANDLER(BlobHostMsg_StartBuildingBlob, OnStartBuildingBlob) + IPC_MESSAGE_HANDLER(BlobHostMsg_AppendBlobDataItem, OnAppendBlobDataItem) + IPC_MESSAGE_HANDLER(BlobHostMsg_SyncAppendSharedMemory, + OnAppendSharedMemory) + IPC_MESSAGE_HANDLER(BlobHostMsg_FinishBuildingBlob, OnFinishBuildingBlob) + IPC_MESSAGE_HANDLER(BlobHostMsg_CloneBlob, OnCloneBlob) + IPC_MESSAGE_HANDLER(BlobHostMsg_RemoveBlob, OnRemoveBlob) IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() return handled; } -// Check if the child process has been granted permission to register the files. -bool BlobMessageFilter::CheckPermission( - webkit_blob::BlobData* blob_data) const { - ChildProcessSecurityPolicy* policy = - ChildProcessSecurityPolicy::GetInstance(); - for (std::vector<webkit_blob::BlobData::Item>::const_iterator iter = - blob_data->items().begin(); - iter != blob_data->items().end(); ++iter) { - if (iter->type() == webkit_blob::BlobData::TYPE_FILE) { - if (!policy->CanReadFile(process_id_, iter->file_path())) - return false; - } - } - return true; +void BlobMessageFilter::OnStartBuildingBlob(const GURL& url) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + blob_storage_context_->controller()->StartBuildingBlob(url); + blob_urls_.insert(url.spec()); } -void BlobMessageFilter::OnRegisterBlobUrl( - const GURL& url, const scoped_refptr<webkit_blob::BlobData>& blob_data) { +void BlobMessageFilter::OnAppendBlobDataItem( + const GURL& url, const BlobData::Item& item) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); - if (!CheckPermission(blob_data.get())) + if (item.type == BlobData::TYPE_FILE && + !ChildProcessSecurityPolicy::GetInstance()->CanReadFile( + process_id_, item.file_path)) { + OnRemoveBlob(url); return; - blob_storage_context_->controller()->RegisterBlobUrl(url, blob_data); - blob_urls_.insert(url.spec()); + } + blob_storage_context_->controller()->AppendBlobDataItem(url, item); +} + +void BlobMessageFilter::OnAppendSharedMemory( + const GURL& url, base::SharedMemoryHandle handle, size_t buffer_size) { + DCHECK(base::SharedMemory::IsHandleValid(handle)); +#if defined(OS_WIN) + base::SharedMemory shared_memory(handle, true, peer_handle()); +#else + base::SharedMemory shared_memory(handle, true); +#endif + if (!shared_memory.Map(buffer_size)) { + OnRemoveBlob(url); + return; + } + + BlobData::Item item; + item.SetToDataExternal(static_cast<char*>(shared_memory.memory()), + buffer_size); + blob_storage_context_->controller()->AppendBlobDataItem(url, item); +} + +void BlobMessageFilter::OnFinishBuildingBlob( + const GURL& url, const std::string& content_type) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + blob_storage_context_->controller()->FinishBuildingBlob(url, content_type); } -void BlobMessageFilter::OnRegisterBlobUrlFrom( +void BlobMessageFilter::OnCloneBlob( const GURL& url, const GURL& src_url) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); - blob_storage_context_->controller()->RegisterBlobUrlFrom(url, src_url); + blob_storage_context_->controller()->CloneBlob(url, src_url); blob_urls_.insert(url.spec()); } -void BlobMessageFilter::OnUnregisterBlobUrl(const GURL& url) { +void BlobMessageFilter::OnRemoveBlob(const GURL& url) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); - blob_storage_context_->controller()->UnregisterBlobUrl(url); + blob_storage_context_->controller()->RemoveBlob(url); blob_urls_.erase(url.spec()); } diff --git a/content/browser/renderer_host/blob_message_filter.h b/content/browser/renderer_host/blob_message_filter.h index ace01db..24758ac 100644 --- a/content/browser/renderer_host/blob_message_filter.h +++ b/content/browser/renderer_host/blob_message_filter.h @@ -6,7 +6,9 @@ #define CONTENT_BROWSER_RENDERER_HOST_BLOB_MESSAGE_FILTER_H_ #include "base/hash_tables.h" +#include "base/shared_memory.h" #include "content/browser/browser_message_filter.h" +#include "webkit/blob/blob_data.h" class ChromeBlobStorageContext; class GURL; @@ -15,10 +17,6 @@ namespace IPC { class Message; } -namespace webkit_blob { -class BlobData; -} - class BlobMessageFilter : public BrowserMessageFilter { public: BlobMessageFilter(int process_id, @@ -31,12 +29,14 @@ class BlobMessageFilter : public BrowserMessageFilter { bool* message_was_ok); private: - void OnRegisterBlobUrl(const GURL& url, - const scoped_refptr<webkit_blob::BlobData>& blob_data); - void OnRegisterBlobUrlFrom(const GURL& url, const GURL& src_url); - void OnUnregisterBlobUrl(const GURL& url); - - bool CheckPermission(webkit_blob::BlobData* blob_data) const; + void OnStartBuildingBlob(const GURL& url); + void OnAppendBlobDataItem(const GURL& url, + const webkit_blob::BlobData::Item& item); + void OnAppendSharedMemory(const GURL& url, base::SharedMemoryHandle handle, + size_t buffer_size); + void OnFinishBuildingBlob(const GURL& url, const std::string& content_type); + void OnCloneBlob(const GURL& url, const GURL& src_url); + void OnRemoveBlob(const GURL& url); int process_id_; scoped_refptr<ChromeBlobStorageContext> blob_storage_context_; diff --git a/content/common/webblob_messages.h b/content/common/webblob_messages.h index 2cbb2b7..6fcd61f 100644 --- a/content/common/webblob_messages.h +++ b/content/common/webblob_messages.h @@ -11,19 +11,47 @@ #define IPC_MESSAGE_START BlobMsgStart +IPC_ENUM_TRAITS(webkit_blob::BlobData::Type) + +IPC_STRUCT_TRAITS_BEGIN(webkit_blob::BlobData::Item) + IPC_STRUCT_TRAITS_MEMBER(type) + IPC_STRUCT_TRAITS_MEMBER(data) + IPC_STRUCT_TRAITS_MEMBER(file_path) + IPC_STRUCT_TRAITS_MEMBER(blob_url) + IPC_STRUCT_TRAITS_MEMBER(offset) + IPC_STRUCT_TRAITS_MEMBER(length) + IPC_STRUCT_TRAITS_MEMBER(expected_modification_time) +IPC_STRUCT_TRAITS_END() + // Blob messages sent from the renderer to the browser. -// Registers a blob URL referring to the specified blob data. -IPC_MESSAGE_CONTROL2(BlobHostMsg_RegisterBlobUrl, + +// Registers a blob as being built. +IPC_MESSAGE_CONTROL1(BlobHostMsg_StartBuildingBlob, + GURL /* url */) + +// Appends data to a blob being built. +IPC_MESSAGE_CONTROL2(BlobHostMsg_AppendBlobDataItem, + GURL /* url */, + webkit_blob::BlobData::Item) + +// Appends data to a blob being built. +IPC_SYNC_MESSAGE_CONTROL3_0(BlobHostMsg_SyncAppendSharedMemory, + GURL /* url */, + base::SharedMemoryHandle, + size_t /* buffer size */) + +// Finishes building a blob. +IPC_MESSAGE_CONTROL2(BlobHostMsg_FinishBuildingBlob, GURL /* url */, - scoped_refptr<webkit_blob::BlobData> /* blob_data */) + std::string /* content_type */) -// Registers a blob URL referring to the blob data identified by the specified -// source URL. -IPC_MESSAGE_CONTROL2(BlobHostMsg_RegisterBlobUrlFrom, +// Creates a new blob that's a clone of an existing src blob. +// The source blob must be fully built. +IPC_MESSAGE_CONTROL2(BlobHostMsg_CloneBlob, GURL /* url */, GURL /* src_url */) -// Unregister a blob URL. -IPC_MESSAGE_CONTROL1(BlobHostMsg_UnregisterBlobUrl, +// Removes a blob. +IPC_MESSAGE_CONTROL1(BlobHostMsg_RemoveBlob, GURL /* url */) diff --git a/content/common/webblobregistry_impl.cc b/content/common/webblobregistry_impl.cc index 7a6a1ea..53d7a74 100644 --- a/content/common/webblobregistry_impl.cc +++ b/content/common/webblobregistry_impl.cc @@ -5,18 +5,21 @@ #include "content/common/webblobregistry_impl.h" #include "base/memory/ref_counted.h" +#include "base/shared_memory.h" +#include "content/common/child_thread.h" #include "content/common/webblob_messages.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebBlobData.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebURL.h" #include "webkit/blob/blob_data.h" +#include "webkit/glue/webkit_glue.h" using WebKit::WebBlobData; using WebKit::WebString; using WebKit::WebURL; -WebBlobRegistryImpl::WebBlobRegistryImpl(IPC::Message::Sender* sender) - : sender_(sender) { +WebBlobRegistryImpl::WebBlobRegistryImpl(ChildThread* child_thread) + : child_thread_(child_thread) { } WebBlobRegistryImpl::~WebBlobRegistryImpl() { @@ -24,16 +27,72 @@ WebBlobRegistryImpl::~WebBlobRegistryImpl() { void WebBlobRegistryImpl::registerBlobURL( const WebURL& url, WebBlobData& data) { - scoped_refptr<webkit_blob::BlobData> blob_data( - new webkit_blob::BlobData(data)); - sender_->Send(new BlobHostMsg_RegisterBlobUrl(url, blob_data)); + const size_t kLargeThresholdBytes = 250 * 1024; + const size_t kMaxSharedMemoryBytes = 10 * 1024 * 1024; + + child_thread_->Send(new BlobHostMsg_StartBuildingBlob(url)); + size_t i = 0; + WebBlobData::Item data_item; + while (data.itemAt(i++, data_item)) { + webkit_blob::BlobData::Item item; + switch (data_item.type) { + case WebBlobData::Item::TypeData: { + // WebBlobData does not allow partial data items. + DCHECK(!data_item.offset && data_item.length == -1); + if (data_item.data.size() < kLargeThresholdBytes) { + item.SetToData(data_item.data.data(), data_item.data.size()); + child_thread_->Send(new BlobHostMsg_AppendBlobDataItem(url, item)); + } else { + // We handle larger amounts of data via SharedMemory instead of + // writing it directly to the IPC channel. + size_t data_size = data_item.data.size(); + const char* data_ptr = data_item.data.data(); + size_t shared_memory_size = std::min( + data_size, kMaxSharedMemoryBytes); + scoped_ptr<base::SharedMemory> shared_memory( + child_thread_->AllocateSharedMemory(shared_memory_size)); + CHECK(shared_memory.get()); + while (data_size) { + size_t chunk_size = std::min(data_size, shared_memory_size); + memcpy(shared_memory->memory(), data_ptr, chunk_size); + child_thread_->Send(new BlobHostMsg_SyncAppendSharedMemory( + url, shared_memory->handle(), chunk_size)); + data_size -= chunk_size; + data_ptr += chunk_size; + } + } + break; + } + case WebBlobData::Item::TypeFile: + item.SetToFile( + webkit_glue::WebStringToFilePath(data_item.filePath), + static_cast<uint64>(data_item.offset), + static_cast<uint64>(data_item.length), + base::Time::FromDoubleT(data_item.expectedModificationTime)); + child_thread_->Send(new BlobHostMsg_AppendBlobDataItem(url, item)); + break; + case WebBlobData::Item::TypeBlob: + if (data_item.length) { + item.SetToBlob( + data_item.blobURL, + static_cast<uint64>(data_item.offset), + static_cast<uint64>(data_item.length)); + } + child_thread_->Send(new BlobHostMsg_AppendBlobDataItem(url, item)); + break; + default: + NOTREACHED(); + } + } + child_thread_->Send(new BlobHostMsg_FinishBuildingBlob( + url, data.contentType().utf8().data())); } void WebBlobRegistryImpl::registerBlobURL( const WebURL& url, const WebURL& src_url) { - sender_->Send(new BlobHostMsg_RegisterBlobUrlFrom(url, src_url)); + child_thread_->Send(new BlobHostMsg_CloneBlob(url, src_url)); } void WebBlobRegistryImpl::unregisterBlobURL(const WebURL& url) { - sender_->Send(new BlobHostMsg_UnregisterBlobUrl(url)); + child_thread_->Send(new BlobHostMsg_RemoveBlob(url)); } diff --git a/content/common/webblobregistry_impl.h b/content/common/webblobregistry_impl.h index 73395d9..6b05683 100644 --- a/content/common/webblobregistry_impl.h +++ b/content/common/webblobregistry_impl.h @@ -6,19 +6,23 @@ #define CHROME_COMMON_WEBBLOBREGISTRY_IMPL_H_ #pragma once -#include "ipc/ipc_message.h" +//#include "ipc/ipc_message.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebBlobRegistry.h" +class ChildThread; + +namespace base { +class SharedMemory; +} + namespace WebKit { class WebBlobData; -class WebBlobStorageData; -class WebString; class WebURL; } class WebBlobRegistryImpl : public WebKit::WebBlobRegistry { public: - explicit WebBlobRegistryImpl(IPC::Message::Sender* sender); + explicit WebBlobRegistryImpl(ChildThread* child_thread); virtual ~WebBlobRegistryImpl(); // See WebBlobRegistry.h for documentation on these functions. @@ -29,7 +33,7 @@ class WebBlobRegistryImpl : public WebKit::WebBlobRegistry { virtual void unregisterBlobURL(const WebKit::WebURL& url); private: - IPC::Message::Sender* sender_; + ChildThread* child_thread_; }; #endif // CHROME_COMMON_WEBBLOBREGISTRY_IMPL_H_ diff --git a/content/common/webkit_param_traits.cc b/content/common/webkit_param_traits.cc index bed2f26..a10eaa8 100644 --- a/content/common/webkit_param_traits.cc +++ b/content/common/webkit_param_traits.cc @@ -150,106 +150,6 @@ void ParamTraits<scoped_refptr<webkit_glue::ResourceDevToolsInfo> >::Log( l->append(")"); } -// Only the webkit_blob::BlobData ParamTraits<> definition needs this -// definition, so keep this in the implementation file so we can forward declare -// BlobData in the header. -template <> -struct ParamTraits<webkit_blob::BlobData::Item> { - typedef webkit_blob::BlobData::Item param_type; - static void Write(Message* m, const param_type& p) { - WriteParam(m, static_cast<int>(p.type())); - if (p.type() == webkit_blob::BlobData::TYPE_DATA) { - WriteParam(m, p.data()); - } else if (p.type() == webkit_blob::BlobData::TYPE_FILE) { - WriteParam(m, p.file_path()); - WriteParam(m, p.offset()); - WriteParam(m, p.length()); - WriteParam(m, p.expected_modification_time()); - } else { - WriteParam(m, p.blob_url()); - WriteParam(m, p.offset()); - WriteParam(m, p.length()); - } - } - static bool Read(const Message* m, void** iter, param_type* r) { - int type; - if (!ReadParam(m, iter, &type)) - return false; - if (type == webkit_blob::BlobData::TYPE_DATA) { - std::string data; - if (!ReadParam(m, iter, &data)) - return false; - r->SetToData(data); - } else if (type == webkit_blob::BlobData::TYPE_FILE) { - FilePath file_path; - uint64 offset, length; - base::Time expected_modification_time; - if (!ReadParam(m, iter, &file_path)) - return false; - if (!ReadParam(m, iter, &offset)) - return false; - if (!ReadParam(m, iter, &length)) - return false; - if (!ReadParam(m, iter, &expected_modification_time)) - return false; - r->SetToFile(file_path, offset, length, expected_modification_time); - } else { - DCHECK(type == webkit_blob::BlobData::TYPE_BLOB); - GURL blob_url; - uint64 offset, length; - if (!ReadParam(m, iter, &blob_url)) - return false; - if (!ReadParam(m, iter, &offset)) - return false; - if (!ReadParam(m, iter, &length)) - return false; - r->SetToBlob(blob_url, offset, length); - } - return true; - } - static void Log(const param_type& p, std::string* l) { - l->append("<BlobData::Item>"); - } -}; - -void ParamTraits<scoped_refptr<webkit_blob::BlobData> >::Write( - Message* m, const param_type& p) { - WriteParam(m, p.get() != NULL); - if (p) { - WriteParam(m, p->items()); - WriteParam(m, p->content_type()); - WriteParam(m, p->content_disposition()); - } -} - -bool ParamTraits<scoped_refptr<webkit_blob::BlobData> >::Read( - const Message* m, void** iter, param_type* r) { - bool has_object; - if (!ReadParam(m, iter, &has_object)) - return false; - if (!has_object) - return true; - std::vector<webkit_blob::BlobData::Item> items; - if (!ReadParam(m, iter, &items)) - return false; - std::string content_type; - if (!ReadParam(m, iter, &content_type)) - return false; - std::string content_disposition; - if (!ReadParam(m, iter, &content_disposition)) - return false; - *r = new webkit_blob::BlobData; - (*r)->swap_items(&items); - (*r)->set_content_type(content_type); - (*r)->set_content_disposition(content_disposition); - return true; -} - -void ParamTraits<scoped_refptr<webkit_blob::BlobData> >::Log( - const param_type& p, std::string* l) { - l->append("<webkit_blob::BlobData>"); -} - void ParamTraits<NPVariant_Param>::Write(Message* m, const param_type& p) { WriteParam(m, static_cast<int>(p.type)); if (p.type == NPVARIANT_PARAM_BOOL) { diff --git a/content/common/webkit_param_traits.h b/content/common/webkit_param_traits.h index 9808e59..8bf9973 100644 --- a/content/common/webkit_param_traits.h +++ b/content/common/webkit_param_traits.h @@ -90,14 +90,6 @@ struct ParamTraits<scoped_refptr<webkit_glue::ResourceDevToolsInfo> > { }; template <> -struct ParamTraits<scoped_refptr<webkit_blob::BlobData > > { - typedef scoped_refptr<webkit_blob::BlobData> param_type; - static void Write(Message* m, const param_type& p); - static bool Read(const Message* m, void** iter, param_type* r); - static void Log(const param_type& p, std::string* l); -}; - -template <> struct ParamTraits<NPVariant_Param> { typedef NPVariant_Param param_type; static void Write(Message* m, const param_type& p); diff --git a/content/renderer/renderer_webkitplatformsupport_impl.cc b/content/renderer/renderer_webkitplatformsupport_impl.cc index 9c71370..6ed042b 100644 --- a/content/renderer/renderer_webkitplatformsupport_impl.cc +++ b/content/renderer/renderer_webkitplatformsupport_impl.cc @@ -604,9 +604,9 @@ RendererWebKitPlatformSupportImpl::signedPublicKeyAndChallengeString( //------------------------------------------------------------------------------ WebBlobRegistry* RendererWebKitPlatformSupportImpl::blobRegistry() { - // RenderThreadImpl::current can be NULL when running some tests. - if (!blob_registry_.get() && RenderThreadImpl::current()) { - blob_registry_.reset(new WebBlobRegistryImpl(RenderThreadImpl::Get())); + // ChildThread::current can be NULL when running some tests. + if (!blob_registry_.get() && ChildThread::current()) { + blob_registry_.reset(new WebBlobRegistryImpl(ChildThread::current())); } return blob_registry_.get(); } |