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

Side by Side Diff: Source/modules/fetch/Body.cpp

Issue 1049983003: [Fetch] Body consume function should not set bodyUsed flag. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@stream-clone
Patch Set: Created 5 years, 8 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
« no previous file with comments | « Source/modules/fetch/Body.h ('k') | Source/modules/fetch/Response.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « Source/modules/fetch/Body.h ('k') | Source/modules/fetch/Response.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698