1 // Copyright 2015 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef V8_INSPECTOR_V8DEBUGGERAGENTIMPL_H_
6 #define V8_INSPECTOR_V8DEBUGGERAGENTIMPL_H_
7 
8 #include <vector>
9 
10 #include "src/base/macros.h"
11 #include "src/inspector/java-script-call-frame.h"
12 #include "src/inspector/protocol/Debugger.h"
13 #include "src/inspector/protocol/Forward.h"
14 
15 namespace v8_inspector {
16 
17 struct ScriptBreakpoint;
18 class JavaScriptCallFrame;
19 class PromiseTracker;
20 class V8Debugger;
21 class V8DebuggerScript;
22 class V8InspectorImpl;
23 class V8InspectorSessionImpl;
24 class V8Regex;
25 class V8StackTraceImpl;
26 
27 using protocol::Maybe;
28 using protocol::Response;
29 
30 class V8DebuggerAgentImpl : public protocol::Debugger::Backend {
31  public:
32   enum SkipPauseRequest {
33     RequestNoSkip,
34     RequestContinue,
35     RequestStepInto,
36     RequestStepOut,
37     RequestStepFrame
38   };
39 
40   enum BreakpointSource {
41     UserBreakpointSource,
42     DebugCommandBreakpointSource,
43     MonitorCommandBreakpointSource
44   };
45 
46   V8DebuggerAgentImpl(V8InspectorSessionImpl*, protocol::FrontendChannel*,
47                       protocol::DictionaryValue* state);
48   ~V8DebuggerAgentImpl() override;
49   void restore();
50 
51   // Part of the protocol.
52   Response enable() override;
53   Response disable() override;
54   Response setBreakpointsActive(bool active) override;
55   Response setSkipAllPauses(bool skip) override;
56   Response setBreakpointByUrl(
57       int lineNumber, Maybe<String16> optionalURL,
58       Maybe<String16> optionalURLRegex, Maybe<int> optionalColumnNumber,
59       Maybe<String16> optionalCondition, String16*,
60       std::unique_ptr<protocol::Array<protocol::Debugger::Location>>* locations)
61       override;
62   Response setBreakpoint(
63       std::unique_ptr<protocol::Debugger::Location>,
64       Maybe<String16> optionalCondition, String16*,
65       std::unique_ptr<protocol::Debugger::Location>* actualLocation) override;
66   Response removeBreakpoint(const String16& breakpointId) override;
67   Response continueToLocation(
68       std::unique_ptr<protocol::Debugger::Location>) override;
69   Response searchInContent(
70       const String16& scriptId, const String16& query,
71       Maybe<bool> optionalCaseSensitive, Maybe<bool> optionalIsRegex,
72       std::unique_ptr<protocol::Array<protocol::Debugger::SearchMatch>>*)
73       override;
74   Response getPossibleBreakpoints(
75       std::unique_ptr<protocol::Debugger::Location> start,
76       Maybe<protocol::Debugger::Location> end,
77       std::unique_ptr<protocol::Array<protocol::Debugger::Location>>* locations)
78       override;
79   Response setScriptSource(
80       const String16& inScriptId, const String16& inScriptSource,
81       Maybe<bool> dryRun,
82       Maybe<protocol::Array<protocol::Debugger::CallFrame>>* optOutCallFrames,
83       Maybe<bool>* optOutStackChanged,
84       Maybe<protocol::Runtime::StackTrace>* optOutAsyncStackTrace,
85       Maybe<protocol::Runtime::ExceptionDetails>* optOutCompileError) override;
86   Response restartFrame(
87       const String16& callFrameId,
88       std::unique_ptr<protocol::Array<protocol::Debugger::CallFrame>>*
89           newCallFrames,
90       Maybe<protocol::Runtime::StackTrace>* asyncStackTrace) override;
91   Response getScriptSource(const String16& scriptId,
92                            String16* scriptSource) override;
93   Response pause() override;
94   Response resume() override;
95   Response stepOver() override;
96   Response stepInto() override;
97   Response stepOut() override;
98   Response setPauseOnExceptions(const String16& pauseState) override;
99   Response evaluateOnCallFrame(
100       const String16& callFrameId, const String16& expression,
101       Maybe<String16> objectGroup, Maybe<bool> includeCommandLineAPI,
102       Maybe<bool> silent, Maybe<bool> returnByValue,
103       Maybe<bool> generatePreview,
104       std::unique_ptr<protocol::Runtime::RemoteObject>* result,
105       Maybe<protocol::Runtime::ExceptionDetails>*) override;
106   Response setVariableValue(
107       int scopeNumber, const String16& variableName,
108       std::unique_ptr<protocol::Runtime::CallArgument> newValue,
109       const String16& callFrame) override;
110   Response setAsyncCallStackDepth(int depth) override;
111   Response setBlackboxPatterns(
112       std::unique_ptr<protocol::Array<String16>> patterns) override;
113   Response setBlackboxedRanges(
114       const String16& scriptId,
115       std::unique_ptr<protocol::Array<protocol::Debugger::ScriptPosition>>
116           positions) override;
117 
118   bool enabled();
119 
120   void setBreakpointAt(const String16& scriptId, int lineNumber,
121                        int columnNumber, BreakpointSource,
122                        const String16& condition = String16());
123   void removeBreakpointAt(const String16& scriptId, int lineNumber,
124                           int columnNumber, BreakpointSource);
125   void schedulePauseOnNextStatement(
126       const String16& breakReason,
127       std::unique_ptr<protocol::DictionaryValue> data);
128   void cancelPauseOnNextStatement();
129   void breakProgram(const String16& breakReason,
130                     std::unique_ptr<protocol::DictionaryValue> data);
131   void breakProgramOnException(const String16& breakReason,
132                                std::unique_ptr<protocol::DictionaryValue> data);
133 
134   void reset();
135 
136   // Interface for V8InspectorImpl
137   SkipPauseRequest didPause(v8::Local<v8::Context>,
138                             v8::Local<v8::Value> exception,
139                             const std::vector<String16>& hitBreakpoints,
140                             bool isPromiseRejection, bool isUncaught);
141   void didContinue();
142   void didParseSource(std::unique_ptr<V8DebuggerScript>, bool success);
143   void willExecuteScript(int scriptId);
144   void didExecuteScript();
145 
isolate()146   v8::Isolate* isolate() { return m_isolate; }
147 
148  private:
149   void enableImpl();
150 
151   SkipPauseRequest shouldSkipExceptionPause(JavaScriptCallFrame* topCallFrame);
152   SkipPauseRequest shouldSkipStepPause(JavaScriptCallFrame* topCallFrame);
153 
154   void schedulePauseOnNextStatementIfSteppingInto();
155 
156   Response currentCallFrames(
157       std::unique_ptr<protocol::Array<protocol::Debugger::CallFrame>>*);
158   std::unique_ptr<protocol::Runtime::StackTrace> currentAsyncStackTrace();
159 
160   void changeJavaScriptRecursionLevel(int step);
161 
162   void setPauseOnExceptionsImpl(int);
163 
164   std::unique_ptr<protocol::Debugger::Location> resolveBreakpoint(
165       const String16& breakpointId, const String16& scriptId,
166       const ScriptBreakpoint&, BreakpointSource);
167   void removeBreakpointImpl(const String16& breakpointId);
168   void clearBreakDetails();
169 
170   bool isCurrentCallStackEmptyOrBlackboxed();
171   bool isTopPausedCallFrameBlackboxed();
172   bool isCallFrameWithUnknownScriptOrBlackboxed(JavaScriptCallFrame*);
173 
174   void internalSetAsyncCallStackDepth(int);
175   void increaseCachedSkipStackGeneration();
176 
177   Response setBlackboxPattern(const String16& pattern);
178 
179   using ScriptsMap =
180       protocol::HashMap<String16, std::unique_ptr<V8DebuggerScript>>;
181   using BreakpointIdToDebuggerBreakpointIdsMap =
182       protocol::HashMap<String16, std::vector<String16>>;
183   using DebugServerBreakpointToBreakpointIdAndSourceMap =
184       protocol::HashMap<String16, std::pair<String16, BreakpointSource>>;
185   using MuteBreakpoins = protocol::HashMap<String16, std::pair<String16, int>>;
186 
187   enum DebuggerStep { NoStep = 0, StepInto, StepOver, StepOut };
188 
189   V8InspectorImpl* m_inspector;
190   V8Debugger* m_debugger;
191   V8InspectorSessionImpl* m_session;
192   bool m_enabled;
193   protocol::DictionaryValue* m_state;
194   protocol::Debugger::Frontend m_frontend;
195   v8::Isolate* m_isolate;
196   v8::Global<v8::Context> m_pausedContext;
197   JavaScriptCallFrames m_pausedCallFrames;
198   ScriptsMap m_scripts;
199   BreakpointIdToDebuggerBreakpointIdsMap m_breakpointIdToDebuggerBreakpointIds;
200   DebugServerBreakpointToBreakpointIdAndSourceMap m_serverBreakpoints;
201   String16 m_continueToLocationBreakpointId;
202   String16 m_breakReason;
203   std::unique_ptr<protocol::DictionaryValue> m_breakAuxData;
204   DebuggerStep m_scheduledDebuggerStep;
205   bool m_skipNextDebuggerStepOut;
206   bool m_javaScriptPauseScheduled;
207   bool m_steppingFromFramework;
208   bool m_pausingOnNativeEvent;
209 
210   int m_skippedStepFrameCount;
211   int m_recursionLevelForStepOut;
212   int m_recursionLevelForStepFrame;
213   bool m_skipAllPauses;
214 
215   std::unique_ptr<V8Regex> m_blackboxPattern;
216   protocol::HashMap<String16, std::vector<std::pair<int, int>>>
217       m_blackboxedPositions;
218 
219   DISALLOW_COPY_AND_ASSIGN(V8DebuggerAgentImpl);
220 };
221 
222 }  // namespace v8_inspector
223 
224 #endif  // V8_INSPECTOR_V8DEBUGGERAGENTIMPL_H_
225