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

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

Issue 1192913007: Change BodyStreamBuffer to be FetchDataConsumerHandle-based and enable backpressure in Fetch API (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Reflect comments. Created 5 years, 6 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/BodyStreamBuffer.h » ('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"
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/dom/ExceptionCode.h"
15 #include "core/fileapi/Blob.h" 16 #include "core/fileapi/Blob.h"
16 #include "core/fileapi/FileReaderLoader.h"
17 #include "core/fileapi/FileReaderLoaderClient.h"
18 #include "core/frame/UseCounter.h" 17 #include "core/frame/UseCounter.h"
19 #include "core/streams/ReadableByteStream.h" 18 #include "core/streams/ReadableByteStream.h"
20 #include "core/streams/ReadableByteStreamReader.h" 19 #include "core/streams/ReadableByteStreamReader.h"
21 #include "core/streams/UnderlyingSource.h" 20 #include "core/streams/UnderlyingSource.h"
22 #include "modules/fetch/BodyStreamBuffer.h" 21 #include "modules/fetch/BodyStreamBuffer.h"
22 #include "modules/fetch/DataConsumerHandleUtil.h"
23 #include "modules/fetch/FetchBlobDataConsumerHandle.h"
23 24
24 namespace blink { 25 namespace blink {
25 26
26 class Body::BlobHandleReceiver final : public BodyStreamBuffer::BlobHandleCreato rClient {
27 public:
28 explicit BlobHandleReceiver(Body* body)
29 : m_body(body)
30 {
31 }
32 void didCreateBlobHandle(PassRefPtr<BlobDataHandle> handle) override
33 {
34 ASSERT(m_body);
35 m_body->readAsyncFromBlob(handle);
36 m_body = nullptr;
37 }
38 void didFail(DOMException* exception) override
39 {
40 ASSERT(m_body);
41 m_body->didBlobHandleReceiveError(exception);
42 m_body = nullptr;
43 }
44 DEFINE_INLINE_VIRTUAL_TRACE()
45 {
46 BodyStreamBuffer::BlobHandleCreatorClient::trace(visitor);
47 visitor->trace(m_body);
48 }
49 private:
50 Member<Body> m_body;
51 };
52
53 // This class is an ActiveDOMObject subclass only for holding the 27 // This class is an ActiveDOMObject subclass only for holding the
54 // ExecutionContext used in |pullSource|. 28 // ExecutionContext used in |pullSource|.
55 class Body::ReadableStreamSource : public BodyStreamBuffer::Observer, public Und erlyingSource, public FileReaderLoaderClient, public ActiveDOMObject { 29 class Body::ReadableStreamSource : public GarbageCollectedFinalized<Body::Readab leStreamSource>, public UnderlyingSource, public WebDataConsumerHandle::Client, public ActiveDOMObject {
56 USING_GARBAGE_COLLECTED_MIXIN(ReadableStreamSource); 30 USING_GARBAGE_COLLECTED_MIXIN(ReadableStreamSource);
57 public: 31 public:
58 enum State { 32 enum State {
59 Initial, 33 Initial,
60 Streaming, 34 Streaming,
61 Closed, 35 Closed,
62 Errored, 36 Errored,
63 }; 37 };
64 ReadableStreamSource(ExecutionContext* executionContext, PassRefPtr<BlobData Handle> handle)
65 : ActiveDOMObject(executionContext)
66 , m_blobDataHandle(handle ? handle : BlobDataHandle::create(BlobData::cr eate(), 0))
67 , m_state(Initial)
68 {
69 suspendIfNeeded();
70 }
71 38
72 ReadableStreamSource(ExecutionContext* executionContext, BodyStreamBuffer* b uffer) 39 ReadableStreamSource(ExecutionContext* executionContext, BodyStreamBuffer* b uffer)
73 : ActiveDOMObject(executionContext) 40 : ActiveDOMObject(executionContext)
74 , m_bodyStreamBuffer(buffer) 41 , m_bodyStreamBuffer(buffer ? buffer : BodyStreamBuffer::createEmpty())
75 , m_state(Initial) 42 , m_state(Initial)
43 , m_streamNeedsMore(false)
44 #if ENABLE(ASSERT)
45 , m_drained(false)
46 #endif
76 { 47 {
77 suspendIfNeeded(); 48 suspendIfNeeded();
78 } 49 }
79 50
80 explicit ReadableStreamSource(ExecutionContext* executionContext) 51 explicit ReadableStreamSource(ExecutionContext* executionContext)
81 : ActiveDOMObject(executionContext) 52 : ActiveDOMObject(executionContext)
82 , m_blobDataHandle(BlobDataHandle::create(BlobData::create(), 0)) 53 , m_bodyStreamBuffer(BodyStreamBuffer::createEmpty())
83 , m_state(Initial) 54 , m_state(Initial)
55 , m_streamNeedsMore(false)
84 { 56 {
85 suspendIfNeeded(); 57 suspendIfNeeded();
86 } 58 }
87 59
88 ~ReadableStreamSource() override { } 60 ~ReadableStreamSource() override { }
89 61
90 State state() const { return m_state; } 62 State state() const { return m_state; }
91 63
92 void startStream(ReadableByteStream* stream) 64 void startStream(ReadableByteStream* stream)
93 { 65 {
94 m_stream = stream; 66 m_stream = stream;
95 stream->didSourceStart(); 67 stream->didSourceStart();
96 } 68 }
97 // Creates a new BodyStreamBuffer to drain the data. 69 // Creates a new BodyStreamBuffer to drain the data.
98 BodyStreamBuffer* createDrainingStream() 70 BodyStreamBuffer* createDrainingStream()
99 { 71 {
100 ASSERT(m_state != Initial); 72 ASSERT(m_state != Initial);
101 73
102 auto drainingStreamBuffer = new BodyStreamBuffer(new Canceller(this));
103 if (m_stream->stateInternal() == ReadableByteStream::Closed) { 74 if (m_stream->stateInternal() == ReadableByteStream::Closed) {
104 drainingStreamBuffer->close(); 75 return BodyStreamBuffer::createEmpty();
105 return drainingStreamBuffer;
106 } 76 }
107 if (m_stream->stateInternal() == ReadableByteStream::Errored) { 77 if (m_stream->stateInternal() == ReadableByteStream::Errored) {
108 drainingStreamBuffer->error(exception()); 78 return BodyStreamBuffer::create(createFetchDataConsumerHandleFromWeb Handle(createUnexpectedErrorDataConsumerHandle()));
109 return drainingStreamBuffer;
110 } 79 }
111 80
112 ASSERT(!m_drainingStreamBuffer); 81 ASSERT(!m_drained);
113 // Take back the data in |m_stream|. 82 #if ENABLE(ASSERT)
114 Deque<std::pair<RefPtr<DOMArrayBufferView>, size_t>> tmp_queue; 83 m_drained = true;
115 ASSERT(m_stream->stateInternal() == ReadableStream::Readable); 84 #endif
116 m_stream->readInternal(tmp_queue); 85 m_reader.clear();
117 while (!tmp_queue.isEmpty()) { 86 return m_bodyStreamBuffer;
118 std::pair<RefPtr<DOMArrayBufferView>, size_t> data = tmp_queue.takeF irst(); 87 }
119 drainingStreamBuffer->write(data.first->buffer());
120 }
121 if (m_state == Closed)
122 drainingStreamBuffer->close();
123 88
124 m_drainingStreamBuffer = drainingStreamBuffer;
125 return m_drainingStreamBuffer;
126 }
127 DEFINE_INLINE_VIRTUAL_TRACE() 89 DEFINE_INLINE_VIRTUAL_TRACE()
128 { 90 {
129 visitor->trace(m_bodyStreamBuffer); 91 visitor->trace(m_bodyStreamBuffer);
130 visitor->trace(m_drainingStreamBuffer);
131 visitor->trace(m_stream); 92 visitor->trace(m_stream);
132 BodyStreamBuffer::Observer::trace(visitor);
133 UnderlyingSource::trace(visitor); 93 UnderlyingSource::trace(visitor);
134 ActiveDOMObject::trace(visitor); 94 ActiveDOMObject::trace(visitor);
135 } 95 }
136 96
137 void close() 97 void close()
138 { 98 {
139 if (m_state == Closed) { 99 if (m_state == Closed) {
140 // It is possible to call |close| from the source side (such 100 // It is possible to call |close| from the source side (such
141 // as blob loading finish) and from the consumer side (such as 101 // as blob loading finish) and from the consumer side (such as
142 // calling |cancel|). Thus we should ignore it here. 102 // calling |cancel|). Thus we should ignore it here.
143 return; 103 return;
144 } 104 }
145 m_state = Closed; 105 m_state = Closed;
146 if (m_drainingStreamBuffer) 106 m_reader.clear();
147 m_drainingStreamBuffer->close();
148 m_stream->close(); 107 m_stream->close();
149 } 108 }
150 void error() 109 void error()
151 { 110 {
152 m_state = Errored; 111 m_state = Errored;
153 if (m_drainingStreamBuffer) 112 m_reader.clear();
154 m_drainingStreamBuffer->error(exception()); 113 m_stream->error(DOMException::create(NetworkError, "network error"));
155 m_stream->error(exception());
156 } 114 }
157 115
158 private: 116 private:
159 class Canceller : public BodyStreamBuffer::Canceller { 117 void didGetReadable() override
yhirano 2015/06/25 11:11:32 Consider using zero-length read in order to detect
hiroshige 2015/06/25 11:27:28 Done.
160 public: 118 {
161 Canceller(ReadableStreamSource* source) : m_source(source) { } 119 processData();
162 void cancel() override 120 }
163 {
164 m_source->cancel();
165 }
166
167 DEFINE_INLINE_VIRTUAL_TRACE()
168 {
169 visitor->trace(m_source);
170 BodyStreamBuffer::Canceller::trace(visitor);
171 }
172
173 private:
174 Member<ReadableStreamSource> m_source;
175 };
176 121
177 // UnderlyingSource functions. 122 // UnderlyingSource functions.
178 void pullSource() override 123 void pullSource() override
179 { 124 {
180 // Note that one |pull| is called only when |read| is called on the 125 ASSERT(!m_streamNeedsMore);
181 // associated ReadableByteStreamReader because we create a stream with 126 m_streamNeedsMore = true;
182 // StrictStrategy. 127
183 if (m_state == Initial) { 128 if (m_state == Initial) {
184 m_state = Streaming; 129 m_state = Streaming;
185 if (m_bodyStreamBuffer) { 130 ASSERT(!m_drained);
186 m_bodyStreamBuffer->registerObserver(this); 131 ASSERT(!m_reader);
187 onWrite(); 132 ASSERT(m_bodyStreamBuffer);
188 if (m_bodyStreamBuffer->hasError()) 133 ASSERT(m_bodyStreamBuffer->handle());
189 return onError(); 134 m_reader = m_bodyStreamBuffer->handle()->obtainReader(this);
190 if (m_bodyStreamBuffer->isClosed()) 135 }
191 return onClose(); 136
192 } else { 137 ASSERT(!m_drained);
193 FileReaderLoader::ReadType readType = FileReaderLoader::ReadAsAr rayBuffer; 138
194 m_loader = adoptPtr(new FileReaderLoader(readType, this)); 139 processData();
195 m_loader->start(executionContext(), m_blobDataHandle); 140 }
141
142 ScriptPromise cancelSource(ScriptState* scriptState, ScriptValue reason) ove rride
143 {
144 close();
145 return ScriptPromise::cast(scriptState, v8::Undefined(scriptState->isola te()));
146 }
147
148 // Reads data and writes the data to |m_stream|, as long as data are
149 // available and the stream has pending reads.
150 void processData()
151 {
152 ASSERT(m_reader);
153 while (m_streamNeedsMore) {
154 const void* buffer;
155 size_t available;
156 WebDataConsumerHandle::Result result = m_reader->beginRead(&buffer, WebDataConsumerHandle::FlagNone, &available);
157 switch (result) {
158 case WebDataConsumerHandle::Ok:
159 m_streamNeedsMore = m_stream->enqueue(DOMUint8Array::create(stat ic_cast<const unsigned char*>(buffer), available));
160 m_reader->endRead(available);
161 break;
162
163 case WebDataConsumerHandle::Done:
164 close();
165 return;
166
167 case WebDataConsumerHandle::ShouldWait:
168 return;
169
170 case WebDataConsumerHandle::Busy:
171 case WebDataConsumerHandle::ResourceExhausted:
172 case WebDataConsumerHandle::UnexpectedError:
173 error();
174 return;
196 } 175 }
197 } 176 }
198 } 177 }
199 178
200 ScriptPromise cancelSource(ScriptState* scriptState, ScriptValue reason) ove rride 179 // Source of data.
201 { 180 Member<BodyStreamBuffer> m_bodyStreamBuffer;
202 cancel(); 181 OwnPtr<FetchDataConsumerHandle::Reader> m_reader;
203 return ScriptPromise::cast(scriptState, v8::Undefined(scriptState->isola te()));
204 }
205 182
206 // BodyStreamBuffer::Observer functions.
207 void onWrite() override
208 {
209 ASSERT(m_state == Streaming);
210 while (RefPtr<DOMArrayBuffer> buf = m_bodyStreamBuffer->read()) {
211 write(buf);
212 }
213 }
214 void onClose() override
215 {
216 ASSERT(m_state == Streaming);
217 close();
218 m_bodyStreamBuffer->unregisterObserver();
219 }
220 void onError() override
221 {
222 ASSERT(m_state == Streaming);
223 error();
224 m_bodyStreamBuffer->unregisterObserver();
225 }
226
227 // FileReaderLoaderClient functions.
228 void didStartLoading() override { }
229 void didReceiveData() override { }
230 void didFinishLoading() override
231 {
232 ASSERT(m_state == Streaming);
233 write(m_loader->arrayBufferResult());
234 close();
235 }
236 void didFail(FileError::ErrorCode) override
237 {
238 ASSERT(m_state == Streaming);
239 error();
240 }
241
242 void write(PassRefPtr<DOMArrayBuffer> buf)
243 {
244 if (m_drainingStreamBuffer) {
245 m_drainingStreamBuffer->write(buf);
246 } else {
247 auto size = buf->byteLength();
248 m_stream->enqueue(DOMUint8Array::create(buf, 0, size));
249 }
250 }
251 void cancel()
252 {
253 if (m_bodyStreamBuffer) {
254 m_bodyStreamBuffer->cancel();
255 // We should not close the stream here, because it is canceller's
256 // responsibility.
257 } else {
258 if (m_loader)
259 m_loader->cancel();
260 close();
261 }
262 }
263
264 DOMException* exception()
265 {
266 if (m_state != Errored)
267 return nullptr;
268 if (m_bodyStreamBuffer) {
269 ASSERT(m_bodyStreamBuffer->exception());
270 return m_bodyStreamBuffer->exception();
271 }
272 return DOMException::create(NetworkError, "network error");
273 }
274
275 // Set when the data container of the Body is a BodyStreamBuffer.
276 Member<BodyStreamBuffer> m_bodyStreamBuffer;
277 // Set when the data container of the Body is a BlobDataHandle.
278 RefPtr<BlobDataHandle> m_blobDataHandle;
279 // Used to read the data from BlobDataHandle.
280 OwnPtr<FileReaderLoader> m_loader;
281 // Created when createDrainingStream is called to drain the data.
282 Member<BodyStreamBuffer> m_drainingStreamBuffer;
283 Member<ReadableByteStream> m_stream; 183 Member<ReadableByteStream> m_stream;
284 State m_state; 184 State m_state;
185 bool m_streamNeedsMore;
186 #if ENABLE(ASSERT)
187 bool m_drained;
188 #endif
285 }; 189 };
286 190
287 ScriptPromise Body::readAsync(ScriptState* scriptState, ResponseType type) 191 ScriptPromise Body::readAsync(ScriptState* scriptState, ResponseType type)
288 { 192 {
289 if (bodyUsed()) 193 if (bodyUsed())
290 return ScriptPromise::reject(scriptState, V8ThrowException::createTypeEr ror(scriptState->isolate(), "Already read")); 194 return ScriptPromise::reject(scriptState, V8ThrowException::createTypeEr ror(scriptState->isolate(), "Already read"));
291 195
292 // When the main thread sends a V8::TerminateExecution() signal to a worker 196 // When the main thread sends a V8::TerminateExecution() signal to a worker
293 // thread, any V8 API on the worker thread starts returning an empty 197 // thread, any V8 API on the worker thread starts returning an empty
294 // handle. This can happen in Body::readAsync. To avoid the situation, we 198 // handle. This can happen in Body::readAsync. To avoid the situation, we
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
333 } 237 }
334 case ResponseUnknown: 238 case ResponseUnknown:
335 ASSERT_NOT_REACHED(); 239 ASSERT_NOT_REACHED();
336 break; 240 break;
337 } 241 }
338 m_resolver.clear(); 242 m_resolver.clear();
339 } else if (m_stream->stateInternal() == ReadableStream::Errored) { 243 } else if (m_stream->stateInternal() == ReadableStream::Errored) {
340 m_resolver->reject(m_stream->storedException()); 244 m_resolver->reject(m_stream->storedException());
341 m_resolver.clear(); 245 m_resolver.clear();
342 } else if (isBodyConsumed()) { 246 } else if (isBodyConsumed()) {
343 m_streamSource->createDrainingStream()->readAllAndCreateBlobHandle(mimeT ype(), new BlobHandleReceiver(this)); 247 readAsyncFromFetchDataConsumerHandle(m_streamSource->createDrainingStrea m(), mimeType());
344 } else if (buffer()) {
345 buffer()->readAllAndCreateBlobHandle(mimeType(), new BlobHandleReceiver( this));
346 } else { 248 } else {
347 readAsyncFromBlob(blobDataHandle()); 249 readAsyncFromFetchDataConsumerHandle(buffer(), mimeType());
348 } 250 }
349 return promise; 251 return promise;
350 } 252 }
351 253
352 void Body::readAsyncFromBlob(PassRefPtr<BlobDataHandle> handle) 254 void Body::readAsyncFromFetchDataConsumerHandle(BodyStreamBuffer* buffer, const String& mimeType)
353 { 255 {
354 FileReaderLoader::ReadType readType = FileReaderLoader::ReadAsText; 256 ASSERT(!m_fetchDataLoader);
355 RefPtr<BlobDataHandle> blobHandle = handle; 257
356 if (!blobHandle)
357 blobHandle = BlobDataHandle::create(BlobData::create(), 0);
358 switch (m_responseType) { 258 switch (m_responseType) {
359 case ResponseAsArrayBuffer: 259 case ResponseAsArrayBuffer:
360 readType = FileReaderLoader::ReadAsArrayBuffer; 260 m_fetchDataLoader = FetchDataLoader::createLoaderAsArrayBuffer();
361 break; 261 break;
262
263 case ResponseAsJSON:
264 case ResponseAsText:
265 m_fetchDataLoader = FetchDataLoader::createLoaderAsString();
266 break;
267
362 case ResponseAsBlob: 268 case ResponseAsBlob:
363 if (blobHandle->size() != kuint64max) { 269 m_fetchDataLoader = FetchDataLoader::createLoaderAsBlobHandle(mimeType);
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; 270 break;
271
383 case ResponseAsFormData: 272 case ResponseAsFormData:
384 // FIXME: Implement this. 273 // FIXME: Implement this.
385 ASSERT_NOT_REACHED(); 274 ASSERT_NOT_REACHED();
386 break; 275 return;
387 case ResponseAsJSON: 276
388 case ResponseAsText:
389 break;
390 default: 277 default:
391 ASSERT_NOT_REACHED(); 278 ASSERT_NOT_REACHED();
279 return;
392 } 280 }
393 281
394 m_loader = adoptPtr(new FileReaderLoader(readType, this)); 282 if (buffer && buffer->handle())
395 m_loader->start(m_resolver->scriptState()->executionContext(), blobHandle); 283 m_fetchDataLoader->start(buffer->handle(), this);
284 else
285 m_fetchDataLoader->start(createFetchDataConsumerHandleFromWebHandle(crea teDoneDataConsumerHandle()).get(), this);
286 }
396 287
397 return; 288
398 }
399 289
400 ScriptPromise Body::arrayBuffer(ScriptState* scriptState) 290 ScriptPromise Body::arrayBuffer(ScriptState* scriptState)
401 { 291 {
402 return readAsync(scriptState, ResponseAsArrayBuffer); 292 return readAsync(scriptState, ResponseAsArrayBuffer);
403 } 293 }
404 294
405 ScriptPromise Body::blob(ScriptState* scriptState) 295 ScriptPromise Body::blob(ScriptState* scriptState)
406 { 296 {
407 return readAsync(scriptState, ResponseAsBlob); 297 return readAsync(scriptState, ResponseAsBlob);
408 } 298 }
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
445 } 335 }
446 336
447 bool Body::isBodyConsumed() const 337 bool Body::isBodyConsumed() const
448 { 338 {
449 if (m_streamSource->state() != m_streamSource->Initial) { 339 if (m_streamSource->state() != m_streamSource->Initial) {
450 // Some data is pulled from the source. 340 // Some data is pulled from the source.
451 return true; 341 return true;
452 } 342 }
453 if (m_stream->stateInternal() == ReadableStream::Closed) { 343 if (m_stream->stateInternal() == ReadableStream::Closed) {
454 // Return true if the blob handle is originally not empty. 344 // Return true if the blob handle is originally not empty.
455 RefPtr<BlobDataHandle> handle = blobDataHandle(); 345 // TODO: delete isBodyConsumed() itself.
456 return handle && handle->size(); 346 return true;
457 } 347 }
458 if (m_stream->stateInternal() == ReadableStream::Errored) { 348 if (m_stream->stateInternal() == ReadableStream::Errored) {
459 // The stream is errored. That means an effort to read data was made. 349 // The stream is errored. That means an effort to read data was made.
460 return true; 350 return true;
461 } 351 }
462 return false; 352 return false;
463 } 353 }
464 354
465 void Body::setBody(ReadableStreamSource* source) 355 void Body::setBody(ReadableStreamSource* source)
466 { 356 {
467 m_streamSource = source; 357 m_streamSource = source;
468 m_stream = new ReadableByteStream(m_streamSource, new ReadableByteStream::St rictStrategy); 358 m_stream = new ReadableByteStream(m_streamSource, new ReadableByteStream::St rictStrategy);
469 m_streamSource->startStream(m_stream); 359 m_streamSource->startStream(m_stream);
470 } 360 }
471 361
472 BodyStreamBuffer* Body::createDrainingStream() 362 BodyStreamBuffer* Body::createDrainingStream()
473 { 363 {
474 return m_streamSource->createDrainingStream(); 364 return m_streamSource->createDrainingStream();
475 } 365 }
476 366
477 void Body::stop() 367 void Body::stop()
478 { 368 {
479 // Canceling the load will call didFail which will remove the resolver. 369 if (m_fetchDataLoader) {
480 if (m_loader) 370 m_fetchDataLoader->cancel();
481 m_loader->cancel(); 371 m_fetchDataLoader.clear();
372 }
482 } 373 }
483 374
484 bool Body::hasPendingActivity() const 375 bool Body::hasPendingActivity() const
485 { 376 {
486 if (executionContext()->activeDOMObjectsAreStopped()) 377 if (executionContext()->activeDOMObjectsAreStopped())
487 return false; 378 return false;
488 if (m_resolver) 379 if (m_resolver)
489 return true; 380 return true;
490 if (m_stream->isLocked()) 381 if (m_stream->isLocked())
491 return true; 382 return true;
492 return false; 383 return false;
493 } 384 }
494 385
495 Body::ReadableStreamSource* Body::createBodySource(PassRefPtr<BlobDataHandle> ha ndle)
496 {
497 return new ReadableStreamSource(executionContext(), handle);
498 }
499
500 Body::ReadableStreamSource* Body::createBodySource(BodyStreamBuffer* buffer) 386 Body::ReadableStreamSource* Body::createBodySource(BodyStreamBuffer* buffer)
501 { 387 {
502 return new ReadableStreamSource(executionContext(), buffer); 388 return new ReadableStreamSource(executionContext(), buffer);
503 } 389 }
504 390
505 DEFINE_TRACE(Body) 391 DEFINE_TRACE(Body)
506 { 392 {
393 visitor->trace(m_fetchDataLoader);
507 visitor->trace(m_resolver); 394 visitor->trace(m_resolver);
508 visitor->trace(m_stream); 395 visitor->trace(m_stream);
509 visitor->trace(m_streamSource); 396 visitor->trace(m_streamSource);
510 ActiveDOMObject::trace(visitor); 397 ActiveDOMObject::trace(visitor);
398 FetchDataLoader::Client::trace(visitor);
511 } 399 }
512 400
513 Body::Body(ExecutionContext* context) 401 Body::Body(ExecutionContext* context)
514 : ActiveDOMObject(context) 402 : ActiveDOMObject(context)
515 , m_bodyUsed(false) 403 , m_bodyUsed(false)
516 , m_responseType(ResponseType::ResponseUnknown) 404 , m_responseType(ResponseType::ResponseUnknown)
517 , m_streamSource(new ReadableStreamSource(context)) 405 , m_streamSource(new ReadableStreamSource(context))
518 , m_stream(new ReadableByteStream(m_streamSource, new ReadableByteStream::St rictStrategy)) 406 , m_stream(new ReadableByteStream(m_streamSource, new ReadableByteStream::St rictStrategy))
519 { 407 {
520 m_streamSource->startStream(m_stream); 408 m_streamSource->startStream(m_stream);
521 } 409 }
522 410
523 void Body::resolveJSON(const String& string) 411 void Body::resolveJSON(const String& string)
524 { 412 {
525 ASSERT(m_responseType == ResponseAsJSON); 413 ASSERT(m_responseType == ResponseAsJSON);
526 ScriptState::Scope scope(m_resolver->scriptState()); 414 ScriptState::Scope scope(m_resolver->scriptState());
527 v8::Isolate* isolate = m_resolver->scriptState()->isolate(); 415 v8::Isolate* isolate = m_resolver->scriptState()->isolate();
528 v8::Local<v8::String> inputString = v8String(isolate, string); 416 v8::Local<v8::String> inputString = v8String(isolate, string);
529 v8::TryCatch trycatch; 417 v8::TryCatch trycatch;
530 v8::Local<v8::Value> parsed; 418 v8::Local<v8::Value> parsed;
531 if (v8Call(v8::JSON::Parse(isolate, inputString), parsed, trycatch)) 419 if (v8Call(v8::JSON::Parse(isolate, inputString), parsed, trycatch))
532 m_resolver->resolve(parsed); 420 m_resolver->resolve(parsed);
533 else 421 else
534 m_resolver->reject(trycatch.Exception()); 422 m_resolver->reject(trycatch.Exception());
535 } 423 }
536 424
537 // FileReaderLoaderClient functions. 425 // FetchDataLoader::Client functions.
538 void Body::didStartLoading() { } 426 void Body::didFetchDataLoadFailed()
539 void Body::didReceiveData() { }
540 void Body::didFinishLoading()
541 { 427 {
542 if (!executionContext() || executionContext()->activeDOMObjectsAreStopped()) 428 ASSERT(m_fetchDataLoader);
543 return; 429 m_fetchDataLoader.clear();
544 430
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()) 431 if (!executionContext() || executionContext()->activeDOMObjectsAreStopped())
578 return; 432 return;
579 433
580 m_streamSource->error(); 434 m_streamSource->error();
581 if (m_resolver) { 435 if (m_resolver) {
582 // FIXME: We should reject the promise. 436 if (!m_resolver->executionContext() || m_resolver->executionContext()->a ctiveDOMObjectsAreStopped()) {
583 m_resolver->resolve(""); 437 m_resolver.clear();
438 return;
439 }
440 ScriptState* state = m_resolver->scriptState();
441 ScriptState::Scope scope(state);
442 m_resolver->reject(V8ThrowException::createTypeError(state->isolate(), " Failed to fetch"));
584 m_resolver.clear(); 443 m_resolver.clear();
585 } 444 }
586 } 445 }
587 446
588 void Body::didBlobHandleReceiveError(DOMException* exception) 447 void Body::didFetchDataLoadedBlobHandle(PassRefPtr<BlobDataHandle> blobDataHandl e)
589 { 448 {
590 if (!m_resolver) 449 ASSERT(m_fetchDataLoader);
450 m_fetchDataLoader.clear();
451
452 if (!executionContext() || executionContext()->activeDOMObjectsAreStopped())
591 return; 453 return;
592 m_streamSource->error(); 454
593 m_resolver->reject(exception); 455 ASSERT(m_responseType == ResponseAsBlob);
456 m_resolver->resolve(Blob::create(blobDataHandle));
457 m_streamSource->close();
594 m_resolver.clear(); 458 m_resolver.clear();
595 } 459 }
596 460
461 void Body::didFetchDataLoadedArrayBuffer(PassRefPtr<DOMArrayBuffer> arrayBuffer)
462 {
463 ASSERT(m_fetchDataLoader);
464 m_fetchDataLoader.clear();
465
466 if (!executionContext() || executionContext()->activeDOMObjectsAreStopped())
467 return;
468
469 ASSERT(m_responseType == ResponseAsArrayBuffer);
470 m_resolver->resolve(arrayBuffer);
471 m_streamSource->close();
472 m_resolver.clear();
473 }
474
475 void Body::didFetchDataLoadedString(const String& str)
476 {
477 ASSERT(m_fetchDataLoader);
478 m_fetchDataLoader.clear();
479
480 if (!executionContext() || executionContext()->activeDOMObjectsAreStopped())
481 return;
482
483 switch (m_responseType) {
484 case ResponseAsJSON:
485 resolveJSON(str);
486 break;
487 case ResponseAsText:
488 m_resolver->resolve(str);
489 break;
490 default:
491 ASSERT_NOT_REACHED();
492 }
493
494 m_streamSource->close();
495 m_resolver.clear();
496 }
497
597 } // namespace blink 498 } // namespace blink
OLDNEW
« no previous file with comments | « Source/modules/fetch/Body.h ('k') | Source/modules/fetch/BodyStreamBuffer.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698