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

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

Powered by Google App Engine
This is Rietveld 408576698