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/Body.h" | 5 #include "modules/fetch/Body.h" |
6 | 6 |
7 #include "bindings/core/v8/ExceptionState.h" | 7 #include "bindings/core/v8/ExceptionState.h" |
8 #include "bindings/core/v8/ScriptPromiseResolver.h" | 8 #include "bindings/core/v8/ScriptPromiseResolver.h" |
9 #include "bindings/core/v8/ScriptState.h" | 9 #include "bindings/core/v8/ScriptState.h" |
10 #include "bindings/core/v8/V8ArrayBuffer.h" | 10 #include "bindings/core/v8/V8ArrayBuffer.h" |
(...skipping 13 matching lines...) Expand all Loading... |
24 namespace { | 24 namespace { |
25 | 25 |
26 class BodyConsumerBase : public GarbageCollectedFinalized<BodyConsumerBase>, pub
lic FetchDataLoader::Client { | 26 class BodyConsumerBase : public GarbageCollectedFinalized<BodyConsumerBase>, pub
lic FetchDataLoader::Client { |
27 WTF_MAKE_NONCOPYABLE(BodyConsumerBase); | 27 WTF_MAKE_NONCOPYABLE(BodyConsumerBase); |
28 USING_GARBAGE_COLLECTED_MIXIN(BodyConsumerBase); | 28 USING_GARBAGE_COLLECTED_MIXIN(BodyConsumerBase); |
29 public: | 29 public: |
30 explicit BodyConsumerBase(ScriptPromiseResolver* resolver) : m_resolver(reso
lver) {} | 30 explicit BodyConsumerBase(ScriptPromiseResolver* resolver) : m_resolver(reso
lver) {} |
31 ScriptPromiseResolver* resolver() { return m_resolver; } | 31 ScriptPromiseResolver* resolver() { return m_resolver; } |
32 void didFetchDataLoadFailed() override | 32 void didFetchDataLoadFailed() override |
33 { | 33 { |
34 ScriptState::Scope scope(resolver()->scriptState()); | 34 ScriptState::Scope scope(resolver()->getScriptState()); |
35 m_resolver->reject(V8ThrowException::createTypeError(resolver()->scriptS
tate()->isolate(), "Failed to fetch")); | 35 m_resolver->reject(V8ThrowException::createTypeError(resolver()->getScri
ptState()->isolate(), "Failed to fetch")); |
36 } | 36 } |
37 | 37 |
38 DEFINE_INLINE_TRACE() | 38 DEFINE_INLINE_TRACE() |
39 { | 39 { |
40 visitor->trace(m_resolver); | 40 visitor->trace(m_resolver); |
41 FetchDataLoader::Client::trace(visitor); | 41 FetchDataLoader::Client::trace(visitor); |
42 } | 42 } |
43 | 43 |
44 private: | 44 private: |
45 Member<ScriptPromiseResolver> m_resolver; | 45 Member<ScriptPromiseResolver> m_resolver; |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
78 } | 78 } |
79 }; | 79 }; |
80 | 80 |
81 class BodyJsonConsumer final : public BodyConsumerBase { | 81 class BodyJsonConsumer final : public BodyConsumerBase { |
82 WTF_MAKE_NONCOPYABLE(BodyJsonConsumer); | 82 WTF_MAKE_NONCOPYABLE(BodyJsonConsumer); |
83 public: | 83 public: |
84 explicit BodyJsonConsumer(ScriptPromiseResolver* resolver) : BodyConsumerBas
e(resolver) {} | 84 explicit BodyJsonConsumer(ScriptPromiseResolver* resolver) : BodyConsumerBas
e(resolver) {} |
85 | 85 |
86 void didFetchDataLoadedString(const String& string) override | 86 void didFetchDataLoadedString(const String& string) override |
87 { | 87 { |
88 if (!resolver()->executionContext() || resolver()->executionContext()->a
ctiveDOMObjectsAreStopped()) | 88 if (!resolver()->getExecutionContext() || resolver()->getExecutionContex
t()->activeDOMObjectsAreStopped()) |
89 return; | 89 return; |
90 ScriptState::Scope scope(resolver()->scriptState()); | 90 ScriptState::Scope scope(resolver()->getScriptState()); |
91 v8::Isolate* isolate = resolver()->scriptState()->isolate(); | 91 v8::Isolate* isolate = resolver()->getScriptState()->isolate(); |
92 v8::Local<v8::String> inputString = v8String(isolate, string); | 92 v8::Local<v8::String> inputString = v8String(isolate, string); |
93 v8::TryCatch trycatch(isolate); | 93 v8::TryCatch trycatch(isolate); |
94 v8::Local<v8::Value> parsed; | 94 v8::Local<v8::Value> parsed; |
95 if (v8Call(v8::JSON::Parse(isolate, inputString), parsed, trycatch)) | 95 if (v8Call(v8::JSON::Parse(isolate, inputString), parsed, trycatch)) |
96 resolver()->resolve(parsed); | 96 resolver()->resolve(parsed); |
97 else | 97 else |
98 resolver()->reject(trycatch.Exception()); | 98 resolver()->reject(trycatch.Exception()); |
99 } | 99 } |
100 }; | 100 }; |
101 | 101 |
102 } // namespace | 102 } // namespace |
103 | 103 |
104 ScriptPromise Body::arrayBuffer(ScriptState* scriptState) | 104 ScriptPromise Body::arrayBuffer(ScriptState* scriptState) |
105 { | 105 { |
106 ScriptPromise promise = rejectInvalidConsumption(scriptState); | 106 ScriptPromise promise = rejectInvalidConsumption(scriptState); |
107 if (!promise.isEmpty()) | 107 if (!promise.isEmpty()) |
108 return promise; | 108 return promise; |
109 | 109 |
110 // 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 |
111 // 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 |
112 // 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 |
113 // first check the ExecutionContext and return immediately if it's already | 113 // first check the ExecutionContext and return immediately if it's already |
114 // gone (which means that the V8::TerminateExecution() signal has been sent | 114 // gone (which means that the V8::TerminateExecution() signal has been sent |
115 // to this worker thread). | 115 // to this worker thread). |
116 if (!scriptState->executionContext()) | 116 if (!scriptState->getExecutionContext()) |
117 return ScriptPromise(); | 117 return ScriptPromise(); |
118 | 118 |
119 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState)
; | 119 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState)
; |
120 promise = resolver->promise(); | 120 promise = resolver->promise(); |
121 if (bodyBuffer()) { | 121 if (bodyBuffer()) { |
122 bodyBuffer()->startLoading(scriptState->executionContext(), FetchDataLoa
der::createLoaderAsArrayBuffer(), new BodyArrayBufferConsumer(resolver)); | 122 bodyBuffer()->startLoading(scriptState->getExecutionContext(), FetchData
Loader::createLoaderAsArrayBuffer(), new BodyArrayBufferConsumer(resolver)); |
123 } else { | 123 } else { |
124 resolver->resolve(DOMArrayBuffer::create(0u, 1)); | 124 resolver->resolve(DOMArrayBuffer::create(0u, 1)); |
125 } | 125 } |
126 return promise; | 126 return promise; |
127 } | 127 } |
128 | 128 |
129 ScriptPromise Body::blob(ScriptState* scriptState) | 129 ScriptPromise Body::blob(ScriptState* scriptState) |
130 { | 130 { |
131 ScriptPromise promise = rejectInvalidConsumption(scriptState); | 131 ScriptPromise promise = rejectInvalidConsumption(scriptState); |
132 if (!promise.isEmpty()) | 132 if (!promise.isEmpty()) |
133 return promise; | 133 return promise; |
134 | 134 |
135 // See above comment. | 135 // See above comment. |
136 if (!scriptState->executionContext()) | 136 if (!scriptState->getExecutionContext()) |
137 return ScriptPromise(); | 137 return ScriptPromise(); |
138 | 138 |
139 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState)
; | 139 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState)
; |
140 promise = resolver->promise(); | 140 promise = resolver->promise(); |
141 if (bodyBuffer()) { | 141 if (bodyBuffer()) { |
142 bodyBuffer()->startLoading(scriptState->executionContext(), FetchDataLoa
der::createLoaderAsBlobHandle(mimeType()), new BodyBlobConsumer(resolver)); | 142 bodyBuffer()->startLoading(scriptState->getExecutionContext(), FetchData
Loader::createLoaderAsBlobHandle(mimeType()), new BodyBlobConsumer(resolver)); |
143 } else { | 143 } else { |
144 OwnPtr<BlobData> blobData = BlobData::create(); | 144 OwnPtr<BlobData> blobData = BlobData::create(); |
145 blobData->setContentType(mimeType()); | 145 blobData->setContentType(mimeType()); |
146 resolver->resolve(Blob::create(BlobDataHandle::create(blobData.release()
, 0))); | 146 resolver->resolve(Blob::create(BlobDataHandle::create(blobData.release()
, 0))); |
147 } | 147 } |
148 return promise; | 148 return promise; |
149 | 149 |
150 } | 150 } |
151 | 151 |
152 ScriptPromise Body::json(ScriptState* scriptState) | 152 ScriptPromise Body::json(ScriptState* scriptState) |
153 { | 153 { |
154 ScriptPromise promise = rejectInvalidConsumption(scriptState); | 154 ScriptPromise promise = rejectInvalidConsumption(scriptState); |
155 if (!promise.isEmpty()) | 155 if (!promise.isEmpty()) |
156 return promise; | 156 return promise; |
157 | 157 |
158 // See above comment. | 158 // See above comment. |
159 if (!scriptState->executionContext()) | 159 if (!scriptState->getExecutionContext()) |
160 return ScriptPromise(); | 160 return ScriptPromise(); |
161 | 161 |
162 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState)
; | 162 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState)
; |
163 promise = resolver->promise(); | 163 promise = resolver->promise(); |
164 if (bodyBuffer()) { | 164 if (bodyBuffer()) { |
165 bodyBuffer()->startLoading(scriptState->executionContext(), FetchDataLoa
der::createLoaderAsString(), new BodyJsonConsumer(resolver)); | 165 bodyBuffer()->startLoading(scriptState->getExecutionContext(), FetchData
Loader::createLoaderAsString(), new BodyJsonConsumer(resolver)); |
166 } else { | 166 } else { |
167 resolver->reject(V8ThrowException::createSyntaxError(scriptState->isolat
e(), "Unexpected end of input")); | 167 resolver->reject(V8ThrowException::createSyntaxError(scriptState->isolat
e(), "Unexpected end of input")); |
168 } | 168 } |
169 return promise; | 169 return promise; |
170 } | 170 } |
171 | 171 |
172 ScriptPromise Body::text(ScriptState* scriptState) | 172 ScriptPromise Body::text(ScriptState* scriptState) |
173 { | 173 { |
174 ScriptPromise promise = rejectInvalidConsumption(scriptState); | 174 ScriptPromise promise = rejectInvalidConsumption(scriptState); |
175 if (!promise.isEmpty()) | 175 if (!promise.isEmpty()) |
176 return promise; | 176 return promise; |
177 | 177 |
178 // See above comment. | 178 // See above comment. |
179 if (!scriptState->executionContext()) | 179 if (!scriptState->getExecutionContext()) |
180 return ScriptPromise(); | 180 return ScriptPromise(); |
181 | 181 |
182 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState)
; | 182 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState)
; |
183 promise = resolver->promise(); | 183 promise = resolver->promise(); |
184 if (bodyBuffer()) { | 184 if (bodyBuffer()) { |
185 bodyBuffer()->startLoading(scriptState->executionContext(), FetchDataLoa
der::createLoaderAsString(), new BodyTextConsumer(resolver)); | 185 bodyBuffer()->startLoading(scriptState->getExecutionContext(), FetchData
Loader::createLoaderAsString(), new BodyTextConsumer(resolver)); |
186 } else { | 186 } else { |
187 resolver->resolve(String()); | 187 resolver->resolve(String()); |
188 } | 188 } |
189 return promise; | 189 return promise; |
190 } | 190 } |
191 | 191 |
192 ReadableByteStream* Body::body() | 192 ReadableByteStream* Body::body() |
193 { | 193 { |
194 return bodyBuffer() ? bodyBuffer()->stream() : nullptr; | 194 return bodyBuffer() ? bodyBuffer()->stream() : nullptr; |
195 } | 195 } |
196 | 196 |
197 ReadableByteStream* Body::bodyWithUseCounter() | 197 ReadableByteStream* Body::bodyWithUseCounter() |
198 { | 198 { |
199 UseCounter::count(executionContext(), UseCounter::FetchBodyStream); | 199 UseCounter::count(getExecutionContext(), UseCounter::FetchBodyStream); |
200 return body(); | 200 return body(); |
201 } | 201 } |
202 | 202 |
203 bool Body::bodyUsed() | 203 bool Body::bodyUsed() |
204 { | 204 { |
205 return body() && body()->isDisturbed(); | 205 return body() && body()->isDisturbed(); |
206 } | 206 } |
207 | 207 |
208 bool Body::isBodyLocked() | 208 bool Body::isBodyLocked() |
209 { | 209 { |
210 return body() && body()->isLocked(); | 210 return body() && body()->isLocked(); |
211 } | 211 } |
212 | 212 |
213 bool Body::hasPendingActivity() const | 213 bool Body::hasPendingActivity() const |
214 { | 214 { |
215 if (executionContext()->activeDOMObjectsAreStopped()) | 215 if (getExecutionContext()->activeDOMObjectsAreStopped()) |
216 return false; | 216 return false; |
217 if (!bodyBuffer()) | 217 if (!bodyBuffer()) |
218 return false; | 218 return false; |
219 return bodyBuffer()->hasPendingActivity(); | 219 return bodyBuffer()->hasPendingActivity(); |
220 } | 220 } |
221 | 221 |
222 Body::Body(ExecutionContext* context) : ActiveDOMObject(context), m_opaque(false
) | 222 Body::Body(ExecutionContext* context) : ActiveDOMObject(context), m_opaque(false
) |
223 { | 223 { |
224 suspendIfNeeded(); | 224 suspendIfNeeded(); |
225 } | 225 } |
226 | 226 |
227 ScriptPromise Body::rejectInvalidConsumption(ScriptState* scriptState) | 227 ScriptPromise Body::rejectInvalidConsumption(ScriptState* scriptState) |
228 { | 228 { |
229 if (m_opaque) | 229 if (m_opaque) |
230 return ScriptPromise::reject(scriptState, V8ThrowException::createTypeEr
ror(scriptState->isolate(), "The body is opaque.")); | 230 return ScriptPromise::reject(scriptState, V8ThrowException::createTypeEr
ror(scriptState->isolate(), "The body is opaque.")); |
231 if (isBodyLocked() || bodyUsed()) | 231 if (isBodyLocked() || bodyUsed()) |
232 return ScriptPromise::reject(scriptState, V8ThrowException::createTypeEr
ror(scriptState->isolate(), "Already read")); | 232 return ScriptPromise::reject(scriptState, V8ThrowException::createTypeEr
ror(scriptState->isolate(), "Already read")); |
233 return ScriptPromise(); | 233 return ScriptPromise(); |
234 } | 234 } |
235 | 235 |
236 } // namespace blink | 236 } // namespace blink |
OLD | NEW |