OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "modules/fetch/BodyStreamBuffer.h" | 5 #include "modules/fetch/BodyStreamBuffer.h" |
6 | 6 |
7 #include "bindings/core/v8/ScriptState.h" | |
8 #include "bindings/core/v8/V8HiddenValue.h" | |
9 #include "core/dom/DOMArrayBuffer.h" | 7 #include "core/dom/DOMArrayBuffer.h" |
10 #include "core/dom/DOMTypedArray.h" | 8 #include "core/dom/DOMTypedArray.h" |
11 #include "core/dom/ExceptionCode.h" | 9 #include "core/dom/ExceptionCode.h" |
12 #include "core/streams/ReadableStreamController.h" | |
13 #include "core/streams/ReadableStreamOperations.h" | |
14 #include "modules/fetch/Body.h" | |
15 #include "modules/fetch/DataConsumerHandleUtil.h" | 10 #include "modules/fetch/DataConsumerHandleUtil.h" |
16 #include "platform/RuntimeEnabledFeatures.h" | |
17 #include "platform/blob/BlobData.h" | 11 #include "platform/blob/BlobData.h" |
18 #include "platform/network/EncodedFormData.h" | 12 #include "platform/network/EncodedFormData.h" |
19 | 13 |
20 namespace blink { | 14 namespace blink { |
21 | 15 |
22 class BodyStreamBuffer::LoaderClient final : public GarbageCollectedFinalized<Lo
aderClient>, public ActiveDOMObject, public FetchDataLoader::Client { | 16 class BodyStreamBuffer::LoaderClient final : public GarbageCollectedFinalized<Lo
aderClient>, public ActiveDOMObject, public FetchDataLoader::Client { |
23 WTF_MAKE_NONCOPYABLE(LoaderClient); | 17 WTF_MAKE_NONCOPYABLE(LoaderClient); |
24 USING_GARBAGE_COLLECTED_MIXIN(LoaderClient); | 18 USING_GARBAGE_COLLECTED_MIXIN(LoaderClient); |
25 public: | 19 public: |
26 LoaderClient(ExecutionContext* executionContext, BodyStreamBuffer* buffer, F
etchDataLoader::Client* client) | 20 LoaderClient(ExecutionContext* executionContext, BodyStreamBuffer* buffer, F
etchDataLoader::Client* client) |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
72 private: | 66 private: |
73 void stop() override | 67 void stop() override |
74 { | 68 { |
75 m_buffer->stopLoading(); | 69 m_buffer->stopLoading(); |
76 } | 70 } |
77 | 71 |
78 Member<BodyStreamBuffer> m_buffer; | 72 Member<BodyStreamBuffer> m_buffer; |
79 Member<FetchDataLoader::Client> m_client; | 73 Member<FetchDataLoader::Client> m_client; |
80 }; | 74 }; |
81 | 75 |
82 BodyStreamBuffer::BodyStreamBuffer(ScriptState* scriptState, PassOwnPtr<FetchDat
aConsumerHandle> handle) | 76 BodyStreamBuffer::BodyStreamBuffer(PassOwnPtr<FetchDataConsumerHandle> handle) |
83 : UnderlyingSourceBase(scriptState) | 77 : m_handle(handle) |
84 , m_scriptState(scriptState) | |
85 , m_handle(handle) | |
86 , m_reader(m_handle->obtainReader(this)) | 78 , m_reader(m_handle->obtainReader(this)) |
| 79 , m_stream(new ReadableByteStream(this, new ReadableByteStream::StrictStrate
gy)) |
| 80 , m_streamNeedsMore(false) |
87 { | 81 { |
88 if (RuntimeEnabledFeatures::responseBodyWithV8ExtraStreamEnabled()) { | 82 m_stream->didSourceStart(); |
89 ScriptState::Scope scope(scriptState); | |
90 v8::Local<v8::Value> bodyValue = toV8(this, scriptState); | |
91 ASSERT(!bodyValue.IsEmpty()); | |
92 ASSERT(bodyValue->IsObject()); | |
93 v8::Local<v8::Object> body = bodyValue.As<v8::Object>(); | |
94 | |
95 ScriptValue readableStream = ReadableStreamOperations::createReadableStr
eam( | |
96 scriptState, this, ReadableStreamOperations::createCountQueuingStrat
egy(scriptState, 0)); | |
97 V8HiddenValue::setHiddenValue(scriptState, body, V8HiddenValue::internal
BodyStream(scriptState->isolate()), readableStream.v8Value()); | |
98 } else { | |
99 m_stream = new ReadableByteStream(this, new ReadableByteStream::StrictSt
rategy); | |
100 m_stream->didSourceStart(); | |
101 } | |
102 } | 83 } |
103 | 84 |
104 ScriptValue BodyStreamBuffer::stream() | 85 PassRefPtr<BlobDataHandle> BodyStreamBuffer::drainAsBlobDataHandle(ExecutionCont
ext* executionContext, FetchDataConsumerHandle::Reader::BlobSizePolicy policy) |
105 { | |
106 ScriptState::Scope scope(m_scriptState.get()); | |
107 if (RuntimeEnabledFeatures::responseBodyWithV8ExtraStreamEnabled()) { | |
108 v8::Local<v8::Value> bodyValue = toV8(this, m_scriptState.get()); | |
109 ASSERT(!bodyValue.IsEmpty()); | |
110 ASSERT(bodyValue->IsObject()); | |
111 v8::Local<v8::Object> body = bodyValue.As<v8::Object>(); | |
112 return ScriptValue(m_scriptState.get(), V8HiddenValue::getHiddenValue(m_
scriptState.get(), body, V8HiddenValue::internalBodyStream(m_scriptState->isolat
e()))); | |
113 } | |
114 return ScriptValue(m_scriptState.get(), toV8(m_stream, m_scriptState.get()))
; | |
115 } | |
116 | |
117 PassRefPtr<BlobDataHandle> BodyStreamBuffer::drainAsBlobDataHandle(FetchDataCons
umerHandle::Reader::BlobSizePolicy policy) | |
118 { | 86 { |
119 ASSERT(!isStreamLocked()); | 87 ASSERT(!isStreamLocked()); |
120 ASSERT(!isStreamDisturbed()); | 88 ASSERT(!isStreamDisturbed()); |
121 if (isStreamClosed() || isStreamErrored()) | 89 if (isStreamClosed() || isStreamErrored()) |
122 return nullptr; | 90 return nullptr; |
123 | 91 |
124 RefPtr<BlobDataHandle> blobDataHandle = m_reader->drainAsBlobDataHandle(poli
cy); | 92 RefPtr<BlobDataHandle> blobDataHandle = m_reader->drainAsBlobDataHandle(poli
cy); |
125 if (blobDataHandle) { | 93 if (blobDataHandle) { |
126 lockAndDisturb(); | 94 NonThrowableExceptionState exceptionState; |
| 95 m_stream->getBytesReader(executionContext, exceptionState); |
| 96 m_stream->setIsDisturbed(); |
127 close(); | 97 close(); |
128 return blobDataHandle.release(); | 98 return blobDataHandle.release(); |
129 } | 99 } |
130 return nullptr; | 100 return nullptr; |
131 } | 101 } |
132 | 102 |
133 PassRefPtr<EncodedFormData> BodyStreamBuffer::drainAsFormData() | 103 PassRefPtr<EncodedFormData> BodyStreamBuffer::drainAsFormData(ExecutionContext*
executionContext) |
134 { | 104 { |
135 ASSERT(!isStreamLocked()); | 105 ASSERT(!isStreamLocked()); |
136 ASSERT(!isStreamDisturbed()); | 106 ASSERT(!isStreamDisturbed()); |
137 if (isStreamClosed() || isStreamErrored()) | 107 if (isStreamClosed() || isStreamErrored()) |
138 return nullptr; | 108 return nullptr; |
139 | 109 |
140 RefPtr<EncodedFormData> formData = m_reader->drainAsFormData(); | 110 RefPtr<EncodedFormData> formData = m_reader->drainAsFormData(); |
141 if (formData) { | 111 if (formData) { |
142 lockAndDisturb(); | 112 NonThrowableExceptionState exceptionState; |
| 113 m_stream->getBytesReader(executionContext, exceptionState); |
| 114 m_stream->setIsDisturbed(); |
143 close(); | 115 close(); |
144 return formData.release(); | 116 return formData.release(); |
145 } | 117 } |
146 return nullptr; | 118 return nullptr; |
147 } | 119 } |
148 | 120 |
149 PassOwnPtr<FetchDataConsumerHandle> BodyStreamBuffer::releaseHandle() | 121 PassOwnPtr<FetchDataConsumerHandle> BodyStreamBuffer::releaseHandle(ExecutionCon
text* executionContext) |
150 { | 122 { |
151 ASSERT(!isStreamLocked()); | 123 ASSERT(!isStreamLocked()); |
152 ASSERT(!isStreamDisturbed()); | 124 ASSERT(!isStreamDisturbed()); |
153 lockAndDisturb(); | 125 m_reader = nullptr; |
| 126 m_stream->setIsDisturbed(); |
| 127 NonThrowableExceptionState exceptionState; |
| 128 m_stream->getBytesReader(executionContext, exceptionState); |
154 | 129 |
155 if (isStreamClosed()) | 130 if (isStreamClosed()) |
156 return createFetchDataConsumerHandleFromWebHandle(createDoneDataConsumer
Handle()); | 131 return createFetchDataConsumerHandleFromWebHandle(createDoneDataConsumer
Handle()); |
157 if (isStreamErrored()) | 132 if (isStreamErrored()) |
158 return createFetchDataConsumerHandleFromWebHandle(createUnexpectedErrorD
ataConsumerHandle()); | 133 return createFetchDataConsumerHandleFromWebHandle(createUnexpectedErrorD
ataConsumerHandle()); |
159 | 134 |
160 ASSERT(m_handle); | 135 ASSERT(m_handle); |
161 OwnPtr<FetchDataConsumerHandle> handle = m_handle.release(); | 136 OwnPtr<FetchDataConsumerHandle> handle = m_handle.release(); |
162 close(); | 137 close(); |
163 return handle.release(); | 138 return handle.release(); |
164 } | 139 } |
165 | 140 |
166 void BodyStreamBuffer::startLoading(FetchDataLoader* loader, FetchDataLoader::Cl
ient* client) | 141 void BodyStreamBuffer::startLoading(ExecutionContext* executionContext, FetchDat
aLoader* loader, FetchDataLoader::Client* client) |
167 { | 142 { |
168 ASSERT(!m_loader); | 143 ASSERT(!m_loader); |
169 ASSERT(m_scriptState->contextIsValid()); | 144 OwnPtr<FetchDataConsumerHandle> handle = releaseHandle(executionContext); |
170 OwnPtr<FetchDataConsumerHandle> handle = releaseHandle(); | |
171 m_loader = loader; | 145 m_loader = loader; |
172 loader->start(handle.get(), new LoaderClient(m_scriptState->getExecutionCont
ext(), this, client)); | 146 loader->start(handle.get(), new LoaderClient(executionContext, this, client)
); |
173 } | 147 } |
174 | 148 |
175 bool BodyStreamBuffer::hasPendingActivity() const | 149 bool BodyStreamBuffer::hasPendingActivity() const |
176 { | 150 { |
177 if (m_loader) | 151 return m_loader || (isStreamLocked() && isStreamReadable()); |
178 return true; | |
179 if (RuntimeEnabledFeatures::responseBodyWithV8ExtraStreamEnabled()) | |
180 return UnderlyingSourceBase::hasPendingActivity(); | |
181 | |
182 return m_stream->stateInternal() == ReadableStream::Readable && m_stream->is
Locked(); | |
183 } | 152 } |
184 | 153 |
185 void BodyStreamBuffer::stop() | 154 void BodyStreamBuffer::stop() |
186 { | 155 { |
187 m_reader = nullptr; | 156 m_reader = nullptr; |
188 m_handle = nullptr; | 157 m_handle = nullptr; |
189 } | 158 } |
190 | 159 |
191 void BodyStreamBuffer::pullSource() | 160 void BodyStreamBuffer::pullSource() |
192 { | 161 { |
193 ASSERT(!m_streamNeedsMore); | 162 ASSERT(!m_streamNeedsMore); |
194 m_streamNeedsMore = true; | 163 m_streamNeedsMore = true; |
195 processData(); | 164 processData(); |
196 } | 165 } |
197 | 166 |
198 ScriptPromise BodyStreamBuffer::cancelSource(ScriptState* scriptState, ScriptVal
ue) | 167 ScriptPromise BodyStreamBuffer::cancelSource(ScriptState* scriptState, ScriptVal
ue) |
199 { | 168 { |
200 ASSERT(scriptState == m_scriptState.get()); | |
201 close(); | 169 close(); |
202 return ScriptPromise::castUndefined(scriptState); | 170 return ScriptPromise::castUndefined(scriptState); |
203 } | 171 } |
204 | |
205 ScriptPromise BodyStreamBuffer::pull(ScriptState* scriptState) | |
206 { | |
207 ASSERT(!m_streamNeedsMore); | |
208 ASSERT(scriptState == m_scriptState.get()); | |
209 m_streamNeedsMore = true; | |
210 processData(); | |
211 return ScriptPromise::castUndefined(scriptState); | |
212 } | |
213 | |
214 ScriptPromise BodyStreamBuffer::cancel(ScriptState* scriptState, ScriptValue rea
son) | |
215 { | |
216 ASSERT(scriptState == m_scriptState.get()); | |
217 close(); | |
218 return ScriptPromise::castUndefined(scriptState); | |
219 } | |
220 | 172 |
221 void BodyStreamBuffer::didGetReadable() | 173 void BodyStreamBuffer::didGetReadable() |
222 { | 174 { |
223 if (!m_reader) | 175 if (!m_reader) |
224 return; | 176 return; |
225 | 177 |
226 if (!m_streamNeedsMore) { | 178 if (!m_streamNeedsMore) { |
227 // Perform zero-length read to call close()/error() early. | 179 // Perform zero-length read to call close()/error() early. |
228 size_t readSize; | 180 size_t readSize; |
229 WebDataConsumerHandle::Result result = m_reader->read(nullptr, 0, WebDat
aConsumerHandle::FlagNone, &readSize); | 181 WebDataConsumerHandle::Result result = m_reader->read(nullptr, 0, WebDat
aConsumerHandle::FlagNone, &readSize); |
230 switch (result) { | 182 switch (result) { |
231 case WebDataConsumerHandle::Ok: | 183 case WebDataConsumerHandle::Ok: |
232 case WebDataConsumerHandle::ShouldWait: | 184 case WebDataConsumerHandle::ShouldWait: |
233 return; | 185 return; |
234 case WebDataConsumerHandle::Done: | 186 case WebDataConsumerHandle::Done: |
235 close(); | 187 close(); |
236 return; | 188 return; |
237 case WebDataConsumerHandle::Busy: | 189 case WebDataConsumerHandle::Busy: |
238 case WebDataConsumerHandle::ResourceExhausted: | 190 case WebDataConsumerHandle::ResourceExhausted: |
239 case WebDataConsumerHandle::UnexpectedError: | 191 case WebDataConsumerHandle::UnexpectedError: |
240 error(); | 192 error(); |
241 return; | 193 return; |
242 } | 194 } |
243 return; | 195 return; |
244 } | 196 } |
245 processData(); | 197 processData(); |
246 } | 198 } |
247 | 199 |
248 bool BodyStreamBuffer::isStreamReadable() | 200 bool BodyStreamBuffer::isStreamReadable() const |
249 { | 201 { |
250 if (RuntimeEnabledFeatures::responseBodyWithV8ExtraStreamEnabled()) { | |
251 ScriptState::Scope scope(m_scriptState.get()); | |
252 return ReadableStreamOperations::isReadable(m_scriptState.get(), stream(
)); | |
253 } | |
254 return m_stream->stateInternal() == ReadableStream::Readable; | 202 return m_stream->stateInternal() == ReadableStream::Readable; |
255 } | 203 } |
256 | 204 |
257 bool BodyStreamBuffer::isStreamClosed() | 205 bool BodyStreamBuffer::isStreamClosed() const |
258 { | 206 { |
259 if (RuntimeEnabledFeatures::responseBodyWithV8ExtraStreamEnabled()) { | |
260 ScriptState::Scope scope(m_scriptState.get()); | |
261 return ReadableStreamOperations::isClosed(m_scriptState.get(), stream())
; | |
262 } | |
263 return m_stream->stateInternal() == ReadableStream::Closed; | 207 return m_stream->stateInternal() == ReadableStream::Closed; |
264 } | 208 } |
265 | 209 |
266 bool BodyStreamBuffer::isStreamErrored() | 210 bool BodyStreamBuffer::isStreamErrored() const |
267 { | 211 { |
268 if (RuntimeEnabledFeatures::responseBodyWithV8ExtraStreamEnabled()) { | |
269 ScriptState::Scope scope(m_scriptState.get()); | |
270 return ReadableStreamOperations::isErrored(m_scriptState.get(), stream()
); | |
271 } | |
272 return m_stream->stateInternal() == ReadableStream::Errored; | 212 return m_stream->stateInternal() == ReadableStream::Errored; |
273 } | 213 } |
274 | 214 |
275 bool BodyStreamBuffer::isStreamLocked() | 215 bool BodyStreamBuffer::isStreamLocked() const |
276 { | 216 { |
277 if (RuntimeEnabledFeatures::responseBodyWithV8ExtraStreamEnabled()) { | |
278 ScriptState::Scope scope(m_scriptState.get()); | |
279 return ReadableStreamOperations::isLocked(m_scriptState.get(), stream())
; | |
280 } | |
281 return m_stream->isLocked(); | 217 return m_stream->isLocked(); |
282 } | 218 } |
283 | 219 |
284 bool BodyStreamBuffer::isStreamDisturbed() | 220 bool BodyStreamBuffer::isStreamDisturbed() const |
285 { | 221 { |
286 if (RuntimeEnabledFeatures::responseBodyWithV8ExtraStreamEnabled()) { | |
287 ScriptState::Scope scope(m_scriptState.get()); | |
288 return ReadableStreamOperations::isDisturbed(m_scriptState.get(), stream
()); | |
289 } | |
290 return m_stream->isDisturbed(); | 222 return m_stream->isDisturbed(); |
291 } | 223 } |
292 | 224 |
293 void BodyStreamBuffer::setDisturbed() | |
294 { | |
295 if (RuntimeEnabledFeatures::responseBodyWithV8ExtraStreamEnabled()) { | |
296 ScriptState::Scope scope(m_scriptState.get()); | |
297 ReadableStreamOperations::setDisturbed(m_scriptState.get(), stream()); | |
298 } else { | |
299 m_stream->setIsDisturbed(); | |
300 } | |
301 } | |
302 | |
303 void BodyStreamBuffer::lockAndDisturb() | |
304 { | |
305 if (RuntimeEnabledFeatures::responseBodyWithV8ExtraStreamEnabled()) { | |
306 ScriptState::Scope scope(m_scriptState.get()); | |
307 NonThrowableExceptionState exceptionState; | |
308 ReadableStreamOperations::getReader(m_scriptState.get(), stream(), excep
tionState); | |
309 ReadableStreamOperations::setDisturbed(m_scriptState.get(), stream()); | |
310 } else { | |
311 NonThrowableExceptionState exceptionState; | |
312 m_stream->getBytesReader(m_scriptState->getExecutionContext(), exception
State); | |
313 m_stream->setIsDisturbed(); | |
314 } | |
315 } | |
316 | |
317 void BodyStreamBuffer::close() | 225 void BodyStreamBuffer::close() |
318 { | 226 { |
319 if (RuntimeEnabledFeatures::responseBodyWithV8ExtraStreamEnabled()) | |
320 controller()->close(); | |
321 else | |
322 m_stream->close(); | |
323 m_reader = nullptr; | 227 m_reader = nullptr; |
324 m_handle = nullptr; | 228 m_stream->close(); |
| 229 m_handle.clear(); |
325 } | 230 } |
326 | 231 |
327 void BodyStreamBuffer::error() | 232 void BodyStreamBuffer::error() |
328 { | 233 { |
329 if (RuntimeEnabledFeatures::responseBodyWithV8ExtraStreamEnabled()) | |
330 controller()->error(DOMException::create(NetworkError, "network error"))
; | |
331 else | |
332 m_stream->error(DOMException::create(NetworkError, "network error")); | |
333 m_reader = nullptr; | 234 m_reader = nullptr; |
334 m_handle = nullptr; | 235 m_stream->error(DOMException::create(NetworkError, "network error")); |
| 236 m_handle.clear(); |
335 } | 237 } |
336 | 238 |
337 void BodyStreamBuffer::processData() | 239 void BodyStreamBuffer::processData() |
338 { | 240 { |
339 ASSERT(m_reader); | 241 ASSERT(m_reader); |
340 while (m_streamNeedsMore) { | 242 while (m_streamNeedsMore) { |
341 const void* buffer; | 243 const void* buffer; |
342 size_t available; | 244 size_t available; |
343 WebDataConsumerHandle::Result result = m_reader->beginRead(&buffer, WebD
ataConsumerHandle::FlagNone, &available); | 245 WebDataConsumerHandle::Result result = m_reader->beginRead(&buffer, WebD
ataConsumerHandle::FlagNone, &available); |
344 switch (result) { | 246 switch (result) { |
345 case WebDataConsumerHandle::Ok: { | 247 case WebDataConsumerHandle::Ok: |
346 DOMUint8Array* array = DOMUint8Array::create(static_cast<const unsig
ned char*>(buffer), available); | 248 m_streamNeedsMore = m_stream->enqueue(DOMUint8Array::create(static_c
ast<const unsigned char*>(buffer), available)); |
347 if (RuntimeEnabledFeatures::responseBodyWithV8ExtraStreamEnabled())
{ | |
348 controller()->enqueue(array); | |
349 m_streamNeedsMore = controller()->desiredSize() > 0; | |
350 } else { | |
351 m_streamNeedsMore = m_stream->enqueue(array); | |
352 } | |
353 m_reader->endRead(available); | 249 m_reader->endRead(available); |
354 break; | 250 break; |
355 } | 251 |
356 case WebDataConsumerHandle::Done: | 252 case WebDataConsumerHandle::Done: |
357 close(); | 253 close(); |
358 return; | 254 return; |
359 | 255 |
360 case WebDataConsumerHandle::ShouldWait: | 256 case WebDataConsumerHandle::ShouldWait: |
361 return; | 257 return; |
362 | 258 |
363 case WebDataConsumerHandle::Busy: | 259 case WebDataConsumerHandle::Busy: |
364 case WebDataConsumerHandle::ResourceExhausted: | 260 case WebDataConsumerHandle::ResourceExhausted: |
365 case WebDataConsumerHandle::UnexpectedError: | 261 case WebDataConsumerHandle::UnexpectedError: |
(...skipping 11 matching lines...) Expand all Loading... |
377 | 273 |
378 void BodyStreamBuffer::stopLoading() | 274 void BodyStreamBuffer::stopLoading() |
379 { | 275 { |
380 if (!m_loader) | 276 if (!m_loader) |
381 return; | 277 return; |
382 m_loader->cancel(); | 278 m_loader->cancel(); |
383 m_loader = nullptr; | 279 m_loader = nullptr; |
384 } | 280 } |
385 | 281 |
386 } // namespace blink | 282 } // namespace blink |
OLD | NEW |