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

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

Issue 2292763002: [Fetch API] Implement Request.formData and Response.formData. (Closed)
Patch Set: Created 4 years, 2 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 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 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/FetchDataLoader.h" 5 #include "modules/fetch/FetchDataLoader.h"
6 6
7 #include "core/fileapi/Blob.h"
8 #include "core/html/FormData.h"
7 #include "core/html/parser/TextResourceDecoder.h" 9 #include "core/html/parser/TextResourceDecoder.h"
8 #include "modules/fetch/BytesConsumer.h" 10 #include "modules/fetch/BytesConsumer.h"
11 #include "modules/fetch/MultipartParser.h"
12 #include "platform/HTTPNames.h"
13 #include "platform/network/ParsedContentType.h"
9 #include "wtf/PtrUtil.h" 14 #include "wtf/PtrUtil.h"
10 #include "wtf/text/StringBuilder.h" 15 #include "wtf/text/StringBuilder.h"
11 #include "wtf/text/WTFString.h" 16 #include "wtf/text/WTFString.h"
12 #include "wtf/typed_arrays/ArrayBufferBuilder.h" 17 #include "wtf/typed_arrays/ArrayBufferBuilder.h"
13 #include <memory> 18 #include <memory>
14 19
15 namespace blink { 20 namespace blink {
16 21
17 namespace { 22 namespace {
18 23
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
161 BytesConsumer::Client::trace(visitor); 166 BytesConsumer::Client::trace(visitor);
162 } 167 }
163 168
164 private: 169 private:
165 Member<BytesConsumer> m_consumer; 170 Member<BytesConsumer> m_consumer;
166 Member<FetchDataLoader::Client> m_client; 171 Member<FetchDataLoader::Client> m_client;
167 172
168 std::unique_ptr<ArrayBufferBuilder> m_rawData; 173 std::unique_ptr<ArrayBufferBuilder> m_rawData;
169 }; 174 };
170 175
176 class FetchDataLoaderAsFormData final : public FetchDataLoader, public BytesCons umer::Client, public MultipartParser::Client {
177 USING_GARBAGE_COLLECTED_MIXIN(FetchDataLoaderAsFormData);
178
179 public:
180 explicit FetchDataLoaderAsFormData(const String& multipartBoundary)
181 : m_multipartBoundary(multipartBoundary)
182 {
183 }
184
185 void start(BytesConsumer* consumer, FetchDataLoader::Client* client) overrid e
186 {
187 DCHECK(!m_client);
188 DCHECK(!m_multipartParser);
189 DCHECK(!m_consumer);
190
191 CString multipartBoundaryCString = m_multipartBoundary.utf8();
horo 2016/09/27 10:45:49 nit: const
e_hakkinen 2016/09/28 15:15:04 Done.
192 Vector<char> multipartBoundaryVector;
193 multipartBoundaryVector.append(multipartBoundaryCString.data(), multipar tBoundaryCString.length());
194
195 m_client = client;
196 m_formData = FormData::create();
197 m_multipartParser = new MultipartParser(std::move(multipartBoundaryVecto r), this);
198 m_consumer = consumer;
199 m_consumer->setClient(this);
200 onStateChange();
201 }
202
203 void onStateChange() override
204 {
205 while (true) {
206 const char* buffer;
207 size_t available;
208 auto result = m_consumer->beginRead(&buffer, &available);
209 if (result == BytesConsumer::Result::ShouldWait)
210 return;
211 if (result == BytesConsumer::Result::Ok) {
212 bool bufferAppended = m_multipartParser->appendData(buffer, avai lable);
horo 2016/09/27 10:45:49 nit: const
e_hakkinen 2016/09/28 15:15:04 Done.
213 bool multipartReceiveFailed = m_multipartParser->isCancelled();
horo 2016/09/27 10:45:49 nit: const
e_hakkinen 2016/09/28 15:15:04 Done.
214 result = m_consumer->endRead(available);
215 if (!bufferAppended || multipartReceiveFailed)
216 result = BytesConsumer::Result::Error;
217 }
218 if (result == BytesConsumer::Result::Done) {
219 if (m_multipartParser->finish()) {
yhirano 2016/09/26 10:59:34 Why don't you move this section into the below swi
e_hakkinen 2016/09/28 15:15:04 Maybe done. I am not if I understood correctly wha
220 DCHECK(!m_multipartParser->isCancelled());
221 m_client->didFetchDataLoadedFormData(m_formData);
222 return;
223 }
224 result = BytesConsumer::Result::Error;
225 }
226 switch (result) {
227 case BytesConsumer::Result::Ok:
228 break;
229 case BytesConsumer::Result::ShouldWait:
230 case BytesConsumer::Result::Done:
231 NOTREACHED();
232 return;
233 case BytesConsumer::Result::Error:
234 cancel();
235 m_client->didFetchDataLoadFailed();
236 return;
237 }
238 }
239 }
240
241 void cancel() override
242 {
243 m_consumer->cancel();
244 m_multipartParser->cancel();
245 }
246
247 DEFINE_INLINE_TRACE()
248 {
249 visitor->trace(m_consumer);
250 visitor->trace(m_client);
251 visitor->trace(m_formData);
252 visitor->trace(m_multipartParser);
253 FetchDataLoader::trace(visitor);
254 BytesConsumer::Client::trace(visitor);
255 MultipartParser::Client::trace(visitor);
256 }
257
258 private:
259 void partHeaderFieldsInMultipartReceived(const ResourceResponse& response) o verride
260 {
261 if (!m_currentEntry.initialize(response))
262 m_multipartParser->cancel();
263 }
264
265 void partDataInMultipartReceived(const char* bytes, size_t size) override
266 {
267 if (!m_currentEntry.appendBytes(bytes, size))
268 m_multipartParser->cancel();
269 }
270
271 void partDataInMultipartFullyReceived() override
272 {
273 if (!m_currentEntry.finish(m_formData))
274 m_multipartParser->cancel();
275 }
276
277 class Entry {
278 public:
279 bool initialize(const ResourceResponse& response)
280 {
281 ParsedContentType disposition(response.httpHeaderField(HTTPNames::Co ntent_Disposition));
horo 2016/09/27 10:45:50 nit: const
e_hakkinen 2016/09/28 15:15:04 Done.
282 String dispositionType = disposition.mimeType();
horo 2016/09/27 10:45:49 nit: const
e_hakkinen 2016/09/28 15:15:04 Done.
283 m_filename = disposition.parameterValueForName("filename");
284 m_name = disposition.parameterValueForName("name");
285 m_blobData.reset();
286 m_stringBuilder.reset();
287 if (dispositionType != "form-data" || m_name.isNull())
288 return false;
289 if (!m_filename.isNull()) {
290 m_blobData = BlobData::create();
291 m_blobData->setContentType(response.httpHeaderField(HTTPNames::C ontent_Type));
292 } else {
yhirano 2016/09/26 10:59:34 You're assuming that each part which doesn't have
e_hakkinen 2016/09/28 15:15:04 I am not sure as https://fetch.spec.whatwg.org/#co
yhirano 2016/09/29 08:30:09 If the spec is unclear, I think it's a good idea t
293 if (!m_decoder)
294 m_decoder = TextResourceDecoder::createAlwaysUseUTF8ForText( );
yhirano 2016/09/26 10:59:34 Is always using utf-8 appropriate? https://tools.i
e_hakkinen 2016/09/28 15:15:04 I think so. The https://fetch.spec.whatwg.org/#co
295 m_stringBuilder.reset(new StringBuilder);
296 }
297 return true;
298 }
299
300 bool appendBytes(const char* bytes, size_t size)
301 {
302 if (m_blobData)
303 m_blobData->appendBytes(bytes, size);
304 if (m_stringBuilder) {
305 m_stringBuilder->append(m_decoder->decode(bytes, size));
306 if (m_decoder->sawError())
307 return false;
308 }
309 return true;
310 }
311
312 bool finish(FormData* formData)
313 {
314 if (m_blobData) {
315 DCHECK(!m_stringBuilder);
316 auto size = m_blobData->length();
horo 2016/09/27 10:45:49 nit: const
e_hakkinen 2016/09/28 15:15:04 Done.
317 formData->append(m_name, Blob::create(BlobDataHandle::create(std ::move(m_blobData), size)), m_filename);
318 }
319 if (m_stringBuilder) {
320 DCHECK(!m_blobData);
321 m_stringBuilder->append(m_decoder->flush());
322 if (m_decoder->sawError())
323 return false;
324 formData->append(m_name, m_stringBuilder->toString());
325 }
326 return true;
327 }
328
329 private:
330 std::unique_ptr<BlobData> m_blobData;
331 std::unique_ptr<TextResourceDecoder> m_decoder;
332 String m_filename;
333 String m_name;
334 std::unique_ptr<StringBuilder> m_stringBuilder;
335 };
336
337 Member<BytesConsumer> m_consumer;
338 Member<FetchDataLoader::Client> m_client;
339 Member<FormData> m_formData;
340 Member<MultipartParser> m_multipartParser;
341
342 Entry m_currentEntry;
343 String m_multipartBoundary;
344 };
345
171 class FetchDataLoaderAsString final : public FetchDataLoader, public BytesConsum er::Client { 346 class FetchDataLoaderAsString final : public FetchDataLoader, public BytesConsum er::Client {
172 USING_GARBAGE_COLLECTED_MIXIN(FetchDataLoaderAsString); 347 USING_GARBAGE_COLLECTED_MIXIN(FetchDataLoaderAsString);
173 public: 348 public:
174 void start(BytesConsumer* consumer, FetchDataLoader::Client* client) overrid e 349 void start(BytesConsumer* consumer, FetchDataLoader::Client* client) overrid e
175 { 350 {
176 DCHECK(!m_client); 351 DCHECK(!m_client);
177 DCHECK(!m_decoder); 352 DCHECK(!m_decoder);
178 DCHECK(!m_consumer); 353 DCHECK(!m_consumer);
179 m_client = client; 354 m_client = client;
180 m_decoder = TextResourceDecoder::createAlwaysUseUTF8ForText(); 355 m_decoder = TextResourceDecoder::createAlwaysUseUTF8ForText();
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
312 FetchDataLoader* FetchDataLoader::createLoaderAsBlobHandle(const String& mimeTyp e) 487 FetchDataLoader* FetchDataLoader::createLoaderAsBlobHandle(const String& mimeTyp e)
313 { 488 {
314 return new FetchDataLoaderAsBlobHandle(mimeType); 489 return new FetchDataLoaderAsBlobHandle(mimeType);
315 } 490 }
316 491
317 FetchDataLoader* FetchDataLoader::createLoaderAsArrayBuffer() 492 FetchDataLoader* FetchDataLoader::createLoaderAsArrayBuffer()
318 { 493 {
319 return new FetchDataLoaderAsArrayBuffer(); 494 return new FetchDataLoaderAsArrayBuffer();
320 } 495 }
321 496
497 FetchDataLoader* FetchDataLoader::createLoaderAsFormData(const String& multipart Boundary)
498 {
499 return new FetchDataLoaderAsFormData(multipartBoundary);
500 }
501
322 FetchDataLoader* FetchDataLoader::createLoaderAsString() 502 FetchDataLoader* FetchDataLoader::createLoaderAsString()
323 { 503 {
324 return new FetchDataLoaderAsString(); 504 return new FetchDataLoaderAsString();
325 } 505 }
326 506
327 FetchDataLoader* FetchDataLoader::createLoaderAsStream(Stream* outStream) 507 FetchDataLoader* FetchDataLoader::createLoaderAsStream(Stream* outStream)
328 { 508 {
329 return new FetchDataLoaderAsStream(outStream); 509 return new FetchDataLoaderAsStream(outStream);
330 } 510 }
331 511
332 } // namespace blink 512 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698