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

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

Powered by Google App Engine
This is Rietveld 408576698