]> git.saurik.com Git - apple/javascriptcore.git/blame - inspector/JSGlobalObjectInspectorController.cpp
JavaScriptCore-7601.1.46.3.tar.gz
[apple/javascriptcore.git] / inspector / JSGlobalObjectInspectorController.cpp
CommitLineData
81345200
A
1/*
2 * Copyright (C) 2014 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "config.h"
27#include "JSGlobalObjectInspectorController.h"
28
81345200 29#include "Completion.h"
ed1e77d3 30#include "ConsoleMessage.h"
81345200 31#include "ErrorHandlingScope.h"
ed1e77d3 32#include "Exception.h"
81345200
A
33#include "InjectedScriptHost.h"
34#include "InjectedScriptManager.h"
35#include "InspectorAgent.h"
36#include "InspectorBackendDispatcher.h"
37#include "InspectorFrontendChannel.h"
81345200
A
38#include "JSGlobalObject.h"
39#include "JSGlobalObjectConsoleAgent.h"
ed1e77d3 40#include "JSGlobalObjectConsoleClient.h"
81345200 41#include "JSGlobalObjectDebuggerAgent.h"
81345200
A
42#include "JSGlobalObjectRuntimeAgent.h"
43#include "ScriptArguments.h"
44#include "ScriptCallStack.h"
45#include "ScriptCallStackFactory.h"
ed1e77d3
A
46#include <wtf/Stopwatch.h>
47
81345200 48#include <cxxabi.h>
ed1e77d3 49#if OS(DARWIN) || (OS(LINUX) && !PLATFORM(GTK))
81345200
A
50#include <dlfcn.h>
51#include <execinfo.h>
ed1e77d3 52#endif
81345200 53
40a37d08
A
54#if ENABLE(REMOTE_INSPECTOR)
55#include "JSGlobalObjectDebuggable.h"
56#include "RemoteInspector.h"
57#endif
58
81345200
A
59using namespace JSC;
60
61namespace Inspector {
62
63JSGlobalObjectInspectorController::JSGlobalObjectInspectorController(JSGlobalObject& globalObject)
64 : m_globalObject(globalObject)
65 , m_injectedScriptManager(std::make_unique<InjectedScriptManager>(*this, InjectedScriptHost::create()))
ed1e77d3
A
66 , m_frontendChannel(nullptr)
67 , m_executionStopwatch(Stopwatch::create())
81345200 68 , m_includeNativeCallStackWithExceptions(true)
ed1e77d3
A
69 , m_isAutomaticInspection(false)
70#if ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS)
71 , m_augmentingClient(nullptr)
72#endif
81345200 73{
ed1e77d3 74 auto inspectorAgent = std::make_unique<InspectorAgent>(*this);
81345200
A
75 auto runtimeAgent = std::make_unique<JSGlobalObjectRuntimeAgent>(m_injectedScriptManager.get(), m_globalObject);
76 auto consoleAgent = std::make_unique<JSGlobalObjectConsoleAgent>(m_injectedScriptManager.get());
77 auto debuggerAgent = std::make_unique<JSGlobalObjectDebuggerAgent>(m_injectedScriptManager.get(), m_globalObject, consoleAgent.get());
81345200 78
ed1e77d3
A
79 m_inspectorAgent = inspectorAgent.get();
80 m_debuggerAgent = debuggerAgent.get();
81345200 81 m_consoleAgent = consoleAgent.get();
ed1e77d3 82 m_consoleClient = std::make_unique<JSGlobalObjectConsoleClient>(m_consoleAgent);
81345200
A
83
84 runtimeAgent->setScriptDebugServer(&debuggerAgent->scriptDebugServer());
81345200 85
ed1e77d3 86 m_agents.append(WTF::move(inspectorAgent));
81345200
A
87 m_agents.append(WTF::move(runtimeAgent));
88 m_agents.append(WTF::move(consoleAgent));
89 m_agents.append(WTF::move(debuggerAgent));
ed1e77d3
A
90
91 m_executionStopwatch->start();
81345200
A
92}
93
94JSGlobalObjectInspectorController::~JSGlobalObjectInspectorController()
95{
96 m_agents.discardAgents();
97}
98
99void JSGlobalObjectInspectorController::globalObjectDestroyed()
100{
ed1e77d3 101 disconnectFrontend(DisconnectReason::InspectedTargetDestroyed);
81345200
A
102
103 m_injectedScriptManager->disconnect();
104}
105
ed1e77d3 106void JSGlobalObjectInspectorController::connectFrontend(FrontendChannel* frontendChannel, bool isAutomaticInspection)
81345200 107{
ed1e77d3
A
108 ASSERT(!m_frontendChannel);
109 ASSERT(!m_backendDispatcher);
81345200 110
ed1e77d3 111 m_isAutomaticInspection = isAutomaticInspection;
81345200 112
ed1e77d3
A
113 m_frontendChannel = frontendChannel;
114 m_backendDispatcher = BackendDispatcher::create(frontendChannel);
115
116 m_agents.didCreateFrontendAndBackend(frontendChannel, m_backendDispatcher.get());
117
118#if ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS)
119 m_inspectorAgent->activateExtraDomains(m_agents.extraDomains());
120
121 if (m_augmentingClient)
122 m_augmentingClient->inspectorConnected();
123#endif
81345200
A
124}
125
ed1e77d3 126void JSGlobalObjectInspectorController::disconnectFrontend(DisconnectReason reason)
81345200 127{
ed1e77d3 128 if (!m_frontendChannel)
81345200
A
129 return;
130
131 m_agents.willDestroyFrontendAndBackend(reason);
132
ed1e77d3
A
133 m_backendDispatcher->clearFrontend();
134 m_backendDispatcher = nullptr;
135 m_frontendChannel = nullptr;
136
137 m_isAutomaticInspection = false;
138
139#if ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS)
140 if (m_augmentingClient)
141 m_augmentingClient->inspectorDisconnected();
142#endif
81345200
A
143}
144
145void JSGlobalObjectInspectorController::dispatchMessageFromFrontend(const String& message)
146{
ed1e77d3
A
147 if (m_backendDispatcher)
148 m_backendDispatcher->dispatch(message);
149}
150
151void JSGlobalObjectInspectorController::pause()
152{
153 if (!m_frontendChannel)
154 return;
155
156 ErrorString dummyError;
157 m_debuggerAgent->enable(dummyError);
158 m_debuggerAgent->pause(dummyError);
81345200
A
159}
160
161void JSGlobalObjectInspectorController::appendAPIBacktrace(ScriptCallStack* callStack)
162{
ed1e77d3 163#if OS(DARWIN) || (OS(LINUX) && !PLATFORM(GTK))
81345200
A
164 static const int framesToShow = 31;
165 static const int framesToSkip = 3; // WTFGetBacktrace, appendAPIBacktrace, reportAPIException.
166
167 void* samples[framesToShow + framesToSkip];
168 int frames = framesToShow + framesToSkip;
169 WTFGetBacktrace(samples, &frames);
170
171 void** stack = samples + framesToSkip;
172 int size = frames - framesToSkip;
173 for (int i = 0; i < size; ++i) {
174 const char* mangledName = nullptr;
175 char* cxaDemangled = nullptr;
176 Dl_info info;
177 if (dladdr(stack[i], &info) && info.dli_sname)
178 mangledName = info.dli_sname;
179 if (mangledName)
180 cxaDemangled = abi::__cxa_demangle(mangledName, nullptr, nullptr, nullptr);
181 if (mangledName || cxaDemangled)
182 callStack->append(ScriptCallFrame(cxaDemangled ? cxaDemangled : mangledName, ASCIILiteral("[native code]"), 0, 0));
183 else
184 callStack->append(ScriptCallFrame(ASCIILiteral("?"), ASCIILiteral("[native code]"), 0, 0));
185 free(cxaDemangled);
186 }
ed1e77d3
A
187#else
188 UNUSED_PARAM(callStack);
189#endif
81345200
A
190}
191
ed1e77d3 192void JSGlobalObjectInspectorController::reportAPIException(ExecState* exec, Exception* exception)
81345200
A
193{
194 if (isTerminatedExecutionException(exception))
195 return;
196
197 ErrorHandlingScope errorScope(exec->vm());
198
199 RefPtr<ScriptCallStack> callStack = createScriptCallStackFromException(exec, exception, ScriptCallStack::maxCallStackSizeToCapture);
200 if (includesNativeCallStackWhenReportingExceptions())
201 appendAPIBacktrace(callStack.get());
202
203 // FIXME: <http://webkit.org/b/115087> Web Inspector: Should not evaluate JavaScript handling exceptions
204 // If this is a custom exception object, call toString on it to try and get a nice string representation for the exception.
ed1e77d3 205 String errorMessage = exception->value().toString(exec)->value(exec);
81345200
A
206 exec->clearException();
207
ed1e77d3 208 if (JSGlobalObjectConsoleClient::logToSystemConsole()) {
81345200
A
209 if (callStack->size()) {
210 const ScriptCallFrame& callFrame = callStack->at(0);
211 ConsoleClient::printConsoleMessage(MessageSource::JS, MessageType::Log, MessageLevel::Error, errorMessage, callFrame.sourceURL(), callFrame.lineNumber(), callFrame.columnNumber());
212 } else
213 ConsoleClient::printConsoleMessage(MessageSource::JS, MessageType::Log, MessageLevel::Error, errorMessage, String(), 0, 0);
214 }
215
ed1e77d3 216 m_consoleAgent->addMessageToConsole(std::make_unique<ConsoleMessage>(MessageSource::JS, MessageType::Log, MessageLevel::Error, errorMessage, callStack));
81345200
A
217}
218
219ConsoleClient* JSGlobalObjectInspectorController::consoleClient() const
220{
221 return m_consoleClient.get();
222}
223
40a37d08
A
224bool JSGlobalObjectInspectorController::developerExtrasEnabled() const
225{
226#if ENABLE(REMOTE_INSPECTOR)
ed1e77d3 227 if (!RemoteInspector::singleton().enabled())
40a37d08
A
228 return false;
229
230 if (!m_globalObject.inspectorDebuggable().remoteDebuggingAllowed())
231 return false;
232#endif
233
234 return true;
235}
236
81345200
A
237InspectorFunctionCallHandler JSGlobalObjectInspectorController::functionCallHandler() const
238{
239 return JSC::call;
240}
241
242InspectorEvaluateHandler JSGlobalObjectInspectorController::evaluateHandler() const
243{
244 return JSC::evaluate;
245}
246
ed1e77d3
A
247void JSGlobalObjectInspectorController::frontendInitialized()
248{
249#if ENABLE(REMOTE_INSPECTOR)
250 if (m_isAutomaticInspection)
251 m_globalObject.inspectorDebuggable().unpauseForInitializedInspector();
252#endif
253}
254
255Ref<Stopwatch> JSGlobalObjectInspectorController::executionStopwatch()
256{
257 return m_executionStopwatch.copyRef();
258}
259
260#if ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS)
261void JSGlobalObjectInspectorController::appendExtraAgent(std::unique_ptr<InspectorAgentBase> agent)
262{
263 String domainName = agent->domainName();
264
265 if (m_frontendChannel)
266 agent->didCreateFrontendAndBackend(m_frontendChannel, m_backendDispatcher.get());
267
268 m_agents.appendExtraAgent(WTF::move(agent));
269
270 if (m_frontendChannel)
271 m_inspectorAgent->activateExtraDomain(domainName);
272}
273#endif
274
81345200
A
275} // namespace Inspector
276