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"
31 #include "Completion.h"
32 #include "ErrorHandlingScope.h"
33 #include "InjectedScriptHost.h"
34 #include "InjectedScriptManager.h"
35 #include "InspectorAgent.h"
36 #include "InspectorBackendDispatcher.h"
37 #include "InspectorFrontendChannel.h"
38 #include "JSConsoleClient.h"
39 #include "JSGlobalObject.h"
40 #include "JSGlobalObjectConsoleAgent.h"
41 #include "JSGlobalObjectDebuggerAgent.h"
42 #include "JSGlobalObjectProfilerAgent.h"
43 #include "JSGlobalObjectRuntimeAgent.h"
44 #include "ScriptArguments.h"
45 #include "ScriptCallStack.h"
46 #include "ScriptCallStackFactory.h"
51 #if ENABLE(REMOTE_INSPECTOR)
52 #include "JSGlobalObjectDebuggable.h"
53 #include "RemoteInspector.h"
60 JSGlobalObjectInspectorController::JSGlobalObjectInspectorController(JSGlobalObject
& globalObject
)
61 : m_globalObject(globalObject
)
62 , m_injectedScriptManager(std::make_unique
<InjectedScriptManager
>(*this, InjectedScriptHost::create()))
63 , m_inspectorFrontendChannel(nullptr)
64 , m_includeNativeCallStackWithExceptions(true)
66 auto runtimeAgent
= std::make_unique
<JSGlobalObjectRuntimeAgent
>(m_injectedScriptManager
.get(), m_globalObject
);
67 auto consoleAgent
= std::make_unique
<JSGlobalObjectConsoleAgent
>(m_injectedScriptManager
.get());
68 auto debuggerAgent
= std::make_unique
<JSGlobalObjectDebuggerAgent
>(m_injectedScriptManager
.get(), m_globalObject
, consoleAgent
.get());
69 auto profilerAgent
= std::make_unique
<JSGlobalObjectProfilerAgent
>(m_globalObject
);
71 m_consoleAgent
= consoleAgent
.get();
72 m_consoleClient
= std::make_unique
<JSConsoleClient
>(m_consoleAgent
, profilerAgent
.get());
74 runtimeAgent
->setScriptDebugServer(&debuggerAgent
->scriptDebugServer());
75 profilerAgent
->setScriptDebugServer(&debuggerAgent
->scriptDebugServer());
77 m_agents
.append(std::make_unique
<InspectorAgent
>());
78 m_agents
.append(WTF::move(runtimeAgent
));
79 m_agents
.append(WTF::move(consoleAgent
));
80 m_agents
.append(WTF::move(debuggerAgent
));
83 JSGlobalObjectInspectorController::~JSGlobalObjectInspectorController()
85 m_agents
.discardAgents();
88 void JSGlobalObjectInspectorController::globalObjectDestroyed()
90 disconnectFrontend(InspectorDisconnectReason::InspectedTargetDestroyed
);
92 m_injectedScriptManager
->disconnect();
95 void JSGlobalObjectInspectorController::connectFrontend(InspectorFrontendChannel
* frontendChannel
)
97 ASSERT(!m_inspectorFrontendChannel
);
98 ASSERT(!m_inspectorBackendDispatcher
);
100 m_inspectorFrontendChannel
= frontendChannel
;
101 m_inspectorBackendDispatcher
= InspectorBackendDispatcher::create(frontendChannel
);
103 m_agents
.didCreateFrontendAndBackend(frontendChannel
, m_inspectorBackendDispatcher
.get());
106 void JSGlobalObjectInspectorController::disconnectFrontend(InspectorDisconnectReason reason
)
108 if (!m_inspectorFrontendChannel
)
111 m_agents
.willDestroyFrontendAndBackend(reason
);
113 m_inspectorBackendDispatcher
->clearFrontend();
114 m_inspectorBackendDispatcher
.clear();
115 m_inspectorFrontendChannel
= nullptr;
118 void JSGlobalObjectInspectorController::dispatchMessageFromFrontend(const String
& message
)
120 if (m_inspectorBackendDispatcher
)
121 m_inspectorBackendDispatcher
->dispatch(message
);
124 void JSGlobalObjectInspectorController::appendAPIBacktrace(ScriptCallStack
* callStack
)
126 static const int framesToShow
= 31;
127 static const int framesToSkip
= 3; // WTFGetBacktrace, appendAPIBacktrace, reportAPIException.
129 void* samples
[framesToShow
+ framesToSkip
];
130 int frames
= framesToShow
+ framesToSkip
;
131 WTFGetBacktrace(samples
, &frames
);
133 void** stack
= samples
+ framesToSkip
;
134 int size
= frames
- framesToSkip
;
135 for (int i
= 0; i
< size
; ++i
) {
136 const char* mangledName
= nullptr;
137 char* cxaDemangled
= nullptr;
139 if (dladdr(stack
[i
], &info
) && info
.dli_sname
)
140 mangledName
= info
.dli_sname
;
142 cxaDemangled
= abi::__cxa_demangle(mangledName
, nullptr, nullptr, nullptr);
143 if (mangledName
|| cxaDemangled
)
144 callStack
->append(ScriptCallFrame(cxaDemangled
? cxaDemangled
: mangledName
, ASCIILiteral("[native code]"), 0, 0));
146 callStack
->append(ScriptCallFrame(ASCIILiteral("?"), ASCIILiteral("[native code]"), 0, 0));
151 void JSGlobalObjectInspectorController::reportAPIException(ExecState
* exec
, JSValue exception
)
153 if (isTerminatedExecutionException(exception
))
156 ErrorHandlingScope
errorScope(exec
->vm());
158 RefPtr
<ScriptCallStack
> callStack
= createScriptCallStackFromException(exec
, exception
, ScriptCallStack::maxCallStackSizeToCapture
);
159 if (includesNativeCallStackWhenReportingExceptions())
160 appendAPIBacktrace(callStack
.get());
162 // FIXME: <http://webkit.org/b/115087> Web Inspector: Should not evaluate JavaScript handling exceptions
163 // If this is a custom exception object, call toString on it to try and get a nice string representation for the exception.
164 String errorMessage
= exception
.toString(exec
)->value(exec
);
165 exec
->clearException();
167 if (JSConsoleClient::logToSystemConsole()) {
168 if (callStack
->size()) {
169 const ScriptCallFrame
& callFrame
= callStack
->at(0);
170 ConsoleClient::printConsoleMessage(MessageSource::JS
, MessageType::Log
, MessageLevel::Error
, errorMessage
, callFrame
.sourceURL(), callFrame
.lineNumber(), callFrame
.columnNumber());
172 ConsoleClient::printConsoleMessage(MessageSource::JS
, MessageType::Log
, MessageLevel::Error
, errorMessage
, String(), 0, 0);
175 m_consoleAgent
->addMessageToConsole(MessageSource::JS
, MessageType::Log
, MessageLevel::Error
, errorMessage
, callStack
);
178 ConsoleClient
* JSGlobalObjectInspectorController::consoleClient() const
180 return m_consoleClient
.get();
183 bool JSGlobalObjectInspectorController::developerExtrasEnabled() const
185 #if ENABLE(REMOTE_INSPECTOR)
186 if (!RemoteInspector::shared().enabled())
189 if (!m_globalObject
.inspectorDebuggable().remoteDebuggingAllowed())
196 InspectorFunctionCallHandler
JSGlobalObjectInspectorController::functionCallHandler() const
201 InspectorEvaluateHandler
JSGlobalObjectInspectorController::evaluateHandler() const
203 return JSC::evaluate
;
206 } // namespace Inspector
208 #endif // ENABLE(INSPECTOR)