Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(36)

Side by Side Diff: third_party/WebKit/Source/modules/fetch/FormDataBytesConsumer.cpp

Issue 2710033003: Add unknown file size handling in ComplexFormDataBytesConsumer (Closed)
Patch Set: fix Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 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 "modules/fetch/FormDataBytesConsumer.h" 5 #include "modules/fetch/FormDataBytesConsumer.h"
6 6
7 #include "bindings/core/v8/ExceptionState.h"
7 #include "core/dom/DOMArrayBuffer.h" 8 #include "core/dom/DOMArrayBuffer.h"
8 #include "core/dom/DOMArrayBufferView.h" 9 #include "core/dom/DOMArrayBufferView.h"
10 #include "core/dom/ExecutionContext.h"
11 #include "core/dom/TaskRunnerHelper.h"
12 #include "core/fileapi/Blob.h"
13 #include "core/fileapi/File.h"
9 #include "modules/fetch/BlobBytesConsumer.h" 14 #include "modules/fetch/BlobBytesConsumer.h"
10 #include "platform/blob/BlobData.h" 15 #include "platform/blob/BlobData.h"
11 #include "platform/network/EncodedFormData.h" 16 #include "platform/network/EncodedFormData.h"
12 #include "wtf/Vector.h" 17 #include "wtf/Vector.h"
13 #include "wtf/text/TextCodec.h" 18 #include "wtf/text/TextCodec.h"
14 #include "wtf/text/TextEncoding.h" 19 #include "wtf/text/TextEncoding.h"
15 #include "wtf/text/WTFString.h" 20 #include "wtf/text/WTFString.h"
16 21
17 namespace blink { 22 namespace blink {
18 23
19 namespace { 24 namespace {
20 25
26 using BytesConsumerFactory = FormDataBytesConsumer::BytesConsumerFactory;
27
21 bool isSimple(const EncodedFormData* formData) { 28 bool isSimple(const EncodedFormData* formData) {
22 for (const auto& element : formData->elements()) { 29 for (const auto& element : formData->elements()) {
23 if (element.m_type != FormDataElement::data) 30 if (element.m_type != FormDataElement::data)
24 return false; 31 return false;
25 } 32 }
26 return true; 33 return true;
27 } 34 }
28 35
29 class SimpleFormDataBytesConsumer : public BytesConsumer { 36 class SimpleFormDataBytesConsumer : public BytesConsumer {
30 public: 37 public:
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
94 101
95 private: 102 private:
96 // either one of |m_formData| and |m_flattenFormData| is usable at a time. 103 // either one of |m_formData| and |m_flattenFormData| is usable at a time.
97 RefPtr<EncodedFormData> m_formData; 104 RefPtr<EncodedFormData> m_formData;
98 Vector<char> m_flattenFormData; 105 Vector<char> m_flattenFormData;
99 size_t m_flattenFormDataOffset = 0; 106 size_t m_flattenFormDataOffset = 0;
100 PublicState m_state = PublicState::ReadableOrWaiting; 107 PublicState m_state = PublicState::ReadableOrWaiting;
101 }; 108 };
102 109
103 class ComplexFormDataBytesConsumer final : public BytesConsumer { 110 class ComplexFormDataBytesConsumer final : public BytesConsumer {
111 enum class State {
112 Clean,
113 Reading,
114 Closed,
115 Errored,
116 };
117
104 public: 118 public:
105 ComplexFormDataBytesConsumer(ExecutionContext* executionContext, 119 ComplexFormDataBytesConsumer(ExecutionContext* executionContext,
106 PassRefPtr<EncodedFormData> formData, 120 PassRefPtr<EncodedFormData> formData,
107 BytesConsumer* consumer) 121 std::unique_ptr<BytesConsumerFactory> factory)
108 : m_formData(formData) { 122 : m_formData(formData),
109 if (consumer) { 123 m_executionContext(executionContext),
110 // For testing. 124 m_factoryForTesting(std::move(factory)) {}
111 m_blobBytesConsumer = consumer;
112 return;
113 }
114
115 std::unique_ptr<BlobData> blobData = BlobData::create();
116 for (const auto& element : m_formData->elements()) {
117 switch (element.m_type) {
118 case FormDataElement::data:
119 blobData->appendBytes(element.m_data.data(), element.m_data.size());
120 break;
121 case FormDataElement::encodedFile:
122 blobData->appendFile(element.m_filename, element.m_fileStart,
123 element.m_fileLength,
dmurph 2017/02/24 19:49:24 Why not just check if the file size is -1, and if
yhirano 2017/03/02 04:05:04 Fixed.
124 element.m_expectedFileModificationTime);
125 break;
126 case FormDataElement::encodedBlob:
127 if (element.m_optionalBlobDataHandle)
128 blobData->appendBlob(element.m_optionalBlobDataHandle, 0,
129 element.m_optionalBlobDataHandle->size());
130 break;
131 case FormDataElement::encodedFileSystemURL:
132 blobData->appendFileSystemURL(
133 element.m_fileSystemURL, element.m_fileStart,
134 element.m_fileLength, element.m_expectedFileModificationTime);
135 break;
136 }
137 }
138 // Here we handle m_formData->boundary() as a C-style string. See
139 // FormDataEncoder::generateUniqueBoundaryString.
140 blobData->setContentType(AtomicString("multipart/form-data; boundary=") +
141 m_formData->boundary().data());
142 auto size = blobData->length();
143 m_blobBytesConsumer = new BlobBytesConsumer(
144 executionContext, BlobDataHandle::create(std::move(blobData), size));
145 }
146 125
147 // BytesConsumer implementation 126 // BytesConsumer implementation
148 Result beginRead(const char** buffer, size_t* available) override { 127 Result beginRead(const char** buffer, size_t* available) override {
128 *buffer = nullptr;
129 *available = 0;
130 if (m_state == State::Closed)
131 return Result::Done;
132 if (m_state == State::Errored)
133 return Result::Error;
134 if (m_state == State::Clean)
135 m_state = State::Reading;
136
137 if (m_blobBytesConsumer) {
138 auto r = m_blobBytesConsumer->beginRead(buffer, available);
139 if (r == Result::Error) {
140 m_state = State::Errored;
141 return r;
142 }
143 if (r == Result::Done) {
144 ++m_elementIndex;
145 m_blobBytesConsumer = nullptr;
146 if (m_elementIndex == m_formData->elements().size()) {
147 m_state = State::Closed;
148 return Result::Done;
149 }
150 return beginRead(buffer, available);
151 }
152 return r;
153 }
154 const auto& element = m_formData->elements()[m_elementIndex];
155 if (element.m_type == FormDataElement::data) {
156 DCHECK_LE(m_offset, element.m_data.size());
157 *buffer = &element.m_data[m_offset];
158 *available = element.m_data.size() - m_offset;
159 return Result::Ok;
160 }
161
162 RefPtr<BlobDataHandle> blobDataHandle = nullptr;
163 const String type = "application/octet-stream";
164 switch (element.m_type) {
165 case FormDataElement::data:
166 NOTREACHED();
167 break;
168 case FormDataElement::encodedBlob:
169 if (element.m_optionalBlobDataHandle)
170 blobDataHandle = element.m_optionalBlobDataHandle;
171 else
172 blobDataHandle = BlobDataHandle::create(element.m_blobUUID, type, -1);
173 break;
174 case FormDataElement::encodedFile: {
175 NonThrowableExceptionState es;
176 Blob* file = File::create(element.m_filename);
177 if (element.m_fileStart > 0) {
178 file =
179 file->slice(element.m_fileStart,
180 element.m_fileStart + element.m_fileLength, type, es);
181 }
182 blobDataHandle = file->blobDataHandle();
183 break;
184 }
185 case FormDataElement::encodedFileSystemURL: {
186 FileMetadata metadata;
187 metadata.length = element.m_fileStart + element.m_fileLength;
188 NonThrowableExceptionState es;
189 Blob* file = File::createForFileSystemFile(
190 element.m_fileSystemURL, metadata, File::IsUserVisible);
191 if (element.m_fileStart > 0) {
192 file =
193 file->slice(element.m_fileStart,
194 element.m_fileStart + element.m_fileLength, type, es);
195 }
196 blobDataHandle = file->blobDataHandle();
197 break;
198 }
199 }
200 if (m_factoryForTesting) {
201 m_blobBytesConsumer =
202 (*m_factoryForTesting)(m_executionContext, std::move(blobDataHandle));
203 } else {
204 m_blobBytesConsumer =
205 new BlobBytesConsumer(m_executionContext, std::move(blobDataHandle));
206 }
207 if (m_client)
208 m_blobBytesConsumer->setClient(m_client);
209 return beginRead(buffer, available);
210 }
211 Result endRead(size_t readSize) override {
212 DCHECK_EQ(m_state, State::Reading);
213 const auto& element = m_formData->elements()[m_elementIndex];
214 if (element.m_type == FormDataElement::data) {
215 DCHECK_LE(m_offset + readSize, element.m_data.size());
216 m_offset += readSize;
217 if (m_offset == element.m_data.size()) {
218 m_offset = 0;
219 ++m_elementIndex;
220 }
221 } else {
222 DCHECK(m_blobBytesConsumer);
223 auto r = m_blobBytesConsumer->endRead(readSize);
224 if (r == Result::Error) {
225 m_state = State::Errored;
226 return r;
227 }
228 if (r == Result::Done) {
229 m_blobBytesConsumer = nullptr;
230 ++m_elementIndex;
231 }
232 }
233 if (m_elementIndex == m_formData->elements().size()) {
234 m_state = State::Closed;
235 return Result::Done;
236 }
237 return Result::Ok;
238 }
239 PassRefPtr<EncodedFormData> drainAsFormData() override {
240 if (m_state != State::Clean)
241 return nullptr;
242 DCHECK(!m_blobBytesConsumer);
243 DCHECK(m_formData);
244 m_state = State::Closed;
245 return m_formData.release();
246 }
247 void setClient(BytesConsumer::Client* client) override {
248 DCHECK(client);
249 m_client = client;
250 if (m_blobBytesConsumer) {
251 m_blobBytesConsumer->setClient(client);
252 } else if (getPublicState() == PublicState::ReadableOrWaiting) {
253 TaskRunnerHelper::get(TaskType::Networking, m_executionContext)
254 ->postTask(BLINK_FROM_HERE,
255 WTF::bind(&BytesConsumer::Client::onStateChange,
256 wrapPersistent(m_client.get())));
257 }
258 }
259 void clearClient() override {
260 m_client = nullptr;
261 if (m_blobBytesConsumer)
262 m_blobBytesConsumer->clearClient();
263 }
264 void cancel() override {
265 if (m_state == State::Closed || m_state == State::Errored)
266 return;
149 m_formData = nullptr; 267 m_formData = nullptr;
150 // Delegate the operation to the underlying consumer. This relies on 268 m_client = nullptr;
151 // the fact that we appropriately notify the draining information to 269 m_state = State::Closed;
152 // the underlying consumer. 270 if (m_blobBytesConsumer)
153 return m_blobBytesConsumer->beginRead(buffer, available); 271 m_blobBytesConsumer->cancel();
154 }
155 Result endRead(size_t readSize) override {
156 return m_blobBytesConsumer->endRead(readSize);
157 }
158 PassRefPtr<BlobDataHandle> drainAsBlobDataHandle(
159 BlobSizePolicy policy) override {
160 RefPtr<BlobDataHandle> handle =
161 m_blobBytesConsumer->drainAsBlobDataHandle(policy);
162 if (handle)
163 m_formData = nullptr;
164 return handle.release();
165 }
166 PassRefPtr<EncodedFormData> drainAsFormData() override {
167 if (!m_formData)
168 return nullptr;
169 m_blobBytesConsumer->cancel();
170 return m_formData.release();
171 }
172 void setClient(BytesConsumer::Client* client) override {
173 m_blobBytesConsumer->setClient(client);
174 }
175 void clearClient() override { m_blobBytesConsumer->clearClient(); }
176 void cancel() override {
177 m_formData = nullptr;
178 m_blobBytesConsumer->cancel();
179 } 272 }
180 PublicState getPublicState() const override { 273 PublicState getPublicState() const override {
181 return m_blobBytesConsumer->getPublicState(); 274 switch (m_state) {
182 } 275 case State::Clean:
183 Error getError() const override { return m_blobBytesConsumer->getError(); } 276 case State::Reading:
277 return PublicState::ReadableOrWaiting;
278 case State::Closed:
279 return PublicState::Closed;
280 case State::Errored:
281 return PublicState::Errored;
282 }
283 NOTREACHED();
284 return PublicState::Errored;
285 }
286 Error getError() const override {
287 if (m_blobBytesConsumer)
288 return m_blobBytesConsumer->getError();
289 return Error();
290 }
184 String debugName() const override { return "ComplexFormDataBytesConsumer"; } 291 String debugName() const override { return "ComplexFormDataBytesConsumer"; }
185 292
186 DEFINE_INLINE_TRACE() { 293 DEFINE_INLINE_TRACE() {
187 visitor->trace(m_blobBytesConsumer); 294 visitor->trace(m_blobBytesConsumer);
295 visitor->trace(m_client);
296 visitor->trace(m_executionContext);
188 BytesConsumer::trace(visitor); 297 BytesConsumer::trace(visitor);
189 } 298 }
190 299
191 private: 300 private:
301 unsigned m_elementIndex = 0;
302 size_t m_offset = 0;
303 State m_state = State::Clean;
192 RefPtr<EncodedFormData> m_formData; 304 RefPtr<EncodedFormData> m_formData;
193 Member<BytesConsumer> m_blobBytesConsumer; 305 Member<BytesConsumer> m_blobBytesConsumer;
306 Member<BytesConsumer::Client> m_client;
307 Member<ExecutionContext> m_executionContext;
308 std::unique_ptr<BytesConsumerFactory> m_factoryForTesting;
194 }; 309 };
195 310
196 } // namespace 311 } // namespace
197 312
198 FormDataBytesConsumer::FormDataBytesConsumer(const String& string) 313 FormDataBytesConsumer::FormDataBytesConsumer(const String& string)
199 : m_impl(new SimpleFormDataBytesConsumer(EncodedFormData::create( 314 : m_impl(new SimpleFormDataBytesConsumer(EncodedFormData::create(
200 UTF8Encoding().encode(string, WTF::EntitiesForUnencodables)))) {} 315 UTF8Encoding().encode(string, WTF::EntitiesForUnencodables)))) {}
201 316
202 FormDataBytesConsumer::FormDataBytesConsumer(DOMArrayBuffer* buffer) 317 FormDataBytesConsumer::FormDataBytesConsumer(DOMArrayBuffer* buffer)
203 : FormDataBytesConsumer(buffer->data(), buffer->byteLength()) {} 318 : FormDataBytesConsumer(buffer->data(), buffer->byteLength()) {}
204 319
205 FormDataBytesConsumer::FormDataBytesConsumer(DOMArrayBufferView* view) 320 FormDataBytesConsumer::FormDataBytesConsumer(DOMArrayBufferView* view)
206 : FormDataBytesConsumer(view->baseAddress(), view->byteLength()) {} 321 : FormDataBytesConsumer(view->baseAddress(), view->byteLength()) {}
207 322
208 FormDataBytesConsumer::FormDataBytesConsumer(const void* data, size_t size) 323 FormDataBytesConsumer::FormDataBytesConsumer(const void* data, size_t size)
209 : m_impl(new SimpleFormDataBytesConsumer( 324 : m_impl(new SimpleFormDataBytesConsumer(
210 EncodedFormData::create(data, size))) {} 325 EncodedFormData::create(data, size))) {}
211 326
212 FormDataBytesConsumer::FormDataBytesConsumer( 327 FormDataBytesConsumer::FormDataBytesConsumer(
213 ExecutionContext* executionContext, 328 ExecutionContext* executionContext,
214 PassRefPtr<EncodedFormData> formData) 329 PassRefPtr<EncodedFormData> formData)
215 : FormDataBytesConsumer(executionContext, std::move(formData), nullptr) {} 330 : FormDataBytesConsumer(executionContext, std::move(formData), nullptr) {}
216 331
217 FormDataBytesConsumer::FormDataBytesConsumer( 332 FormDataBytesConsumer::FormDataBytesConsumer(
218 ExecutionContext* executionContext, 333 ExecutionContext* executionContext,
219 PassRefPtr<EncodedFormData> formData, 334 PassRefPtr<EncodedFormData> formData,
220 BytesConsumer* consumer) 335 std::unique_ptr<BytesConsumerFactory> factory)
221 : m_impl(isSimple(formData.get()) 336 : m_impl(isSimple(formData.get())
222 ? static_cast<BytesConsumer*>( 337 ? static_cast<BytesConsumer*>(
223 new SimpleFormDataBytesConsumer(std::move(formData))) 338 new SimpleFormDataBytesConsumer(std::move(formData)))
224 : static_cast<BytesConsumer*>( 339 : static_cast<BytesConsumer*>(
225 new ComplexFormDataBytesConsumer(executionContext, 340 new ComplexFormDataBytesConsumer(executionContext,
226 std::move(formData), 341 std::move(formData),
227 consumer))) {} 342 std::move(factory)))) {}
228 343
229 } // namespace blink 344 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698