1 | /* |
2 | * Copyright (C) 2000 Harri Porten (porten@kde.org) |
3 | * Copyright (C) 2006 Jon Shier (jshier@iastate.edu) |
4 | * Copyright (C) 2003-2017 Apple Inc. All rights reseved. |
5 | * Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org) |
6 | * Copyright (C) 2009 Google Inc. All rights reseved. |
7 | * |
8 | * This library is free software; you can redistribute it and/or |
9 | * modify it under the terms of the GNU Lesser General Public |
10 | * License as published by the Free Software Foundation; either |
11 | * version 2 of the License, or (at your option) any later version. |
12 | * |
13 | * This library is distributed in the hope that it will be useful, |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
16 | * Lesser General Public License for more details. |
17 | * |
18 | * You should have received a copy of the GNU Lesser General Public |
19 | * License along with this library; if not, write to the Free Software |
20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 |
21 | * USA |
22 | */ |
23 | |
24 | #include "config.h" |
25 | #include "ScheduledAction.h" |
26 | |
27 | #include "ContentSecurityPolicy.h" |
28 | #include "DOMWindow.h" |
29 | #include "DOMWrapperWorld.h" |
30 | #include "Document.h" |
31 | #include "Frame.h" |
32 | #include "FrameLoader.h" |
33 | #include "JSDOMExceptionHandling.h" |
34 | #include "JSDOMWindow.h" |
35 | #include "JSExecState.h" |
36 | #include "JSExecStateInstrumentation.h" |
37 | #include "JSWorkerGlobalScope.h" |
38 | #include "ScriptController.h" |
39 | #include "ScriptExecutionContext.h" |
40 | #include "ScriptSourceCode.h" |
41 | #include "WorkerGlobalScope.h" |
42 | #include "WorkerThread.h" |
43 | #include <JavaScriptCore/JSLock.h> |
44 | |
45 | namespace WebCore { |
46 | using namespace JSC; |
47 | |
48 | std::unique_ptr<ScheduledAction> ScheduledAction::create(DOMWrapperWorld& isolatedWorld, JSC::Strong<JSC::Unknown>&& function) |
49 | { |
50 | return std::unique_ptr<ScheduledAction>(new ScheduledAction(isolatedWorld, WTFMove(function))); |
51 | } |
52 | |
53 | std::unique_ptr<ScheduledAction> ScheduledAction::create(DOMWrapperWorld& isolatedWorld, String&& code) |
54 | { |
55 | return std::unique_ptr<ScheduledAction>(new ScheduledAction(isolatedWorld, WTFMove(code))); |
56 | } |
57 | |
58 | ScheduledAction::ScheduledAction(DOMWrapperWorld& isolatedWorld, JSC::Strong<JSC::Unknown>&& function) |
59 | : m_isolatedWorld(isolatedWorld) |
60 | , m_function(WTFMove(function)) |
61 | { |
62 | } |
63 | |
64 | ScheduledAction::ScheduledAction(DOMWrapperWorld& isolatedWorld, String&& code) |
65 | : m_isolatedWorld(isolatedWorld) |
66 | , m_function(isolatedWorld.vm()) |
67 | , m_code(WTFMove(code)) |
68 | { |
69 | } |
70 | |
71 | ScheduledAction::~ScheduledAction() = default; |
72 | |
73 | void ScheduledAction::addArguments(Vector<JSC::Strong<JSC::Unknown>>&& arguments) |
74 | { |
75 | m_arguments = WTFMove(arguments); |
76 | } |
77 | |
78 | auto ScheduledAction::type() const -> Type |
79 | { |
80 | return m_function ? Type::Function : Type::Code; |
81 | } |
82 | |
83 | void ScheduledAction::execute(ScriptExecutionContext& context) |
84 | { |
85 | if (is<Document>(context)) |
86 | execute(downcast<Document>(context)); |
87 | else |
88 | execute(downcast<WorkerGlobalScope>(context)); |
89 | } |
90 | |
91 | void ScheduledAction::executeFunctionInContext(JSGlobalObject* globalObject, JSValue thisValue, ScriptExecutionContext& context) |
92 | { |
93 | ASSERT(m_function); |
94 | VM& vm = context.vm(); |
95 | JSLockHolder lock(vm); |
96 | auto scope = DECLARE_THROW_SCOPE(vm); |
97 | |
98 | CallData callData; |
99 | CallType callType = getCallData(vm, m_function.get(), callData); |
100 | if (callType == CallType::None) |
101 | return; |
102 | |
103 | ExecState* exec = globalObject->globalExec(); |
104 | |
105 | MarkedArgumentBuffer arguments; |
106 | for (auto& argument : m_arguments) |
107 | arguments.append(argument.get()); |
108 | if (UNLIKELY(arguments.hasOverflowed())) { |
109 | throwOutOfMemoryError(exec, scope); |
110 | NakedPtr<JSC::Exception> exception = scope.exception(); |
111 | reportException(exec, exception); |
112 | return; |
113 | } |
114 | |
115 | InspectorInstrumentationCookie cookie = JSExecState::instrumentFunctionCall(&context, callType, callData); |
116 | |
117 | NakedPtr<JSC::Exception> exception; |
118 | JSExecState::profiledCall(exec, JSC::ProfilingReason::Other, m_function.get(), callType, callData, thisValue, arguments, exception); |
119 | |
120 | InspectorInstrumentation::didCallFunction(cookie, &context); |
121 | |
122 | if (exception) |
123 | reportException(exec, exception); |
124 | } |
125 | |
126 | void ScheduledAction::execute(Document& document) |
127 | { |
128 | JSDOMWindow* window = toJSDOMWindow(document.frame(), m_isolatedWorld); |
129 | if (!window) |
130 | return; |
131 | |
132 | RefPtr<Frame> frame = window->wrapped().frame(); |
133 | if (!frame || !frame->script().canExecuteScripts(AboutToExecuteScript)) |
134 | return; |
135 | |
136 | if (m_function) |
137 | executeFunctionInContext(window, window->proxy(), document); |
138 | else |
139 | frame->script().executeScriptInWorld(m_isolatedWorld, m_code); |
140 | } |
141 | |
142 | void ScheduledAction::execute(WorkerGlobalScope& workerGlobalScope) |
143 | { |
144 | // In a Worker, the execution should always happen on a worker thread. |
145 | ASSERT(workerGlobalScope.thread().thread() == &Thread::current()); |
146 | |
147 | WorkerScriptController* scriptController = workerGlobalScope.script(); |
148 | |
149 | if (m_function) { |
150 | JSWorkerGlobalScope* contextWrapper = scriptController->workerGlobalScopeWrapper(); |
151 | executeFunctionInContext(contextWrapper, contextWrapper, workerGlobalScope); |
152 | } else { |
153 | ScriptSourceCode code(m_code, URL(workerGlobalScope.url())); |
154 | scriptController->evaluate(code); |
155 | } |
156 | } |
157 | |
158 | } // namespace WebCore |
159 | |