f14a53fb94afaf5a35b9158c89c3eb1ae5e5ba50
[WebKit-https.git] / Source / JavaScriptCore / inspector / agents / InspectorDebuggerAgent.h
1 /*
2  * Copyright (C) 2010, 2013, 2015 Apple Inc. All rights reserved.
3  * Copyright (C) 2010, 2011 Google Inc. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1.  Redistributions of source code must retain the above copyright
10  *     notice, this list of conditions and the following disclaimer.
11  * 2.  Redistributions in binary form must reproduce the above copyright
12  *     notice, this list of conditions and the following disclaimer in the
13  *     documentation and/or other materials provided with the distribution.
14  * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
15  *     its contributors may be used to endorse or promote products derived
16  *     from this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
19  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
22  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29
30 #pragma once
31
32 #include "InspectorBackendDispatchers.h"
33 #include "InspectorFrontendDispatchers.h"
34 #include "bindings/ScriptValue.h"
35 #include "debugger/Debugger.h"
36 #include "inspector/InspectorAgentBase.h"
37 #include "inspector/ScriptBreakpoint.h"
38 #include "inspector/ScriptCallStack.h"
39 #include "inspector/ScriptDebugListener.h"
40 #include <wtf/Forward.h>
41 #include <wtf/HashMap.h>
42 #include <wtf/Noncopyable.h>
43 #include <wtf/Vector.h>
44
45 namespace Inspector {
46
47 class InjectedScript;
48 class InjectedScriptManager;
49 class InspectorArray;
50 class InspectorObject;
51 class ScriptDebugServer;
52 struct AsyncCallData;
53 typedef String ErrorString;
54
55 class JS_EXPORT_PRIVATE InspectorDebuggerAgent : public InspectorAgentBase, public ScriptDebugListener, public DebuggerBackendDispatcherHandler {
56     WTF_MAKE_NONCOPYABLE(InspectorDebuggerAgent);
57     WTF_MAKE_FAST_ALLOCATED;
58 public:
59     static const char* backtraceObjectGroup;
60
61     virtual ~InspectorDebuggerAgent();
62
63     void didCreateFrontendAndBackend(FrontendRouter*, BackendDispatcher*) final;
64     void willDestroyFrontendAndBackend(DisconnectReason) final;
65
66     void enable(ErrorString&) final;
67     void disable(ErrorString&) final;
68     void setAsyncStackTraceDepth(ErrorString&, int depth) final;
69     void setBreakpointsActive(ErrorString&, bool active) final;
70     void setBreakpointByUrl(ErrorString&, int lineNumber, const String* optionalURL, const String* optionalURLRegex, const int* optionalColumnNumber, const Inspector::InspectorObject* options, Inspector::Protocol::Debugger::BreakpointId*, RefPtr<Inspector::Protocol::Array<Inspector::Protocol::Debugger::Location>>& locations) final;
71     void setBreakpoint(ErrorString&, const Inspector::InspectorObject& location, const Inspector::InspectorObject* options, Inspector::Protocol::Debugger::BreakpointId*, RefPtr<Inspector::Protocol::Debugger::Location>& actualLocation) final;
72     void removeBreakpoint(ErrorString&, const String& breakpointIdentifier) final;
73     void continueUntilNextRunLoop(ErrorString&) final;
74     void continueToLocation(ErrorString&, const InspectorObject& location) final;
75     void searchInContent(ErrorString&, const String& scriptID, const String& query, const bool* optionalCaseSensitive, const bool* optionalIsRegex, RefPtr<Inspector::Protocol::Array<Inspector::Protocol::GenericTypes::SearchMatch>>&) final;
76     void getScriptSource(ErrorString&, const String& scriptID, String* scriptSource) final;
77     void getFunctionDetails(ErrorString&, const String& functionId, RefPtr<Inspector::Protocol::Debugger::FunctionDetails>&) final;
78     void pause(ErrorString&) final;
79     void resume(ErrorString&) final;
80     void stepOver(ErrorString&) final;
81     void stepInto(ErrorString&) final;
82     void stepOut(ErrorString&) final;
83     void setPauseOnExceptions(ErrorString&, const String& pauseState) final;
84     void setPauseOnAssertions(ErrorString&, bool enabled) final;
85     void evaluateOnCallFrame(ErrorString&, const String& callFrameId, const String& expression, const String* objectGroup, const bool* includeCommandLineAPI, const bool* doNotPauseOnExceptionsAndMuteConsole, const bool* returnByValue, const bool* generatePreview, const bool* saveResult, RefPtr<Inspector::Protocol::Runtime::RemoteObject>& result, Inspector::Protocol::OptOutput<bool>* wasThrown, Inspector::Protocol::OptOutput<int>* savedResultIndex) final;
86     void setOverlayMessage(ErrorString&, const String*) override;
87
88     bool isPaused() const;
89     bool breakpointsActive() const;
90
91     void setSuppressAllPauses(bool);
92
93     void handleConsoleAssert(const String& message);
94
95     void didScheduleAsyncCall(JSC::ExecState*, int asyncCallType, int callbackIdentifier, bool singleShot);
96     void didCancelAsyncCall(int asyncCallType, int callbackIdentifier);
97     void willDispatchAsyncCall(int asyncCallType, int callbackIdentifier);
98     void didDispatchAsyncCall();
99
100     void schedulePauseOnNextStatement(DebuggerFrontendDispatcher::Reason breakReason, RefPtr<InspectorObject>&& data);
101     void cancelPauseOnNextStatement();
102     bool pauseOnNextStatementEnabled() const { return m_javaScriptPauseScheduled; }
103
104     void breakProgram(DebuggerFrontendDispatcher::Reason breakReason, RefPtr<InspectorObject>&& data);
105     void scriptExecutionBlockedByCSP(const String& directiveText);
106
107     class Listener {
108     public:
109         virtual ~Listener() { }
110         virtual void debuggerWasEnabled() = 0;
111         virtual void debuggerWasDisabled() = 0;
112     };
113     void setListener(Listener* listener) { m_listener = listener; }
114
115 protected:
116     InspectorDebuggerAgent(AgentContext&);
117
118     InjectedScriptManager& injectedScriptManager() const { return m_injectedScriptManager; }
119     virtual InjectedScript injectedScriptForEval(ErrorString&, const int* executionContextId) = 0;
120
121     ScriptDebugServer& scriptDebugServer() { return m_scriptDebugServer; }
122
123     virtual void muteConsole() = 0;
124     virtual void unmuteConsole() = 0;
125
126     virtual void enable();
127     virtual void disable(bool skipRecompile);
128     void didPause(JSC::ExecState&, JSC::JSValue callFrames, JSC::JSValue exceptionOrCaughtValue) final;
129     void didContinue() final;
130
131     virtual String sourceMapURLForScript(const Script&);
132
133     void didClearGlobalObject();
134
135 private:
136     Ref<Inspector::Protocol::Array<Inspector::Protocol::Debugger::CallFrame>> currentCallFrames(const InjectedScript&);
137
138     void didParseSource(JSC::SourceID, const Script&) final;
139     void failedToParseSource(const String& url, const String& data, int firstLine, int errorLine, const String& errorMessage) final;
140
141     void breakpointActionSound(int breakpointActionIdentifier) final;
142     void breakpointActionProbe(JSC::ExecState&, const ScriptBreakpointAction&, unsigned batchId, unsigned sampleId, JSC::JSValue sample) final;
143
144     void resolveBreakpoint(const Script&, JSC::Breakpoint&);
145     void setBreakpoint(JSC::Breakpoint&, bool& existing);    
146     void didSetBreakpoint(const JSC::Breakpoint&, const String&, const ScriptBreakpoint&);
147
148     bool assertPaused(ErrorString&);
149     void clearDebuggerBreakpointState();
150     void clearInspectorBreakpointState();
151     void clearBreakDetails();
152     void clearExceptionValue();
153     void clearAsyncStackTraceData();
154
155     enum class ShouldDispatchResumed { No, WhenIdle, WhenContinued };
156     void registerIdleHandler();
157     void willStepAndMayBecomeIdle();
158     void didBecomeIdle();
159
160     RefPtr<InspectorObject> buildBreakpointPauseReason(JSC::BreakpointID);
161     RefPtr<InspectorObject> buildExceptionPauseReason(JSC::JSValue exception, const InjectedScript&);
162
163     bool breakpointActionsFromProtocol(ErrorString&, RefPtr<InspectorArray>& actions, BreakpointActions* result);
164
165     typedef std::pair<int, int> AsyncCallIdentifier;
166
167     RefPtr<Inspector::Protocol::Console::StackTrace> buildAsyncStackTrace(const AsyncCallIdentifier&);
168     void refAsyncCallData(const AsyncCallIdentifier&);
169     void derefAsyncCallData(const AsyncCallIdentifier&);
170
171     typedef HashMap<JSC::SourceID, Script> ScriptsMap;
172     typedef HashMap<String, Vector<JSC::BreakpointID>> BreakpointIdentifierToDebugServerBreakpointIDsMap;
173     typedef HashMap<String, RefPtr<InspectorObject>> BreakpointIdentifierToBreakpointMap;
174     typedef HashMap<JSC::BreakpointID, String> DebugServerBreakpointIDToBreakpointIdentifier;
175
176     struct AsyncCallData {
177         AsyncCallData(RefPtr<ScriptCallStack> callStack, std::optional<AsyncCallIdentifier> parentAsyncCallIdentifier, bool singleShot)
178             : callStack(callStack)
179             , parentAsyncCallIdentifier(parentAsyncCallIdentifier)
180             , referenceCount(singleShot ? 0 : 1)
181         {
182         }
183
184         AsyncCallData() = default;
185
186         RefPtr<ScriptCallStack> callStack;
187         std::optional<AsyncCallIdentifier> parentAsyncCallIdentifier { std::nullopt };
188         unsigned referenceCount { 0 };
189     };
190
191     InjectedScriptManager& m_injectedScriptManager;
192     std::unique_ptr<DebuggerFrontendDispatcher> m_frontendDispatcher;
193     RefPtr<DebuggerBackendDispatcher> m_backendDispatcher;
194     ScriptDebugServer& m_scriptDebugServer;
195     Listener* m_listener { nullptr };
196     JSC::ExecState* m_pausedScriptState { nullptr };
197     Deprecated::ScriptValue m_currentCallStack;
198     ScriptsMap m_scripts;
199     BreakpointIdentifierToDebugServerBreakpointIDsMap m_breakpointIdentifierToDebugServerBreakpointIDs;
200     BreakpointIdentifierToBreakpointMap m_javaScriptBreakpoints;
201     DebugServerBreakpointIDToBreakpointIdentifier m_debuggerBreakpointIdentifierToInspectorBreakpointIdentifier;
202     JSC::BreakpointID m_continueToLocationBreakpointID;
203     DebuggerFrontendDispatcher::Reason m_breakReason;
204     RefPtr<InspectorObject> m_breakAuxData;
205     ShouldDispatchResumed m_conditionToDispatchResumed { ShouldDispatchResumed::No };
206     bool m_enablePauseWhenIdle { false };
207     HashMap<AsyncCallIdentifier, AsyncCallData> m_asyncCallIdentifierToData;
208     std::optional<AsyncCallIdentifier> m_currentAsyncCallIdentifier { std::nullopt };
209     bool m_enabled { false };
210     bool m_javaScriptPauseScheduled { false };
211     bool m_hasExceptionValue { false };
212     bool m_didPauseStopwatch { false };
213     bool m_pauseOnAssertionFailures { false };
214     bool m_registeredIdleCallback { false };
215     int m_asyncStackTraceDepth { 0 };
216 };
217
218 } // namespace Inspector