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

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

Issue 1899873006: Make Response::body return v8-extra based stream behind flag (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@notify-locked-released
Patch Set: Created 4 years, 8 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/Body.h" 5 #include "modules/fetch/Body.h"
6 6
7 #include "bindings/core/v8/ExceptionState.h"
8 #include "bindings/core/v8/ScriptPromiseResolver.h" 7 #include "bindings/core/v8/ScriptPromiseResolver.h"
9 #include "bindings/core/v8/ScriptState.h" 8 #include "bindings/core/v8/ScriptState.h"
10 #include "bindings/core/v8/V8ArrayBuffer.h" 9 #include "bindings/core/v8/V8ArrayBuffer.h"
10 #include "bindings/core/v8/V8HiddenValue.h"
Yuki 2016/04/20 12:15:26 Why do you need to include V8HiddenValue.h?
yhirano 2016/04/21 03:41:42 Deleted.
11 #include "bindings/core/v8/V8ThrowException.h" 11 #include "bindings/core/v8/V8ThrowException.h"
12 #include "core/dom/DOMArrayBuffer.h" 12 #include "core/dom/DOMArrayBuffer.h"
13 #include "core/dom/DOMTypedArray.h" 13 #include "core/dom/DOMTypedArray.h"
14 #include "core/dom/ExceptionCode.h" 14 #include "core/dom/ExceptionCode.h"
15 #include "core/fileapi/Blob.h" 15 #include "core/fileapi/Blob.h"
16 #include "core/frame/UseCounter.h" 16 #include "core/frame/UseCounter.h"
17 #include "core/streams/ReadableStreamController.h"
18 #include "core/streams/ReadableStreamOperations.h"
19 #include "core/streams/UnderlyingSourceBase.h"
20 #include "modules/fetch/BodyStreamBuffer.h" 17 #include "modules/fetch/BodyStreamBuffer.h"
21 #include "modules/fetch/FetchDataLoader.h" 18 #include "modules/fetch/FetchDataLoader.h"
19 #include "platform/RuntimeEnabledFeatures.h"
Yuki 2016/04/20 12:15:26 Why do you need to include RuntimeEnabledFeatures.
yhirano 2016/04/21 03:41:42 Deleted.
22 #include "public/platform/WebDataConsumerHandle.h" 20 #include "public/platform/WebDataConsumerHandle.h"
23 #include "wtf/OwnPtr.h" 21 #include "wtf/OwnPtr.h"
24 #include "wtf/PassRefPtr.h" 22 #include "wtf/PassRefPtr.h"
25 #include "wtf/RefPtr.h" 23 #include "wtf/RefPtr.h"
26 24
27 namespace blink { 25 namespace blink {
28 26
29 namespace { 27 namespace {
30 28
31 class BodyConsumerBase : public GarbageCollectedFinalized<BodyConsumerBase>, pub lic FetchDataLoader::Client { 29 class BodyConsumerBase : public GarbageCollectedFinalized<BodyConsumerBase>, pub lic FetchDataLoader::Client {
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
97 v8::Local<v8::String> inputString = v8String(isolate, string); 95 v8::Local<v8::String> inputString = v8String(isolate, string);
98 v8::TryCatch trycatch(isolate); 96 v8::TryCatch trycatch(isolate);
99 v8::Local<v8::Value> parsed; 97 v8::Local<v8::Value> parsed;
100 if (v8Call(v8::JSON::Parse(isolate, inputString), parsed, trycatch)) 98 if (v8Call(v8::JSON::Parse(isolate, inputString), parsed, trycatch))
101 resolver()->resolve(parsed); 99 resolver()->resolve(parsed);
102 else 100 else
103 resolver()->reject(trycatch.Exception()); 101 resolver()->reject(trycatch.Exception());
104 } 102 }
105 }; 103 };
106 104
107 class UnderlyingSourceFromDataConsumerHandle final : public UnderlyingSourceBase , public WebDataConsumerHandle::Client {
108 EAGERLY_FINALIZE();
109 DECLARE_EAGER_FINALIZATION_OPERATOR_NEW();
110 public:
111 UnderlyingSourceFromDataConsumerHandle(ScriptState* scriptState, PassOwnPtr< WebDataConsumerHandle> handle)
112 : UnderlyingSourceBase(scriptState)
113 , m_scriptState(scriptState)
114 , m_reader(handle->obtainReader(this))
115 {
116 }
117
118 ScriptPromise pull(ScriptState* scriptState) override
119 {
120 didGetReadable();
121 return ScriptPromise::castUndefined(scriptState);
122 }
123
124 ScriptPromise cancel(ScriptState* scriptState, ScriptValue reason) override
125 {
126 m_reader = nullptr;
127 return ScriptPromise::castUndefined(scriptState);
128 }
129
130 void didGetReadable() override
131 {
132 while (controller()->desiredSize() > 0) {
133 size_t available = 0;
134 const void* buffer = nullptr;
135 WebDataConsumerHandle::Result result = m_reader->beginRead(&buffer, WebDataConsumerHandle::FlagNone, &available);
136 if (result == WebDataConsumerHandle::Ok) {
137 RefPtr<ArrayBuffer> arrayBuffer = ArrayBuffer::create(available, 1);
138 memcpy(arrayBuffer->data(), buffer, available);
139 m_reader->endRead(available);
140 controller()->enqueue(DOMUint8Array::create(arrayBuffer.release( ), 0, available));
141 } else if (result == WebDataConsumerHandle::ShouldWait) {
142 break;
143 } else if (result == WebDataConsumerHandle::Done) {
144 m_reader = nullptr;
145 controller()->close();
146 break;
147 } else {
148 m_reader = nullptr;
149 controller()->error(V8ThrowException::createTypeError(m_scriptSt ate->isolate(), "Network error"));
150 break;
151 }
152 }
153 }
154
155 private:
156 RefPtr<ScriptState> m_scriptState;
157 OwnPtr<WebDataConsumerHandle::Reader> m_reader;
158 };
159
160 } // namespace 105 } // namespace
161 106
162 ScriptPromise Body::arrayBuffer(ScriptState* scriptState) 107 ScriptPromise Body::arrayBuffer(ScriptState* scriptState)
163 { 108 {
164 ScriptPromise promise = rejectInvalidConsumption(scriptState); 109 ScriptPromise promise = rejectInvalidConsumption(scriptState);
165 if (!promise.isEmpty()) 110 if (!promise.isEmpty())
166 return promise; 111 return promise;
167 112
168 // When the main thread sends a V8::TerminateExecution() signal to a worker 113 // When the main thread sends a V8::TerminateExecution() signal to a worker
169 // thread, any V8 API on the worker thread starts returning an empty 114 // thread, any V8 API on the worker thread starts returning an empty
170 // handle. This can happen in this function. To avoid the situation, we 115 // handle. This can happen in this function. To avoid the situation, we
171 // first check the ExecutionContext and return immediately if it's already 116 // first check the ExecutionContext and return immediately if it's already
172 // gone (which means that the V8::TerminateExecution() signal has been sent 117 // gone (which means that the V8::TerminateExecution() signal has been sent
173 // to this worker thread). 118 // to this worker thread).
174 if (!scriptState->getExecutionContext()) 119 if (!scriptState->getExecutionContext())
175 return ScriptPromise(); 120 return ScriptPromise();
176 121
177 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState) ; 122 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState) ;
178 promise = resolver->promise(); 123 promise = resolver->promise();
179 if (bodyBuffer()) { 124 if (bodyBuffer()) {
180 bodyBuffer()->startLoading(scriptState->getExecutionContext(), FetchData Loader::createLoaderAsArrayBuffer(), new BodyArrayBufferConsumer(resolver)); 125 bodyBuffer()->startLoading(FetchDataLoader::createLoaderAsArrayBuffer(), new BodyArrayBufferConsumer(resolver));
181 } else { 126 } else {
182 resolver->resolve(DOMArrayBuffer::create(0u, 1)); 127 resolver->resolve(DOMArrayBuffer::create(0u, 1));
183 } 128 }
184 return promise; 129 return promise;
185 } 130 }
186 131
187 ScriptPromise Body::blob(ScriptState* scriptState) 132 ScriptPromise Body::blob(ScriptState* scriptState)
188 { 133 {
189 ScriptPromise promise = rejectInvalidConsumption(scriptState); 134 ScriptPromise promise = rejectInvalidConsumption(scriptState);
190 if (!promise.isEmpty()) 135 if (!promise.isEmpty())
191 return promise; 136 return promise;
192 137
193 // See above comment. 138 // See above comment.
194 if (!scriptState->getExecutionContext()) 139 if (!scriptState->getExecutionContext())
195 return ScriptPromise(); 140 return ScriptPromise();
196 141
197 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState) ; 142 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState) ;
198 promise = resolver->promise(); 143 promise = resolver->promise();
199 if (bodyBuffer()) { 144 if (bodyBuffer()) {
200 bodyBuffer()->startLoading(scriptState->getExecutionContext(), FetchData Loader::createLoaderAsBlobHandle(mimeType()), new BodyBlobConsumer(resolver)); 145 bodyBuffer()->startLoading(FetchDataLoader::createLoaderAsBlobHandle(mim eType()), new BodyBlobConsumer(resolver));
201 } else { 146 } else {
202 OwnPtr<BlobData> blobData = BlobData::create(); 147 OwnPtr<BlobData> blobData = BlobData::create();
203 blobData->setContentType(mimeType()); 148 blobData->setContentType(mimeType());
204 resolver->resolve(Blob::create(BlobDataHandle::create(blobData.release() , 0))); 149 resolver->resolve(Blob::create(BlobDataHandle::create(blobData.release() , 0)));
205 } 150 }
206 return promise; 151 return promise;
207 152
208 } 153 }
209 154
210 ScriptPromise Body::json(ScriptState* scriptState) 155 ScriptPromise Body::json(ScriptState* scriptState)
211 { 156 {
212 ScriptPromise promise = rejectInvalidConsumption(scriptState); 157 ScriptPromise promise = rejectInvalidConsumption(scriptState);
213 if (!promise.isEmpty()) 158 if (!promise.isEmpty())
214 return promise; 159 return promise;
215 160
216 // See above comment. 161 // See above comment.
217 if (!scriptState->getExecutionContext()) 162 if (!scriptState->getExecutionContext())
218 return ScriptPromise(); 163 return ScriptPromise();
219 164
220 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState) ; 165 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState) ;
221 promise = resolver->promise(); 166 promise = resolver->promise();
222 if (bodyBuffer()) { 167 if (bodyBuffer()) {
223 bodyBuffer()->startLoading(scriptState->getExecutionContext(), FetchData Loader::createLoaderAsString(), new BodyJsonConsumer(resolver)); 168 bodyBuffer()->startLoading(FetchDataLoader::createLoaderAsString(), new BodyJsonConsumer(resolver));
224 } else { 169 } else {
225 resolver->reject(V8ThrowException::createSyntaxError(scriptState->isolat e(), "Unexpected end of input")); 170 resolver->reject(V8ThrowException::createSyntaxError(scriptState->isolat e(), "Unexpected end of input"));
226 } 171 }
227 return promise; 172 return promise;
228 } 173 }
229 174
230 ScriptPromise Body::text(ScriptState* scriptState) 175 ScriptPromise Body::text(ScriptState* scriptState)
231 { 176 {
232 ScriptPromise promise = rejectInvalidConsumption(scriptState); 177 ScriptPromise promise = rejectInvalidConsumption(scriptState);
233 if (!promise.isEmpty()) 178 if (!promise.isEmpty())
234 return promise; 179 return promise;
235 180
236 // See above comment. 181 // See above comment.
237 if (!scriptState->getExecutionContext()) 182 if (!scriptState->getExecutionContext())
238 return ScriptPromise(); 183 return ScriptPromise();
239 184
240 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState) ; 185 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState) ;
241 promise = resolver->promise(); 186 promise = resolver->promise();
242 if (bodyBuffer()) { 187 if (bodyBuffer()) {
243 bodyBuffer()->startLoading(scriptState->getExecutionContext(), FetchData Loader::createLoaderAsString(), new BodyTextConsumer(resolver)); 188 bodyBuffer()->startLoading(FetchDataLoader::createLoaderAsString(), new BodyTextConsumer(resolver));
244 } else { 189 } else {
245 resolver->resolve(String()); 190 resolver->resolve(String());
246 } 191 }
247 return promise; 192 return promise;
248 } 193 }
249 194
250 ReadableByteStream* Body::body() 195 ScriptValue Body::bodyWithUseCounter(ScriptState* scriptState)
251 {
252 return bodyBuffer() ? bodyBuffer()->stream() : nullptr;
253 }
254
255 ReadableByteStream* Body::bodyWithUseCounter()
256 { 196 {
257 UseCounter::count(getExecutionContext(), UseCounter::FetchBodyStream); 197 UseCounter::count(getExecutionContext(), UseCounter::FetchBodyStream);
258 return body(); 198 if (!bodyBuffer())
259 } 199 return ScriptValue::createNull(scriptState);
260 200 ScriptValue stream = bodyBuffer()->stream();
261 ScriptValue Body::v8ExtraStreamBody(ScriptState* scriptState) 201 ASSERT(stream.getScriptState() == scriptState);
262 { 202 return stream;
263 if (bodyUsed() || isBodyLocked() || !bodyBuffer())
264 return ScriptValue(scriptState, v8::Undefined(scriptState->isolate()));
265 OwnPtr<FetchDataConsumerHandle> handle = bodyBuffer()->releaseHandle(scriptS tate->getExecutionContext());
266 return ReadableStreamOperations::createReadableStream(scriptState,
267 new UnderlyingSourceFromDataConsumerHandle(scriptState, handle.release() ),
268 ScriptValue(scriptState, v8::Undefined(scriptState->isolate())));
269 } 203 }
270 204
271 bool Body::bodyUsed() 205 bool Body::bodyUsed()
272 { 206 {
273 return bodyBuffer() && bodyBuffer()->isStreamDisturbed(); 207 return bodyBuffer() && bodyBuffer()->isStreamDisturbed();
274 } 208 }
275 209
276 bool Body::isBodyLocked() 210 bool Body::isBodyLocked()
277 { 211 {
278 return bodyBuffer() && bodyBuffer()->isStreamLocked(); 212 return bodyBuffer() && bodyBuffer()->isStreamLocked();
(...skipping 16 matching lines...) Expand all
295 } 229 }
296 230
297 ScriptPromise Body::rejectInvalidConsumption(ScriptState* scriptState) 231 ScriptPromise Body::rejectInvalidConsumption(ScriptState* scriptState)
298 { 232 {
299 if (isBodyLocked() || bodyUsed()) 233 if (isBodyLocked() || bodyUsed())
300 return ScriptPromise::reject(scriptState, V8ThrowException::createTypeEr ror(scriptState->isolate(), "Already read")); 234 return ScriptPromise::reject(scriptState, V8ThrowException::createTypeEr ror(scriptState->isolate(), "Already read"));
301 return ScriptPromise(); 235 return ScriptPromise();
302 } 236 }
303 237
304 } // namespace blink 238 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698