| 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" |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 103 DEFINE_INLINE_VIRTUAL_TRACE() | 103 DEFINE_INLINE_VIRTUAL_TRACE() |
| 104 { | 104 { |
| 105 visitor->trace(m_body); | 105 visitor->trace(m_body); |
| 106 visitor->trace(m_bodyStreamBuffer); | 106 visitor->trace(m_bodyStreamBuffer); |
| 107 visitor->trace(m_drainingStreamBuffer); | 107 visitor->trace(m_drainingStreamBuffer); |
| 108 visitor->trace(m_stream); | 108 visitor->trace(m_stream); |
| 109 BodyStreamBuffer::Observer::trace(visitor); | 109 BodyStreamBuffer::Observer::trace(visitor); |
| 110 UnderlyingSource::trace(visitor); | 110 UnderlyingSource::trace(visitor); |
| 111 } | 111 } |
| 112 | 112 |
| 113 void close() |
| 114 { |
| 115 if (m_state == Closed) { |
| 116 // It is possible to call |close| from the source side (such |
| 117 // as blob loading finish) and from the consumer side (such as |
| 118 // calling |cancel|). Thus we should ignore it here. |
| 119 return; |
| 120 } |
| 121 m_state = Closed; |
| 122 if (m_drainingStreamBuffer) |
| 123 m_drainingStreamBuffer->close(); |
| 124 m_stream->close(); |
| 125 } |
| 126 void error() |
| 127 { |
| 128 m_state = Errored; |
| 129 if (m_drainingStreamBuffer) |
| 130 m_drainingStreamBuffer->error(exception()); |
| 131 m_stream->error(exception()); |
| 132 } |
| 133 |
| 113 private: | 134 private: |
| 114 class Canceller : public BodyStreamBuffer::Canceller { | 135 class Canceller : public BodyStreamBuffer::Canceller { |
| 115 public: | 136 public: |
| 116 Canceller(ReadableStreamSource* source) : m_source(source) { } | 137 Canceller(ReadableStreamSource* source) : m_source(source) { } |
| 117 void cancel() override | 138 void cancel() override |
| 118 { | 139 { |
| 119 m_source->cancel(); | 140 m_source->cancel(); |
| 120 } | 141 } |
| 121 | 142 |
| 122 DEFINE_INLINE_VIRTUAL_TRACE() | 143 DEFINE_INLINE_VIRTUAL_TRACE() |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 200 | 221 |
| 201 void write(PassRefPtr<DOMArrayBuffer> buf) | 222 void write(PassRefPtr<DOMArrayBuffer> buf) |
| 202 { | 223 { |
| 203 if (m_drainingStreamBuffer) { | 224 if (m_drainingStreamBuffer) { |
| 204 m_drainingStreamBuffer->write(buf); | 225 m_drainingStreamBuffer->write(buf); |
| 205 } else { | 226 } else { |
| 206 auto size = buf->byteLength(); | 227 auto size = buf->byteLength(); |
| 207 m_stream->enqueue(DOMUint8Array::create(buf, 0, size)); | 228 m_stream->enqueue(DOMUint8Array::create(buf, 0, size)); |
| 208 } | 229 } |
| 209 } | 230 } |
| 210 void close() | |
| 211 { | |
| 212 m_state = Closed; | |
| 213 if (m_drainingStreamBuffer) | |
| 214 m_drainingStreamBuffer->close(); | |
| 215 m_stream->close(); | |
| 216 } | |
| 217 void error() | |
| 218 { | |
| 219 m_state = Errored; | |
| 220 if (m_drainingStreamBuffer) | |
| 221 m_drainingStreamBuffer->error(exception()); | |
| 222 m_stream->error(exception()); | |
| 223 } | |
| 224 void cancel() | 231 void cancel() |
| 225 { | 232 { |
| 226 if (m_bodyStreamBuffer) { | 233 if (m_bodyStreamBuffer) { |
| 227 m_bodyStreamBuffer->cancel(); | 234 m_bodyStreamBuffer->cancel(); |
| 228 // We should not close the stream here, because it is canceller's | 235 // We should not close the stream here, because it is canceller's |
| 229 // responsibility. | 236 // responsibility. |
| 230 } else { | 237 } else { |
| 231 if (m_loader) | 238 if (m_loader) |
| 232 m_loader->cancel(); | 239 m_loader->cancel(); |
| 233 close(); | 240 close(); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 266 // When the main thread sends a V8::TerminateExecution() signal to a worker | 273 // When the main thread sends a V8::TerminateExecution() signal to a worker |
| 267 // thread, any V8 API on the worker thread starts returning an empty | 274 // thread, any V8 API on the worker thread starts returning an empty |
| 268 // handle. This can happen in Body::readAsync. To avoid the situation, we | 275 // handle. This can happen in Body::readAsync. To avoid the situation, we |
| 269 // first check the ExecutionContext and return immediately if it's already | 276 // first check the ExecutionContext and return immediately if it's already |
| 270 // gone (which means that the V8::TerminateExecution() signal has been sent | 277 // gone (which means that the V8::TerminateExecution() signal has been sent |
| 271 // to this worker thread). | 278 // to this worker thread). |
| 272 ExecutionContext* executionContext = scriptState->executionContext(); | 279 ExecutionContext* executionContext = scriptState->executionContext(); |
| 273 if (!executionContext) | 280 if (!executionContext) |
| 274 return ScriptPromise(); | 281 return ScriptPromise(); |
| 275 | 282 |
| 276 lockBody(PassBody); | 283 lockBody(); |
| 277 m_responseType = type; | 284 m_responseType = type; |
| 278 | 285 |
| 279 ASSERT(!m_resolver); | 286 ASSERT(!m_resolver); |
| 280 m_resolver = ScriptPromiseResolver::create(scriptState); | 287 m_resolver = ScriptPromiseResolver::create(scriptState); |
| 281 ScriptPromise promise = m_resolver->promise(); | 288 ScriptPromise promise = m_resolver->promise(); |
| 282 | 289 |
| 283 if (streamAccessed()) { | 290 if (m_stream->stateInternal() == ReadableStream::Closed) { |
| 291 // We resolve the resolver manually in order not to use member |
| 292 // variables. |
| 293 switch (m_responseType) { |
| 294 case ResponseAsArrayBuffer: |
| 295 m_resolver->resolve(DOMArrayBuffer::create(nullptr, 0)); |
| 296 break; |
| 297 case ResponseAsBlob: { |
| 298 OwnPtr<BlobData> blobData = BlobData::create(); |
| 299 blobData->setContentType(mimeType()); |
| 300 m_resolver->resolve(Blob::create(BlobDataHandle::create(blobData.rel
ease(), 0))); |
| 301 break; |
| 302 } |
| 303 case ResponseAsText: |
| 304 m_resolver->resolve(String()); |
| 305 break; |
| 306 case ResponseAsFormData: |
| 307 // TODO(yhirano): Implement this. |
| 308 ASSERT_NOT_REACHED(); |
| 309 break; |
| 310 case ResponseAsJSON: { |
| 311 ScriptState::Scope scope(m_resolver->scriptState()); |
| 312 m_resolver->reject(V8ThrowException::createSyntaxError(m_resolver->s
criptState()->isolate(), "Unexpected end of input")); |
| 313 break; |
| 314 } |
| 315 case ResponseUnknown: |
| 316 ASSERT_NOT_REACHED(); |
| 317 break; |
| 318 } |
| 319 m_resolver.clear(); |
| 320 } else if (m_stream->stateInternal() == ReadableStream::Errored) { |
| 321 m_resolver->reject(m_stream->storedException()); |
| 322 m_resolver.clear(); |
| 323 } else if (isBodyConsumed()) { |
| 284 m_streamSource->createDrainingStream()->readAllAndCreateBlobHandle(mimeT
ype(), new BlobHandleReceiver(this)); | 324 m_streamSource->createDrainingStream()->readAllAndCreateBlobHandle(mimeT
ype(), new BlobHandleReceiver(this)); |
| 285 } else if (buffer()) { | 325 } else if (buffer()) { |
| 286 buffer()->readAllAndCreateBlobHandle(mimeType(), new BlobHandleReceiver(
this)); | 326 buffer()->readAllAndCreateBlobHandle(mimeType(), new BlobHandleReceiver(
this)); |
| 287 } else { | 327 } else { |
| 288 readAsyncFromBlob(blobDataHandle()); | 328 readAsyncFromBlob(blobDataHandle()); |
| 289 } | 329 } |
| 290 return promise; | 330 return promise; |
| 291 } | 331 } |
| 292 | 332 |
| 293 void Body::readAsyncFromBlob(PassRefPtr<BlobDataHandle> handle) | 333 void Body::readAsyncFromBlob(PassRefPtr<BlobDataHandle> handle) |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 377 { | 417 { |
| 378 ASSERT(!bodyUsed()); | 418 ASSERT(!bodyUsed()); |
| 379 if (option == PassBody) | 419 if (option == PassBody) |
| 380 m_bodyUsed = true; | 420 m_bodyUsed = true; |
| 381 ASSERT(!m_stream->isLocked()); | 421 ASSERT(!m_stream->isLocked()); |
| 382 TrackExceptionState exceptionState; | 422 TrackExceptionState exceptionState; |
| 383 m_stream->getBytesReader(executionContext(), exceptionState); | 423 m_stream->getBytesReader(executionContext(), exceptionState); |
| 384 ASSERT(!exceptionState.hadException()); | 424 ASSERT(!exceptionState.hadException()); |
| 385 } | 425 } |
| 386 | 426 |
| 387 bool Body::streamAccessed() const | 427 bool Body::isBodyConsumed() const |
| 388 { | 428 { |
| 389 return m_streamSource->state() != m_streamSource->Initial; | 429 if (m_streamSource->state() != m_streamSource->Initial) { |
| 430 // Some data is pulled from the source. |
| 431 return true; |
| 432 } |
| 433 if (m_stream->stateInternal() == ReadableStream::Closed) { |
| 434 // Return true if the blob handle is originally not empty. |
| 435 RefPtr<BlobDataHandle> handle = blobDataHandle(); |
| 436 return handle && handle->size(); |
| 437 } |
| 438 if (m_stream->stateInternal() == ReadableStream::Errored) { |
| 439 // The stream is errored. That means an effort to read data was made. |
| 440 return true; |
| 441 } |
| 442 return false; |
| 390 } | 443 } |
| 391 | 444 |
| 392 void Body::refreshBody() | 445 void Body::refreshBody() |
| 393 { | 446 { |
| 394 m_streamSource = new ReadableStreamSource(this); | 447 m_streamSource = new ReadableStreamSource(this); |
| 395 m_stream = new ReadableByteStream(m_streamSource, new ReadableByteStream::St
rictStrategy); | 448 m_stream = new ReadableByteStream(m_streamSource, new ReadableByteStream::St
rictStrategy); |
| 396 m_streamSource->startStream(m_stream); | 449 m_streamSource->startStream(m_stream); |
| 397 } | 450 } |
| 398 | 451 |
| 399 BodyStreamBuffer* Body::createDrainingStream() | 452 BodyStreamBuffer* Body::createDrainingStream() |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 478 break; | 531 break; |
| 479 case ResponseAsJSON: | 532 case ResponseAsJSON: |
| 480 resolveJSON(m_loader->stringResult()); | 533 resolveJSON(m_loader->stringResult()); |
| 481 break; | 534 break; |
| 482 case ResponseAsText: | 535 case ResponseAsText: |
| 483 m_resolver->resolve(m_loader->stringResult()); | 536 m_resolver->resolve(m_loader->stringResult()); |
| 484 break; | 537 break; |
| 485 default: | 538 default: |
| 486 ASSERT_NOT_REACHED(); | 539 ASSERT_NOT_REACHED(); |
| 487 } | 540 } |
| 488 m_stream->close(); | 541 m_streamSource->close(); |
| 489 m_resolver.clear(); | 542 m_resolver.clear(); |
| 490 } | 543 } |
| 491 | 544 |
| 492 void Body::didFail(FileError::ErrorCode code) | 545 void Body::didFail(FileError::ErrorCode code) |
| 493 { | 546 { |
| 494 if (!executionContext() || executionContext()->activeDOMObjectsAreStopped()) | 547 if (!executionContext() || executionContext()->activeDOMObjectsAreStopped()) |
| 495 return; | 548 return; |
| 496 | 549 |
| 497 m_stream->error(DOMException::create(NetworkError, "network error")); | 550 m_streamSource->error(); |
| 498 if (m_resolver) { | 551 if (m_resolver) { |
| 499 // FIXME: We should reject the promise. | 552 // FIXME: We should reject the promise. |
| 500 m_resolver->resolve(""); | 553 m_resolver->resolve(""); |
| 501 m_resolver.clear(); | 554 m_resolver.clear(); |
| 502 } | 555 } |
| 503 } | 556 } |
| 504 | 557 |
| 505 void Body::didBlobHandleReceiveError(PassRefPtrWillBeRawPtr<DOMException> except
ion) | 558 void Body::didBlobHandleReceiveError(PassRefPtrWillBeRawPtr<DOMException> except
ion) |
| 506 { | 559 { |
| 507 if (!m_resolver) | 560 if (!m_resolver) |
| 508 return; | 561 return; |
| 509 m_stream->error(DOMException::create(NetworkError, "network error")); | 562 m_streamSource->error(); |
| 510 m_resolver->reject(exception); | 563 m_resolver->reject(exception); |
| 511 m_resolver.clear(); | 564 m_resolver.clear(); |
| 512 } | 565 } |
| 513 | 566 |
| 514 } // namespace blink | 567 } // namespace blink |
| OLD | NEW |