1 /*
2  * Copyright (c) 2010, Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  *     * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *     * Redistributions in binary form must reproduce the above
11  * copyright notice, this list of conditions and the following disclaimer
12  * in the documentation and/or other materials provided with the
13  * distribution.
14  *     * Neither the name of Google Inc. nor the names of its
15  * contributors may be used to endorse or promote products derived from
16  * this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 #ifndef V8_INSPECTOR_V8_INSPECTOR_IMPL_H_
32 #define V8_INSPECTOR_V8_INSPECTOR_IMPL_H_
33 
34 #include <functional>
35 #include <map>
36 #include <memory>
37 #include <unordered_map>
38 
39 #include "include/v8-inspector.h"
40 #include "src/base/macros.h"
41 #include "src/base/platform/mutex.h"
42 #include "src/inspector/injected-script.h"
43 #include "src/inspector/protocol/Protocol.h"
44 
45 namespace v8_inspector {
46 
47 class InspectedContext;
48 class V8Console;
49 class V8ConsoleMessageStorage;
50 class V8Debugger;
51 class V8DebuggerAgentImpl;
52 class V8InspectorSessionImpl;
53 class V8ProfilerAgentImpl;
54 class V8RuntimeAgentImpl;
55 class V8StackTraceImpl;
56 
57 class V8InspectorImpl : public V8Inspector {
58  public:
59   V8_EXPORT_PRIVATE V8InspectorImpl(v8::Isolate*, V8InspectorClient*);
60   ~V8InspectorImpl() override;
61   V8InspectorImpl(const V8InspectorImpl&) = delete;
62   V8InspectorImpl& operator=(const V8InspectorImpl&) = delete;
63 
isolate()64   v8::Isolate* isolate() const { return m_isolate; }
client()65   V8InspectorClient* client() { return m_client; }
debugger()66   V8Debugger* debugger() { return m_debugger.get(); }
67   int contextGroupId(v8::Local<v8::Context>) const;
68   int contextGroupId(int contextId) const;
isolateId()69   uint64_t isolateId() const { return m_isolateId; }
70   int resolveUniqueContextId(V8DebuggerId uniqueId) const;
71 
72   v8::MaybeLocal<v8::Value> compileAndRunInternalScript(v8::Local<v8::Context>,
73                                                         v8::Local<v8::String>);
74   v8::MaybeLocal<v8::Script> compileScript(v8::Local<v8::Context>,
75                                            const String16& code,
76                                            const String16& fileName);
77   v8::MaybeLocal<v8::Context> regexContext();
78   v8::MaybeLocal<v8::Context> exceptionMetaDataContext();
79 
80   // V8Inspector implementation.
81   std::unique_ptr<V8InspectorSession> connect(int contextGroupId,
82                                               V8Inspector::Channel*,
83                                               StringView state) override;
84   void contextCreated(const V8ContextInfo&) override;
85   void contextDestroyed(v8::Local<v8::Context>) override;
86   v8::MaybeLocal<v8::Context> contextById(int contextId) override;
87   void contextCollected(int contextGroupId, int contextId);
88   void resetContextGroup(int contextGroupId) override;
89   void idleStarted() override;
90   void idleFinished() override;
91   unsigned exceptionThrown(v8::Local<v8::Context>, StringView message,
92                            v8::Local<v8::Value> exception,
93                            StringView detailedMessage, StringView url,
94                            unsigned lineNumber, unsigned columnNumber,
95                            std::unique_ptr<V8StackTrace>,
96                            int scriptId) override;
97   void exceptionRevoked(v8::Local<v8::Context>, unsigned exceptionId,
98                         StringView message) override;
99   std::unique_ptr<V8StackTrace> createStackTrace(
100       v8::Local<v8::StackTrace>) override;
101   std::unique_ptr<V8StackTrace> captureStackTrace(bool fullStack) override;
102   void asyncTaskScheduled(StringView taskName, void* task,
103                           bool recurring) override;
104   void asyncTaskCanceled(void* task) override;
105   void asyncTaskStarted(void* task) override;
106   void asyncTaskFinished(void* task) override;
107   void allAsyncTasksCanceled() override;
108 
109   V8StackTraceId storeCurrentStackTrace(StringView description) override;
110   void externalAsyncTaskStarted(const V8StackTraceId& parent) override;
111   void externalAsyncTaskFinished(const V8StackTraceId& parent) override;
112 
113   V8_EXPORT_PRIVATE bool associateExceptionData(
114       v8::Local<v8::Context>, v8::Local<v8::Value> exception,
115       v8::Local<v8::Name> key, v8::Local<v8::Value> value) override;
116 
nextExceptionId()117   unsigned nextExceptionId() { return ++m_lastExceptionId; }
118   void enableStackCapturingIfNeeded();
119   void disableStackCapturingIfNeeded();
120   void muteExceptions(int contextGroupId);
121   void unmuteExceptions(int contextGroupId);
122   V8ConsoleMessageStorage* ensureConsoleMessageStorage(int contextGroupId);
123   bool hasConsoleMessageStorage(int contextGroupId);
124   void discardInspectedContext(int contextGroupId, int contextId);
125   void disconnect(V8InspectorSessionImpl*);
126   V8InspectorSessionImpl* sessionById(int contextGroupId, int sessionId);
127   InspectedContext* getContext(int groupId, int contextId) const;
128   InspectedContext* getContext(int contextId) const;
129   V8Console* console();
130   void forEachContext(int contextGroupId,
131                       const std::function<void(InspectedContext*)>& callback);
132   void forEachSession(
133       int contextGroupId,
134       const std::function<void(V8InspectorSessionImpl*)>& callback);
135   int64_t generateUniqueId();
136   V8_EXPORT_PRIVATE v8::MaybeLocal<v8::Object> getAssociatedExceptionData(
137       v8::Local<v8::Value> exception);
138 
139   class EvaluateScope {
140    public:
141     explicit EvaluateScope(const InjectedScript::Scope& scope);
142     ~EvaluateScope();
143 
144     protocol::Response setTimeout(double timeout);
145 
146    private:
147     class TerminateTask;
148     struct CancelToken;
149 
150     const InjectedScript::Scope& m_scope;
151     v8::Isolate* m_isolate;
152     std::shared_ptr<CancelToken> m_cancelToken;
153     v8::Isolate::SafeForTerminationScope m_safeForTerminationScope;
154   };
155 
156  private:
157   v8::Isolate* m_isolate;
158   V8InspectorClient* m_client;
159   std::unique_ptr<V8Debugger> m_debugger;
160   v8::Global<v8::Context> m_regexContext;
161   v8::Global<v8::Context> m_exceptionMetaDataContext;
162   v8::Global<v8::debug::EphemeronTable> m_exceptionMetaData;
163   int m_capturingStackTracesCount;
164   unsigned m_lastExceptionId;
165   int m_lastContextId;
166   int m_lastSessionId = 0;
167   uint64_t m_isolateId;
168 
169   using MuteExceptionsMap = std::unordered_map<int, int>;
170   MuteExceptionsMap m_muteExceptionsMap;
171 
172   using ContextByIdMap =
173       std::unordered_map<int, std::unique_ptr<InspectedContext>>;
174   using ContextsByGroupMap =
175       std::unordered_map<int, std::unique_ptr<ContextByIdMap>>;
176   ContextsByGroupMap m_contexts;
177 
178   // contextGroupId -> sessionId -> session
179   std::unordered_map<int, std::map<int, V8InspectorSessionImpl*>> m_sessions;
180 
181   using ConsoleStorageMap =
182       std::unordered_map<int, std::unique_ptr<V8ConsoleMessageStorage>>;
183   ConsoleStorageMap m_consoleStorageMap;
184 
185   std::unordered_map<int, int> m_contextIdToGroupIdMap;
186   std::map<std::pair<int64_t, int64_t>, int> m_uniqueIdToContextId;
187 
188   std::unique_ptr<V8Console> m_console;
189 };
190 
191 }  // namespace v8_inspector
192 
193 #endif  // V8_INSPECTOR_V8_INSPECTOR_IMPL_H_
194