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

Side by Side Diff: third_party/WebKit/Source/modules/fetch/BodyStreamBuffer.cpp

Issue 1969333002: [Fetch API] |(new Response(stream)).body| should return |stream| (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 7 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 "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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698