| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "config.h" | 5 #include "config.h" |
| 6 #include "modules/fetch/Body.h" | 6 #include "modules/fetch/Body.h" |
| 7 | 7 |
| 8 #include "bindings/core/v8/ExceptionState.h" | 8 #include "bindings/core/v8/ExceptionState.h" |
| 9 #include "bindings/core/v8/ScriptPromiseResolver.h" | 9 #include "bindings/core/v8/ScriptPromiseResolver.h" |
| 10 #include "bindings/core/v8/ScriptState.h" | 10 #include "bindings/core/v8/ScriptState.h" |
| 11 #include "bindings/core/v8/V8ArrayBuffer.h" | 11 #include "bindings/core/v8/V8ArrayBuffer.h" |
| 12 #include "bindings/core/v8/V8ThrowException.h" | 12 #include "bindings/core/v8/V8ThrowException.h" |
| 13 #include "core/dom/DOMArrayBuffer.h" | 13 #include "core/dom/DOMArrayBuffer.h" |
| 14 #include "core/dom/DOMTypedArray.h" | 14 #include "core/dom/DOMTypedArray.h" |
| 15 #include "core/fileapi/Blob.h" | 15 #include "core/fileapi/Blob.h" |
| 16 #include "core/fileapi/FileReaderLoader.h" | 16 #include "core/fileapi/FileReaderLoader.h" |
| 17 #include "core/fileapi/FileReaderLoaderClient.h" | 17 #include "core/fileapi/FileReaderLoaderClient.h" |
| 18 #include "core/frame/UseCounter.h" | 18 #include "core/frame/UseCounter.h" |
| 19 #include "core/streams/ReadableByteStream.h" | 19 #include "core/streams/ReadableByteStream.h" |
| 20 #include "core/streams/ReadableByteStreamReader.h" | 20 #include "core/streams/ReadableByteStreamReader.h" |
| 21 #include "core/streams/UnderlyingSource.h" | 21 #include "core/streams/UnderlyingSource.h" |
| 22 #include "modules/fetch/BodyStreamBuffer.h" | 22 #include "modules/fetch/BodyStreamBuffer.h" |
| 23 #include "modules/fetch/DataConsumerHandleUtil.h" |
| 24 #include "modules/fetch/FetchBlobDataConsumerHandle.h" |
| 23 | 25 |
| 24 namespace blink { | 26 namespace blink { |
| 25 | 27 |
| 26 class Body::BlobHandleReceiver final : public BodyStreamBuffer::BlobHandleCreato
rClient { | 28 class Body::BlobHandleReceiver final : public BodyStreamBuffer::BlobHandleCreato
rClient { |
| 27 public: | 29 public: |
| 28 explicit BlobHandleReceiver(Body* body) | 30 explicit BlobHandleReceiver(Body* body) |
| 29 : m_body(body) | 31 : m_body(body) |
| 30 { | 32 { |
| 31 } | 33 } |
| 32 void didCreateBlobHandle(PassRefPtr<BlobDataHandle> handle) override | 34 void didCreateBlobHandle(PassRefPtr<BlobDataHandle> handle) override |
| (...skipping 309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 342 } else if (isBodyConsumed()) { | 344 } else if (isBodyConsumed()) { |
| 343 m_streamSource->createDrainingStream()->readAllAndCreateBlobHandle(mimeT
ype(), new BlobHandleReceiver(this)); | 345 m_streamSource->createDrainingStream()->readAllAndCreateBlobHandle(mimeT
ype(), new BlobHandleReceiver(this)); |
| 344 } else if (buffer()) { | 346 } else if (buffer()) { |
| 345 buffer()->readAllAndCreateBlobHandle(mimeType(), new BlobHandleReceiver(
this)); | 347 buffer()->readAllAndCreateBlobHandle(mimeType(), new BlobHandleReceiver(
this)); |
| 346 } else { | 348 } else { |
| 347 readAsyncFromBlob(blobDataHandle()); | 349 readAsyncFromBlob(blobDataHandle()); |
| 348 } | 350 } |
| 349 return promise; | 351 return promise; |
| 350 } | 352 } |
| 351 | 353 |
| 354 void Body::readAsyncFromFetchDataConsumerHandle(FetchDataConsumerHandle* handle,
const String& mimeType) |
| 355 { |
| 356 ASSERT(!m_fetchDataLoader); |
| 357 |
| 358 switch (m_responseType) { |
| 359 case ResponseAsArrayBuffer: |
| 360 m_fetchDataLoader = FetchDataLoader::createLoaderAsArrayBuffer(); |
| 361 break; |
| 362 |
| 363 case ResponseAsJSON: |
| 364 case ResponseAsText: |
| 365 m_fetchDataLoader = FetchDataLoader::createLoaderAsString(); |
| 366 break; |
| 367 |
| 368 case ResponseAsBlob: |
| 369 m_fetchDataLoader = FetchDataLoader::createLoaderAsBlobHandle(mimeType); |
| 370 break; |
| 371 |
| 372 case ResponseAsFormData: |
| 373 // FIXME: Implement this. |
| 374 ASSERT_NOT_REACHED(); |
| 375 return; |
| 376 |
| 377 default: |
| 378 ASSERT_NOT_REACHED(); |
| 379 return; |
| 380 } |
| 381 |
| 382 m_fetchDataLoader->start(handle, this); |
| 383 } |
| 384 |
| 352 void Body::readAsyncFromBlob(PassRefPtr<BlobDataHandle> handle) | 385 void Body::readAsyncFromBlob(PassRefPtr<BlobDataHandle> handle) |
| 353 { | 386 { |
| 354 FileReaderLoader::ReadType readType = FileReaderLoader::ReadAsText; | 387 readAsyncFromFetchDataConsumerHandle(FetchBlobDataConsumerHandle::create(exe
cutionContext(), handle).get(), mimeType()); |
| 355 RefPtr<BlobDataHandle> blobHandle = handle; | |
| 356 if (!blobHandle) | |
| 357 blobHandle = BlobDataHandle::create(BlobData::create(), 0); | |
| 358 switch (m_responseType) { | |
| 359 case ResponseAsArrayBuffer: | |
| 360 readType = FileReaderLoader::ReadAsArrayBuffer; | |
| 361 break; | |
| 362 case ResponseAsBlob: | |
| 363 if (blobHandle->size() != kuint64max) { | |
| 364 // If the size of |blobHandle| is set correctly, creates Blob from | |
| 365 // it. | |
| 366 if (blobHandle->type() != mimeType()) { | |
| 367 // A new BlobDataHandle is created to override the Blob's type. | |
| 368 m_resolver->resolve(Blob::create(BlobDataHandle::create(blobHand
le->uuid(), mimeType(), blobHandle->size()))); | |
| 369 } else { | |
| 370 m_resolver->resolve(Blob::create(blobHandle)); | |
| 371 } | |
| 372 m_stream->close(); | |
| 373 m_resolver.clear(); | |
| 374 return; | |
| 375 } | |
| 376 // If the size is not set, read as ArrayBuffer and create a new blob to | |
| 377 // get the size. | |
| 378 // FIXME: This workaround is not good for performance. | |
| 379 // When we will stop using Blob as a base system of Body to support | |
| 380 // stream, this problem should be solved. | |
| 381 readType = FileReaderLoader::ReadAsArrayBuffer; | |
| 382 break; | |
| 383 case ResponseAsFormData: | |
| 384 // FIXME: Implement this. | |
| 385 ASSERT_NOT_REACHED(); | |
| 386 break; | |
| 387 case ResponseAsJSON: | |
| 388 case ResponseAsText: | |
| 389 break; | |
| 390 default: | |
| 391 ASSERT_NOT_REACHED(); | |
| 392 } | |
| 393 | |
| 394 m_loader = FileReaderLoader::create(readType, this); | |
| 395 m_loader->start(m_resolver->scriptState()->executionContext(), blobHandle); | |
| 396 | |
| 397 return; | |
| 398 } | 388 } |
| 399 | 389 |
| 400 ScriptPromise Body::arrayBuffer(ScriptState* scriptState) | 390 ScriptPromise Body::arrayBuffer(ScriptState* scriptState) |
| 401 { | 391 { |
| 402 return readAsync(scriptState, ResponseAsArrayBuffer); | 392 return readAsync(scriptState, ResponseAsArrayBuffer); |
| 403 } | 393 } |
| 404 | 394 |
| 405 ScriptPromise Body::blob(ScriptState* scriptState) | 395 ScriptPromise Body::blob(ScriptState* scriptState) |
| 406 { | 396 { |
| 407 return readAsync(scriptState, ResponseAsBlob); | 397 return readAsync(scriptState, ResponseAsBlob); |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 469 m_streamSource->startStream(m_stream); | 459 m_streamSource->startStream(m_stream); |
| 470 } | 460 } |
| 471 | 461 |
| 472 BodyStreamBuffer* Body::createDrainingStream() | 462 BodyStreamBuffer* Body::createDrainingStream() |
| 473 { | 463 { |
| 474 return m_streamSource->createDrainingStream(); | 464 return m_streamSource->createDrainingStream(); |
| 475 } | 465 } |
| 476 | 466 |
| 477 void Body::stop() | 467 void Body::stop() |
| 478 { | 468 { |
| 479 // Canceling the load will call didFail which will remove the resolver. | 469 if (m_fetchDataLoader) { |
| 480 if (m_loader) | 470 m_fetchDataLoader->cancel(); |
| 481 m_loader->cancel(); | 471 m_fetchDataLoader.clear(); |
| 472 } |
| 482 } | 473 } |
| 483 | 474 |
| 484 bool Body::hasPendingActivity() const | 475 bool Body::hasPendingActivity() const |
| 485 { | 476 { |
| 486 if (executionContext()->activeDOMObjectsAreStopped()) | 477 if (executionContext()->activeDOMObjectsAreStopped()) |
| 487 return false; | 478 return false; |
| 488 if (m_resolver) | 479 if (m_resolver) |
| 489 return true; | 480 return true; |
| 490 if (m_stream->isLocked()) | 481 if (m_stream->isLocked()) |
| 491 return true; | 482 return true; |
| 492 return false; | 483 return false; |
| 493 } | 484 } |
| 494 | 485 |
| 495 Body::ReadableStreamSource* Body::createBodySource(PassRefPtr<BlobDataHandle> ha
ndle) | 486 Body::ReadableStreamSource* Body::createBodySource(PassRefPtr<BlobDataHandle> ha
ndle) |
| 496 { | 487 { |
| 497 return new ReadableStreamSource(executionContext(), handle); | 488 return new ReadableStreamSource(executionContext(), handle); |
| 498 } | 489 } |
| 499 | 490 |
| 500 Body::ReadableStreamSource* Body::createBodySource(BodyStreamBuffer* buffer) | 491 Body::ReadableStreamSource* Body::createBodySource(BodyStreamBuffer* buffer) |
| 501 { | 492 { |
| 502 return new ReadableStreamSource(executionContext(), buffer); | 493 return new ReadableStreamSource(executionContext(), buffer); |
| 503 } | 494 } |
| 504 | 495 |
| 505 DEFINE_TRACE(Body) | 496 DEFINE_TRACE(Body) |
| 506 { | 497 { |
| 498 visitor->trace(m_fetchDataLoader); |
| 507 visitor->trace(m_resolver); | 499 visitor->trace(m_resolver); |
| 508 visitor->trace(m_stream); | 500 visitor->trace(m_stream); |
| 509 visitor->trace(m_streamSource); | 501 visitor->trace(m_streamSource); |
| 510 ActiveDOMObject::trace(visitor); | 502 ActiveDOMObject::trace(visitor); |
| 503 FetchDataLoader::Client::trace(visitor); |
| 511 } | 504 } |
| 512 | 505 |
| 513 Body::Body(ExecutionContext* context) | 506 Body::Body(ExecutionContext* context) |
| 514 : ActiveDOMObject(context) | 507 : ActiveDOMObject(context) |
| 515 , m_bodyUsed(false) | 508 , m_bodyUsed(false) |
| 516 , m_responseType(ResponseType::ResponseUnknown) | 509 , m_responseType(ResponseType::ResponseUnknown) |
| 517 , m_streamSource(new ReadableStreamSource(context)) | 510 , m_streamSource(new ReadableStreamSource(context)) |
| 518 , m_stream(new ReadableByteStream(m_streamSource, new ReadableByteStream::St
rictStrategy)) | 511 , m_stream(new ReadableByteStream(m_streamSource, new ReadableByteStream::St
rictStrategy)) |
| 519 { | 512 { |
| 520 m_streamSource->startStream(m_stream); | 513 m_streamSource->startStream(m_stream); |
| 521 } | 514 } |
| 522 | 515 |
| 523 void Body::resolveJSON(const String& string) | 516 void Body::resolveJSON(const String& string) |
| 524 { | 517 { |
| 525 ASSERT(m_responseType == ResponseAsJSON); | 518 ASSERT(m_responseType == ResponseAsJSON); |
| 526 ScriptState::Scope scope(m_resolver->scriptState()); | 519 ScriptState::Scope scope(m_resolver->scriptState()); |
| 527 v8::Isolate* isolate = m_resolver->scriptState()->isolate(); | 520 v8::Isolate* isolate = m_resolver->scriptState()->isolate(); |
| 528 v8::Local<v8::String> inputString = v8String(isolate, string); | 521 v8::Local<v8::String> inputString = v8String(isolate, string); |
| 529 v8::TryCatch trycatch; | 522 v8::TryCatch trycatch; |
| 530 v8::Local<v8::Value> parsed; | 523 v8::Local<v8::Value> parsed; |
| 531 if (v8Call(v8::JSON::Parse(isolate, inputString), parsed, trycatch)) | 524 if (v8Call(v8::JSON::Parse(isolate, inputString), parsed, trycatch)) |
| 532 m_resolver->resolve(parsed); | 525 m_resolver->resolve(parsed); |
| 533 else | 526 else |
| 534 m_resolver->reject(trycatch.Exception()); | 527 m_resolver->reject(trycatch.Exception()); |
| 535 } | 528 } |
| 536 | 529 |
| 537 // FileReaderLoaderClient functions. | 530 // FetchDataLoader::Client functions. |
| 538 void Body::didStartLoading() { } | 531 void Body::didFetchDataLoadFailed() |
| 539 void Body::didReceiveData() { } | |
| 540 void Body::didFinishLoading() | |
| 541 { | 532 { |
| 542 if (!executionContext() || executionContext()->activeDOMObjectsAreStopped()) | 533 ASSERT(m_fetchDataLoader); |
| 543 return; | 534 m_fetchDataLoader.clear(); |
| 544 | 535 |
| 545 switch (m_responseType) { | |
| 546 case ResponseAsArrayBuffer: | |
| 547 m_resolver->resolve(m_loader->arrayBufferResult()); | |
| 548 break; | |
| 549 case ResponseAsBlob: { | |
| 550 ASSERT(blobDataHandle()->size() == kuint64max); | |
| 551 OwnPtr<BlobData> blobData = BlobData::create(); | |
| 552 RefPtr<DOMArrayBuffer> buffer = m_loader->arrayBufferResult(); | |
| 553 blobData->appendBytes(buffer->data(), buffer->byteLength()); | |
| 554 blobData->setContentType(mimeType()); | |
| 555 const size_t length = blobData->length(); | |
| 556 m_resolver->resolve(Blob::create(BlobDataHandle::create(blobData.release
(), length))); | |
| 557 break; | |
| 558 } | |
| 559 case ResponseAsFormData: | |
| 560 ASSERT_NOT_REACHED(); | |
| 561 break; | |
| 562 case ResponseAsJSON: | |
| 563 resolveJSON(m_loader->stringResult()); | |
| 564 break; | |
| 565 case ResponseAsText: | |
| 566 m_resolver->resolve(m_loader->stringResult()); | |
| 567 break; | |
| 568 default: | |
| 569 ASSERT_NOT_REACHED(); | |
| 570 } | |
| 571 m_streamSource->close(); | |
| 572 m_resolver.clear(); | |
| 573 } | |
| 574 | |
| 575 void Body::didFail(FileError::ErrorCode code) | |
| 576 { | |
| 577 if (!executionContext() || executionContext()->activeDOMObjectsAreStopped()) | 536 if (!executionContext() || executionContext()->activeDOMObjectsAreStopped()) |
| 578 return; | 537 return; |
| 579 | 538 |
| 580 m_streamSource->error(); | 539 m_streamSource->error(); |
| 581 if (m_resolver) { | 540 if (m_resolver) { |
| 582 // FIXME: We should reject the promise. | 541 if (!m_resolver->executionContext() || m_resolver->executionContext()->a
ctiveDOMObjectsAreStopped()) { |
| 583 m_resolver->resolve(""); | 542 m_resolver.clear(); |
| 543 return; |
| 544 } |
| 545 ScriptState* state = m_resolver->scriptState(); |
| 546 ScriptState::Scope scope(state); |
| 547 m_resolver->reject(V8ThrowException::createTypeError(state->isolate(), "
Failed to fetch")); |
| 584 m_resolver.clear(); | 548 m_resolver.clear(); |
| 585 } | 549 } |
| 586 } | 550 } |
| 587 | 551 |
| 552 void Body::didFetchDataLoadedBlobHandle(PassRefPtr<BlobDataHandle> blobDataHandl
e) |
| 553 { |
| 554 ASSERT(m_fetchDataLoader); |
| 555 m_fetchDataLoader.clear(); |
| 556 |
| 557 if (!executionContext() || executionContext()->activeDOMObjectsAreStopped()) |
| 558 return; |
| 559 |
| 560 ASSERT(m_responseType == ResponseAsBlob); |
| 561 m_resolver->resolve(Blob::create(blobDataHandle)); |
| 562 m_streamSource->close(); |
| 563 m_resolver.clear(); |
| 564 } |
| 565 |
| 566 void Body::didFetchDataLoadedArrayBuffer(PassRefPtr<DOMArrayBuffer> arrayBuffer) |
| 567 { |
| 568 ASSERT(m_fetchDataLoader); |
| 569 m_fetchDataLoader.clear(); |
| 570 |
| 571 if (!executionContext() || executionContext()->activeDOMObjectsAreStopped()) |
| 572 return; |
| 573 |
| 574 ASSERT(m_responseType == ResponseAsArrayBuffer); |
| 575 m_resolver->resolve(arrayBuffer); |
| 576 m_streamSource->close(); |
| 577 m_resolver.clear(); |
| 578 } |
| 579 |
| 580 void Body::didFetchDataLoadedString(const String& str) |
| 581 { |
| 582 ASSERT(m_fetchDataLoader); |
| 583 m_fetchDataLoader.clear(); |
| 584 |
| 585 if (!executionContext() || executionContext()->activeDOMObjectsAreStopped()) |
| 586 return; |
| 587 |
| 588 switch (m_responseType) { |
| 589 case ResponseAsJSON: |
| 590 resolveJSON(str); |
| 591 break; |
| 592 case ResponseAsText: |
| 593 m_resolver->resolve(str); |
| 594 break; |
| 595 default: |
| 596 ASSERT_NOT_REACHED(); |
| 597 } |
| 598 |
| 599 m_streamSource->close(); |
| 600 m_resolver.clear(); |
| 601 } |
| 602 |
| 588 void Body::didBlobHandleReceiveError(DOMException* exception) | 603 void Body::didBlobHandleReceiveError(DOMException* exception) |
| 589 { | 604 { |
| 590 if (!m_resolver) | 605 if (!m_resolver) |
| 591 return; | 606 return; |
| 592 m_streamSource->error(); | 607 m_streamSource->error(); |
| 593 m_resolver->reject(exception); | 608 m_resolver->reject(exception); |
| 594 m_resolver.clear(); | 609 m_resolver.clear(); |
| 595 } | 610 } |
| 596 | 611 |
| 597 } // namespace blink | 612 } // namespace blink |
| OLD | NEW |