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

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

Powered by Google App Engine
This is Rietveld 408576698