| Index: content/browser/loader/upload_data_stream_builder.cc
|
| diff --git a/content/browser/loader/upload_data_stream_builder.cc b/content/browser/loader/upload_data_stream_builder.cc
|
| index 12b4b80c9cf06bb5c2a0a22cf0eaff2dd6978a43..cab3a104572e3811b5c85d948c299b94b5bf33fb 100644
|
| --- a/content/browser/loader/upload_data_stream_builder.cc
|
| +++ b/content/browser/loader/upload_data_stream_builder.cc
|
| @@ -4,7 +4,6 @@
|
|
|
| #include "content/browser/loader/upload_data_stream_builder.h"
|
|
|
| -#include <limits>
|
| #include <utility>
|
| #include <vector>
|
|
|
| @@ -14,11 +13,11 @@
|
| #include "content/common/resource_request_body.h"
|
| #include "net/base/elements_upload_data_stream.h"
|
| #include "net/base/upload_bytes_element_reader.h"
|
| +#include "net/base/upload_disk_cache_entry_element_reader.h"
|
| #include "net/base/upload_file_element_reader.h"
|
| #include "storage/browser/blob/blob_data_handle.h"
|
| -#include "storage/browser/blob/blob_reader.h"
|
| +#include "storage/browser/blob/blob_data_snapshot.h"
|
| #include "storage/browser/blob/blob_storage_context.h"
|
| -#include "storage/browser/blob/upload_blob_element_reader.h"
|
|
|
| namespace disk_cache {
|
| class Entry;
|
| @@ -70,15 +69,89 @@
|
| DISALLOW_COPY_AND_ASSIGN(FileElementReader);
|
| };
|
|
|
| +// This owns the provided ResourceRequestBody. This is necessary to ensure the
|
| +// BlobData and open disk cache entries survive until upload completion.
|
| +class DiskCacheElementReader : public net::UploadDiskCacheEntryElementReader {
|
| + public:
|
| + DiskCacheElementReader(ResourceRequestBody* resource_request_body,
|
| + disk_cache::Entry* disk_cache_entry,
|
| + int disk_cache_stream_index,
|
| + const ResourceRequestBody::Element& element)
|
| + : net::UploadDiskCacheEntryElementReader(disk_cache_entry,
|
| + disk_cache_stream_index,
|
| + element.offset(),
|
| + element.length()),
|
| + resource_request_body_(resource_request_body) {
|
| + DCHECK_EQ(ResourceRequestBody::Element::TYPE_DISK_CACHE_ENTRY,
|
| + element.type());
|
| + }
|
| +
|
| + ~DiskCacheElementReader() override {}
|
| +
|
| + private:
|
| + scoped_refptr<ResourceRequestBody> resource_request_body_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(DiskCacheElementReader);
|
| +};
|
| +
|
| +void ResolveBlobReference(
|
| + ResourceRequestBody* body,
|
| + storage::BlobStorageContext* blob_context,
|
| + const ResourceRequestBody::Element& element,
|
| + std::vector<std::pair<const ResourceRequestBody::Element*,
|
| + const storage::BlobDataItem*>>* resolved_elements) {
|
| + DCHECK(blob_context);
|
| + scoped_ptr<storage::BlobDataHandle> handle =
|
| + blob_context->GetBlobDataFromUUID(element.blob_uuid());
|
| + DCHECK(handle);
|
| + if (!handle)
|
| + return;
|
| +
|
| + // TODO(dmurph): Create a reader for blobs instead of decomposing the blob
|
| + // and storing the snapshot on the request to keep the resources around.
|
| + // Currently a handle is attached to the request in the resource dispatcher
|
| + // host, so we know the blob won't go away, but it's not very clear or useful.
|
| + scoped_ptr<storage::BlobDataSnapshot> snapshot = handle->CreateSnapshot();
|
| + // If there is no element in the referred blob data, just return.
|
| + if (snapshot->items().empty())
|
| + return;
|
| +
|
| + // Append the elements in the referenced blob data.
|
| + for (const auto& item : snapshot->items()) {
|
| + DCHECK_NE(storage::DataElement::TYPE_BLOB, item->type());
|
| + resolved_elements->push_back(
|
| + std::make_pair(item->data_element_ptr(), item.get()));
|
| + }
|
| + const void* key = snapshot.get();
|
| + body->SetUserData(key, snapshot.release());
|
| +}
|
| +
|
| } // namespace
|
|
|
| scoped_ptr<net::UploadDataStream> UploadDataStreamBuilder::Build(
|
| ResourceRequestBody* body,
|
| storage::BlobStorageContext* blob_context,
|
| storage::FileSystemContext* file_system_context,
|
| - base::SingleThreadTaskRunner* file_task_runner) {
|
| + base::TaskRunner* file_task_runner) {
|
| + // Resolve all blob elements.
|
| + std::vector<std::pair<const ResourceRequestBody::Element*,
|
| + const storage::BlobDataItem*>> resolved_elements;
|
| + for (size_t i = 0; i < body->elements()->size(); ++i) {
|
| + const ResourceRequestBody::Element& element = (*body->elements())[i];
|
| + if (element.type() == ResourceRequestBody::Element::TYPE_BLOB) {
|
| + ResolveBlobReference(body, blob_context, element, &resolved_elements);
|
| + } else if (element.type() !=
|
| + ResourceRequestBody::Element::TYPE_DISK_CACHE_ENTRY) {
|
| + resolved_elements.push_back(std::make_pair(&element, nullptr));
|
| + } else {
|
| + NOTREACHED();
|
| + }
|
| + }
|
| +
|
| ScopedVector<net::UploadElementReader> element_readers;
|
| - for (const auto& element : *body->elements()) {
|
| + for (const auto& element_and_blob_item_pair : resolved_elements) {
|
| + const ResourceRequestBody::Element& element =
|
| + *element_and_blob_item_pair.first;
|
| switch (element.type()) {
|
| case ResourceRequestBody::Element::TYPE_BYTES:
|
| element_readers.push_back(new BytesElementReader(body, element));
|
| @@ -99,18 +172,22 @@
|
| element.length(),
|
| element.expected_modification_time()));
|
| break;
|
| - case ResourceRequestBody::Element::TYPE_BLOB: {
|
| - DCHECK_EQ(std::numeric_limits<uint64_t>::max(), element.length());
|
| - DCHECK_EQ(0ul, element.offset());
|
| - scoped_ptr<storage::BlobDataHandle> handle =
|
| - blob_context->GetBlobDataFromUUID(element.blob_uuid());
|
| - storage::BlobDataHandle* handle_ptr = handle.get();
|
| - element_readers.push_back(new storage::UploadBlobElementReader(
|
| - handle_ptr->CreateReader(file_system_context, file_task_runner),
|
| - handle.Pass()));
|
| + case ResourceRequestBody::Element::TYPE_BLOB:
|
| + // Blob elements should be resolved beforehand.
|
| + // TODO(dmurph): Create blob reader and store the snapshot in there.
|
| + NOTREACHED();
|
| + break;
|
| + case ResourceRequestBody::Element::TYPE_DISK_CACHE_ENTRY: {
|
| + // TODO(gavinp): If Build() is called with a DataElement of
|
| + // TYPE_DISK_CACHE_ENTRY then this code won't work because we won't call
|
| + // ResolveBlobReference() and so we won't find |item|. Is this OK?
|
| + const storage::BlobDataItem* item = element_and_blob_item_pair.second;
|
| + element_readers.push_back(
|
| + new DiskCacheElementReader(body, item->disk_cache_entry(),
|
| + item->disk_cache_stream_index(),
|
| + element));
|
| break;
|
| }
|
| - case ResourceRequestBody::Element::TYPE_DISK_CACHE_ENTRY:
|
| case ResourceRequestBody::Element::TYPE_UNKNOWN:
|
| NOTREACHED();
|
| break;
|
|
|