blob: 8de74fd293566774bda78e6c5bd84fb1b3f4531e [file] [log] [blame]
[email protected]b0ef9af2015-06-19 09:20:441// Copyright 2015 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]b0ef9af2015-06-19 09:20:445#include "modules/fetch/FetchDataLoader.h"
6
Yuta Kitamura68130af2017-04-11 08:20:367#include <memory>
eero.hakkinen6bd271f2017-05-22 11:36:048#include "core/fileapi/File.h"
9#include "core/html/FormData.h"
[email protected]3e1cfc82015-07-21 13:54:3810#include "core/html/parser/TextResourceDecoder.h"
yhirano6963b6b2016-08-17 04:14:5611#include "modules/fetch/BytesConsumer.h"
eero.hakkinen6bd271f2017-05-22 11:36:0412#include "modules/fetch/MultipartParser.h"
shimazu1ac68cf2017-04-20 06:03:4613#include "mojo/public/cpp/system/simple_watcher.h"
eero.hakkinen6bd271f2017-05-22 11:36:0414#include "platform/HTTPNames.h"
Hiroshige Hayashizakiee353af2017-06-20 22:37:3315#include "platform/loader/fetch/TextResourceDecoderOptions.h"
eero.hakkinenfb83c2d2017-05-24 06:53:3216#include "platform/network/ParsedContentDisposition.h"
shimazu1ac68cf2017-04-20 06:03:4617#include "platform/wtf/Functional.h"
Yuta Kitamura68130af2017-04-11 08:20:3618#include "platform/wtf/PtrUtil.h"
19#include "platform/wtf/text/StringBuilder.h"
20#include "platform/wtf/text/WTFString.h"
21#include "platform/wtf/typed_arrays/ArrayBufferBuilder.h"
[email protected]b0ef9af2015-06-19 09:20:4422
23namespace blink {
24
25namespace {
26
Blink Reformat1c8e1a772016-10-01 00:25:3227class FetchDataLoaderAsBlobHandle final : public FetchDataLoader,
28 public BytesConsumer::Client {
29 USING_GARBAGE_COLLECTED_MIXIN(FetchDataLoaderAsBlobHandle);
30
31 public:
Blink Reformat1c4d759e2017-04-09 16:34:5432 explicit FetchDataLoaderAsBlobHandle(const String& mime_type)
33 : mime_type_(mime_type) {}
Blink Reformat1c8e1a772016-10-01 00:25:3234
Blink Reformat1c4d759e2017-04-09 16:34:5435 void Start(BytesConsumer* consumer,
Blink Reformat1c8e1a772016-10-01 00:25:3236 FetchDataLoader::Client* client) override {
Blink Reformat1c4d759e2017-04-09 16:34:5437 DCHECK(!client_);
38 DCHECK(!consumer_);
Blink Reformat1c8e1a772016-10-01 00:25:3239
Blink Reformat1c4d759e2017-04-09 16:34:5440 client_ = client;
41 consumer_ = consumer;
Blink Reformat1c8e1a772016-10-01 00:25:3242
Blink Reformat1c4d759e2017-04-09 16:34:5443 RefPtr<BlobDataHandle> blob_handle = consumer_->DrainAsBlobDataHandle();
44 if (blob_handle) {
45 DCHECK_NE(UINT64_MAX, blob_handle->size());
46 if (blob_handle->GetType() != mime_type_) {
Marijn Kruisselbrink058ca542017-08-01 22:55:2147 storage::mojom::blink::BlobPtr blob_clone = blob_handle->CloneBlobPtr();
Blink Reformat1c8e1a772016-10-01 00:25:3248 // A new BlobDataHandle is created to override the Blob's type.
Marijn Kruisselbrink058ca542017-08-01 22:55:2149 // TODO(mek): It might be cleaner to create a new blob (referencing the
50 // old blob) rather than just a new BlobDataHandle with mime type not
51 // matching the type of the underlying blob.
Blink Reformat1c4d759e2017-04-09 16:34:5452 client_->DidFetchDataLoadedBlobHandle(BlobDataHandle::Create(
Marijn Kruisselbrink058ca542017-08-01 22:55:2153 blob_handle->Uuid(), mime_type_, blob_handle->size(),
54 blob_clone.PassInterface()));
Blink Reformat1c8e1a772016-10-01 00:25:3255 } else {
Blink Reformat1c4d759e2017-04-09 16:34:5456 client_->DidFetchDataLoadedBlobHandle(std::move(blob_handle));
Blink Reformat1c8e1a772016-10-01 00:25:3257 }
58 return;
[email protected]b0ef9af2015-06-19 09:20:4459 }
60
Blink Reformat1c4d759e2017-04-09 16:34:5461 blob_data_ = BlobData::Create();
62 blob_data_->SetContentType(mime_type_);
63 consumer_->SetClient(this);
64 OnStateChange();
Blink Reformat1c8e1a772016-10-01 00:25:3265 }
[email protected]b0ef9af2015-06-19 09:20:4466
Blink Reformat1c4d759e2017-04-09 16:34:5467 void Cancel() override { consumer_->Cancel(); }
yhirano6963b6b2016-08-17 04:14:5668
Blink Reformat1c4d759e2017-04-09 16:34:5469 void OnStateChange() override {
Blink Reformat1c8e1a772016-10-01 00:25:3270 while (true) {
71 const char* buffer;
72 size_t available;
Blink Reformat1c4d759e2017-04-09 16:34:5473 auto result = consumer_->BeginRead(&buffer, &available);
74 if (result == BytesConsumer::Result::kShouldWait)
Blink Reformat1c8e1a772016-10-01 00:25:3275 return;
Blink Reformat1c4d759e2017-04-09 16:34:5476 if (result == BytesConsumer::Result::kOk) {
77 blob_data_->AppendBytes(buffer, available);
78 result = consumer_->EndRead(available);
Blink Reformat1c8e1a772016-10-01 00:25:3279 }
80 switch (result) {
Blink Reformat1c4d759e2017-04-09 16:34:5481 case BytesConsumer::Result::kOk:
Blink Reformat1c8e1a772016-10-01 00:25:3282 break;
Blink Reformat1c4d759e2017-04-09 16:34:5483 case BytesConsumer::Result::kShouldWait:
Blink Reformat1c8e1a772016-10-01 00:25:3284 NOTREACHED();
85 return;
Blink Reformat1c4d759e2017-04-09 16:34:5486 case BytesConsumer::Result::kDone: {
87 auto size = blob_data_->length();
88 client_->DidFetchDataLoadedBlobHandle(
89 BlobDataHandle::Create(std::move(blob_data_), size));
Blink Reformat1c8e1a772016-10-01 00:25:3290 return;
91 }
Blink Reformat1c4d759e2017-04-09 16:34:5492 case BytesConsumer::Result::kError:
93 client_->DidFetchDataLoadFailed();
Blink Reformat1c8e1a772016-10-01 00:25:3294 return;
95 }
96 }
97 }
98
99 DEFINE_INLINE_TRACE() {
Blink Reformat1c4d759e2017-04-09 16:34:54100 visitor->Trace(consumer_);
101 visitor->Trace(client_);
102 FetchDataLoader::Trace(visitor);
103 BytesConsumer::Client::Trace(visitor);
Blink Reformat1c8e1a772016-10-01 00:25:32104 }
105
106 private:
Blink Reformat1c4d759e2017-04-09 16:34:54107 Member<BytesConsumer> consumer_;
108 Member<FetchDataLoader::Client> client_;
Blink Reformat1c8e1a772016-10-01 00:25:32109
Blink Reformat1c4d759e2017-04-09 16:34:54110 String mime_type_;
111 std::unique_ptr<BlobData> blob_data_;
Blink Reformat1c8e1a772016-10-01 00:25:32112};
113
114class FetchDataLoaderAsArrayBuffer final : public FetchDataLoader,
115 public BytesConsumer::Client {
116 USING_GARBAGE_COLLECTED_MIXIN(FetchDataLoaderAsArrayBuffer)
117 public:
Blink Reformat1c4d759e2017-04-09 16:34:54118 void Start(BytesConsumer* consumer,
Blink Reformat1c8e1a772016-10-01 00:25:32119 FetchDataLoader::Client* client) override {
Blink Reformat1c4d759e2017-04-09 16:34:54120 DCHECK(!client_);
121 DCHECK(!raw_data_);
122 DCHECK(!consumer_);
123 client_ = client;
124 raw_data_ = WTF::MakeUnique<ArrayBufferBuilder>();
125 consumer_ = consumer;
126 consumer_->SetClient(this);
127 OnStateChange();
Blink Reformat1c8e1a772016-10-01 00:25:32128 }
129
Blink Reformat1c4d759e2017-04-09 16:34:54130 void Cancel() override { consumer_->Cancel(); }
Blink Reformat1c8e1a772016-10-01 00:25:32131
Blink Reformat1c4d759e2017-04-09 16:34:54132 void OnStateChange() override {
Blink Reformat1c8e1a772016-10-01 00:25:32133 while (true) {
134 const char* buffer;
135 size_t available;
Blink Reformat1c4d759e2017-04-09 16:34:54136 auto result = consumer_->BeginRead(&buffer, &available);
137 if (result == BytesConsumer::Result::kShouldWait)
Blink Reformat1c8e1a772016-10-01 00:25:32138 return;
Blink Reformat1c4d759e2017-04-09 16:34:54139 if (result == BytesConsumer::Result::kOk) {
Blink Reformat1c8e1a772016-10-01 00:25:32140 if (available > 0) {
Blink Reformat1c4d759e2017-04-09 16:34:54141 unsigned bytes_appended = raw_data_->Append(buffer, available);
142 if (!bytes_appended) {
143 auto unused = consumer_->EndRead(0);
Blink Reformat1c8e1a772016-10-01 00:25:32144 ALLOW_UNUSED_LOCAL(unused);
Blink Reformat1c4d759e2017-04-09 16:34:54145 consumer_->Cancel();
146 client_->DidFetchDataLoadFailed();
[email protected]b0ef9af2015-06-19 09:20:44147 return;
Blink Reformat1c8e1a772016-10-01 00:25:32148 }
Blink Reformat1c4d759e2017-04-09 16:34:54149 DCHECK_EQ(bytes_appended, available);
[email protected]b0ef9af2015-06-19 09:20:44150 }
Blink Reformat1c4d759e2017-04-09 16:34:54151 result = consumer_->EndRead(available);
Blink Reformat1c8e1a772016-10-01 00:25:32152 }
153 switch (result) {
Blink Reformat1c4d759e2017-04-09 16:34:54154 case BytesConsumer::Result::kOk:
Blink Reformat1c8e1a772016-10-01 00:25:32155 break;
Blink Reformat1c4d759e2017-04-09 16:34:54156 case BytesConsumer::Result::kShouldWait:
Blink Reformat1c8e1a772016-10-01 00:25:32157 NOTREACHED();
158 return;
Blink Reformat1c4d759e2017-04-09 16:34:54159 case BytesConsumer::Result::kDone:
160 client_->DidFetchDataLoadedArrayBuffer(
161 DOMArrayBuffer::Create(raw_data_->ToArrayBuffer()));
Blink Reformat1c8e1a772016-10-01 00:25:32162 return;
Blink Reformat1c4d759e2017-04-09 16:34:54163 case BytesConsumer::Result::kError:
164 client_->DidFetchDataLoadFailed();
Blink Reformat1c8e1a772016-10-01 00:25:32165 return;
166 }
[email protected]b0ef9af2015-06-19 09:20:44167 }
Blink Reformat1c8e1a772016-10-01 00:25:32168 }
[email protected]b0ef9af2015-06-19 09:20:44169
Blink Reformat1c8e1a772016-10-01 00:25:32170 DEFINE_INLINE_TRACE() {
Blink Reformat1c4d759e2017-04-09 16:34:54171 visitor->Trace(consumer_);
172 visitor->Trace(client_);
173 FetchDataLoader::Trace(visitor);
174 BytesConsumer::Client::Trace(visitor);
Blink Reformat1c8e1a772016-10-01 00:25:32175 }
[email protected]b0ef9af2015-06-19 09:20:44176
Blink Reformat1c8e1a772016-10-01 00:25:32177 private:
Blink Reformat1c4d759e2017-04-09 16:34:54178 Member<BytesConsumer> consumer_;
179 Member<FetchDataLoader::Client> client_;
yhirano6963b6b2016-08-17 04:14:56180
Blink Reformat1c4d759e2017-04-09 16:34:54181 std::unique_ptr<ArrayBufferBuilder> raw_data_;
[email protected]b0ef9af2015-06-19 09:20:44182};
183
eero.hakkinen6bd271f2017-05-22 11:36:04184class FetchDataLoaderAsFailure final : public FetchDataLoader,
185 public BytesConsumer::Client {
186 USING_GARBAGE_COLLECTED_MIXIN(FetchDataLoaderAsFailure);
187
188 public:
189 void Start(BytesConsumer* consumer,
190 FetchDataLoader::Client* client) override {
191 DCHECK(!client_);
192 DCHECK(!consumer_);
193 client_ = client;
194 consumer_ = consumer;
195 consumer_->SetClient(this);
196 OnStateChange();
197 }
198
199 void OnStateChange() override {
200 while (true) {
201 const char* buffer;
202 size_t available;
203 auto result = consumer_->BeginRead(&buffer, &available);
204 if (result == BytesConsumer::Result::kShouldWait)
205 return;
206 if (result == BytesConsumer::Result::kOk)
207 result = consumer_->EndRead(available);
208 switch (result) {
209 case BytesConsumer::Result::kOk:
210 break;
211 case BytesConsumer::Result::kShouldWait:
212 NOTREACHED();
213 return;
214 case BytesConsumer::Result::kDone:
215 case BytesConsumer::Result::kError:
216 client_->DidFetchDataLoadFailed();
217 return;
218 }
219 }
220 }
221
222 void Cancel() override { consumer_->Cancel(); }
223
224 DEFINE_INLINE_TRACE() {
225 visitor->Trace(consumer_);
226 visitor->Trace(client_);
227 FetchDataLoader::Trace(visitor);
228 BytesConsumer::Client::Trace(visitor);
229 }
230
231 private:
232 Member<BytesConsumer> consumer_;
233 Member<FetchDataLoader::Client> client_;
234};
235
236class FetchDataLoaderAsFormData final : public FetchDataLoader,
237 public BytesConsumer::Client,
238 public MultipartParser::Client {
239 USING_GARBAGE_COLLECTED_MIXIN(FetchDataLoaderAsFormData);
240
241 public:
242 explicit FetchDataLoaderAsFormData(const String& multipart_boundary)
243 : multipart_boundary_(multipart_boundary) {}
244
245 void Start(BytesConsumer* consumer,
246 FetchDataLoader::Client* client) override {
247 DCHECK(!client_);
248 DCHECK(!consumer_);
249 DCHECK(!form_data_);
250 DCHECK(!multipart_parser_);
251
252 const CString multipart_boundary_utf8 = multipart_boundary_.Utf8();
253 Vector<char> multipart_boundary_vector;
254 multipart_boundary_vector.Append(multipart_boundary_utf8.data(),
255 multipart_boundary_utf8.length());
256
257 client_ = client;
258 form_data_ = FormData::Create();
259 multipart_parser_ =
260 new MultipartParser(std::move(multipart_boundary_vector), this);
261 consumer_ = consumer;
262 consumer_->SetClient(this);
263 OnStateChange();
264 }
265
266 void OnStateChange() override {
267 while (true) {
268 const char* buffer;
269 size_t available;
270 auto result = consumer_->BeginRead(&buffer, &available);
271 if (result == BytesConsumer::Result::kShouldWait)
272 return;
273 if (result == BytesConsumer::Result::kOk) {
274 const bool buffer_appended =
275 multipart_parser_->AppendData(buffer, available);
276 const bool multipart_receive_failed = multipart_parser_->IsCancelled();
277 result = consumer_->EndRead(available);
278 if (!buffer_appended || multipart_receive_failed)
279 result = BytesConsumer::Result::kError;
280 }
281 switch (result) {
282 case BytesConsumer::Result::kOk:
283 break;
284 case BytesConsumer::Result::kShouldWait:
285 NOTREACHED();
286 return;
287 case BytesConsumer::Result::kDone:
288 if (multipart_parser_->Finish()) {
289 DCHECK(!multipart_parser_->IsCancelled());
290 client_->DidFetchDataLoadedFormData(form_data_);
291 } else {
292 client_->DidFetchDataLoadFailed();
293 }
294 return;
295 case BytesConsumer::Result::kError:
296 client_->DidFetchDataLoadFailed();
297 return;
298 }
299 }
300 }
301
302 void Cancel() override {
303 consumer_->Cancel();
304 multipart_parser_->Cancel();
305 }
306
307 DEFINE_INLINE_TRACE() {
308 visitor->Trace(consumer_);
309 visitor->Trace(client_);
310 visitor->Trace(form_data_);
311 visitor->Trace(multipart_parser_);
312 FetchDataLoader::Trace(visitor);
313 BytesConsumer::Client::Trace(visitor);
314 MultipartParser::Client::Trace(visitor);
315 }
316
317 private:
318 void PartHeaderFieldsInMultipartReceived(
319 const HTTPHeaderMap& header_fields) override {
320 if (!current_entry_.Initialize(header_fields))
321 multipart_parser_->Cancel();
322 }
323
324 void PartDataInMultipartReceived(const char* bytes, size_t size) override {
325 if (!current_entry_.AppendBytes(bytes, size))
326 multipart_parser_->Cancel();
327 }
328
329 void PartDataInMultipartFullyReceived() override {
330 if (!current_entry_.Finish(form_data_))
331 multipart_parser_->Cancel();
332 }
333
334 class Entry {
335 public:
336 bool Initialize(const HTTPHeaderMap& header_fields) {
eero.hakkinenfb83c2d2017-05-24 06:53:32337 const ParsedContentDisposition disposition(
338 header_fields.Get(HTTPNames::Content_Disposition));
339 const String disposition_type = disposition.Type();
340 filename_ = disposition.Filename();
eero.hakkinen6bd271f2017-05-22 11:36:04341 name_ = disposition.ParameterValueForName("name");
342 blob_data_.reset();
343 string_builder_.reset();
344 if (disposition_type != "form-data" || name_.IsNull())
345 return false;
346 if (!filename_.IsNull()) {
347 blob_data_ = BlobData::Create();
348 const AtomicString& content_type =
349 header_fields.Get(HTTPNames::Content_Type);
350 blob_data_->SetContentType(content_type.IsNull() ? "text/plain"
351 : content_type);
352 } else {
Hiroshige Hayashizakiee353af2017-06-20 22:37:33353 if (!string_decoder_) {
354 string_decoder_ = TextResourceDecoder::Create(
355 TextResourceDecoderOptions::CreateAlwaysUseUTF8ForText());
356 }
eero.hakkinen6bd271f2017-05-22 11:36:04357 string_builder_.reset(new StringBuilder);
358 }
359 return true;
360 }
361
362 bool AppendBytes(const char* bytes, size_t size) {
363 if (blob_data_)
364 blob_data_->AppendBytes(bytes, size);
365 if (string_builder_) {
366 string_builder_->Append(string_decoder_->Decode(bytes, size));
367 if (string_decoder_->SawError())
368 return false;
369 }
370 return true;
371 }
372
373 bool Finish(FormData* form_data) {
374 if (blob_data_) {
375 DCHECK(!string_builder_);
376 const auto size = blob_data_->length();
377 File* file =
378 File::Create(filename_, InvalidFileTime(),
379 BlobDataHandle::Create(std::move(blob_data_), size));
380 form_data->append(name_, file, filename_);
381 return true;
382 }
383 DCHECK(!blob_data_);
384 DCHECK(string_builder_);
385 string_builder_->Append(string_decoder_->Flush());
386 if (string_decoder_->SawError())
387 return false;
388 form_data->append(name_, string_builder_->ToString());
389 return true;
390 }
391
392 private:
393 std::unique_ptr<BlobData> blob_data_;
394 String filename_;
395 String name_;
396 std::unique_ptr<StringBuilder> string_builder_;
397 std::unique_ptr<TextResourceDecoder> string_decoder_;
398 };
399
400 Member<BytesConsumer> consumer_;
401 Member<FetchDataLoader::Client> client_;
402 Member<FormData> form_data_;
403 Member<MultipartParser> multipart_parser_;
404
405 Entry current_entry_;
406 String multipart_boundary_;
407};
408
Blink Reformat1c8e1a772016-10-01 00:25:32409class FetchDataLoaderAsString final : public FetchDataLoader,
410 public BytesConsumer::Client {
411 USING_GARBAGE_COLLECTED_MIXIN(FetchDataLoaderAsString);
412
413 public:
Blink Reformat1c4d759e2017-04-09 16:34:54414 void Start(BytesConsumer* consumer,
Blink Reformat1c8e1a772016-10-01 00:25:32415 FetchDataLoader::Client* client) override {
Blink Reformat1c4d759e2017-04-09 16:34:54416 DCHECK(!client_);
417 DCHECK(!decoder_);
418 DCHECK(!consumer_);
419 client_ = client;
Hiroshige Hayashizakiee353af2017-06-20 22:37:33420 decoder_ = TextResourceDecoder::Create(
421 TextResourceDecoderOptions::CreateAlwaysUseUTF8ForText());
Blink Reformat1c4d759e2017-04-09 16:34:54422 consumer_ = consumer;
423 consumer_->SetClient(this);
424 OnStateChange();
Blink Reformat1c8e1a772016-10-01 00:25:32425 }
426
Blink Reformat1c4d759e2017-04-09 16:34:54427 void OnStateChange() override {
Blink Reformat1c8e1a772016-10-01 00:25:32428 while (true) {
429 const char* buffer;
430 size_t available;
Blink Reformat1c4d759e2017-04-09 16:34:54431 auto result = consumer_->BeginRead(&buffer, &available);
432 if (result == BytesConsumer::Result::kShouldWait)
Blink Reformat1c8e1a772016-10-01 00:25:32433 return;
Blink Reformat1c4d759e2017-04-09 16:34:54434 if (result == BytesConsumer::Result::kOk) {
Blink Reformat1c8e1a772016-10-01 00:25:32435 if (available > 0)
Blink Reformat1c4d759e2017-04-09 16:34:54436 builder_.Append(decoder_->Decode(buffer, available));
437 result = consumer_->EndRead(available);
Blink Reformat1c8e1a772016-10-01 00:25:32438 }
439 switch (result) {
Blink Reformat1c4d759e2017-04-09 16:34:54440 case BytesConsumer::Result::kOk:
Blink Reformat1c8e1a772016-10-01 00:25:32441 break;
Blink Reformat1c4d759e2017-04-09 16:34:54442 case BytesConsumer::Result::kShouldWait:
Blink Reformat1c8e1a772016-10-01 00:25:32443 NOTREACHED();
444 return;
Blink Reformat1c4d759e2017-04-09 16:34:54445 case BytesConsumer::Result::kDone:
446 builder_.Append(decoder_->Flush());
447 client_->DidFetchDataLoadedString(builder_.ToString());
Blink Reformat1c8e1a772016-10-01 00:25:32448 return;
Blink Reformat1c4d759e2017-04-09 16:34:54449 case BytesConsumer::Result::kError:
450 client_->DidFetchDataLoadFailed();
Blink Reformat1c8e1a772016-10-01 00:25:32451 return;
452 }
[email protected]b0ef9af2015-06-19 09:20:44453 }
Blink Reformat1c8e1a772016-10-01 00:25:32454 }
[email protected]b0ef9af2015-06-19 09:20:44455
Blink Reformat1c4d759e2017-04-09 16:34:54456 void Cancel() override { consumer_->Cancel(); }
[email protected]b0ef9af2015-06-19 09:20:44457
Blink Reformat1c8e1a772016-10-01 00:25:32458 DEFINE_INLINE_TRACE() {
Blink Reformat1c4d759e2017-04-09 16:34:54459 visitor->Trace(consumer_);
460 visitor->Trace(client_);
461 FetchDataLoader::Trace(visitor);
462 BytesConsumer::Client::Trace(visitor);
Blink Reformat1c8e1a772016-10-01 00:25:32463 }
[email protected]b0ef9af2015-06-19 09:20:44464
Blink Reformat1c8e1a772016-10-01 00:25:32465 private:
Blink Reformat1c4d759e2017-04-09 16:34:54466 Member<BytesConsumer> consumer_;
467 Member<FetchDataLoader::Client> client_;
[email protected]b0ef9af2015-06-19 09:20:44468
Blink Reformat1c4d759e2017-04-09 16:34:54469 std::unique_ptr<TextResourceDecoder> decoder_;
470 StringBuilder builder_;
[email protected]b0ef9af2015-06-19 09:20:44471};
472
shimazu1ac68cf2017-04-20 06:03:46473class FetchDataLoaderAsDataPipe final : public FetchDataLoader,
474 public BytesConsumer::Client {
475 USING_GARBAGE_COLLECTED_MIXIN(FetchDataLoaderAsDataPipe);
Blink Reformat1c8e1a772016-10-01 00:25:32476
477 public:
shimazu1ac68cf2017-04-20 06:03:46478 explicit FetchDataLoaderAsDataPipe(
479 mojo::ScopedDataPipeProducerHandle out_data_pipe)
480 : out_data_pipe_(std::move(out_data_pipe)),
481 data_pipe_watcher_(FROM_HERE,
482 mojo::SimpleWatcher::ArmingPolicy::MANUAL) {}
483 ~FetchDataLoaderAsDataPipe() override {}
Blink Reformat1c8e1a772016-10-01 00:25:32484
Blink Reformat1c4d759e2017-04-09 16:34:54485 void Start(BytesConsumer* consumer,
Blink Reformat1c8e1a772016-10-01 00:25:32486 FetchDataLoader::Client* client) override {
Blink Reformat1c4d759e2017-04-09 16:34:54487 DCHECK(!client_);
488 DCHECK(!consumer_);
shimazu1ac68cf2017-04-20 06:03:46489 data_pipe_watcher_.Watch(
490 out_data_pipe_.get(), MOJO_HANDLE_SIGNAL_WRITABLE,
491 ConvertToBaseCallback(WTF::Bind(&FetchDataLoaderAsDataPipe::OnWritable,
492 WrapWeakPersistent(this))));
493 data_pipe_watcher_.ArmOrNotify();
Blink Reformat1c4d759e2017-04-09 16:34:54494 client_ = client;
495 consumer_ = consumer;
496 consumer_->SetClient(this);
Blink Reformat1c8e1a772016-10-01 00:25:32497 }
498
shimazu1ac68cf2017-04-20 06:03:46499 void OnWritable(MojoResult) { OnStateChange(); }
500
501 // Implements BytesConsumer::Client.
Blink Reformat1c4d759e2017-04-09 16:34:54502 void OnStateChange() override {
shimazu1ac68cf2017-04-20 06:03:46503 bool should_wait = false;
504 while (!should_wait) {
Blink Reformat1c8e1a772016-10-01 00:25:32505 const char* buffer;
506 size_t available;
Blink Reformat1c4d759e2017-04-09 16:34:54507 auto result = consumer_->BeginRead(&buffer, &available);
shimazu1ac68cf2017-04-20 06:03:46508 if (result == BytesConsumer::Result::kShouldWait)
Blink Reformat1c8e1a772016-10-01 00:25:32509 return;
Blink Reformat1c4d759e2017-04-09 16:34:54510 if (result == BytesConsumer::Result::kOk) {
shimazu1ac68cf2017-04-20 06:03:46511 DCHECK_GT(available, 0UL);
512 uint32_t num_bytes = available;
513 MojoResult mojo_result =
514 mojo::WriteDataRaw(out_data_pipe_.get(), buffer, &num_bytes,
515 MOJO_WRITE_DATA_FLAG_NONE);
516 if (mojo_result == MOJO_RESULT_OK) {
517 result = consumer_->EndRead(num_bytes);
518 } else if (mojo_result == MOJO_RESULT_SHOULD_WAIT) {
519 result = consumer_->EndRead(0);
520 should_wait = true;
521 data_pipe_watcher_.ArmOrNotify();
522 } else {
523 result = consumer_->EndRead(0);
524 StopInternal();
525 client_->DidFetchDataLoadFailed();
526 return;
527 }
Blink Reformat1c8e1a772016-10-01 00:25:32528 }
529 switch (result) {
Blink Reformat1c4d759e2017-04-09 16:34:54530 case BytesConsumer::Result::kOk:
Blink Reformat1c8e1a772016-10-01 00:25:32531 break;
Blink Reformat1c4d759e2017-04-09 16:34:54532 case BytesConsumer::Result::kShouldWait:
Blink Reformat1c8e1a772016-10-01 00:25:32533 NOTREACHED();
534 return;
Blink Reformat1c4d759e2017-04-09 16:34:54535 case BytesConsumer::Result::kDone:
shimazu1ac68cf2017-04-20 06:03:46536 StopInternal();
537 client_->DidFetchDataLoadedDataPipe();
Blink Reformat1c8e1a772016-10-01 00:25:32538 return;
Blink Reformat1c4d759e2017-04-09 16:34:54539 case BytesConsumer::Result::kError:
shimazu1ac68cf2017-04-20 06:03:46540 StopInternal();
Blink Reformat1c4d759e2017-04-09 16:34:54541 client_->DidFetchDataLoadFailed();
Blink Reformat1c8e1a772016-10-01 00:25:32542 return;
543 }
[email protected]3e1cfc82015-07-21 13:54:38544 }
Blink Reformat1c8e1a772016-10-01 00:25:32545 }
[email protected]3e1cfc82015-07-21 13:54:38546
shimazu1ac68cf2017-04-20 06:03:46547 void Cancel() override { StopInternal(); }
[email protected]3e1cfc82015-07-21 13:54:38548
Blink Reformat1c8e1a772016-10-01 00:25:32549 DEFINE_INLINE_TRACE() {
Blink Reformat1c4d759e2017-04-09 16:34:54550 visitor->Trace(consumer_);
551 visitor->Trace(client_);
Blink Reformat1c4d759e2017-04-09 16:34:54552 FetchDataLoader::Trace(visitor);
553 BytesConsumer::Client::Trace(visitor);
Blink Reformat1c8e1a772016-10-01 00:25:32554 }
[email protected]3e1cfc82015-07-21 13:54:38555
shimazu1ac68cf2017-04-20 06:03:46556 private:
557 void StopInternal() {
558 consumer_->Cancel();
559 data_pipe_watcher_.Cancel();
560 out_data_pipe_.reset();
561 }
562
Blink Reformat1c4d759e2017-04-09 16:34:54563 Member<BytesConsumer> consumer_;
564 Member<FetchDataLoader::Client> client_;
shimazu1ac68cf2017-04-20 06:03:46565
566 mojo::ScopedDataPipeProducerHandle out_data_pipe_;
567 mojo::SimpleWatcher data_pipe_watcher_;
[email protected]3e1cfc82015-07-21 13:54:38568};
569
Blink Reformat1c8e1a772016-10-01 00:25:32570} // namespace
[email protected]f4b82b92015-06-25 12:39:33571
Blink Reformat1c4d759e2017-04-09 16:34:54572FetchDataLoader* FetchDataLoader::CreateLoaderAsBlobHandle(
573 const String& mime_type) {
574 return new FetchDataLoaderAsBlobHandle(mime_type);
[email protected]b0ef9af2015-06-19 09:20:44575}
576
Blink Reformat1c4d759e2017-04-09 16:34:54577FetchDataLoader* FetchDataLoader::CreateLoaderAsArrayBuffer() {
Blink Reformat1c8e1a772016-10-01 00:25:32578 return new FetchDataLoaderAsArrayBuffer();
[email protected]b0ef9af2015-06-19 09:20:44579}
580
eero.hakkinen6bd271f2017-05-22 11:36:04581FetchDataLoader* FetchDataLoader::CreateLoaderAsFailure() {
582 return new FetchDataLoaderAsFailure();
583}
584
585FetchDataLoader* FetchDataLoader::CreateLoaderAsFormData(
586 const String& multipartBoundary) {
587 return new FetchDataLoaderAsFormData(multipartBoundary);
588}
589
Blink Reformat1c4d759e2017-04-09 16:34:54590FetchDataLoader* FetchDataLoader::CreateLoaderAsString() {
Blink Reformat1c8e1a772016-10-01 00:25:32591 return new FetchDataLoaderAsString();
[email protected]b0ef9af2015-06-19 09:20:44592}
593
shimazu1ac68cf2017-04-20 06:03:46594FetchDataLoader* FetchDataLoader::CreateLoaderAsDataPipe(
595 mojo::ScopedDataPipeProducerHandle out_data_pipe) {
596 return new FetchDataLoaderAsDataPipe(std::move(out_data_pipe));
[email protected]f4b82b92015-06-25 12:39:33597}
598
Blink Reformat1c8e1a772016-10-01 00:25:32599} // namespace blink