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

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

Issue 1171913003: **** [WIP] Blink-side: Implement FetchBlobDataConsumerHandle **** (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Clean up. 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) 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::create(createF etchDataConsumerHandleFromWebHandle(createDoneDataConsumerHandle())))
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::create(createFetchDataConsumerHa ndleFromWebHandle(createDoneDataConsumerHandle())))
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()
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::create(createFetchDataConsumerHandleFromWe bHandle(createDoneDataConsumerHandle()));
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)
122 drainingStreamBuffer->close(); 82 return BodyStreamBuffer2::create(createFetchDataConsumerHandleFromWe bHandle(createDoneDataConsumerHandle()));
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;
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)
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()->handle(), mimeType());
344 } else if (buffer()) { 244 } else if (buffer()) {
345 buffer()->readAllAndCreateBlobHandle(mimeType(), new BlobHandleReceiver( this)); 245 readAsyncFromFetchDataConsumerHandle(buffer()->handle(), mimeType());
346 } else { 246 } else {
347 readAsyncFromBlob(blobDataHandle()); 247 readAsyncFromFetchDataConsumerHandle(createFetchDataConsumerHandleFromWe bHandle(createDoneDataConsumerHandle()).get(), mimeType());
348 } 248 }
349 return promise; 249 return promise;
350 } 250 }
351 251
352 void Body::readAsyncFromBlob(PassRefPtr<BlobDataHandle> handle) 252 void Body::readAsyncFromFetchDataConsumerHandle(FetchDataConsumerHandle* handle, const String& mimeType)
353 { 253 {
354 FileReaderLoader::ReadType readType = FileReaderLoader::ReadAsText; 254 ASSERT(!m_fetchDataLoader);
355 RefPtr<BlobDataHandle> blobHandle = handle; 255
356 if (!blobHandle)
357 blobHandle = BlobDataHandle::create(BlobData::create(), 0);
358 switch (m_responseType) { 256 switch (m_responseType) {
359 case ResponseAsArrayBuffer: 257 case ResponseAsArrayBuffer:
360 readType = FileReaderLoader::ReadAsArrayBuffer; 258 m_fetchDataLoader = FetchDataLoader::createLoaderAsArrayBuffer();
361 break; 259 break;
260
261 case ResponseAsJSON:
262 case ResponseAsText:
263 m_fetchDataLoader = FetchDataLoader::createLoaderAsString();
264 break;
265
362 case ResponseAsBlob: 266 case ResponseAsBlob:
363 if (blobHandle->size() != kuint64max) { 267 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; 268 break;
269
383 case ResponseAsFormData: 270 case ResponseAsFormData:
384 // FIXME: Implement this. 271 // FIXME: Implement this.
385 ASSERT_NOT_REACHED(); 272 ASSERT_NOT_REACHED();
386 break; 273 return;
387 case ResponseAsJSON: 274
388 case ResponseAsText:
389 break;
390 default: 275 default:
391 ASSERT_NOT_REACHED(); 276 ASSERT_NOT_REACHED();
277 return;
392 } 278 }
393 279
394 m_loader = adoptPtr(new FileReaderLoader(readType, this)); 280 if (handle)
395 m_loader->start(m_resolver->scriptState()->executionContext(), blobHandle); 281 m_fetchDataLoader->start(handle, this);
282 else
283 m_fetchDataLoader->start(createFetchDataConsumerHandleFromWebHandle(crea teDoneDataConsumerHandle()).get(), this);
284 }
396 285
397 return; 286
398 }
399 287
400 ScriptPromise Body::arrayBuffer(ScriptState* scriptState) 288 ScriptPromise Body::arrayBuffer(ScriptState* scriptState)
401 { 289 {
402 return readAsync(scriptState, ResponseAsArrayBuffer); 290 return readAsync(scriptState, ResponseAsArrayBuffer);
403 } 291 }
404 292
405 ScriptPromise Body::blob(ScriptState* scriptState) 293 ScriptPromise Body::blob(ScriptState* scriptState)
406 { 294 {
407 return readAsync(scriptState, ResponseAsBlob); 295 return readAsync(scriptState, ResponseAsBlob);
408 } 296 }
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
445 } 333 }
446 334
447 bool Body::isBodyConsumed() const 335 bool Body::isBodyConsumed() const
448 { 336 {
449 if (m_streamSource->state() != m_streamSource->Initial) { 337 if (m_streamSource->state() != m_streamSource->Initial) {
450 // Some data is pulled from the source. 338 // Some data is pulled from the source.
451 return true; 339 return true;
452 } 340 }
453 if (m_stream->stateInternal() == ReadableStream::Closed) { 341 if (m_stream->stateInternal() == ReadableStream::Closed) {
454 // Return true if the blob handle is originally not empty. 342 // Return true if the blob handle is originally not empty.
455 RefPtr<BlobDataHandle> handle = blobDataHandle(); 343 // TODO: delete isBodyConsumed() itself.
456 return handle && handle->size(); 344 return true;
457 } 345 }
458 if (m_stream->stateInternal() == ReadableStream::Errored) { 346 if (m_stream->stateInternal() == ReadableStream::Errored) {
459 // The stream is errored. That means an effort to read data was made. 347 // The stream is errored. That means an effort to read data was made.
460 return true; 348 return true;
461 } 349 }
462 return false; 350 return false;
463 } 351 }
464 352
465 void Body::setBody(ReadableStreamSource* source) 353 void Body::setBody(ReadableStreamSource* source)
466 { 354 {
467 m_streamSource = source; 355 m_streamSource = source;
468 m_stream = new ReadableByteStream(m_streamSource, new ReadableByteStream::St rictStrategy); 356 m_stream = new ReadableByteStream(m_streamSource, new ReadableByteStream::St rictStrategy);
469 m_streamSource->startStream(m_stream); 357 m_streamSource->startStream(m_stream);
470 } 358 }
471 359
472 BodyStreamBuffer* Body::createDrainingStream() 360 BodyStreamBuffer2* Body::createDrainingStream()
473 { 361 {
474 return m_streamSource->createDrainingStream(); 362 return m_streamSource->createDrainingStream();
475 } 363 }
476 364
477 void Body::stop() 365 void Body::stop()
478 { 366 {
479 // Canceling the load will call didFail which will remove the resolver. 367 if (m_fetchDataLoader) {
480 if (m_loader) 368 m_fetchDataLoader->cancel();
481 m_loader->cancel(); 369 m_fetchDataLoader.clear();
370 }
482 } 371 }
483 372
484 bool Body::hasPendingActivity() const 373 bool Body::hasPendingActivity() const
485 { 374 {
486 if (executionContext()->activeDOMObjectsAreStopped()) 375 if (executionContext()->activeDOMObjectsAreStopped())
487 return false; 376 return false;
488 if (m_resolver) 377 if (m_resolver)
489 return true; 378 return true;
490 if (m_stream->isLocked()) 379 if (m_stream->isLocked())
491 return true; 380 return true;
492 return false; 381 return false;
493 } 382 }
494 383
495 Body::ReadableStreamSource* Body::createBodySource(PassRefPtr<BlobDataHandle> ha ndle) 384 Body::ReadableStreamSource* Body::createBodySource(BodyStreamBuffer2* buffer)
496 {
497 return new ReadableStreamSource(executionContext(), handle);
498 }
499
500 Body::ReadableStreamSource* Body::createBodySource(BodyStreamBuffer* buffer)
501 { 385 {
502 return new ReadableStreamSource(executionContext(), buffer); 386 return new ReadableStreamSource(executionContext(), buffer);
503 } 387 }
504 388
505 DEFINE_TRACE(Body) 389 DEFINE_TRACE(Body)
506 { 390 {
391 visitor->trace(m_fetchDataLoader);
507 visitor->trace(m_resolver); 392 visitor->trace(m_resolver);
508 visitor->trace(m_stream); 393 visitor->trace(m_stream);
509 visitor->trace(m_streamSource); 394 visitor->trace(m_streamSource);
510 ActiveDOMObject::trace(visitor); 395 ActiveDOMObject::trace(visitor);
396 FetchDataLoader::Client::trace(visitor);
511 } 397 }
512 398
513 Body::Body(ExecutionContext* context) 399 Body::Body(ExecutionContext* context)
514 : ActiveDOMObject(context) 400 : ActiveDOMObject(context)
515 , m_bodyUsed(false) 401 , m_bodyUsed(false)
516 , m_responseType(ResponseType::ResponseUnknown) 402 , m_responseType(ResponseType::ResponseUnknown)
517 , m_streamSource(new ReadableStreamSource(context)) 403 , m_streamSource(new ReadableStreamSource(context))
518 , m_stream(new ReadableByteStream(m_streamSource, new ReadableByteStream::St rictStrategy)) 404 , m_stream(new ReadableByteStream(m_streamSource, new ReadableByteStream::St rictStrategy))
519 { 405 {
520 m_streamSource->startStream(m_stream); 406 m_streamSource->startStream(m_stream);
521 } 407 }
522 408
523 void Body::resolveJSON(const String& string) 409 void Body::resolveJSON(const String& string)
524 { 410 {
525 ASSERT(m_responseType == ResponseAsJSON); 411 ASSERT(m_responseType == ResponseAsJSON);
526 ScriptState::Scope scope(m_resolver->scriptState()); 412 ScriptState::Scope scope(m_resolver->scriptState());
527 v8::Isolate* isolate = m_resolver->scriptState()->isolate(); 413 v8::Isolate* isolate = m_resolver->scriptState()->isolate();
528 v8::Local<v8::String> inputString = v8String(isolate, string); 414 v8::Local<v8::String> inputString = v8String(isolate, string);
529 v8::TryCatch trycatch; 415 v8::TryCatch trycatch;
530 v8::Local<v8::Value> parsed; 416 v8::Local<v8::Value> parsed;
531 if (v8Call(v8::JSON::Parse(isolate, inputString), parsed, trycatch)) 417 if (v8Call(v8::JSON::Parse(isolate, inputString), parsed, trycatch))
532 m_resolver->resolve(parsed); 418 m_resolver->resolve(parsed);
533 else 419 else
534 m_resolver->reject(trycatch.Exception()); 420 m_resolver->reject(trycatch.Exception());
535 } 421 }
536 422
537 // FileReaderLoaderClient functions. 423 // FetchDataLoader::Client functions.
538 void Body::didStartLoading() { } 424 void Body::didFetchDataLoadFailed()
539 void Body::didReceiveData() { }
540 void Body::didFinishLoading()
541 { 425 {
542 if (!executionContext() || executionContext()->activeDOMObjectsAreStopped()) 426 ASSERT(m_fetchDataLoader);
543 return; 427 m_fetchDataLoader.clear();
544 428
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()) 429 if (!executionContext() || executionContext()->activeDOMObjectsAreStopped())
578 return; 430 return;
579 431
580 m_streamSource->error(); 432 m_streamSource->error();
581 if (m_resolver) { 433 if (m_resolver) {
582 // FIXME: We should reject the promise. 434 m_resolver->reject("");
583 m_resolver->resolve("");
584 m_resolver.clear(); 435 m_resolver.clear();
585 } 436 }
586 } 437 }
587 438
588 void Body::didBlobHandleReceiveError(DOMException* exception) 439 void Body::didFetchDataLoadedBlobHandle(PassRefPtr<BlobDataHandle> blobDataHandl e)
589 { 440 {
590 if (!m_resolver) 441 ASSERT(m_fetchDataLoader);
442 m_fetchDataLoader.clear();
443
444 if (!executionContext() || executionContext()->activeDOMObjectsAreStopped())
591 return; 445 return;
592 m_streamSource->error(); 446
593 m_resolver->reject(exception); 447 ASSERT(m_responseType == ResponseAsBlob);
448 m_resolver->resolve(Blob::create(blobDataHandle));
449 m_streamSource->close();
594 m_resolver.clear(); 450 m_resolver.clear();
595 } 451 }
596 452
453 void Body::didFetchDataLoadedArrayBuffer(PassRefPtr<DOMArrayBuffer> arrayBuffer)
454 {
455 ASSERT(m_fetchDataLoader);
456 m_fetchDataLoader.clear();
457
458 if (!executionContext() || executionContext()->activeDOMObjectsAreStopped())
459 return;
460
461 ASSERT(m_responseType == ResponseAsArrayBuffer);
462 m_resolver->resolve(arrayBuffer);
463 m_streamSource->close();
464 m_resolver.clear();
465 }
466
467 void Body::didFetchDataLoadedString(const String& str)
468 {
469 ASSERT(m_fetchDataLoader);
470 m_fetchDataLoader.clear();
471
472 if (!executionContext() || executionContext()->activeDOMObjectsAreStopped())
473 return;
474
475 switch (m_responseType) {
476 case ResponseAsJSON:
477 resolveJSON(str);
478 break;
479 case ResponseAsText:
480 m_resolver->resolve(str);
481 break;
482 default:
483 ASSERT_NOT_REACHED();
484 }
485
486 m_streamSource->close();
487 m_resolver.clear();
488 }
489
597 } // namespace blink 490 } // 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