| 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 c497c16c0a769ea50c20469ba1fc44e47708dc31..cab3a104572e3811b5c85d948c299b94b5bf33fb 100644
|
| --- a/content/browser/loader/upload_data_stream_builder.cc
|
| +++ b/content/browser/loader/upload_data_stream_builder.cc
|
| @@ -4,16 +4,25 @@
|
|
|
| #include "content/browser/loader/upload_data_stream_builder.h"
|
|
|
| +#include <utility>
|
| +#include <vector>
|
| +
|
| #include "base/logging.h"
|
| +#include "base/memory/ref_counted.h"
|
| #include "content/browser/fileapi/upload_file_system_file_element_reader.h"
|
| #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_data_snapshot.h"
|
| #include "storage/browser/blob/blob_storage_context.h"
|
|
|
| +namespace disk_cache {
|
| +class Entry;
|
| +}
|
| +
|
| namespace content {
|
| namespace {
|
|
|
| @@ -60,11 +69,37 @@ class FileElementReader : public net::UploadFileElementReader {
|
| 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<const ResourceRequestBody::Element*>* resolved_elements) {
|
| + 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());
|
| @@ -84,7 +119,8 @@ void ResolveBlobReference(
|
| // 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(item->data_element_ptr());
|
| + resolved_elements->push_back(
|
| + std::make_pair(item->data_element_ptr(), item.get()));
|
| }
|
| const void* key = snapshot.get();
|
| body->SetUserData(key, snapshot.release());
|
| @@ -98,18 +134,24 @@ scoped_ptr<net::UploadDataStream> UploadDataStreamBuilder::Build(
|
| storage::FileSystemContext* file_system_context,
|
| base::TaskRunner* file_task_runner) {
|
| // Resolve all blob elements.
|
| - std::vector<const ResourceRequestBody::Element*> resolved_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)
|
| + if (element.type() == ResourceRequestBody::Element::TYPE_BLOB) {
|
| ResolveBlobReference(body, blob_context, element, &resolved_elements);
|
| - else
|
| - resolved_elements.push_back(&element);
|
| + } 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 (size_t i = 0; i < resolved_elements.size(); ++i) {
|
| - const ResourceRequestBody::Element& element = *resolved_elements[i];
|
| + 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));
|
| @@ -135,6 +177,17 @@ scoped_ptr<net::UploadDataStream> UploadDataStreamBuilder::Build(
|
| // 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_UNKNOWN:
|
| NOTREACHED();
|
| break;
|
|
|