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

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 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
154 BytesConsumer::Client::trace(visitor); 159 BytesConsumer::Client::trace(visitor);
155 } 160 }
156 161
157 private: 162 private:
158 Member<BytesConsumer> m_consumer; 163 Member<BytesConsumer> m_consumer;
159 Member<FetchDataLoader::Client> m_client; 164 Member<FetchDataLoader::Client> m_client;
160 165
161 std::unique_ptr<ArrayBufferBuilder> m_rawData; 166 std::unique_ptr<ArrayBufferBuilder> m_rawData;
162 }; 167 };
163 168
169 class FetchDataLoaderAsFormData final : public FetchDataLoader, public BytesCons umer::Client, public MultipartParser::Client {
170 USING_GARBAGE_COLLECTED_MIXIN(FetchDataLoaderAsFormData);
171
172 public:
173 explicit FetchDataLoaderAsFormData(const String& multipartBoundary)
174 : m_multipartBoundary(multipartBoundary)
175 {
176 }
177
178 void start(BytesConsumer* consumer, FetchDataLoader::Client* client) overrid e
179 {
180 DCHECK(!m_client);
181 DCHECK(!m_multipartParser);
182 DCHECK(!m_consumer);
183
184 CString multipartBoundaryCString = m_multipartBoundary.utf8();
185 Vector<char> multipartBoundaryVector;
186 multipartBoundaryVector.append(multipartBoundaryCString.data(), multipar tBoundaryCString.length());
187
188 m_client = client;
189 m_formData = FormData::create();
190 m_multipartParser = new MultipartParser(std::move(multipartBoundaryVecto r), this);
191 m_consumer = consumer;
192 m_consumer->setClient(this);
193 onStateChange();
194 }
195
196 void onStateChange() override
197 {
198 while (!m_multipartParser->isCancelled()) {
199 const char* buffer;
200 size_t available;
201 switch (m_consumer->beginRead(&buffer, &available)) {
202 case BytesConsumer::Result::Ok:
203 if (available > 0) {
204 if (!m_multipartParser->appendData(buffer, available))
205 failed();
206 }
207 m_consumer->endRead(available);
208 break;
209 case BytesConsumer::Result::ShouldWait:
210 return;
211 case BytesConsumer::Result::Done:
212 if (m_multipartParser->finish()) {
213 m_client->didFetchDataLoadedFormData(m_formData);
214 } else {
215 m_client->didFetchDataLoadFailed();
216 }
217 return;
218 case BytesConsumer::Result::Error:
219 m_client->didFetchDataLoadFailed();
220 return;
221 }
222 }
223 }
224
225 void cancel() override
226 {
227 m_consumer->cancel();
228 m_multipartParser->cancel();
229 }
230
231 DEFINE_INLINE_TRACE()
232 {
233 visitor->trace(m_consumer);
234 visitor->trace(m_client);
235 visitor->trace(m_formData);
236 visitor->trace(m_multipartParser);
237 FetchDataLoader::trace(visitor);
238 BytesConsumer::Client::trace(visitor);
239 MultipartParser::Client::trace(visitor);
240 }
241
242 private:
243 void failed()
244 {
245 m_client->didFetchDataLoadFailed();
246 // The client does not like to be notified multiple times thus stop
247 // parsing so that no more errors will be reached.
248 cancel();
249 }
250
251 void partHeaderFieldsInMultipartReceived(const ResourceResponse& response) o verride
252 {
253 if (!m_currentEntry.initialize(response))
254 failed();
255 }
256
257 void partDataInMultipartReceived(const char* bytes, size_t size) override
258 {
259 if (!m_currentEntry.appendBytes(bytes, size))
260 failed();
261 }
262
263 void partDataInMultipartFullyReceived() override
264 {
265 if (!m_currentEntry.finish(m_formData))
266 failed();
267 }
268
269 class Entry {
270 public:
271 bool initialize(const ResourceResponse& response)
272 {
273 ParsedContentType disposition(response.httpHeaderField(HTTPNames::Co ntent_Disposition));
274 String dispositionType = disposition.mimeType();
275 m_filename = disposition.parameterValueForName("filename");
276 m_name = disposition.parameterValueForName("name");
277 m_blobData.reset();
278 m_stringBuilder.reset();
279 if (dispositionType != "form-data" || m_name.isNull())
280 return false;
281 if (!m_filename.isNull()) {
282 m_blobData = BlobData::create();
283 m_blobData->setContentType(response.httpHeaderField(HTTPNames::C ontent_Type));
284 } else {
285 if (!m_decoder)
286 m_decoder = TextResourceDecoder::createAlwaysUseUTF8ForText( );
287 m_stringBuilder.reset(new StringBuilder);
288 }
289 return true;
290 }
291
292 bool appendBytes(const char* bytes, size_t size)
293 {
294 if (m_blobData)
295 m_blobData->appendBytes(bytes, size);
296 if (m_stringBuilder) {
297 m_stringBuilder->append(m_decoder->decode(bytes, size));
298 if (m_decoder->sawError())
299 return false;
300 }
301 return true;
302 }
303
304 bool finish(FormData* formData)
305 {
306 if (m_blobData) {
307 DCHECK(!m_stringBuilder);
308 auto size = m_blobData->length();
309 formData->append(m_name, Blob::create(BlobDataHandle::create(std ::move(m_blobData), size)), m_filename);
310 }
311 if (m_stringBuilder) {
312 DCHECK(!m_blobData);
313 m_stringBuilder->append(m_decoder->flush());
314 if (m_decoder->sawError())
315 return false;
316 formData->append(m_name, m_stringBuilder->toString());
317 }
318 return true;
319 }
320
321 private:
322 std::unique_ptr<BlobData> m_blobData;
323 std::unique_ptr<TextResourceDecoder> m_decoder;
324 String m_filename;
325 String m_name;
326 std::unique_ptr<StringBuilder> m_stringBuilder;
327 };
328
329 Member<BytesConsumer> m_consumer;
330 Member<FetchDataLoader::Client> m_client;
331 Member<FormData> m_formData;
332 Member<MultipartParser> m_multipartParser;
333
334 Entry m_currentEntry;
335 String m_multipartBoundary;
336 };
337
164 class FetchDataLoaderAsString final : public FetchDataLoader, public BytesConsum er::Client { 338 class FetchDataLoaderAsString final : public FetchDataLoader, public BytesConsum er::Client {
165 USING_GARBAGE_COLLECTED_MIXIN(FetchDataLoaderAsString); 339 USING_GARBAGE_COLLECTED_MIXIN(FetchDataLoaderAsString);
166 public: 340 public:
167 void start(BytesConsumer* consumer, FetchDataLoader::Client* client) overrid e 341 void start(BytesConsumer* consumer, FetchDataLoader::Client* client) overrid e
168 { 342 {
169 DCHECK(!m_client); 343 DCHECK(!m_client);
170 DCHECK(!m_decoder); 344 DCHECK(!m_decoder);
171 DCHECK(!m_consumer); 345 DCHECK(!m_consumer);
172 m_client = client; 346 m_client = client;
173 m_decoder = TextResourceDecoder::createAlwaysUseUTF8ForText(); 347 m_decoder = TextResourceDecoder::createAlwaysUseUTF8ForText();
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
298 FetchDataLoader* FetchDataLoader::createLoaderAsBlobHandle(const String& mimeTyp e) 472 FetchDataLoader* FetchDataLoader::createLoaderAsBlobHandle(const String& mimeTyp e)
299 { 473 {
300 return new FetchDataLoaderAsBlobHandle(mimeType); 474 return new FetchDataLoaderAsBlobHandle(mimeType);
301 } 475 }
302 476
303 FetchDataLoader* FetchDataLoader::createLoaderAsArrayBuffer() 477 FetchDataLoader* FetchDataLoader::createLoaderAsArrayBuffer()
304 { 478 {
305 return new FetchDataLoaderAsArrayBuffer(); 479 return new FetchDataLoaderAsArrayBuffer();
306 } 480 }
307 481
482 FetchDataLoader* FetchDataLoader::createLoaderAsFormData(const String& multipart Boundary)
483 {
484 return new FetchDataLoaderAsFormData(multipartBoundary);
485 }
486
308 FetchDataLoader* FetchDataLoader::createLoaderAsString() 487 FetchDataLoader* FetchDataLoader::createLoaderAsString()
309 { 488 {
310 return new FetchDataLoaderAsString(); 489 return new FetchDataLoaderAsString();
311 } 490 }
312 491
313 FetchDataLoader* FetchDataLoader::createLoaderAsStream(Stream* outStream) 492 FetchDataLoader* FetchDataLoader::createLoaderAsStream(Stream* outStream)
314 { 493 {
315 return new FetchDataLoaderAsStream(outStream); 494 return new FetchDataLoaderAsStream(outStream);
316 } 495 }
317 496
318 } // namespace blink 497 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698