Separate Simple Backend creation from initialization.
[chromium-blink-merge.git] / webkit / glue / resource_request_body.cc
blob763c7d07d95d2e81236dbb8b4d0643283e9a629c
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "webkit/glue/resource_request_body.h"
7 #include "base/logging.h"
8 #include "net/base/upload_bytes_element_reader.h"
9 #include "net/base/upload_data_stream.h"
10 #include "net/base/upload_file_element_reader.h"
11 #include "webkit/blob/blob_storage_controller.h"
12 #include "webkit/fileapi/upload_file_system_file_element_reader.h"
14 using webkit_blob::BlobData;
15 using webkit_blob::BlobStorageController;
17 namespace webkit_glue {
19 namespace {
21 // A subclass of net::UploadBytesElementReader which owns ResourceRequestBody.
22 class BytesElementReader : public net::UploadBytesElementReader {
23 public:
24 BytesElementReader(ResourceRequestBody* resource_request_body,
25 const ResourceRequestBody::Element& element)
26 : net::UploadBytesElementReader(element.bytes(), element.length()),
27 resource_request_body_(resource_request_body) {
28 DCHECK_EQ(ResourceRequestBody::Element::TYPE_BYTES, element.type());
31 virtual ~BytesElementReader() {}
33 private:
34 scoped_refptr<ResourceRequestBody> resource_request_body_;
36 DISALLOW_COPY_AND_ASSIGN(BytesElementReader);
39 // A subclass of net::UploadFileElementReader which owns ResourceRequestBody.
40 // This class is necessary to ensure the BlobData and any attached shareable
41 // files survive until upload completion.
42 class FileElementReader : public net::UploadFileElementReader {
43 public:
44 FileElementReader(ResourceRequestBody* resource_request_body,
45 base::TaskRunner* task_runner,
46 const ResourceRequestBody::Element& element)
47 : net::UploadFileElementReader(task_runner,
48 element.path(),
49 element.offset(),
50 element.length(),
51 element.expected_modification_time()),
52 resource_request_body_(resource_request_body) {
53 DCHECK_EQ(ResourceRequestBody::Element::TYPE_FILE, element.type());
56 virtual ~FileElementReader() {}
58 private:
59 scoped_refptr<ResourceRequestBody> resource_request_body_;
61 DISALLOW_COPY_AND_ASSIGN(FileElementReader);
64 } // namespace
66 ResourceRequestBody::ResourceRequestBody() : identifier_(0) {}
68 void ResourceRequestBody::AppendBytes(const char* bytes, int bytes_len) {
69 if (bytes_len > 0) {
70 elements_.push_back(Element());
71 elements_.back().SetToBytes(bytes, bytes_len);
75 void ResourceRequestBody::AppendFileRange(
76 const base::FilePath& file_path,
77 uint64 offset, uint64 length,
78 const base::Time& expected_modification_time) {
79 elements_.push_back(Element());
80 elements_.back().SetToFilePathRange(file_path, offset, length,
81 expected_modification_time);
84 void ResourceRequestBody::AppendBlob(const GURL& blob_url) {
85 elements_.push_back(Element());
86 elements_.back().SetToBlobUrl(blob_url);
89 void ResourceRequestBody::AppendFileSystemFileRange(
90 const GURL& url, uint64 offset, uint64 length,
91 const base::Time& expected_modification_time) {
92 elements_.push_back(Element());
93 elements_.back().SetToFileSystemUrlRange(url, offset, length,
94 expected_modification_time);
97 net::UploadDataStream*
98 ResourceRequestBody::ResolveElementsAndCreateUploadDataStream(
99 BlobStorageController* blob_controller,
100 fileapi::FileSystemContext* file_system_context,
101 base::TaskRunner* file_task_runner) {
102 // Resolve all blob elements.
103 std::vector<const Element*> resolved_elements;
104 for (size_t i = 0; i < elements_.size(); ++i) {
105 const Element& element = elements_[i];
106 if (element.type() == Element::TYPE_BLOB) {
107 ResolveBlobReference(blob_controller, element.url(), &resolved_elements);
108 } else {
109 // No need to resolve, just append the element.
110 resolved_elements.push_back(&element);
114 ScopedVector<net::UploadElementReader> element_readers;
115 for (size_t i = 0; i < resolved_elements.size(); ++i) {
116 const Element& element = *resolved_elements[i];
117 switch (element.type()) {
118 case Element::TYPE_BYTES:
119 element_readers.push_back(new BytesElementReader(this, element));
120 break;
121 case Element::TYPE_FILE:
122 element_readers.push_back(
123 new FileElementReader(this, file_task_runner, element));
124 break;
125 case Element::TYPE_FILE_FILESYSTEM:
126 element_readers.push_back(
127 new fileapi::UploadFileSystemFileElementReader(
128 file_system_context,
129 element.url(),
130 element.offset(),
131 element.length(),
132 element.expected_modification_time()));
133 break;
134 case Element::TYPE_BLOB:
135 // Blob elements should be resolved beforehand.
136 NOTREACHED();
137 break;
138 case Element::TYPE_UNKNOWN:
139 NOTREACHED();
140 break;
143 return new net::UploadDataStream(&element_readers, identifier_);
146 ResourceRequestBody::~ResourceRequestBody() {}
148 void ResourceRequestBody::ResolveBlobReference(
149 webkit_blob::BlobStorageController* blob_controller,
150 const GURL& blob_url,
151 std::vector<const Element*>* resolved_elements) {
152 DCHECK(blob_controller);
153 BlobData* blob_data = blob_controller->GetBlobDataFromUrl(blob_url);
154 DCHECK(blob_data);
155 if (!blob_data)
156 return;
158 // If there is no element in the referred blob data, just return.
159 if (blob_data->items().empty())
160 return;
162 // Ensure the blob and any attached shareable files survive until
163 // upload completion.
164 SetUserData(blob_data, new base::UserDataAdapter<BlobData>(blob_data));
166 // Append the elements in the referred blob data.
167 for (size_t i = 0; i < blob_data->items().size(); ++i) {
168 const BlobData::Item& item = blob_data->items().at(i);
169 DCHECK_NE(BlobData::Item::TYPE_BLOB, item.type());
170 resolved_elements->push_back(&item);
174 } // namespace webkit_glue