1 // Copyright 2016 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 #include "src/inspector/inspected-context.h"
6
7 #include "src/debug/debug-interface.h"
8 #include "src/inspector/injected-script.h"
9 #include "src/inspector/string-util.h"
10 #include "src/inspector/v8-console.h"
11 #include "src/inspector/v8-inspector-impl.h"
12
13 #include "include/v8-inspector.h"
14
15 namespace v8_inspector {
16
17 class InspectedContext::WeakCallbackData {
18 public:
WeakCallbackData(InspectedContext * context,V8InspectorImpl * inspector,int groupId,int contextId)19 WeakCallbackData(InspectedContext* context, V8InspectorImpl* inspector,
20 int groupId, int contextId)
21 : m_context(context),
22 m_inspector(inspector),
23 m_groupId(groupId),
24 m_contextId(contextId) {}
25
resetContext(const v8::WeakCallbackInfo<WeakCallbackData> & data)26 static void resetContext(const v8::WeakCallbackInfo<WeakCallbackData>& data) {
27 // InspectedContext is alive here because weak handler is still alive.
28 data.GetParameter()->m_context->m_weakCallbackData = nullptr;
29 data.GetParameter()->m_context->m_context.Reset();
30 data.SetSecondPassCallback(&callContextCollected);
31 }
32
callContextCollected(const v8::WeakCallbackInfo<WeakCallbackData> & data)33 static void callContextCollected(
34 const v8::WeakCallbackInfo<WeakCallbackData>& data) {
35 // InspectedContext can be dead here since anything can happen between first
36 // and second pass callback.
37 WeakCallbackData* callbackData = data.GetParameter();
38 callbackData->m_inspector->contextCollected(callbackData->m_groupId,
39 callbackData->m_contextId);
40 delete callbackData;
41 }
42
43 private:
44 InspectedContext* m_context;
45 V8InspectorImpl* m_inspector;
46 int m_groupId;
47 int m_contextId;
48 };
49
InspectedContext(V8InspectorImpl * inspector,const V8ContextInfo & info,int contextId)50 InspectedContext::InspectedContext(V8InspectorImpl* inspector,
51 const V8ContextInfo& info, int contextId)
52 : m_inspector(inspector),
53 m_context(info.context->GetIsolate(), info.context),
54 m_contextId(contextId),
55 m_contextGroupId(info.contextGroupId),
56 m_origin(toString16(info.origin)),
57 m_humanReadableName(toString16(info.humanReadableName)),
58 m_auxData(toString16(info.auxData)) {
59 v8::debug::SetContextId(info.context, contextId);
60 m_weakCallbackData =
61 new WeakCallbackData(this, m_inspector, m_contextGroupId, m_contextId);
62 m_context.SetWeak(m_weakCallbackData,
63 &InspectedContext::WeakCallbackData::resetContext,
64 v8::WeakCallbackType::kParameter);
65 if (!info.hasMemoryOnConsole) return;
66 v8::Context::Scope contextScope(info.context);
67 v8::Local<v8::Object> global = info.context->Global();
68 v8::Local<v8::Value> console;
69 if (global->Get(info.context, toV8String(m_inspector->isolate(), "console"))
70 .ToLocal(&console) &&
71 console->IsObject()) {
72 m_inspector->console()->installMemoryGetter(
73 info.context, v8::Local<v8::Object>::Cast(console));
74 }
75 }
76
~InspectedContext()77 InspectedContext::~InspectedContext() {
78 // If we destory InspectedContext before weak callback is invoked then we need
79 // to delete data here.
80 if (!m_context.IsEmpty()) delete m_weakCallbackData;
81 }
82
83 // static
contextId(v8::Local<v8::Context> context)84 int InspectedContext::contextId(v8::Local<v8::Context> context) {
85 return v8::debug::GetContextId(context);
86 }
87
context() const88 v8::Local<v8::Context> InspectedContext::context() const {
89 return m_context.Get(isolate());
90 }
91
isolate() const92 v8::Isolate* InspectedContext::isolate() const {
93 return m_inspector->isolate();
94 }
95
isReported(int sessionId) const96 bool InspectedContext::isReported(int sessionId) const {
97 return m_reportedSessionIds.find(sessionId) != m_reportedSessionIds.cend();
98 }
99
setReported(int sessionId,bool reported)100 void InspectedContext::setReported(int sessionId, bool reported) {
101 if (reported)
102 m_reportedSessionIds.insert(sessionId);
103 else
104 m_reportedSessionIds.erase(sessionId);
105 }
106
getInjectedScript(int sessionId)107 InjectedScript* InspectedContext::getInjectedScript(int sessionId) {
108 auto it = m_injectedScripts.find(sessionId);
109 return it == m_injectedScripts.end() ? nullptr : it->second.get();
110 }
111
createInjectedScript(int sessionId)112 bool InspectedContext::createInjectedScript(int sessionId) {
113 std::unique_ptr<InjectedScript> injectedScript =
114 InjectedScript::create(this, sessionId);
115 // InjectedScript::create can destroy |this|.
116 if (!injectedScript) return false;
117 CHECK(m_injectedScripts.find(sessionId) == m_injectedScripts.end());
118 m_injectedScripts[sessionId] = std::move(injectedScript);
119 return true;
120 }
121
discardInjectedScript(int sessionId)122 void InspectedContext::discardInjectedScript(int sessionId) {
123 m_injectedScripts.erase(sessionId);
124 }
125
126 } // namespace v8_inspector
127