Skip to content
Permalink
Browse files
Web Inspector: Should be able to attach a debugger to a JSContext bef…
…ore anything is executed

https://bugs.webkit.org/show_bug.cgi?id=136893

Patch by Joseph Pecoraro <pecoraro@apple.com> on 2014-09-18
Reviewed by Timothy Hatcher.

Source/JavaScriptCore:

Adds new remote inspector protocol handling for automatic inspection.
Debuggers can signal they have enabled automatic inspection, and
when debuggables are created the current application will pause to
see if the debugger will inspect or decline to inspect the debuggable.

* inspector/remote/RemoteInspectorConstants.h:
* inspector/remote/RemoteInspector.h:
* inspector/remote/RemoteInspector.mm:
(Inspector::globalAutomaticInspectionState):
(Inspector::RemoteInspector::RemoteInspector):
(Inspector::RemoteInspector::start):
When first starting, check the global "is there an auto-inspect" debugger state.
This is necessary so that the current application knows if it should pause or
not when a debuggable is created, even without having connected to webinspectord yet.

(Inspector::RemoteInspector::updateDebuggableAutomaticInspectCandidate):
When a debuggable has enabled remote inspection, take this path to propose
it as an automatic inspection candidate if there is an auto-inspect debugger.

(Inspector::RemoteInspector::sendAutomaticInspectionCandidateMessage):
Send the automatic inspection candidate message.

(Inspector::RemoteInspector::receivedSetupMessage):
(Inspector::RemoteInspector::setupFailed):
(Inspector::RemoteInspector::setupSucceeded):
After attempting to open an inspector, unpause if it was for the
automatic inspection candidate.

(Inspector::RemoteInspector::waitingForAutomaticInspection):
When running a nested runloop, check if we should remain paused.

(Inspector::RemoteInspector::setupXPCConnectionIfNeeded):
If by the time we connect to webinspectord we have a candidate, then
immediately send the candidate message.

(Inspector::RemoteInspector::stopInternal):
(Inspector::RemoteInspector::xpcConnectionFailed):
In error cases, clear our state.

(Inspector::RemoteInspector::xpcConnectionReceivedMessage):
(Inspector::RemoteInspector::receivedAutomaticInspectionConfigurationMessage):
(Inspector::RemoteInspector::receivedAutomaticInspectionRejectMessage):
Update state when receiving new messages.

* inspector/remote/RemoteInspectorDebuggable.h:
* inspector/remote/RemoteInspectorDebuggable.cpp:
(Inspector::RemoteInspectorDebuggable::setRemoteDebuggingAllowed):
Special case when a debuggable is newly allowed to be debuggable.

(Inspector::RemoteInspectorDebuggable::pauseWaitingForAutomaticInspection):
Run a nested run loop while this is an automatic inspection candidate.

* inspector/JSGlobalObjectInspectorController.h:
* inspector/JSGlobalObjectInspectorController.cpp:
(Inspector::JSGlobalObjectInspectorController::JSGlobalObjectInspectorController):
(Inspector::JSGlobalObjectInspectorController::connectFrontend):
When the inspector starts via automatic inspection automatically pause.
We plan on removing this condition by having the frontend signal to the
backend when it is completely initialized.

* inspector/remote/RemoteInspectorDebuggableConnection.h:
* inspector/remote/RemoteInspectorDebuggableConnection.mm:
(Inspector::RemoteInspectorDebuggableConnection::setup):
Pass on the flag of whether or not this was automatic inspection.

* runtime/JSGlobalObjectDebuggable.h:
* runtime/JSGlobalObjectDebuggable.cpp:
(JSC::JSGlobalObjectDebuggable::connect):
(JSC::JSGlobalObjectDebuggable::pauseWaitingForAutomaticInspection):
When pausing in a JSGlobalObject we need to release the API lock.

Source/WebCore:

Automatic inspection is currently disabled for web pages.
This just updates the interfaces that changed.

* WebCore.exp.in:
* inspector/InspectorController.cpp:
(WebCore::InspectorController::connectFrontend):
(WebCore::InspectorController::show):
* inspector/InspectorController.h:
* page/PageDebuggable.cpp:
(WebCore::PageDebuggable::connect):
* page/PageDebuggable.h:
* testing/Internals.cpp:
(WebCore::Internals::openDummyInspectorFrontend):

Source/WTF:

Currently automatic inspection only happens in processes that have a
debugger attached. That condition may change in the future, but this
function can stand on its own in WTF. It may be useful in the future
to perhaps continue though ASSERTs if you have a debugger attached.

* wtf/Assertions.cpp:
* wtf/Assertions.h:

Canonical link: https://commits.webkit.org/154747@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@173731 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
JosephPecoraro authored and webkit-commit-queue committed Sep 18, 2014
1 parent 5172c8f commit f692ea04609896da0ac047cbf226f932162a546e
Showing 22 changed files with 355 additions and 21 deletions.
@@ -1,3 +1,82 @@
2014-09-18 Joseph Pecoraro <pecoraro@apple.com>

Web Inspector: Should be able to attach a debugger to a JSContext before anything is executed
https://bugs.webkit.org/show_bug.cgi?id=136893

Reviewed by Timothy Hatcher.

Adds new remote inspector protocol handling for automatic inspection.
Debuggers can signal they have enabled automatic inspection, and
when debuggables are created the current application will pause to
see if the debugger will inspect or decline to inspect the debuggable.

* inspector/remote/RemoteInspectorConstants.h:
* inspector/remote/RemoteInspector.h:
* inspector/remote/RemoteInspector.mm:
(Inspector::globalAutomaticInspectionState):
(Inspector::RemoteInspector::RemoteInspector):
(Inspector::RemoteInspector::start):
When first starting, check the global "is there an auto-inspect" debugger state.
This is necessary so that the current application knows if it should pause or
not when a debuggable is created, even without having connected to webinspectord yet.

(Inspector::RemoteInspector::updateDebuggableAutomaticInspectCandidate):
When a debuggable has enabled remote inspection, take this path to propose
it as an automatic inspection candidate if there is an auto-inspect debugger.

(Inspector::RemoteInspector::sendAutomaticInspectionCandidateMessage):
Send the automatic inspection candidate message.

(Inspector::RemoteInspector::receivedSetupMessage):
(Inspector::RemoteInspector::setupFailed):
(Inspector::RemoteInspector::setupSucceeded):
After attempting to open an inspector, unpause if it was for the
automatic inspection candidate.

(Inspector::RemoteInspector::waitingForAutomaticInspection):
When running a nested runloop, check if we should remain paused.

(Inspector::RemoteInspector::setupXPCConnectionIfNeeded):
If by the time we connect to webinspectord we have a candidate, then
immediately send the candidate message.

(Inspector::RemoteInspector::stopInternal):
(Inspector::RemoteInspector::xpcConnectionFailed):
In error cases, clear our state.

(Inspector::RemoteInspector::xpcConnectionReceivedMessage):
(Inspector::RemoteInspector::receivedAutomaticInspectionConfigurationMessage):
(Inspector::RemoteInspector::receivedAutomaticInspectionRejectMessage):
Update state when receiving new messages.


* inspector/remote/RemoteInspectorDebuggable.h:
* inspector/remote/RemoteInspectorDebuggable.cpp:
(Inspector::RemoteInspectorDebuggable::setRemoteDebuggingAllowed):
Special case when a debuggable is newly allowed to be debuggable.

(Inspector::RemoteInspectorDebuggable::pauseWaitingForAutomaticInspection):
Run a nested run loop while this is an automatic inspection candidate.

* inspector/JSGlobalObjectInspectorController.h:
* inspector/JSGlobalObjectInspectorController.cpp:
(Inspector::JSGlobalObjectInspectorController::JSGlobalObjectInspectorController):
(Inspector::JSGlobalObjectInspectorController::connectFrontend):
When the inspector starts via automatic inspection automatically pause.
We plan on removing this condition by having the frontend signal to the
backend when it is completely initialized.

* inspector/remote/RemoteInspectorDebuggableConnection.h:
* inspector/remote/RemoteInspectorDebuggableConnection.mm:
(Inspector::RemoteInspectorDebuggableConnection::setup):
Pass on the flag of whether or not this was automatic inspection.

* runtime/JSGlobalObjectDebuggable.h:
* runtime/JSGlobalObjectDebuggable.cpp:
(JSC::JSGlobalObjectDebuggable::connect):
(JSC::JSGlobalObjectDebuggable::pauseWaitingForAutomaticInspection):
When pausing in a JSGlobalObject we need to release the API lock.

2014-09-18 Eva Balazsfalvi <evab.u-szeged@partner.samsung.com>

Fix "Tools/Scripts/build-webkit --efl --no-inspector" build
@@ -61,6 +61,7 @@ JSGlobalObjectInspectorController::JSGlobalObjectInspectorController(JSGlobalObj
auto consoleAgent = std::make_unique<JSGlobalObjectConsoleAgent>(m_injectedScriptManager.get());
auto debuggerAgent = std::make_unique<JSGlobalObjectDebuggerAgent>(m_injectedScriptManager.get(), m_globalObject, consoleAgent.get());

m_debuggerAgent = debuggerAgent.get();
m_consoleAgent = consoleAgent.get();
m_consoleClient = std::make_unique<JSGlobalObjectConsoleClient>(m_consoleAgent);

@@ -84,7 +85,7 @@ void JSGlobalObjectInspectorController::globalObjectDestroyed()
m_injectedScriptManager->disconnect();
}

void JSGlobalObjectInspectorController::connectFrontend(InspectorFrontendChannel* frontendChannel)
void JSGlobalObjectInspectorController::connectFrontend(InspectorFrontendChannel* frontendChannel, bool isAutomaticInspection)
{
ASSERT(!m_inspectorFrontendChannel);
ASSERT(!m_inspectorBackendDispatcher);
@@ -93,6 +94,15 @@ void JSGlobalObjectInspectorController::connectFrontend(InspectorFrontendChannel
m_inspectorBackendDispatcher = InspectorBackendDispatcher::create(frontendChannel);

m_agents.didCreateFrontendAndBackend(frontendChannel, m_inspectorBackendDispatcher.get());

if (isAutomaticInspection) {
// FIXME: We should not always pause for automatic inspection.
// Currently if we don't automatically pause, then we may miss a breakpoint, since breakpoints
// come from the frontend and might be received after some evaluateScript message. We should
// have the frontend signal the backend when its setup messages are complete.
m_debuggerAgent->enable(nullptr);
m_debuggerAgent->pause(nullptr);
}
}

void JSGlobalObjectInspectorController::disconnectFrontend(InspectorDisconnectReason reason)
@@ -47,6 +47,7 @@ class InjectedScriptManager;
class InspectorConsoleAgent;
class InspectorBackendDispatcher;
class InspectorConsoleAgent;
class InspectorDebuggerAgent;
class InspectorFrontendChannel;
class JSGlobalObjectConsoleClient;
class ScriptCallStack;
@@ -58,7 +59,7 @@ class JSGlobalObjectInspectorController final : public InspectorEnvironment {
JSGlobalObjectInspectorController(JSC::JSGlobalObject&);
~JSGlobalObjectInspectorController();

void connectFrontend(InspectorFrontendChannel*);
void connectFrontend(InspectorFrontendChannel*, bool isAutomaticInspection);
void disconnectFrontend(InspectorDisconnectReason reason);
void dispatchMessageFromFrontend(const String&);

@@ -85,6 +86,7 @@ class JSGlobalObjectInspectorController final : public InspectorEnvironment {
std::unique_ptr<InjectedScriptManager> m_injectedScriptManager;
std::unique_ptr<JSGlobalObjectConsoleClient> m_consoleClient;
InspectorConsoleAgent* m_consoleAgent;
InspectorDebuggerAgent* m_debuggerAgent;
InspectorAgentRegistry m_agents;
InspectorFrontendChannel* m_inspectorFrontendChannel;
RefPtr<InspectorBackendDispatcher> m_inspectorBackendDispatcher;
@@ -52,8 +52,11 @@ class JS_EXPORT_PRIVATE RemoteInspector final : public RemoteInspectorXPCConnect
void registerDebuggable(RemoteInspectorDebuggable*);
void unregisterDebuggable(RemoteInspectorDebuggable*);
void updateDebuggable(RemoteInspectorDebuggable*);
void updateDebuggableAutomaticInspectCandidate(RemoteInspectorDebuggable*);
void sendMessageToRemoteFrontend(unsigned identifier, const String& message);
void setupFailed(unsigned identifier);
void setupSucceeded(unsigned identifier);
bool waitingForAutomaticInspection(unsigned identifier);

bool enabled() const { return m_enabled; }
bool hasActiveDebugSession() const { return m_hasActiveDebugSession; }
@@ -83,6 +86,8 @@ class JS_EXPORT_PRIVATE RemoteInspector final : public RemoteInspectorXPCConnect

void updateHasActiveDebugSession();

void sendAutomaticInspectionCandidateMessage();

virtual void xpcConnectionReceivedMessage(RemoteInspectorXPCConnection*, NSString *messageName, NSDictionary *userInfo) override;
virtual void xpcConnectionFailed(RemoteInspectorXPCConnection*) override;
virtual void xpcConnectionUnhandledMessage(RemoteInspectorXPCConnection*, xpc_object_t) override;
@@ -94,6 +99,8 @@ class JS_EXPORT_PRIVATE RemoteInspector final : public RemoteInspectorXPCConnect
void receivedIndicateMessage(NSDictionary *userInfo);
void receivedProxyApplicationSetupMessage(NSDictionary *userInfo);
void receivedConnectionDiedMessage(NSDictionary *userInfo);
void receivedAutomaticInspectionConfigurationMessage(NSDictionary *userInfo);
void receivedAutomaticInspectionRejectMessage(NSDictionary *userInfo);

static bool startEnabled;

@@ -117,6 +124,9 @@ class JS_EXPORT_PRIVATE RemoteInspector final : public RemoteInspectorXPCConnect
pid_t m_parentProcessIdentifier;
RetainPtr<CFDataRef> m_parentProcessAuditData;
bool m_shouldSendParentProcessInformation;
bool m_automaticInspectionEnabled;
bool m_automaticInspectionPaused;
unsigned m_automaticInspectionCandidateIdentifier;
};

} // namespace Inspector

0 comments on commit f692ea0

Please sign in to comment.