OLD | NEW |
---|---|
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/browser/loader/upload_data_stream_builder.h" | 5 #include "content/browser/loader/upload_data_stream_builder.h" |
6 | 6 |
7 #include <utility> | 7 #include <utility> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
11 #include "base/memory/ref_counted.h" | 11 #include "base/memory/ref_counted.h" |
12 #include "content/browser/fileapi/upload_file_system_file_element_reader.h" | 12 #include "content/browser/fileapi/upload_file_system_file_element_reader.h" |
13 #include "content/common/resource_request_body.h" | 13 #include "content/common/resource_request_body.h" |
14 #include "net/base/elements_upload_data_stream.h" | 14 #include "net/base/elements_upload_data_stream.h" |
15 #include "net/base/upload_bytes_element_reader.h" | 15 #include "net/base/upload_bytes_element_reader.h" |
16 #include "net/base/upload_disk_cache_entry_element_reader.h" | |
17 #include "net/base/upload_file_element_reader.h" | 16 #include "net/base/upload_file_element_reader.h" |
18 #include "storage/browser/blob/blob_data_handle.h" | 17 #include "storage/browser/blob/blob_data_handle.h" |
19 #include "storage/browser/blob/blob_data_snapshot.h" | 18 #include "storage/browser/blob/blob_reader.h" |
20 #include "storage/browser/blob/blob_storage_context.h" | 19 #include "storage/browser/blob/blob_storage_context.h" |
20 #include "storage/browser/blob/upload_blob_element_reader.h" | |
21 | 21 |
22 namespace disk_cache { | 22 namespace disk_cache { |
23 class Entry; | 23 class Entry; |
24 } | 24 } |
25 | 25 |
26 namespace content { | 26 namespace content { |
27 namespace { | 27 namespace { |
28 | 28 |
29 // A subclass of net::UploadBytesElementReader which owns ResourceRequestBody. | 29 // A subclass of net::UploadBytesElementReader which owns ResourceRequestBody. |
30 class BytesElementReader : public net::UploadBytesElementReader { | 30 class BytesElementReader : public net::UploadBytesElementReader { |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
62 } | 62 } |
63 | 63 |
64 ~FileElementReader() override {} | 64 ~FileElementReader() override {} |
65 | 65 |
66 private: | 66 private: |
67 scoped_refptr<ResourceRequestBody> resource_request_body_; | 67 scoped_refptr<ResourceRequestBody> resource_request_body_; |
68 | 68 |
69 DISALLOW_COPY_AND_ASSIGN(FileElementReader); | 69 DISALLOW_COPY_AND_ASSIGN(FileElementReader); |
70 }; | 70 }; |
71 | 71 |
72 // This owns the provided ResourceRequestBody. This is necessary to ensure the | |
73 // BlobData and open disk cache entries survive until upload completion. | |
74 class DiskCacheElementReader : public net::UploadDiskCacheEntryElementReader { | |
75 public: | |
76 DiskCacheElementReader(ResourceRequestBody* resource_request_body, | |
77 disk_cache::Entry* disk_cache_entry, | |
78 int disk_cache_stream_index, | |
79 const ResourceRequestBody::Element& element) | |
80 : net::UploadDiskCacheEntryElementReader(disk_cache_entry, | |
81 disk_cache_stream_index, | |
82 element.offset(), | |
83 element.length()), | |
84 resource_request_body_(resource_request_body) { | |
85 DCHECK_EQ(ResourceRequestBody::Element::TYPE_DISK_CACHE_ENTRY, | |
86 element.type()); | |
87 } | |
88 | |
89 ~DiskCacheElementReader() override {} | |
90 | |
91 private: | |
92 scoped_refptr<ResourceRequestBody> resource_request_body_; | |
93 | |
94 DISALLOW_COPY_AND_ASSIGN(DiskCacheElementReader); | |
95 }; | |
96 | |
97 void ResolveBlobReference( | |
98 ResourceRequestBody* body, | |
99 storage::BlobStorageContext* blob_context, | |
100 const ResourceRequestBody::Element& element, | |
101 std::vector<std::pair<const ResourceRequestBody::Element*, | |
102 const storage::BlobDataItem*>>* resolved_elements) { | |
103 DCHECK(blob_context); | |
104 scoped_ptr<storage::BlobDataHandle> handle = | |
105 blob_context->GetBlobDataFromUUID(element.blob_uuid()); | |
106 DCHECK(handle); | |
107 if (!handle) | |
108 return; | |
109 | |
110 // TODO(dmurph): Create a reader for blobs instead of decomposing the blob | |
111 // and storing the snapshot on the request to keep the resources around. | |
112 // Currently a handle is attached to the request in the resource dispatcher | |
113 // host, so we know the blob won't go away, but it's not very clear or useful. | |
114 scoped_ptr<storage::BlobDataSnapshot> snapshot = handle->CreateSnapshot(); | |
115 // If there is no element in the referred blob data, just return. | |
116 if (snapshot->items().empty()) | |
117 return; | |
118 | |
119 // Append the elements in the referenced blob data. | |
120 for (const auto& item : snapshot->items()) { | |
121 DCHECK_NE(storage::DataElement::TYPE_BLOB, item->type()); | |
122 resolved_elements->push_back( | |
123 std::make_pair(item->data_element_ptr(), item.get())); | |
124 } | |
125 const void* key = snapshot.get(); | |
126 body->SetUserData(key, snapshot.release()); | |
127 } | |
128 | |
129 } // namespace | 72 } // namespace |
130 | 73 |
131 scoped_ptr<net::UploadDataStream> UploadDataStreamBuilder::Build( | 74 scoped_ptr<net::UploadDataStream> UploadDataStreamBuilder::Build( |
132 ResourceRequestBody* body, | 75 ResourceRequestBody* body, |
133 storage::BlobStorageContext* blob_context, | 76 storage::BlobStorageContext* blob_context, |
134 storage::FileSystemContext* file_system_context, | 77 storage::FileSystemContext* file_system_context, |
135 base::TaskRunner* file_task_runner) { | 78 base::SingleThreadTaskRunner* file_task_runner) { |
136 // Resolve all blob elements. | |
137 std::vector<std::pair<const ResourceRequestBody::Element*, | |
138 const storage::BlobDataItem*>> resolved_elements; | |
139 for (size_t i = 0; i < body->elements()->size(); ++i) { | |
140 const ResourceRequestBody::Element& element = (*body->elements())[i]; | |
141 if (element.type() == ResourceRequestBody::Element::TYPE_BLOB) { | |
142 ResolveBlobReference(body, blob_context, element, &resolved_elements); | |
143 } else if (element.type() != | |
144 ResourceRequestBody::Element::TYPE_DISK_CACHE_ENTRY) { | |
145 resolved_elements.push_back(std::make_pair(&element, nullptr)); | |
146 } else { | |
147 NOTREACHED(); | |
148 } | |
149 } | |
150 | |
151 ScopedVector<net::UploadElementReader> element_readers; | 79 ScopedVector<net::UploadElementReader> element_readers; |
152 for (const auto& element_and_blob_item_pair : resolved_elements) { | 80 for (const auto& element : *body->elements()) { |
153 const ResourceRequestBody::Element& element = | |
154 *element_and_blob_item_pair.first; | |
155 switch (element.type()) { | 81 switch (element.type()) { |
156 case ResourceRequestBody::Element::TYPE_BYTES: | 82 case ResourceRequestBody::Element::TYPE_BYTES: |
157 element_readers.push_back(new BytesElementReader(body, element)); | 83 element_readers.push_back(new BytesElementReader(body, element)); |
158 break; | 84 break; |
159 case ResourceRequestBody::Element::TYPE_FILE: | 85 case ResourceRequestBody::Element::TYPE_FILE: |
160 element_readers.push_back( | 86 element_readers.push_back( |
161 new FileElementReader(body, file_task_runner, element)); | 87 new FileElementReader(body, file_task_runner, element)); |
162 break; | 88 break; |
163 case ResourceRequestBody::Element::TYPE_FILE_FILESYSTEM: | 89 case ResourceRequestBody::Element::TYPE_FILE_FILESYSTEM: |
164 // If |body| contains any filesystem URLs, the caller should have | 90 // If |body| contains any filesystem URLs, the caller should have |
165 // supplied a FileSystemContext. | 91 // supplied a FileSystemContext. |
166 DCHECK(file_system_context); | 92 DCHECK(file_system_context); |
167 element_readers.push_back( | 93 element_readers.push_back( |
168 new content::UploadFileSystemFileElementReader( | 94 new content::UploadFileSystemFileElementReader( |
169 file_system_context, | 95 file_system_context, |
170 element.filesystem_url(), | 96 element.filesystem_url(), |
171 element.offset(), | 97 element.offset(), |
172 element.length(), | 98 element.length(), |
173 element.expected_modification_time())); | 99 element.expected_modification_time())); |
174 break; | 100 break; |
175 case ResourceRequestBody::Element::TYPE_BLOB: | 101 case ResourceRequestBody::Element::TYPE_BLOB: { |
176 // Blob elements should be resolved beforehand. | 102 scoped_ptr<storage::BlobDataHandle> handle = |
177 // TODO(dmurph): Create blob reader and store the snapshot in there. | 103 blob_context->GetBlobDataFromUUID(element.blob_uuid()); |
178 NOTREACHED(); | 104 storage::BlobDataHandle* handle_ptr = handle.get(); |
179 break; | 105 element_readers.push_back(new storage::UploadBlobElementReader( |
michaeln
2015/09/23 18:52:46
Either comment about or dcheck assumptions about e
dmurph
2015/09/25 17:11:43
Done.
| |
180 case ResourceRequestBody::Element::TYPE_DISK_CACHE_ENTRY: { | 106 handle_ptr->CreateReader(file_system_context, file_task_runner), |
181 // TODO(gavinp): If Build() is called with a DataElement of | 107 handle.Pass())); |
182 // TYPE_DISK_CACHE_ENTRY then this code won't work because we won't call | |
183 // ResolveBlobReference() and so we won't find |item|. Is this OK? | |
184 const storage::BlobDataItem* item = element_and_blob_item_pair.second; | |
185 element_readers.push_back( | |
186 new DiskCacheElementReader(body, item->disk_cache_entry(), | |
187 item->disk_cache_stream_index(), | |
188 element)); | |
189 break; | 108 break; |
190 } | 109 } |
110 case ResourceRequestBody::Element::TYPE_DISK_CACHE_ENTRY: | |
191 case ResourceRequestBody::Element::TYPE_UNKNOWN: | 111 case ResourceRequestBody::Element::TYPE_UNKNOWN: |
192 NOTREACHED(); | 112 NOTREACHED(); |
193 break; | 113 break; |
194 } | 114 } |
195 } | 115 } |
196 | 116 |
197 return make_scoped_ptr( | 117 return make_scoped_ptr( |
198 new net::ElementsUploadDataStream(element_readers.Pass(), | 118 new net::ElementsUploadDataStream(element_readers.Pass(), |
199 body->identifier())); | 119 body->identifier())); |
200 } | 120 } |
201 | 121 |
202 } // namespace content | 122 } // namespace content |
OLD | NEW |