| Index: content/child/webblobregistry_impl.cc
|
| diff --git a/content/child/webblobregistry_impl.cc b/content/child/webblobregistry_impl.cc
|
| index 22f6f43acdc25c351b2e70b575a56bc04540d2a4..1967c7b151a0e551cf6d0cddb17c1ff5ef0567aa 100644
|
| --- a/content/child/webblobregistry_impl.cc
|
| +++ b/content/child/webblobregistry_impl.cc
|
| @@ -7,6 +7,7 @@
|
| #include "base/files/file_path.h"
|
| #include "base/guid.h"
|
| #include "base/memory/ref_counted.h"
|
| +#include "base/memory/scoped_ptr.h"
|
| #include "base/memory/shared_memory.h"
|
| #include "base/message_loop/message_loop.h"
|
| #include "base/trace_event/trace_event.h"
|
| @@ -22,6 +23,8 @@ using blink::WebBlobData;
|
| using blink::WebString;
|
| using blink::WebThreadSafeData;
|
| using blink::WebURL;
|
| +using blink::WebBlobRegistry;
|
| +using storage::DataElement;
|
|
|
| namespace content {
|
|
|
| @@ -42,79 +45,55 @@ WebBlobRegistryImpl::WebBlobRegistryImpl(ThreadSafeSender* sender)
|
| WebBlobRegistryImpl::~WebBlobRegistryImpl() {
|
| }
|
|
|
| -void WebBlobRegistryImpl::registerBlobData(
|
| - const blink::WebString& uuid, const blink::WebBlobData& data) {
|
| - TRACE_EVENT0("Blob", "Registry::RegisterBlob");
|
| - const std::string uuid_str(uuid.utf8());
|
| +blink::WebBlobRegistry::Builder* WebBlobRegistryImpl::createBuilder(
|
| + const blink::WebString& uuid,
|
| + const blink::WebString& contentType) {
|
| + return new BuilderImpl(uuid, contentType, sender_.get());
|
| +}
|
|
|
| - storage::DataElement data_buffer;
|
| - data_buffer.SetToEmptyBytes();
|
| +void WebBlobRegistryImpl::registerBlobData(const blink::WebString& uuid,
|
| + const blink::WebBlobData& data) {
|
| + TRACE_EVENT0("Blob", "Registry::RegisterBlob");
|
| + scoped_ptr<Builder> builder(createBuilder(uuid, data.contentType()));
|
|
|
| - sender_->Send(new BlobHostMsg_StartBuilding(uuid_str));
|
| + // This is temporary until we move to createBuilder() as our blob creation
|
| + // method.
|
| size_t i = 0;
|
| WebBlobData::Item data_item;
|
| while (data.itemAt(i++, data_item)) {
|
| - // NOTE: data_item.length == -1 when we want to use the whole file. This
|
| - // only happens when we are creating a file object in Blink, and the file
|
| - // object is the only item in the 'blob'. If we use that file blob to
|
| - // create another blob, it is sent here as a 'file' item and not a blob,
|
| - // and the correct size is populated.
|
| - // static_cast<uint64>(-1) == kuint64max, which is what DataElement uses
|
| - // to specificy "use the whole file".
|
| if (data_item.length == 0) {
|
| continue;
|
| }
|
| - if (data_item.type != WebBlobData::Item::TypeData &&
|
| - data_buffer.length() != 0) {
|
| - FlushBlobItemBuffer(uuid_str, &data_buffer);
|
| - }
|
| - storage::DataElement 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() == 0) {
|
| - continue;
|
| - }
|
| - BufferBlobData(uuid_str, data_item.data, &data_buffer);
|
| + builder->appendData(data_item.data);
|
| break;
|
| }
|
| case WebBlobData::Item::TypeFile:
|
| - item.SetToFilePathRange(
|
| - base::FilePath::FromUTF16Unsafe(data_item.filePath),
|
| - static_cast<uint64>(data_item.offset),
|
| - static_cast<uint64>(data_item.length),
|
| - base::Time::FromDoubleT(data_item.expectedModificationTime));
|
| - sender_->Send(new BlobHostMsg_AppendBlobDataItem(uuid_str, item));
|
| + builder->appendFile(data_item.filePath,
|
| + static_cast<uint64_t>(data_item.offset),
|
| + static_cast<uint64_t>(data_item.length),
|
| + data_item.expectedModificationTime);
|
| break;
|
| case WebBlobData::Item::TypeBlob:
|
| - item.SetToBlobRange(
|
| - data_item.blobUUID.utf8(),
|
| - static_cast<uint64>(data_item.offset),
|
| - static_cast<uint64>(data_item.length));
|
| - sender_->Send(
|
| - new BlobHostMsg_AppendBlobDataItem(uuid_str, item));
|
| + builder->appendBlob(data_item.blobUUID, data_item.offset,
|
| + data_item.length);
|
| break;
|
| case WebBlobData::Item::TypeFileSystemURL:
|
| // We only support filesystem URL as of now.
|
| DCHECK(GURL(data_item.fileSystemURL).SchemeIsFileSystem());
|
| - item.SetToFileSystemUrlRange(
|
| - data_item.fileSystemURL,
|
| - static_cast<uint64>(data_item.offset),
|
| - static_cast<uint64>(data_item.length),
|
| - base::Time::FromDoubleT(data_item.expectedModificationTime));
|
| - sender_->Send(
|
| - new BlobHostMsg_AppendBlobDataItem(uuid_str, item));
|
| + builder->appendFileSystemURL(data_item.fileSystemURL,
|
| + static_cast<uint64>(data_item.offset),
|
| + static_cast<uint64>(data_item.length),
|
| + data_item.expectedModificationTime);
|
| break;
|
| default:
|
| NOTREACHED();
|
| }
|
| }
|
| - if (data_buffer.length() != 0) {
|
| - FlushBlobItemBuffer(uuid_str, &data_buffer);
|
| - }
|
| - sender_->Send(new BlobHostMsg_FinishBuilding(
|
| - uuid_str, data.contentType().utf8().data()));
|
| + builder->build();
|
| }
|
|
|
| void WebBlobRegistryImpl::addBlobDataRef(const WebString& uuid) {
|
| @@ -125,8 +104,8 @@ void WebBlobRegistryImpl::removeBlobDataRef(const WebString& uuid) {
|
| sender_->Send(new BlobHostMsg_DecrementRefCount(uuid.utf8()));
|
| }
|
|
|
| -void WebBlobRegistryImpl::registerPublicBlobURL(
|
| - const WebURL& url, const WebString& uuid) {
|
| +void WebBlobRegistryImpl::registerPublicBlobURL(const WebURL& url,
|
| + const WebString& uuid) {
|
| sender_->Send(new BlobHostMsg_RegisterPublicURL(url, uuid.utf8()));
|
| }
|
|
|
| @@ -134,88 +113,34 @@ void WebBlobRegistryImpl::revokePublicBlobURL(const WebURL& url) {
|
| sender_->Send(new BlobHostMsg_RevokePublicURL(url));
|
| }
|
|
|
| -void WebBlobRegistryImpl::FlushBlobItemBuffer(
|
| - const std::string& uuid_str,
|
| - storage::DataElement* data_buffer) const {
|
| - DCHECK_NE(data_buffer->length(), 0ul);
|
| - DCHECK_LT(data_buffer->length(), kLargeThresholdBytes);
|
| - sender_->Send(new BlobHostMsg_AppendBlobDataItem(uuid_str, *data_buffer));
|
| - data_buffer->SetToEmptyBytes();
|
| -}
|
| -
|
| -void WebBlobRegistryImpl::BufferBlobData(const std::string& uuid_str,
|
| - const blink::WebThreadSafeData& data,
|
| - storage::DataElement* data_buffer) {
|
| - size_t buffer_size = data_buffer->length();
|
| - size_t data_size = data.size();
|
| - DCHECK_NE(data_size, 0ul);
|
| - if (buffer_size != 0 && buffer_size + data_size >= kLargeThresholdBytes) {
|
| - FlushBlobItemBuffer(uuid_str, data_buffer);
|
| - buffer_size = 0;
|
| - }
|
| - if (data_size >= kLargeThresholdBytes) {
|
| - TRACE_EVENT0("Blob", "Registry::SendOversizedBlobData");
|
| - SendOversizedDataForBlob(uuid_str, data);
|
| - } else {
|
| - DCHECK_LT(buffer_size + data_size, kLargeThresholdBytes);
|
| - data_buffer->AppendBytes(data.data(), data_size);
|
| - }
|
| -}
|
| -
|
| -void WebBlobRegistryImpl::SendOversizedDataForBlob(
|
| - const std::string& uuid_str,
|
| - const blink::WebThreadSafeData& data) {
|
| - DCHECK_GE(data.size(), kLargeThresholdBytes);
|
| - // We handle larger amounts of data via SharedMemory instead of
|
| - // writing it directly to the IPC channel.
|
| - size_t shared_memory_size = std::min(data.size(), kMaxSharedMemoryBytes);
|
| - scoped_ptr<base::SharedMemory> shared_memory(
|
| - ChildThreadImpl::AllocateSharedMemory(shared_memory_size, sender_.get()));
|
| - CHECK(shared_memory.get());
|
| - if (!shared_memory->Map(shared_memory_size))
|
| - CHECK(false);
|
| -
|
| - size_t data_size = data.size();
|
| - const char* data_ptr = data.data();
|
| - while (data_size) {
|
| - TRACE_EVENT0("Blob", "Registry::SendOversizedBlobItem");
|
| - size_t chunk_size = std::min(data_size, shared_memory_size);
|
| - memcpy(shared_memory->memory(), data_ptr, chunk_size);
|
| - sender_->Send(new BlobHostMsg_SyncAppendSharedMemory(
|
| - uuid_str, shared_memory->handle(), chunk_size));
|
| - data_size -= chunk_size;
|
| - data_ptr += chunk_size;
|
| - }
|
| -}
|
| -
|
| // ------ streams stuff -----
|
|
|
| -void WebBlobRegistryImpl::registerStreamURL(
|
| - const WebURL& url, const WebString& content_type) {
|
| +void WebBlobRegistryImpl::registerStreamURL(const WebURL& url,
|
| + const WebString& content_type) {
|
| DCHECK(ChildThreadImpl::current());
|
| sender_->Send(new StreamHostMsg_StartBuilding(url, content_type.utf8()));
|
| }
|
|
|
| -void WebBlobRegistryImpl::registerStreamURL(
|
| - const WebURL& url, const WebURL& src_url) {
|
| +void WebBlobRegistryImpl::registerStreamURL(const WebURL& url,
|
| + const WebURL& src_url) {
|
| DCHECK(ChildThreadImpl::current());
|
| sender_->Send(new StreamHostMsg_Clone(url, src_url));
|
| }
|
|
|
| void WebBlobRegistryImpl::addDataToStream(const WebURL& url,
|
| - const char* data, size_t length) {
|
| + const char* data,
|
| + size_t length) {
|
| DCHECK(ChildThreadImpl::current());
|
| if (length == 0)
|
| return;
|
| if (length < kLargeThresholdBytes) {
|
| - storage::DataElement item;
|
| + DataElement item;
|
| item.SetToBytes(data, length);
|
| sender_->Send(new StreamHostMsg_AppendBlobDataItem(url, item));
|
| } else {
|
| // We handle larger amounts of data via SharedMemory instead of
|
| // writing it directly to the IPC channel.
|
| - size_t shared_memory_size = std::min(
|
| - length, kMaxSharedMemoryBytes);
|
| + size_t shared_memory_size = std::min(length, kMaxSharedMemoryBytes);
|
| scoped_ptr<base::SharedMemory> shared_memory(
|
| ChildThreadImpl::AllocateSharedMemory(shared_memory_size,
|
| sender_.get()));
|
| @@ -256,4 +181,129 @@ void WebBlobRegistryImpl::unregisterStreamURL(const WebURL& url) {
|
| sender_->Send(new StreamHostMsg_Remove(url));
|
| }
|
|
|
| +WebBlobRegistryImpl::BuilderImpl::BuilderImpl(
|
| + const blink::WebString& uuid,
|
| + const blink::WebString& content_type,
|
| + ThreadSafeSender* sender)
|
| + : uuid_(uuid.utf8()), content_type_(content_type.utf8()), sender_(sender) {
|
| +}
|
| +
|
| +WebBlobRegistryImpl::BuilderImpl::~BuilderImpl() {
|
| +}
|
| +
|
| +void WebBlobRegistryImpl::BuilderImpl::appendData(
|
| + const WebThreadSafeData& data) {
|
| + consolidation_.AddDataItem(data);
|
| +}
|
| +
|
| +void WebBlobRegistryImpl::BuilderImpl::appendBlob(const WebString& uuid,
|
| + uint64_t offset,
|
| + uint64_t length) {
|
| + consolidation_.AddBlobItem(uuid.utf8(), offset, length);
|
| +}
|
| +
|
| +void WebBlobRegistryImpl::BuilderImpl::appendFile(
|
| + const WebString& path,
|
| + uint64_t offset,
|
| + uint64_t length,
|
| + double expected_modification_time) {
|
| + consolidation_.AddFileItem(
|
| + base::FilePath::FromUTF16Unsafe(base::string16(path)), offset, length,
|
| + expected_modification_time);
|
| +}
|
| +
|
| +void WebBlobRegistryImpl::BuilderImpl::appendFileSystemURL(
|
| + const WebURL& fileSystemURL,
|
| + uint64_t offset,
|
| + uint64_t length,
|
| + double expected_modification_time) {
|
| + DCHECK(GURL(fileSystemURL).SchemeIsFileSystem());
|
| + consolidation_.AddFileSystemItem(GURL(fileSystemURL), offset, length,
|
| + expected_modification_time);
|
| +}
|
| +
|
| +void WebBlobRegistryImpl::BuilderImpl::build() {
|
| + sender_->Send(new BlobHostMsg_StartBuilding(uuid_));
|
| + const auto& items = consolidation_.consolidated_items();
|
| +
|
| + // We still need a buffer to hold the continuous block of data so the
|
| + // DataElement can hold it.
|
| + size_t buffer_size = 0;
|
| + scoped_ptr<char[]> buffer;
|
| + for (size_t i = 0; i < items.size(); i++) {
|
| + const BlobConsolidation::ConsolidatedItem& item = items[i];
|
| + DataElement element;
|
| + // NOTE: length == -1 when we want to use the whole file. This
|
| + // only happens when we are creating a file object in Blink, and the file
|
| + // object is the only item in the 'blob'. If we use that file blob to
|
| + // create another blob, it is sent here as a 'file' item and not a blob,
|
| + // and the correct size is populated.
|
| + // static_cast<uint64>(-1) == kuint64max, which is what DataElement uses
|
| + // to specificy "use the whole file".
|
| + switch (item.type) {
|
| + case DataElement::TYPE_BYTES:
|
| + if (item.length > kLargeThresholdBytes) {
|
| + SendOversizedDataForBlob(i);
|
| + break;
|
| + }
|
| + if (buffer_size < item.length) {
|
| + buffer.reset(new char[item.length]);
|
| + buffer_size = item.length;
|
| + }
|
| + consolidation_.ReadMemory(i, 0, item.length, buffer.get());
|
| + element.SetToSharedBytes(buffer.get(), item.length);
|
| + sender_->Send(new BlobHostMsg_AppendBlobDataItem(uuid_, element));
|
| + break;
|
| + case DataElement::TYPE_FILE:
|
| + element.SetToFilePathRange(
|
| + item.path, item.offset, item.length,
|
| + base::Time::FromDoubleT(item.expected_modification_time));
|
| + sender_->Send(new BlobHostMsg_AppendBlobDataItem(uuid_, element));
|
| + break;
|
| + case DataElement::TYPE_BLOB:
|
| + element.SetToBlobRange(item.blob_uuid, item.offset, item.length);
|
| + sender_->Send(new BlobHostMsg_AppendBlobDataItem(uuid_, element));
|
| + break;
|
| + case DataElement::TYPE_FILE_FILESYSTEM:
|
| + element.SetToFileSystemUrlRange(
|
| + item.filesystem_url, item.offset, item.length,
|
| + base::Time::FromDoubleT(item.expected_modification_time));
|
| + sender_->Send(new BlobHostMsg_AppendBlobDataItem(uuid_, element));
|
| + break;
|
| + default:
|
| + NOTREACHED();
|
| + }
|
| + }
|
| + sender_->Send(new BlobHostMsg_FinishBuilding(uuid_, content_type_));
|
| +}
|
| +
|
| +void WebBlobRegistryImpl::BuilderImpl::SendOversizedDataForBlob(
|
| + size_t consolidated_item_index) {
|
| + TRACE_EVENT0("Blob", "Registry::SendOversizedBlobData");
|
| + const BlobConsolidation::ConsolidatedItem& item =
|
| + consolidation_.consolidated_items()[consolidated_item_index];
|
| + // We handle larger amounts of data via SharedMemory instead of
|
| + // writing it directly to the IPC channel.
|
| +
|
| + size_t data_size = item.length;
|
| + size_t shared_memory_size = std::min(data_size, kMaxSharedMemoryBytes);
|
| + scoped_ptr<base::SharedMemory> shared_memory(
|
| + ChildThreadImpl::AllocateSharedMemory(shared_memory_size, sender_.get()));
|
| + CHECK(shared_memory.get());
|
| + const bool mapped = shared_memory->Map(shared_memory_size);
|
| + CHECK(mapped) << "Unable to map shared memory.";
|
| +
|
| + size_t offset = 0;
|
| + while (data_size) {
|
| + TRACE_EVENT0("Blob", "Registry::SendOversizedBlobItem");
|
| + size_t chunk_size = std::min(data_size, shared_memory_size);
|
| + consolidation_.ReadMemory(consolidated_item_index, offset, chunk_size,
|
| + shared_memory->memory());
|
| + sender_->Send(new BlobHostMsg_SyncAppendSharedMemory(
|
| + uuid_, shared_memory->handle(), chunk_size));
|
| + data_size -= chunk_size;
|
| + offset += chunk_size;
|
| + }
|
| +}
|
| +
|
| } // namespace content
|
|
|