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
53namespace WebCore {
54
55using namespace JSC;
56using namespace Inspector;
57
58Ref<CommandLineAPIHost> CommandLineAPIHost::create()
59{
60 return adoptRef(*new CommandLineAPIHost);
61}
62
63CommandLineAPIHost::CommandLineAPIHost()
64 : m_inspectedObject(std::make_unique<InspectableObject>())
65{
66}
67
68CommandLineAPIHost::~CommandLineAPIHost() = default;
69
70void CommandLineAPIHost::disconnect()
71{
72
73 m_instrumentingAgents = nullptr;
74}
75
76void 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
93CommandLineAPIHost::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() != &currentWorld(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
130void 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
143void CommandLineAPIHost::copyText(const String& text)
144{
145 Pasteboard::createForCopyAndPaste()->writePlainText(text, Pasteboard::CannotSmartReplace);
146}
147
148JSC::JSValue CommandLineAPIHost::InspectableObject::get(JSC::ExecState&)
149{
150 return { };
151}
152
153void CommandLineAPIHost::addInspectedObject(std::unique_ptr<CommandLineAPIHost::InspectableObject> object)
154{
155 m_inspectedObject = WTFMove(object);
156}
157
158JSC::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
168String 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
177String CommandLineAPIHost::storageId(Storage& storage)
178{
179 return InspectorDOMStorageAgent::storageId(storage);
180}
181
182JSValue 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
196void CommandLineAPIHost::clearAllWrappers()
197{
198 m_wrappers.clearAllWrappers();
199 m_inspectedObject = std::make_unique<InspectableObject>();
200}
201
202} // namespace WebCore
203