Chromium Code Reviews| 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 "web/SuspendableScriptExecutor.h" | 5 #include "web/SuspendableScriptExecutor.h" |
| 6 | 6 |
| 7 #include "bindings/core/v8/ScriptController.h" | 7 #include "bindings/core/v8/ScriptController.h" |
| 8 #include "bindings/core/v8/ScriptSourceCode.h" | 8 #include "bindings/core/v8/ScriptSourceCode.h" |
| 9 #include "bindings/core/v8/V8PersistentValueVector.h" | 9 #include "bindings/core/v8/V8PersistentValueVector.h" |
| 10 #include "bindings/core/v8/WindowProxy.h" | |
| 10 #include "core/dom/Document.h" | 11 #include "core/dom/Document.h" |
| 11 #include "core/dom/DocumentUserGestureToken.h" | 12 #include "core/dom/DocumentUserGestureToken.h" |
| 12 #include "core/frame/LocalFrame.h" | 13 #include "core/frame/LocalFrame.h" |
| 13 #include "platform/UserGestureIndicator.h" | 14 #include "platform/UserGestureIndicator.h" |
| 14 #include "public/platform/WebVector.h" | 15 #include "public/platform/WebVector.h" |
| 15 #include "public/web/WebScriptExecutionCallback.h" | 16 #include "public/web/WebScriptExecutionCallback.h" |
| 16 #include "wtf/PtrUtil.h" | 17 #include "wtf/PtrUtil.h" |
| 17 #include "wtf/Vector.h" | 18 #include "wtf/Vector.h" |
| 18 #include <memory> | 19 #include <memory> |
| 19 | 20 |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 70 m_sources.first()); | 71 m_sources.first()); |
| 71 results.append(scriptValue); | 72 results.append(scriptValue); |
| 72 } | 73 } |
| 73 | 74 |
| 74 return results; | 75 return results; |
| 75 } | 76 } |
| 76 | 77 |
| 77 class V8FunctionExecutor : public SuspendableScriptExecutor::Executor { | 78 class V8FunctionExecutor : public SuspendableScriptExecutor::Executor { |
| 78 public: | 79 public: |
| 79 V8FunctionExecutor(v8::Isolate*, | 80 V8FunctionExecutor(v8::Isolate*, |
| 80 ScriptState*, | |
| 81 v8::Local<v8::Function>, | 81 v8::Local<v8::Function>, |
| 82 v8::Local<v8::Value> receiver, | 82 v8::Local<v8::Value> receiver, |
| 83 int argc, | 83 int argc, |
| 84 v8::Local<v8::Value> argv[]); | 84 v8::Local<v8::Value> argv[]); |
| 85 | 85 |
| 86 Vector<v8::Local<v8::Value>> execute(LocalFrame*) override; | 86 Vector<v8::Local<v8::Value>> execute(LocalFrame*) override; |
| 87 | 87 |
| 88 private: | 88 private: |
| 89 ScopedPersistent<v8::Function> m_function; | 89 ScopedPersistent<v8::Function> m_function; |
| 90 ScopedPersistent<v8::Value> m_receiver; | 90 ScopedPersistent<v8::Value> m_receiver; |
| 91 V8PersistentValueVector<v8::Value> m_args; | 91 V8PersistentValueVector<v8::Value> m_args; |
| 92 RefPtr<ScriptState> m_scriptState; | 92 RefPtr<UserGestureToken> m_gestureToken; |
| 93 }; | 93 }; |
| 94 | 94 |
| 95 V8FunctionExecutor::V8FunctionExecutor(v8::Isolate* isolate, | 95 V8FunctionExecutor::V8FunctionExecutor(v8::Isolate* isolate, |
| 96 ScriptState* scriptState, | |
| 97 v8::Local<v8::Function> function, | 96 v8::Local<v8::Function> function, |
| 98 v8::Local<v8::Value> receiver, | 97 v8::Local<v8::Value> receiver, |
| 99 int argc, | 98 int argc, |
| 100 v8::Local<v8::Value> argv[]) | 99 v8::Local<v8::Value> argv[]) |
| 101 : m_function(isolate, function), | 100 : m_function(isolate, function), |
| 102 m_receiver(isolate, receiver), | 101 m_receiver(isolate, receiver), |
| 103 m_args(isolate), | 102 m_args(isolate), |
| 104 m_scriptState(scriptState) { | 103 m_gestureToken(UserGestureIndicator::currentToken()) { |
| 105 m_args.ReserveCapacity(argc); | 104 m_args.ReserveCapacity(argc); |
| 106 for (int i = 0; i < argc; ++i) | 105 for (int i = 0; i < argc; ++i) |
| 107 m_args.Append(argv[i]); | 106 m_args.Append(argv[i]); |
| 108 } | 107 } |
| 109 | 108 |
| 110 Vector<v8::Local<v8::Value>> V8FunctionExecutor::execute(LocalFrame* frame) { | 109 Vector<v8::Local<v8::Value>> V8FunctionExecutor::execute(LocalFrame* frame) { |
| 111 v8::Isolate* isolate = v8::Isolate::GetCurrent(); | 110 v8::Isolate* isolate = v8::Isolate::GetCurrent(); |
| 112 Vector<v8::Local<v8::Value>> results; | 111 Vector<v8::Local<v8::Value>> results; |
| 113 if (!m_scriptState->contextIsValid()) | |
| 114 return results; | |
| 115 ScriptState::Scope scope(m_scriptState.get()); | |
| 116 v8::Local<v8::Value> singleResult; | 112 v8::Local<v8::Value> singleResult; |
| 117 Vector<v8::Local<v8::Value>> args; | 113 Vector<v8::Local<v8::Value>> args; |
| 118 args.reserveCapacity(m_args.Size()); | 114 args.reserveCapacity(m_args.Size()); |
| 119 for (size_t i = 0; i < m_args.Size(); ++i) | 115 for (size_t i = 0; i < m_args.Size(); ++i) |
| 120 args.append(m_args.Get(i)); | 116 args.append(m_args.Get(i)); |
| 121 if (V8ScriptRunner::callFunction(m_function.newLocal(isolate), | 117 { |
| 122 frame->document(), | 118 std::unique_ptr<UserGestureIndicator> gestureIndicator; |
| 123 m_receiver.newLocal(isolate), args.size(), | 119 if (m_gestureToken) { |
| 124 args.data(), toIsolate(frame)) | 120 gestureIndicator = |
| 125 .ToLocal(&singleResult)) | 121 wrapUnique(new UserGestureIndicator(m_gestureToken.release())); |
| 126 results.append(singleResult); | 122 } |
| 123 if (V8ScriptRunner::callFunction(m_function.newLocal(isolate), | |
| 124 frame->document(), | |
| 125 m_receiver.newLocal(isolate), args.size(), | |
| 126 args.data(), toIsolate(frame)) | |
| 127 .ToLocal(&singleResult)) | |
| 128 results.append(singleResult); | |
| 129 } | |
| 127 return results; | 130 return results; |
| 128 } | 131 } |
| 129 | 132 |
| 130 } // namespace | 133 } // namespace |
| 131 | 134 |
| 132 void SuspendableScriptExecutor::createAndRun( | 135 void SuspendableScriptExecutor::createAndRun( |
| 133 LocalFrame* frame, | 136 LocalFrame* frame, |
| 134 int worldID, | 137 int worldID, |
| 135 const HeapVector<ScriptSourceCode>& sources, | 138 const HeapVector<ScriptSourceCode>& sources, |
| 136 int extensionGroup, | 139 int extensionGroup, |
| 137 bool userGesture, | 140 bool userGesture, |
| 138 WebScriptExecutionCallback* callback) { | 141 WebScriptExecutionCallback* callback) { |
| 142 ScriptState* scriptState = ScriptState::forWorld( | |
| 143 frame, *DOMWrapperWorld::fromWorldId(v8::Isolate::GetCurrent(), worldID, | |
|
haraken
2016/11/03 14:37:04
Use toIsolate(frame), or explicitly pass in v8::Is
Devlin
2016/11/04 05:40:32
Went with toIsolate(frame) for now, but added a TO
| |
| 144 extensionGroup)); | |
| 139 SuspendableScriptExecutor* executor = new SuspendableScriptExecutor( | 145 SuspendableScriptExecutor* executor = new SuspendableScriptExecutor( |
| 140 frame, callback, | 146 frame, scriptState, callback, |
| 141 new WebScriptExecutor(sources, worldID, extensionGroup, userGesture)); | 147 new WebScriptExecutor(sources, worldID, extensionGroup, userGesture)); |
| 142 executor->run(); | 148 executor->run(); |
| 143 } | 149 } |
| 144 | 150 |
| 145 void SuspendableScriptExecutor::createAndRun( | 151 void SuspendableScriptExecutor::createAndRun( |
| 146 LocalFrame* frame, | 152 LocalFrame* frame, |
| 147 v8::Isolate* isolate, | 153 v8::Isolate* isolate, |
| 148 v8::Local<v8::Context> context, | 154 v8::Local<v8::Context> context, |
| 149 v8::Local<v8::Function> function, | 155 v8::Local<v8::Function> function, |
| 150 v8::Local<v8::Value> receiver, | 156 v8::Local<v8::Value> receiver, |
| 151 int argc, | 157 int argc, |
| 152 v8::Local<v8::Value> argv[], | 158 v8::Local<v8::Value> argv[], |
| 153 WebScriptExecutionCallback* callback) { | 159 WebScriptExecutionCallback* callback) { |
| 154 ScriptState* scriptState = ScriptState::from(context); | 160 ScriptState* scriptState = ScriptState::from(context); |
| 155 if (!scriptState->contextIsValid()) { | 161 if (!scriptState->contextIsValid()) { |
| 156 if (callback) | 162 if (callback) |
| 157 callback->completed(Vector<v8::Local<v8::Value>>()); | 163 callback->completed(Vector<v8::Local<v8::Value>>()); |
| 158 return; | 164 return; |
| 159 } | 165 } |
| 160 SuspendableScriptExecutor* executor = new SuspendableScriptExecutor( | 166 SuspendableScriptExecutor* executor = new SuspendableScriptExecutor( |
| 161 frame, callback, new V8FunctionExecutor(isolate, scriptState, function, | 167 frame, scriptState, callback, |
| 162 receiver, argc, argv)); | 168 new V8FunctionExecutor(isolate, function, receiver, argc, argv)); |
| 163 executor->run(); | 169 executor->run(); |
| 164 } | 170 } |
| 165 | 171 |
| 166 void SuspendableScriptExecutor::contextDestroyed() { | 172 void SuspendableScriptExecutor::contextDestroyed() { |
| 167 SuspendableTimer::contextDestroyed(); | 173 SuspendableTimer::contextDestroyed(); |
| 168 if (m_callback) | 174 if (m_callback) |
| 169 m_callback->completed(Vector<v8::Local<v8::Value>>()); | 175 m_callback->completed(Vector<v8::Local<v8::Value>>()); |
| 170 dispose(); | 176 dispose(); |
| 171 } | 177 } |
| 172 | 178 |
| 173 SuspendableScriptExecutor::SuspendableScriptExecutor( | 179 SuspendableScriptExecutor::SuspendableScriptExecutor( |
| 174 LocalFrame* frame, | 180 LocalFrame* frame, |
| 181 ScriptState* scriptState, | |
| 175 WebScriptExecutionCallback* callback, | 182 WebScriptExecutionCallback* callback, |
| 176 Executor* executor) | 183 Executor* executor) |
| 177 : SuspendableTimer(frame->document()), | 184 : SuspendableTimer(frame->document()), |
| 178 m_frame(frame), | 185 m_frame(frame), |
| 186 m_scriptState(scriptState), | |
| 179 m_callback(callback), | 187 m_callback(callback), |
| 180 m_keepAlive(this), | 188 m_keepAlive(this), |
| 181 m_executor(executor) {} | 189 m_executor(executor) {} |
| 182 | 190 |
| 183 SuspendableScriptExecutor::~SuspendableScriptExecutor() {} | 191 SuspendableScriptExecutor::~SuspendableScriptExecutor() {} |
| 184 | 192 |
| 185 void SuspendableScriptExecutor::fired() { | 193 void SuspendableScriptExecutor::fired() { |
| 186 executeAndDestroySelf(); | 194 executeAndDestroySelf(); |
| 187 } | 195 } |
| 188 | 196 |
| 189 void SuspendableScriptExecutor::run() { | 197 void SuspendableScriptExecutor::run() { |
| 190 ExecutionContext* context = getExecutionContext(); | 198 ExecutionContext* context = getExecutionContext(); |
| 191 DCHECK(context); | 199 DCHECK(context); |
| 192 if (!context->activeDOMObjectsAreSuspended()) { | 200 if (!context->activeDOMObjectsAreSuspended()) { |
| 193 suspendIfNeeded(); | 201 suspendIfNeeded(); |
| 194 executeAndDestroySelf(); | 202 executeAndDestroySelf(); |
| 195 return; | 203 return; |
| 196 } | 204 } |
| 197 startOneShot(0, BLINK_FROM_HERE); | 205 startOneShot(0, BLINK_FROM_HERE); |
| 198 suspendIfNeeded(); | 206 suspendIfNeeded(); |
| 199 } | 207 } |
| 200 | 208 |
| 201 void SuspendableScriptExecutor::executeAndDestroySelf() { | 209 void SuspendableScriptExecutor::executeAndDestroySelf() { |
| 202 v8::HandleScope scope(v8::Isolate::GetCurrent()); | 210 CHECK(m_scriptState->contextIsValid()); |
| 211 | |
| 212 ScriptState::Scope scriptScope(m_scriptState.get()); | |
| 203 Vector<v8::Local<v8::Value>> results = m_executor->execute(m_frame); | 213 Vector<v8::Local<v8::Value>> results = m_executor->execute(m_frame); |
| 204 | 214 |
| 205 // The script may have removed the frame, in which case contextDestroyed() | 215 // The script may have removed the frame, in which case contextDestroyed() |
| 206 // will have handled the disposal/callback. | 216 // will have handled the disposal/callback. |
| 207 if (!m_frame->client()) | 217 if (!lifecycleContext()) |
|
haraken
2016/11/03 14:37:04
This will work but I'd prefer checking m_scriptSta
Devlin
2016/11/04 05:40:32
Done.
| |
| 208 return; | 218 return; |
| 209 | 219 |
| 220 // We need to call the callback before scriptScope goes out of scope. | |
|
haraken
2016/11/03 14:37:04
This comment doesn't make much sense now.
Devlin
2016/11/04 05:40:32
Whoops, done.
| |
| 210 if (m_callback) | 221 if (m_callback) |
| 211 m_callback->completed(results); | 222 m_callback->completed(results); |
| 223 | |
| 212 dispose(); | 224 dispose(); |
| 213 } | 225 } |
| 214 | 226 |
| 215 void SuspendableScriptExecutor::dispose() { | 227 void SuspendableScriptExecutor::dispose() { |
| 216 // Remove object as a ContextLifecycleObserver. | 228 // Remove object as a ContextLifecycleObserver. |
| 217 ActiveDOMObject::clearContext(); | 229 ActiveDOMObject::clearContext(); |
| 218 m_keepAlive.clear(); | 230 m_keepAlive.clear(); |
| 219 stop(); | 231 stop(); |
| 220 } | 232 } |
| 221 | 233 |
| 222 DEFINE_TRACE(SuspendableScriptExecutor) { | 234 DEFINE_TRACE(SuspendableScriptExecutor) { |
| 223 visitor->trace(m_frame); | 235 visitor->trace(m_frame); |
| 224 visitor->trace(m_executor); | 236 visitor->trace(m_executor); |
| 225 SuspendableTimer::trace(visitor); | 237 SuspendableTimer::trace(visitor); |
| 226 } | 238 } |
| 227 | 239 |
| 228 } // namespace blink | 240 } // namespace blink |
| OLD | NEW |