| 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" | 7 #include "bindings/core/v8/ScriptState.h" |
| 8 #include "bindings/core/v8/V8HiddenValue.h" | 8 #include "bindings/core/v8/V8HiddenValue.h" |
| 9 #include "core/dom/DOMArrayBuffer.h" | 9 #include "core/dom/DOMArrayBuffer.h" |
| 10 #include "core/dom/DOMTypedArray.h" | 10 #include "core/dom/DOMTypedArray.h" |
| 11 #include "core/dom/ExceptionCode.h" | 11 #include "core/dom/ExceptionCode.h" |
| 12 #include "core/streams/ReadableStreamController.h" | 12 #include "core/streams/ReadableStreamController.h" |
| 13 #include "core/streams/ReadableStreamOperations.h" | 13 #include "core/streams/ReadableStreamOperations.h" |
| 14 #include "modules/fetch/Body.h" | 14 #include "modules/fetch/Body.h" |
| 15 #include "modules/fetch/DataConsumerHandleUtil.h" | 15 #include "modules/fetch/DataConsumerHandleUtil.h" |
| 16 #include "modules/fetch/DataConsumerTee.h" |
| 17 #include "modules/fetch/ReadableStreamDataConsumerHandle.h" |
| 16 #include "platform/RuntimeEnabledFeatures.h" | 18 #include "platform/RuntimeEnabledFeatures.h" |
| 17 #include "platform/blob/BlobData.h" | 19 #include "platform/blob/BlobData.h" |
| 18 #include "platform/network/EncodedFormData.h" | 20 #include "platform/network/EncodedFormData.h" |
| 19 | 21 |
| 20 namespace blink { | 22 namespace blink { |
| 21 | 23 |
| 22 class BodyStreamBuffer::LoaderClient final : public GarbageCollectedFinalized<Lo
aderClient>, public ActiveDOMObject, public FetchDataLoader::Client { | 24 class BodyStreamBuffer::LoaderClient final : public GarbageCollectedFinalized<Lo
aderClient>, public ActiveDOMObject, public FetchDataLoader::Client { |
| 23 WTF_MAKE_NONCOPYABLE(LoaderClient); | 25 WTF_MAKE_NONCOPYABLE(LoaderClient); |
| 24 USING_GARBAGE_COLLECTED_MIXIN(LoaderClient); | 26 USING_GARBAGE_COLLECTED_MIXIN(LoaderClient); |
| 25 public: | 27 public: |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 77 | 79 |
| 78 Member<BodyStreamBuffer> m_buffer; | 80 Member<BodyStreamBuffer> m_buffer; |
| 79 Member<FetchDataLoader::Client> m_client; | 81 Member<FetchDataLoader::Client> m_client; |
| 80 }; | 82 }; |
| 81 | 83 |
| 82 BodyStreamBuffer::BodyStreamBuffer(ScriptState* scriptState, PassOwnPtr<FetchDat
aConsumerHandle> handle) | 84 BodyStreamBuffer::BodyStreamBuffer(ScriptState* scriptState, PassOwnPtr<FetchDat
aConsumerHandle> handle) |
| 83 : UnderlyingSourceBase(scriptState) | 85 : UnderlyingSourceBase(scriptState) |
| 84 , m_scriptState(scriptState) | 86 , m_scriptState(scriptState) |
| 85 , m_handle(std::move(handle)) | 87 , m_handle(std::move(handle)) |
| 86 , m_reader(m_handle->obtainReader(this)) | 88 , m_reader(m_handle->obtainReader(this)) |
| 89 , m_madeFromReadableStream(false) |
| 87 { | 90 { |
| 88 if (RuntimeEnabledFeatures::responseBodyWithV8ExtraStreamEnabled()) { | 91 if (RuntimeEnabledFeatures::responseBodyWithV8ExtraStreamEnabled()) { |
| 89 ScriptState::Scope scope(scriptState); | 92 ScriptState::Scope scope(scriptState); |
| 90 v8::Local<v8::Value> bodyValue = toV8(this, scriptState); | 93 v8::Local<v8::Value> bodyValue = toV8(this, scriptState); |
| 91 ASSERT(!bodyValue.IsEmpty()); | 94 ASSERT(!bodyValue.IsEmpty()); |
| 92 ASSERT(bodyValue->IsObject()); | 95 ASSERT(bodyValue->IsObject()); |
| 93 v8::Local<v8::Object> body = bodyValue.As<v8::Object>(); | 96 v8::Local<v8::Object> body = bodyValue.As<v8::Object>(); |
| 94 | 97 |
| 95 ScriptValue readableStream = ReadableStreamOperations::createReadableStr
eam( | 98 ScriptValue readableStream = ReadableStreamOperations::createReadableStr
eam( |
| 96 scriptState, this, ReadableStreamOperations::createCountQueuingStrat
egy(scriptState, 0)); | 99 scriptState, this, ReadableStreamOperations::createCountQueuingStrat
egy(scriptState, 0)); |
| 97 V8HiddenValue::setHiddenValue(scriptState, body, V8HiddenValue::internal
BodyStream(scriptState->isolate()), readableStream.v8Value()); | 100 V8HiddenValue::setHiddenValue(scriptState, body, V8HiddenValue::internal
BodyStream(scriptState->isolate()), readableStream.v8Value()); |
| 98 } else { | 101 } else { |
| 99 m_stream = new ReadableByteStream(this, new ReadableByteStream::StrictSt
rategy); | 102 m_stream = new ReadableByteStream(this, new ReadableByteStream::StrictSt
rategy); |
| 100 m_stream->didSourceStart(); | 103 m_stream->didSourceStart(); |
| 101 } | 104 } |
| 102 } | 105 } |
| 103 | 106 |
| 107 BodyStreamBuffer::BodyStreamBuffer(ScriptState* scriptState, ScriptValue stream) |
| 108 : UnderlyingSourceBase(scriptState) |
| 109 , m_scriptState(scriptState) |
| 110 , m_madeFromReadableStream(true) |
| 111 { |
| 112 ScriptState::Scope scope(scriptState); |
| 113 DCHECK(RuntimeEnabledFeatures::responseBodyWithV8ExtraStreamEnabled()); |
| 114 DCHECK(ReadableStreamOperations::isReadableStream(scriptState, stream)); |
| 115 v8::Local<v8::Value> bodyValue = toV8(this, scriptState); |
| 116 DCHECK(!bodyValue.IsEmpty()); |
| 117 DCHECK(bodyValue->IsObject()); |
| 118 v8::Local<v8::Object> body = bodyValue.As<v8::Object>(); |
| 119 |
| 120 V8HiddenValue::setHiddenValue(scriptState, body, V8HiddenValue::internalBody
Stream(scriptState->isolate()), stream.v8Value()); |
| 121 } |
| 122 |
| 104 ScriptValue BodyStreamBuffer::stream() | 123 ScriptValue BodyStreamBuffer::stream() |
| 105 { | 124 { |
| 106 ScriptState::Scope scope(m_scriptState.get()); | 125 ScriptState::Scope scope(m_scriptState.get()); |
| 107 if (RuntimeEnabledFeatures::responseBodyWithV8ExtraStreamEnabled()) { | 126 if (RuntimeEnabledFeatures::responseBodyWithV8ExtraStreamEnabled()) { |
| 108 v8::Local<v8::Value> bodyValue = toV8(this, m_scriptState.get()); | 127 v8::Local<v8::Value> bodyValue = toV8(this, m_scriptState.get()); |
| 109 ASSERT(!bodyValue.IsEmpty()); | 128 ASSERT(!bodyValue.IsEmpty()); |
| 110 ASSERT(bodyValue->IsObject()); | 129 ASSERT(bodyValue->IsObject()); |
| 111 v8::Local<v8::Object> body = bodyValue.As<v8::Object>(); | 130 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()))); | 131 return ScriptValue(m_scriptState.get(), V8HiddenValue::getHiddenValue(m_
scriptState.get(), body, V8HiddenValue::internalBodyStream(m_scriptState->isolat
e()))); |
| 113 } | 132 } |
| 114 return ScriptValue(m_scriptState.get(), toV8(m_stream, m_scriptState.get()))
; | 133 return ScriptValue(m_scriptState.get(), toV8(m_stream, m_scriptState.get()))
; |
| 115 } | 134 } |
| 116 | 135 |
| 117 PassRefPtr<BlobDataHandle> BodyStreamBuffer::drainAsBlobDataHandle(FetchDataCons
umerHandle::Reader::BlobSizePolicy policy) | 136 PassRefPtr<BlobDataHandle> BodyStreamBuffer::drainAsBlobDataHandle(FetchDataCons
umerHandle::Reader::BlobSizePolicy policy) |
| 118 { | 137 { |
| 119 ASSERT(!isStreamLocked()); | 138 ASSERT(!isStreamLocked()); |
| 120 ASSERT(!isStreamDisturbed()); | 139 ASSERT(!isStreamDisturbed()); |
| 121 if (isStreamClosed() || isStreamErrored()) | 140 if (isStreamClosed() || isStreamErrored()) |
| 122 return nullptr; | 141 return nullptr; |
| 123 | 142 |
| 143 if (m_madeFromReadableStream) |
| 144 return nullptr; |
| 145 |
| 124 RefPtr<BlobDataHandle> blobDataHandle = m_reader->drainAsBlobDataHandle(poli
cy); | 146 RefPtr<BlobDataHandle> blobDataHandle = m_reader->drainAsBlobDataHandle(poli
cy); |
| 125 if (blobDataHandle) { | 147 if (blobDataHandle) { |
| 126 closeAndLockAndDisturb(); | 148 closeAndLockAndDisturb(); |
| 127 return blobDataHandle.release(); | 149 return blobDataHandle.release(); |
| 128 } | 150 } |
| 129 return nullptr; | 151 return nullptr; |
| 130 } | 152 } |
| 131 | 153 |
| 132 PassRefPtr<EncodedFormData> BodyStreamBuffer::drainAsFormData() | 154 PassRefPtr<EncodedFormData> BodyStreamBuffer::drainAsFormData() |
| 133 { | 155 { |
| 134 ASSERT(!isStreamLocked()); | 156 ASSERT(!isStreamLocked()); |
| 135 ASSERT(!isStreamDisturbed()); | 157 ASSERT(!isStreamDisturbed()); |
| 136 if (isStreamClosed() || isStreamErrored()) | 158 if (isStreamClosed() || isStreamErrored()) |
| 137 return nullptr; | 159 return nullptr; |
| 138 | 160 |
| 161 if (m_madeFromReadableStream) |
| 162 return nullptr; |
| 163 |
| 139 RefPtr<EncodedFormData> formData = m_reader->drainAsFormData(); | 164 RefPtr<EncodedFormData> formData = m_reader->drainAsFormData(); |
| 140 if (formData) { | 165 if (formData) { |
| 141 closeAndLockAndDisturb(); | 166 closeAndLockAndDisturb(); |
| 142 return formData.release(); | 167 return formData.release(); |
| 143 } | 168 } |
| 144 return nullptr; | 169 return nullptr; |
| 145 } | 170 } |
| 146 | 171 |
| 147 PassOwnPtr<FetchDataConsumerHandle> BodyStreamBuffer::releaseHandle() | |
| 148 { | |
| 149 ASSERT(!isStreamLocked()); | |
| 150 ASSERT(!isStreamDisturbed()); | |
| 151 // We need to call these before calling closeAndLockAndDisturb. | |
| 152 const bool isClosed = isStreamClosed(); | |
| 153 const bool isErrored = isStreamErrored(); | |
| 154 OwnPtr<FetchDataConsumerHandle> handle = std::move(m_handle); | |
| 155 | |
| 156 closeAndLockAndDisturb(); | |
| 157 | |
| 158 if (isClosed) { | |
| 159 // Note that the stream cannot be "draining", because it doesn't have | |
| 160 // the internal buffer. | |
| 161 return createFetchDataConsumerHandleFromWebHandle(createDoneDataConsumer
Handle()); | |
| 162 } | |
| 163 if (isErrored) | |
| 164 return createFetchDataConsumerHandleFromWebHandle(createUnexpectedErrorD
ataConsumerHandle()); | |
| 165 | |
| 166 ASSERT(handle); | |
| 167 return handle; | |
| 168 } | |
| 169 | |
| 170 void BodyStreamBuffer::startLoading(FetchDataLoader* loader, FetchDataLoader::Cl
ient* client) | 172 void BodyStreamBuffer::startLoading(FetchDataLoader* loader, FetchDataLoader::Cl
ient* client) |
| 171 { | 173 { |
| 172 ASSERT(!m_loader); | 174 ASSERT(!m_loader); |
| 173 ASSERT(m_scriptState->contextIsValid()); | 175 ASSERT(m_scriptState->contextIsValid()); |
| 174 OwnPtr<FetchDataConsumerHandle> handle = releaseHandle(); | 176 OwnPtr<FetchDataConsumerHandle> handle = releaseHandle(); |
| 175 m_loader = loader; | 177 m_loader = loader; |
| 176 loader->start(handle.get(), new LoaderClient(m_scriptState->getExecutionCont
ext(), this, client)); | 178 loader->start(handle.get(), new LoaderClient(m_scriptState->getExecutionCont
ext(), this, client)); |
| 177 } | 179 } |
| 178 | 180 |
| 181 void BodyStreamBuffer::tee(BodyStreamBuffer** branch1, BodyStreamBuffer** branch
2) |
| 182 { |
| 183 DCHECK(!isStreamLocked()); |
| 184 DCHECK(!isStreamDisturbed()); |
| 185 *branch1 = nullptr; |
| 186 *branch2 = nullptr; |
| 187 |
| 188 if (m_madeFromReadableStream) { |
| 189 ScriptState::Scope scope(m_scriptState.get()); |
| 190 ScriptValue stream1, stream2; |
| 191 ReadableStreamOperations::tee(m_scriptState.get(), stream(), &stream1, &
stream2); |
| 192 *branch1 = new BodyStreamBuffer(m_scriptState.get(), stream1); |
| 193 *branch2 = new BodyStreamBuffer(m_scriptState.get(), stream2); |
| 194 return; |
| 195 } |
| 196 OwnPtr<FetchDataConsumerHandle> handle = releaseHandle(); |
| 197 OwnPtr<FetchDataConsumerHandle> handle1, handle2; |
| 198 DataConsumerTee::create(m_scriptState->getExecutionContext(), std::move(hand
le), &handle1, &handle2); |
| 199 *branch1 = new BodyStreamBuffer(m_scriptState.get(), std::move(handle1)); |
| 200 *branch2 = new BodyStreamBuffer(m_scriptState.get(), std::move(handle2)); |
| 201 } |
| 202 |
| 179 void BodyStreamBuffer::pullSource() | 203 void BodyStreamBuffer::pullSource() |
| 180 { | 204 { |
| 181 ASSERT(!m_streamNeedsMore); | 205 ASSERT(!m_streamNeedsMore); |
| 182 m_streamNeedsMore = true; | 206 m_streamNeedsMore = true; |
| 183 processData(); | 207 processData(); |
| 184 } | 208 } |
| 185 | 209 |
| 186 ScriptPromise BodyStreamBuffer::cancelSource(ScriptState* scriptState, ScriptVal
ue) | 210 ScriptPromise BodyStreamBuffer::cancelSource(ScriptState* scriptState, ScriptVal
ue) |
| 187 { | 211 { |
| 188 ASSERT(scriptState == m_scriptState.get()); | 212 ASSERT(scriptState == m_scriptState.get()); |
| (...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 377 } | 401 } |
| 378 | 402 |
| 379 void BodyStreamBuffer::stopLoading() | 403 void BodyStreamBuffer::stopLoading() |
| 380 { | 404 { |
| 381 if (!m_loader) | 405 if (!m_loader) |
| 382 return; | 406 return; |
| 383 m_loader->cancel(); | 407 m_loader->cancel(); |
| 384 m_loader = nullptr; | 408 m_loader = nullptr; |
| 385 } | 409 } |
| 386 | 410 |
| 411 PassOwnPtr<FetchDataConsumerHandle> BodyStreamBuffer::releaseHandle() |
| 412 { |
| 413 DCHECK(!isStreamLocked()); |
| 414 DCHECK(!isStreamDisturbed()); |
| 415 |
| 416 if (m_madeFromReadableStream) { |
| 417 ScriptState::Scope scope(m_scriptState.get()); |
| 418 // We need to have |reader| alive by some means (as written in |
| 419 // ReadableStreamDataConsumerHandle). Based on the following facts |
| 420 // - This function is used only from tee and startLoading. |
| 421 // - This branch cannot be taken when called from tee. |
| 422 // - startLoading makes hasPendingActivity return true while loading. |
| 423 // , we don't need to keep the reader explicitly. |
| 424 NonThrowableExceptionState exceptionState; |
| 425 ScriptValue reader = ReadableStreamOperations::getReader(m_scriptState.g
et(), stream(), exceptionState); |
| 426 return ReadableStreamDataConsumerHandle::create(m_scriptState.get(), rea
der); |
| 427 } |
| 428 // We need to call these before calling closeAndLockAndDisturb. |
| 429 const bool isClosed = isStreamClosed(); |
| 430 const bool isErrored = isStreamErrored(); |
| 431 OwnPtr<FetchDataConsumerHandle> handle = m_handle.release(); |
| 432 |
| 433 closeAndLockAndDisturb(); |
| 434 |
| 435 if (isClosed) { |
| 436 // Note that the stream cannot be "draining", because it doesn't have |
| 437 // the internal buffer. |
| 438 return createFetchDataConsumerHandleFromWebHandle(createDoneDataConsumer
Handle()); |
| 439 } |
| 440 if (isErrored) |
| 441 return createFetchDataConsumerHandleFromWebHandle(createUnexpectedErrorD
ataConsumerHandle()); |
| 442 |
| 443 DCHECK(handle); |
| 444 return handle; |
| 445 } |
| 446 |
| 387 } // namespace blink | 447 } // namespace blink |
| OLD | NEW |