| 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 |