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 |