1 | /* |
2 | * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. |
3 | * Copyright (C) 2008 Matt Lilek <webkit@mattlilek.com> |
4 | * Copyright (C) 2010 Google Inc. All rights reserved. |
5 | * |
6 | * Redistribution and use in source and binary forms, with or without |
7 | * modification, are permitted provided that the following conditions |
8 | * are met: |
9 | * |
10 | * 1. Redistributions of source code must retain the above copyright |
11 | * notice, this list of conditions and the following disclaimer. |
12 | * 2. Redistributions in binary form must reproduce the above copyright |
13 | * notice, this list of conditions and the following disclaimer in the |
14 | * documentation and/or other materials provided with the distribution. |
15 | * 3. Neither the name of Apple Inc. ("Apple") nor the names of |
16 | * its contributors may be used to endorse or promote products derived |
17 | * from this software without specific prior written permission. |
18 | * |
19 | * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY |
20 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
21 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
22 | * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY |
23 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
24 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
25 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
26 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
27 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
28 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
29 | */ |
30 | |
31 | #include "config.h" |
32 | #include "CommandLineAPIHost.h" |
33 | |
34 | #include "Database.h" |
35 | #include "Document.h" |
36 | #include "EventTarget.h" |
37 | #include "InspectorDOMStorageAgent.h" |
38 | #include "InspectorDatabaseAgent.h" |
39 | #include "JSCommandLineAPIHost.h" |
40 | #include "JSDOMGlobalObject.h" |
41 | #include "JSEventListener.h" |
42 | #include "Pasteboard.h" |
43 | #include "Storage.h" |
44 | #include "WebConsoleAgent.h" |
45 | #include <JavaScriptCore/InspectorAgent.h> |
46 | #include <JavaScriptCore/JSCInlines.h> |
47 | #include <JavaScriptCore/JSLock.h> |
48 | #include <JavaScriptCore/ScriptValue.h> |
49 | #include <wtf/JSONValues.h> |
50 | #include <wtf/RefPtr.h> |
51 | #include <wtf/StdLibExtras.h> |
52 | |
53 | namespace WebCore { |
54 | |
55 | using namespace JSC; |
56 | using namespace Inspector; |
57 | |
58 | Ref<CommandLineAPIHost> CommandLineAPIHost::create() |
59 | { |
60 | return adoptRef(*new CommandLineAPIHost); |
61 | } |
62 | |
63 | CommandLineAPIHost::CommandLineAPIHost() |
64 | : m_inspectedObject(std::make_unique<InspectableObject>()) |
65 | { |
66 | } |
67 | |
68 | CommandLineAPIHost::~CommandLineAPIHost() = default; |
69 | |
70 | void CommandLineAPIHost::disconnect() |
71 | { |
72 | |
73 | m_instrumentingAgents = nullptr; |
74 | } |
75 | |
76 | void CommandLineAPIHost::inspect(JSC::ExecState& state, JSC::JSValue valueToInspect, JSC::JSValue hintsValue) |
77 | { |
78 | if (!m_instrumentingAgents) |
79 | return; |
80 | |
81 | auto* inspectorAgent = m_instrumentingAgents->inspectorAgent(); |
82 | if (!inspectorAgent) |
83 | return; |
84 | |
85 | RefPtr<JSON::Object> hintsObject; |
86 | if (!Inspector::toInspectorValue(state, hintsValue)->asObject(hintsObject)) |
87 | return; |
88 | |
89 | auto remoteObject = BindingTraits<Inspector::Protocol::Runtime::RemoteObject>::runtimeCast(Inspector::toInspectorValue(state, valueToInspect)); |
90 | inspectorAgent->inspect(WTFMove(remoteObject), WTFMove(hintsObject)); |
91 | } |
92 | |
93 | CommandLineAPIHost::EventListenersRecord CommandLineAPIHost::getEventListeners(ExecState& state, EventTarget& target) |
94 | { |
95 | auto* scriptExecutionContext = target.scriptExecutionContext(); |
96 | if (!scriptExecutionContext) |
97 | return { }; |
98 | |
99 | EventListenersRecord result; |
100 | |
101 | VM& vm = state.vm(); |
102 | |
103 | for (auto& eventType : target.eventTypes()) { |
104 | Vector<CommandLineAPIHost::ListenerEntry> entries; |
105 | |
106 | for (auto& eventListener : target.eventListeners(eventType)) { |
107 | if (!is<JSEventListener>(eventListener->callback())) |
108 | continue; |
109 | |
110 | auto& jsListener = downcast<JSEventListener>(eventListener->callback()); |
111 | |
112 | // Hide listeners from other contexts. |
113 | if (&jsListener.isolatedWorld() != ¤tWorld(state)) |
114 | continue; |
115 | |
116 | auto* function = jsListener.jsFunction(*scriptExecutionContext); |
117 | if (!function) |
118 | continue; |
119 | |
120 | entries.append({ Strong<JSObject>(vm, function), eventListener->useCapture(), eventListener->isPassive(), eventListener->isOnce() }); |
121 | } |
122 | |
123 | if (!entries.isEmpty()) |
124 | result.append({ eventType, WTFMove(entries) }); |
125 | } |
126 | |
127 | return result; |
128 | } |
129 | |
130 | void CommandLineAPIHost::clearConsoleMessages() |
131 | { |
132 | if (!m_instrumentingAgents) |
133 | return; |
134 | |
135 | auto* consoleAgent = m_instrumentingAgents->webConsoleAgent(); |
136 | if (!consoleAgent) |
137 | return; |
138 | |
139 | ErrorString unused; |
140 | consoleAgent->clearMessages(unused); |
141 | } |
142 | |
143 | void CommandLineAPIHost::copyText(const String& text) |
144 | { |
145 | Pasteboard::createForCopyAndPaste()->writePlainText(text, Pasteboard::CannotSmartReplace); |
146 | } |
147 | |
148 | JSC::JSValue CommandLineAPIHost::InspectableObject::get(JSC::ExecState&) |
149 | { |
150 | return { }; |
151 | } |
152 | |
153 | void CommandLineAPIHost::addInspectedObject(std::unique_ptr<CommandLineAPIHost::InspectableObject> object) |
154 | { |
155 | m_inspectedObject = WTFMove(object); |
156 | } |
157 | |
158 | JSC::JSValue CommandLineAPIHost::inspectedObject(JSC::ExecState& state) |
159 | { |
160 | if (!m_inspectedObject) |
161 | return jsUndefined(); |
162 | |
163 | JSC::JSLockHolder lock(&state); |
164 | auto scriptValue = m_inspectedObject->get(state); |
165 | return scriptValue ? scriptValue : jsUndefined(); |
166 | } |
167 | |
168 | String CommandLineAPIHost::databaseId(Database& database) |
169 | { |
170 | if (m_instrumentingAgents) { |
171 | if (auto* databaseAgent = m_instrumentingAgents->inspectorDatabaseAgent()) |
172 | return databaseAgent->databaseId(database); |
173 | } |
174 | return { }; |
175 | } |
176 | |
177 | String CommandLineAPIHost::storageId(Storage& storage) |
178 | { |
179 | return InspectorDOMStorageAgent::storageId(storage); |
180 | } |
181 | |
182 | JSValue CommandLineAPIHost::wrapper(ExecState* exec, JSDOMGlobalObject* globalObject) |
183 | { |
184 | JSValue value = m_wrappers.getWrapper(globalObject); |
185 | if (value) |
186 | return value; |
187 | |
188 | JSObject* prototype = JSCommandLineAPIHost::createPrototype(exec->vm(), *globalObject); |
189 | Structure* structure = JSCommandLineAPIHost::createStructure(exec->vm(), globalObject, prototype); |
190 | JSCommandLineAPIHost* commandLineAPIHost = JSCommandLineAPIHost::create(structure, globalObject, makeRef(*this)); |
191 | m_wrappers.addWrapper(globalObject, commandLineAPIHost); |
192 | |
193 | return commandLineAPIHost; |
194 | } |
195 | |
196 | void CommandLineAPIHost::clearAllWrappers() |
197 | { |
198 | m_wrappers.clearAllWrappers(); |
199 | m_inspectedObject = std::make_unique<InspectableObject>(); |
200 | } |
201 | |
202 | } // namespace WebCore |
203 | |