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

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 3 years, 7 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 <memory> 7 #include <memory>
8 #include "core/fileapi/File.h"
9 #include "core/html/FormData.h"
8 #include "core/html/parser/TextResourceDecoder.h" 10 #include "core/html/parser/TextResourceDecoder.h"
9 #include "modules/fetch/BytesConsumer.h" 11 #include "modules/fetch/BytesConsumer.h"
12 #include "modules/fetch/MultipartParser.h"
10 #include "mojo/public/cpp/system/simple_watcher.h" 13 #include "mojo/public/cpp/system/simple_watcher.h"
14 #include "platform/HTTPNames.h"
15 #include "platform/network/ParsedContentType.h"
11 #include "platform/wtf/Functional.h" 16 #include "platform/wtf/Functional.h"
12 #include "platform/wtf/PtrUtil.h" 17 #include "platform/wtf/PtrUtil.h"
13 #include "platform/wtf/text/StringBuilder.h" 18 #include "platform/wtf/text/StringBuilder.h"
14 #include "platform/wtf/text/WTFString.h" 19 #include "platform/wtf/text/WTFString.h"
15 #include "platform/wtf/typed_arrays/ArrayBufferBuilder.h" 20 #include "platform/wtf/typed_arrays/ArrayBufferBuilder.h"
16 21
17 namespace blink { 22 namespace blink {
18 23
19 namespace { 24 namespace {
20 25
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
163 BytesConsumer::Client::Trace(visitor); 168 BytesConsumer::Client::Trace(visitor);
164 } 169 }
165 170
166 private: 171 private:
167 Member<BytesConsumer> consumer_; 172 Member<BytesConsumer> consumer_;
168 Member<FetchDataLoader::Client> client_; 173 Member<FetchDataLoader::Client> client_;
169 174
170 std::unique_ptr<ArrayBufferBuilder> raw_data_; 175 std::unique_ptr<ArrayBufferBuilder> raw_data_;
171 }; 176 };
172 177
178 class FetchDataLoaderAsFormData final : public FetchDataLoader,
179 public BytesConsumer::Client,
180 public MultipartParser::Client {
181 USING_GARBAGE_COLLECTED_MIXIN(FetchDataLoaderAsFormData);
182
183 public:
184 explicit FetchDataLoaderAsFormData(const String& multipart_boundary)
185 : multipart_boundary_(multipart_boundary) {}
186
187 void Start(BytesConsumer* consumer,
188 FetchDataLoader::Client* client) override {
189 DCHECK(!client_);
190 DCHECK(!consumer_);
191 DCHECK(!form_data_);
192 DCHECK(!multipart_parser_);
193
194 const CString multipart_boundary_utf8 = multipart_boundary_.Utf8();
195 Vector<char> multipart_boundary_vector;
196 multipart_boundary_vector.Append(multipart_boundary_utf8.data(),
197 multipart_boundary_utf8.length());
198
199 client_ = client;
200 form_data_ = FormData::Create();
201 multipart_parser_ =
202 new MultipartParser(std::move(multipart_boundary_vector), this);
203 consumer_ = consumer;
204 consumer_->SetClient(this);
205 OnStateChange();
206 }
207
208 void OnStateChange() override {
209 while (true) {
210 const char* buffer;
211 size_t available;
212 auto result = consumer_->BeginRead(&buffer, &available);
213 if (result == BytesConsumer::Result::kShouldWait)
214 return;
215 if (result == BytesConsumer::Result::kOk) {
216 const bool buffer_appended =
217 multipart_parser_->AppendData(buffer, available);
218 const bool multipart_receive_failed = multipart_parser_->IsCancelled();
219 result = consumer_->EndRead(available);
220 if (!buffer_appended || multipart_receive_failed)
221 result = BytesConsumer::Result::kError;
222 }
223 switch (result) {
224 case BytesConsumer::Result::kOk:
225 break;
226 case BytesConsumer::Result::kShouldWait:
227 NOTREACHED();
228 return;
229 case BytesConsumer::Result::kDone:
230 if (multipart_parser_->Finish()) {
231 DCHECK(!multipart_parser_->IsCancelled());
232 client_->DidFetchDataLoadedFormData(form_data_);
233 } else {
234 client_->DidFetchDataLoadFailed();
235 }
236 return;
237 case BytesConsumer::Result::kError:
238 client_->DidFetchDataLoadFailed();
239 return;
240 }
241 }
242 }
243
244 void Cancel() override {
245 consumer_->Cancel();
246 multipart_parser_->Cancel();
247 }
248
249 DEFINE_INLINE_TRACE() {
250 visitor->Trace(consumer_);
251 visitor->Trace(client_);
252 visitor->Trace(form_data_);
253 visitor->Trace(multipart_parser_);
254 FetchDataLoader::Trace(visitor);
255 BytesConsumer::Client::Trace(visitor);
256 MultipartParser::Client::Trace(visitor);
257 }
258
259 private:
260 void PartHeaderFieldsInMultipartReceived(
261 const HTTPHeaderMap& header_fields) override {
262 if (!current_entry_.Initialize(header_fields))
263 multipart_parser_->Cancel();
264 }
265
266 void PartDataInMultipartReceived(const char* bytes, size_t size) override {
267 if (!current_entry_.AppendBytes(bytes, size))
268 multipart_parser_->Cancel();
269 }
270
271 void PartDataInMultipartFullyReceived() override {
272 if (!current_entry_.Finish(form_data_))
273 multipart_parser_->Cancel();
274 }
275
276 class Entry {
277 public:
278 bool Initialize(const HTTPHeaderMap& header_fields) {
279 const ParsedContentType disposition(
yhirano 2017/05/10 05:59:36 Need some comments why we use x-fake.
e_hakkinen 2017/05/11 11:01:51 Done. I also created https://crrev.com/2880543003
280 "x-fake/" + header_fields.Get(HTTPNames::Content_Disposition));
281 const String disposition_type = disposition.MimeType().Substring(7u);
yhirano 2017/05/10 05:59:36 Need some comments for the magic number.
e_hakkinen 2017/05/11 11:01:51 Done.
282 filename_ = disposition.ParameterValueForName("filename");
283 name_ = disposition.ParameterValueForName("name");
284 blob_data_.reset();
285 string_builder_.reset();
286 if (disposition_type != "form-data" || name_.IsNull())
287 return false;
288 if (!filename_.IsNull()) {
289 blob_data_ = BlobData::Create();
290 const AtomicString& content_type =
291 header_fields.Get(HTTPNames::Content_Type);
292 blob_data_->SetContentType(content_type.IsNull() ? "text/plain"
293 : content_type);
294 } else {
295 if (!string_decoder_)
296 string_decoder_ = TextResourceDecoder::CreateAlwaysUseUTF8ForText();
297 string_builder_.reset(new StringBuilder);
298 }
299 return true;
300 }
301
302 bool AppendBytes(const char* bytes, size_t size) {
303 if (blob_data_)
304 blob_data_->AppendBytes(bytes, size);
305 if (string_builder_) {
306 string_builder_->Append(string_decoder_->Decode(bytes, size));
307 if (string_decoder_->SawError())
308 return false;
309 }
310 return true;
311 }
312
313 bool Finish(FormData* form_data) {
314 if (blob_data_) {
315 DCHECK(!string_builder_);
316 const auto size = blob_data_->length();
317 File* file =
318 File::Create(filename_, InvalidFileTime(),
319 BlobDataHandle::Create(std::move(blob_data_), size));
320 form_data->append(name_, file, filename_);
321 }
322 if (string_builder_) {
323 DCHECK(!blob_data_);
324 string_builder_->Append(string_decoder_->Flush());
325 if (string_decoder_->SawError())
326 return false;
327 form_data->append(name_, string_builder_->ToString());
328 }
329 return true;
330 }
331
332 private:
333 std::unique_ptr<BlobData> blob_data_;
334 String filename_;
335 String name_;
336 std::unique_ptr<StringBuilder> string_builder_;
337 std::unique_ptr<TextResourceDecoder> string_decoder_;
338 };
339
340 Member<BytesConsumer> consumer_;
341 Member<FetchDataLoader::Client> client_;
342 Member<FormData> form_data_;
343 Member<MultipartParser> multipart_parser_;
344
345 Entry current_entry_;
346 String multipart_boundary_;
347 };
348
173 class FetchDataLoaderAsString final : public FetchDataLoader, 349 class FetchDataLoaderAsString final : public FetchDataLoader,
174 public BytesConsumer::Client { 350 public BytesConsumer::Client {
175 USING_GARBAGE_COLLECTED_MIXIN(FetchDataLoaderAsString); 351 USING_GARBAGE_COLLECTED_MIXIN(FetchDataLoaderAsString);
176 352
177 public: 353 public:
178 void Start(BytesConsumer* consumer, 354 void Start(BytesConsumer* consumer,
179 FetchDataLoader::Client* client) override { 355 FetchDataLoader::Client* client) override {
180 DCHECK(!client_); 356 DCHECK(!client_);
181 DCHECK(!decoder_); 357 DCHECK(!decoder_);
182 DCHECK(!consumer_); 358 DCHECK(!consumer_);
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after
334 510
335 FetchDataLoader* FetchDataLoader::CreateLoaderAsBlobHandle( 511 FetchDataLoader* FetchDataLoader::CreateLoaderAsBlobHandle(
336 const String& mime_type) { 512 const String& mime_type) {
337 return new FetchDataLoaderAsBlobHandle(mime_type); 513 return new FetchDataLoaderAsBlobHandle(mime_type);
338 } 514 }
339 515
340 FetchDataLoader* FetchDataLoader::CreateLoaderAsArrayBuffer() { 516 FetchDataLoader* FetchDataLoader::CreateLoaderAsArrayBuffer() {
341 return new FetchDataLoaderAsArrayBuffer(); 517 return new FetchDataLoaderAsArrayBuffer();
342 } 518 }
343 519
520 FetchDataLoader* FetchDataLoader::CreateLoaderAsFormData(
521 const String& multipartBoundary) {
522 return new FetchDataLoaderAsFormData(multipartBoundary);
523 }
524
344 FetchDataLoader* FetchDataLoader::CreateLoaderAsString() { 525 FetchDataLoader* FetchDataLoader::CreateLoaderAsString() {
345 return new FetchDataLoaderAsString(); 526 return new FetchDataLoaderAsString();
346 } 527 }
347 528
348 FetchDataLoader* FetchDataLoader::CreateLoaderAsDataPipe( 529 FetchDataLoader* FetchDataLoader::CreateLoaderAsDataPipe(
349 mojo::ScopedDataPipeProducerHandle out_data_pipe) { 530 mojo::ScopedDataPipeProducerHandle out_data_pipe) {
350 return new FetchDataLoaderAsDataPipe(std::move(out_data_pipe)); 531 return new FetchDataLoaderAsDataPipe(std::move(out_data_pipe));
351 } 532 }
352 533
353 } // namespace blink 534 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698