2 * Copyright (C) 2014 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
27 #include "JSGlobalObjectInspectorController.h"
29 #include "Completion.h"
30 #include "ConsoleMessage.h"
31 #include "ErrorHandlingScope.h"
32 #include "Exception.h"
33 #include "InjectedScriptHost.h"
34 #include "InjectedScriptManager.h"
35 #include "InspectorAgent.h"
36 #include "InspectorBackendDispatcher.h"
37 #include "InspectorFrontendChannel.h"
38 #include "JSGlobalObject.h"
39 #include "JSGlobalObjectConsoleAgent.h"
40 #include "JSGlobalObjectConsoleClient.h"
41 #include "JSGlobalObjectDebuggerAgent.h"
42 #include "JSGlobalObjectRuntimeAgent.h"
43 #include "ScriptArguments.h"
44 #include "ScriptCallStack.h"
45 #include "ScriptCallStackFactory.h"
46 #include <wtf/Stopwatch.h>
49 #if OS(DARWIN) || (OS(LINUX) && !PLATFORM(GTK))
54 #if ENABLE(REMOTE_INSPECTOR)
55 #include "JSGlobalObjectDebuggable.h"
56 #include "RemoteInspector.h"
63 JSGlobalObjectInspectorController::JSGlobalObjectInspectorController(JSGlobalObject
& globalObject
)
64 : m_globalObject(globalObject
)
65 , m_injectedScriptManager(std::make_unique
<InjectedScriptManager
>(*this, InjectedScriptHost::create()))
66 , m_frontendChannel(nullptr)
67 , m_executionStopwatch(Stopwatch::create())
68 , m_includeNativeCallStackWithExceptions(true)
69 , m_isAutomaticInspection(false)
70 #if ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS)
71 , m_augmentingClient(nullptr)
74 auto inspectorAgent
= std::make_unique
<InspectorAgent
>(*this);
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());
79 m_inspectorAgent
= inspectorAgent
.get();
80 m_debuggerAgent
= debuggerAgent
.get();
81 m_consoleAgent
= consoleAgent
.get();
82 m_consoleClient
= std::make_unique
<JSGlobalObjectConsoleClient
>(m_consoleAgent
);
84 runtimeAgent
->setScriptDebugServer(&debuggerAgent
->scriptDebugServer());
86 m_agents
.append(WTF::move(inspectorAgent
));
87 m_agents
.append(WTF::move(runtimeAgent
));
88 m_agents
.append(WTF::move(consoleAgent
));
89 m_agents
.append(WTF::move(debuggerAgent
));
91 m_executionStopwatch
->start();
94 JSGlobalObjectInspectorController::~JSGlobalObjectInspectorController()
96 m_agents
.discardAgents();
99 void JSGlobalObjectInspectorController::globalObjectDestroyed()
101 disconnectFrontend(DisconnectReason::InspectedTargetDestroyed
);
103 m_injectedScriptManager
->disconnect();
106 void JSGlobalObjectInspectorController::connectFrontend(FrontendChannel
* frontendChannel
, bool isAutomaticInspection
)
108 ASSERT(!m_frontendChannel
);
109 ASSERT(!m_backendDispatcher
);
111 m_isAutomaticInspection
= isAutomaticInspection
;
113 m_frontendChannel
= frontendChannel
;
114 m_backendDispatcher
= BackendDispatcher::create(frontendChannel
);
116 m_agents
.didCreateFrontendAndBackend(frontendChannel
, m_backendDispatcher
.get());
118 #if ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS)
119 m_inspectorAgent
->activateExtraDomains(m_agents
.extraDomains());
121 if (m_augmentingClient
)
122 m_augmentingClient
->inspectorConnected();
126 void JSGlobalObjectInspectorController::disconnectFrontend(DisconnectReason reason
)
128 if (!m_frontendChannel
)
131 m_agents
.willDestroyFrontendAndBackend(reason
);
133 m_backendDispatcher
->clearFrontend();
134 m_backendDispatcher
= nullptr;
135 m_frontendChannel
= nullptr;
137 m_isAutomaticInspection
= false;
139 #if ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS)
140 if (m_augmentingClient
)
141 m_augmentingClient
->inspectorDisconnected();
145 void JSGlobalObjectInspectorController::dispatchMessageFromFrontend(const String
& message
)
147 if (m_backendDispatcher
)
148 m_backendDispatcher
->dispatch(message
);
151 void JSGlobalObjectInspectorController::pause()
153 if (!m_frontendChannel
)
156 ErrorString dummyError
;
157 m_debuggerAgent
->enable(dummyError
);
158 m_debuggerAgent
->pause(dummyError
);
161 void JSGlobalObjectInspectorController::appendAPIBacktrace(ScriptCallStack
* callStack
)
163 #if OS(DARWIN) || (OS(LINUX) && !PLATFORM(GTK))
164 static const int framesToShow
= 31;
165 static const int framesToSkip
= 3; // WTFGetBacktrace, appendAPIBacktrace, reportAPIException.
167 void* samples
[framesToShow
+ framesToSkip
];
168 int frames
= framesToShow
+ framesToSkip
;
169 WTFGetBacktrace(samples
, &frames
);
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;
177 if (dladdr(stack
[i
], &info
) && info
.dli_sname
)
178 mangledName
= info
.dli_sname
;
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));
184 callStack
->append(ScriptCallFrame(ASCIILiteral("?"), ASCIILiteral("[native code]"), 0, 0));
188 UNUSED_PARAM(callStack
);
192 void JSGlobalObjectInspectorController::reportAPIException(ExecState
* exec
, Exception
* exception
)
194 if (isTerminatedExecutionException(exception
))
197 ErrorHandlingScope
errorScope(exec
->vm());
199 RefPtr
<ScriptCallStack
> callStack
= createScriptCallStackFromException(exec
, exception
, ScriptCallStack::maxCallStackSizeToCapture
);
200 if (includesNativeCallStackWhenReportingExceptions())
201 appendAPIBacktrace(callStack
.get());
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.
205 String errorMessage
= exception
->value().toString(exec
)->value(exec
);
206 exec
->clearException();
208 if (JSGlobalObjectConsoleClient::logToSystemConsole()) {
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());
213 ConsoleClient::printConsoleMessage(MessageSource::JS
, MessageType::Log
, MessageLevel::Error
, errorMessage
, String(), 0, 0);
216 m_consoleAgent
->addMessageToConsole(std::make_unique
<ConsoleMessage
>(MessageSource::JS
, MessageType::Log
, MessageLevel::Error
, errorMessage
, callStack
));
219 ConsoleClient
* JSGlobalObjectInspectorController::consoleClient() const
221 return m_consoleClient
.get();
224 bool JSGlobalObjectInspectorController::developerExtrasEnabled() const
226 #if ENABLE(REMOTE_INSPECTOR)
227 if (!RemoteInspector::singleton().enabled())
230 if (!m_globalObject
.inspectorDebuggable().remoteDebuggingAllowed())
237 InspectorFunctionCallHandler
JSGlobalObjectInspectorController::functionCallHandler() const
242 InspectorEvaluateHandler
JSGlobalObjectInspectorController::evaluateHandler() const
244 return JSC::evaluate
;
247 void JSGlobalObjectInspectorController::frontendInitialized()
249 #if ENABLE(REMOTE_INSPECTOR)
250 if (m_isAutomaticInspection
)
251 m_globalObject
.inspectorDebuggable().unpauseForInitializedInspector();
255 Ref
<Stopwatch
> JSGlobalObjectInspectorController::executionStopwatch()
257 return m_executionStopwatch
.copyRef();
260 #if ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS)
261 void JSGlobalObjectInspectorController::appendExtraAgent(std::unique_ptr
<InspectorAgentBase
> agent
)
263 String domainName
= agent
->domainName();
265 if (m_frontendChannel
)
266 agent
->didCreateFrontendAndBackend(m_frontendChannel
, m_backendDispatcher
.get());
268 m_agents
.appendExtraAgent(WTF::move(agent
));
270 if (m_frontendChannel
)
271 m_inspectorAgent
->activateExtraDomain(domainName
);
275 } // namespace Inspector