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

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: Parse functions etc Created 4 years, 3 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 {
yhirano 2016/09/21 09:02:57 Please add unittests.
e_hakkinen 2016/09/22 22:27:15 Done.
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();
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 (!m_multipartParser->isCancelled()) {
206 const char* buffer;
207 size_t available;
208 switch (m_consumer->beginRead(&buffer, &available)) {
209 case BytesConsumer::Result::Ok:
210 if (available > 0) {
211 if (!m_multipartParser->appendData(buffer, available))
212 failed();
yhirano 2016/09/21 09:02:57 BytesConsumer::cancel cannot be called in a two-ph
e_hakkinen 2016/09/22 22:27:15 Done.
213 }
214 if (m_consumer->endRead(available) != BytesConsumer::Result::Ok) {
yhirano 2016/09/21 09:02:57 I recently changed BytesConsumer::endRead so that
e_hakkinen 2016/09/22 22:27:16 Done.
215 m_client->didFetchDataLoadFailed();
yhirano 2016/09/21 09:02:57 failed()?
e_hakkinen 2016/09/22 22:27:16 Yeah, but there is not really need for failed() to
216 return;
217 }
218 break;
219 case BytesConsumer::Result::ShouldWait:
220 return;
221 case BytesConsumer::Result::Done:
222 if (m_multipartParser->finish()) {
223 m_client->didFetchDataLoadedFormData(m_formData);
224 } else {
225 m_client->didFetchDataLoadFailed();
226 }
227 return;
228 case BytesConsumer::Result::Error:
229 m_client->didFetchDataLoadFailed();
230 return;
231 }
232 }
233 }
234
235 void cancel() override
236 {
237 m_consumer->cancel();
238 m_multipartParser->cancel();
239 }
240
241 DEFINE_INLINE_TRACE()
242 {
243 visitor->trace(m_consumer);
244 visitor->trace(m_client);
245 visitor->trace(m_formData);
246 visitor->trace(m_multipartParser);
247 FetchDataLoader::trace(visitor);
248 BytesConsumer::Client::trace(visitor);
249 MultipartParser::Client::trace(visitor);
250 }
251
252 private:
253 void failed()
254 {
255 m_client->didFetchDataLoadFailed();
256 // The client does not like to be notified multiple times thus stop
257 // parsing so that no more errors will be reached.
258 cancel();
259 }
260
261 void partHeaderFieldsInMultipartReceived(const ResourceResponse& response) o verride
262 {
263 if (!m_currentEntry.initialize(response))
264 failed();
265 }
266
267 void partDataInMultipartReceived(const char* bytes, size_t size) override
268 {
269 if (!m_currentEntry.appendBytes(bytes, size))
270 failed();
271 }
272
273 void partDataInMultipartFullyReceived() override
274 {
275 if (!m_currentEntry.finish(m_formData))
276 failed();
277 }
278
279 class Entry {
280 public:
281 bool initialize(const ResourceResponse& response)
282 {
283 ParsedContentType disposition(response.httpHeaderField(HTTPNames::Co ntent_Disposition));
284 String dispositionType = disposition.mimeType();
285 m_filename = disposition.parameterValueForName("filename");
286 m_name = disposition.parameterValueForName("name");
287 m_blobData.reset();
288 m_stringBuilder.reset();
289 if (dispositionType != "form-data" || m_name.isNull())
290 return false;
291 if (!m_filename.isNull()) {
292 m_blobData = BlobData::create();
293 m_blobData->setContentType(response.httpHeaderField(HTTPNames::C ontent_Type));
294 } else {
295 if (!m_decoder)
296 m_decoder = TextResourceDecoder::createAlwaysUseUTF8ForText( );
297 m_stringBuilder.reset(new StringBuilder);
298 }
299 return true;
300 }
301
302 bool appendBytes(const char* bytes, size_t size)
303 {
304 if (m_blobData)
305 m_blobData->appendBytes(bytes, size);
306 if (m_stringBuilder) {
307 m_stringBuilder->append(m_decoder->decode(bytes, size));
308 if (m_decoder->sawError())
309 return false;
310 }
311 return true;
312 }
313
314 bool finish(FormData* formData)
315 {
316 if (m_blobData) {
317 DCHECK(!m_stringBuilder);
318 auto size = m_blobData->length();
319 formData->append(m_name, Blob::create(BlobDataHandle::create(std ::move(m_blobData), size)), m_filename);
320 }
321 if (m_stringBuilder) {
322 DCHECK(!m_blobData);
323 m_stringBuilder->append(m_decoder->flush());
324 if (m_decoder->sawError())
325 return false;
326 formData->append(m_name, m_stringBuilder->toString());
327 }
328 return true;
329 }
330
331 private:
332 std::unique_ptr<BlobData> m_blobData;
333 std::unique_ptr<TextResourceDecoder> m_decoder;
334 String m_filename;
335 String m_name;
336 std::unique_ptr<StringBuilder> m_stringBuilder;
337 };
338
339 Member<BytesConsumer> m_consumer;
340 Member<FetchDataLoader::Client> m_client;
341 Member<FormData> m_formData;
342 Member<MultipartParser> m_multipartParser;
343
344 Entry m_currentEntry;
345 String m_multipartBoundary;
346 };
347
171 class FetchDataLoaderAsString final : public FetchDataLoader, public BytesConsum er::Client { 348 class FetchDataLoaderAsString final : public FetchDataLoader, public BytesConsum er::Client {
172 USING_GARBAGE_COLLECTED_MIXIN(FetchDataLoaderAsString); 349 USING_GARBAGE_COLLECTED_MIXIN(FetchDataLoaderAsString);
173 public: 350 public:
174 void start(BytesConsumer* consumer, FetchDataLoader::Client* client) overrid e 351 void start(BytesConsumer* consumer, FetchDataLoader::Client* client) overrid e
175 { 352 {
176 DCHECK(!m_client); 353 DCHECK(!m_client);
177 DCHECK(!m_decoder); 354 DCHECK(!m_decoder);
178 DCHECK(!m_consumer); 355 DCHECK(!m_consumer);
179 m_client = client; 356 m_client = client;
180 m_decoder = TextResourceDecoder::createAlwaysUseUTF8ForText(); 357 m_decoder = TextResourceDecoder::createAlwaysUseUTF8ForText();
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
312 FetchDataLoader* FetchDataLoader::createLoaderAsBlobHandle(const String& mimeTyp e) 489 FetchDataLoader* FetchDataLoader::createLoaderAsBlobHandle(const String& mimeTyp e)
313 { 490 {
314 return new FetchDataLoaderAsBlobHandle(mimeType); 491 return new FetchDataLoaderAsBlobHandle(mimeType);
315 } 492 }
316 493
317 FetchDataLoader* FetchDataLoader::createLoaderAsArrayBuffer() 494 FetchDataLoader* FetchDataLoader::createLoaderAsArrayBuffer()
318 { 495 {
319 return new FetchDataLoaderAsArrayBuffer(); 496 return new FetchDataLoaderAsArrayBuffer();
320 } 497 }
321 498
499 FetchDataLoader* FetchDataLoader::createLoaderAsFormData(const String& multipart Boundary)
500 {
501 return new FetchDataLoaderAsFormData(multipartBoundary);
502 }
503
322 FetchDataLoader* FetchDataLoader::createLoaderAsString() 504 FetchDataLoader* FetchDataLoader::createLoaderAsString()
323 { 505 {
324 return new FetchDataLoaderAsString(); 506 return new FetchDataLoaderAsString();
325 } 507 }
326 508
327 FetchDataLoader* FetchDataLoader::createLoaderAsStream(Stream* outStream) 509 FetchDataLoader* FetchDataLoader::createLoaderAsStream(Stream* outStream)
328 { 510 {
329 return new FetchDataLoaderAsStream(outStream); 511 return new FetchDataLoaderAsStream(outStream);
330 } 512 }
331 513
332 } // namespace blink 514 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698