Index: src/inspector/V8InspectorSessionImpl.cpp |
diff --git a/src/inspector/V8InspectorSessionImpl.cpp b/src/inspector/V8InspectorSessionImpl.cpp |
new file mode 100644 |
index 0000000000000000000000000000000000000000..31fe22108ba9a223c1c418bc8161e829ba25fbee |
--- /dev/null |
+++ b/src/inspector/V8InspectorSessionImpl.cpp |
@@ -0,0 +1,420 @@ |
+// Copyright 2016 the V8 project authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "src/inspector/V8InspectorSessionImpl.h" |
+ |
+#include "src/inspector/InjectedScript.h" |
+#include "src/inspector/InspectedContext.h" |
+#include "src/inspector/RemoteObjectId.h" |
+#include "src/inspector/SearchUtil.h" |
+#include "src/inspector/StringUtil.h" |
+#include "src/inspector/V8ConsoleAgentImpl.h" |
+#include "src/inspector/V8Debugger.h" |
+#include "src/inspector/V8DebuggerAgentImpl.h" |
+#include "src/inspector/V8HeapProfilerAgentImpl.h" |
+#include "src/inspector/V8InspectorImpl.h" |
+#include "src/inspector/V8ProfilerAgentImpl.h" |
+#include "src/inspector/V8RuntimeAgentImpl.h" |
+#include "src/inspector/V8SchemaAgentImpl.h" |
+#include "src/inspector/protocol/Protocol.h" |
+#include "src/inspector/public/V8ContextInfo.h" |
+#include "src/inspector/public/V8InspectorClient.h" |
+ |
+namespace v8_inspector { |
+ |
+// static |
+bool V8InspectorSession::canDispatchMethod(const StringView& method) { |
+ return stringViewStartsWith(method, |
+ protocol::Runtime::Metainfo::commandPrefix) || |
+ stringViewStartsWith(method, |
+ protocol::Debugger::Metainfo::commandPrefix) || |
+ stringViewStartsWith(method, |
+ protocol::Profiler::Metainfo::commandPrefix) || |
+ stringViewStartsWith( |
+ method, protocol::HeapProfiler::Metainfo::commandPrefix) || |
+ stringViewStartsWith(method, |
+ protocol::Console::Metainfo::commandPrefix) || |
+ stringViewStartsWith(method, |
+ protocol::Schema::Metainfo::commandPrefix); |
+} |
+ |
+std::unique_ptr<V8InspectorSessionImpl> V8InspectorSessionImpl::create( |
+ V8InspectorImpl* inspector, int contextGroupId, |
+ V8Inspector::Channel* channel, const StringView& state) { |
+ return wrapUnique( |
+ new V8InspectorSessionImpl(inspector, contextGroupId, channel, state)); |
+} |
+ |
+V8InspectorSessionImpl::V8InspectorSessionImpl(V8InspectorImpl* inspector, |
+ int contextGroupId, |
+ V8Inspector::Channel* channel, |
+ const StringView& savedState) |
+ : m_contextGroupId(contextGroupId), |
+ m_inspector(inspector), |
+ m_channel(channel), |
+ m_customObjectFormatterEnabled(false), |
+ m_dispatcher(this), |
+ m_state(nullptr), |
+ m_runtimeAgent(nullptr), |
+ m_debuggerAgent(nullptr), |
+ m_heapProfilerAgent(nullptr), |
+ m_profilerAgent(nullptr), |
+ m_consoleAgent(nullptr), |
+ m_schemaAgent(nullptr) { |
+ if (savedState.length()) { |
+ std::unique_ptr<protocol::Value> state = |
+ protocol::parseJSON(toString16(savedState)); |
+ if (state) m_state = protocol::DictionaryValue::cast(std::move(state)); |
+ if (!m_state) m_state = protocol::DictionaryValue::create(); |
+ } else { |
+ m_state = protocol::DictionaryValue::create(); |
+ } |
+ |
+ m_runtimeAgent = wrapUnique(new V8RuntimeAgentImpl( |
+ this, this, agentState(protocol::Runtime::Metainfo::domainName))); |
+ protocol::Runtime::Dispatcher::wire(&m_dispatcher, m_runtimeAgent.get()); |
+ |
+ m_debuggerAgent = wrapUnique(new V8DebuggerAgentImpl( |
+ this, this, agentState(protocol::Debugger::Metainfo::domainName))); |
+ protocol::Debugger::Dispatcher::wire(&m_dispatcher, m_debuggerAgent.get()); |
+ |
+ m_profilerAgent = wrapUnique(new V8ProfilerAgentImpl( |
+ this, this, agentState(protocol::Profiler::Metainfo::domainName))); |
+ protocol::Profiler::Dispatcher::wire(&m_dispatcher, m_profilerAgent.get()); |
+ |
+ m_heapProfilerAgent = wrapUnique(new V8HeapProfilerAgentImpl( |
+ this, this, agentState(protocol::HeapProfiler::Metainfo::domainName))); |
+ protocol::HeapProfiler::Dispatcher::wire(&m_dispatcher, |
+ m_heapProfilerAgent.get()); |
+ |
+ m_consoleAgent = wrapUnique(new V8ConsoleAgentImpl( |
+ this, this, agentState(protocol::Console::Metainfo::domainName))); |
+ protocol::Console::Dispatcher::wire(&m_dispatcher, m_consoleAgent.get()); |
+ |
+ m_schemaAgent = wrapUnique(new V8SchemaAgentImpl( |
+ this, this, agentState(protocol::Schema::Metainfo::domainName))); |
+ protocol::Schema::Dispatcher::wire(&m_dispatcher, m_schemaAgent.get()); |
+ |
+ if (savedState.length()) { |
+ m_runtimeAgent->restore(); |
+ m_debuggerAgent->restore(); |
+ m_heapProfilerAgent->restore(); |
+ m_profilerAgent->restore(); |
+ m_consoleAgent->restore(); |
+ } |
+} |
+ |
+V8InspectorSessionImpl::~V8InspectorSessionImpl() { |
+ ErrorString errorString; |
+ m_consoleAgent->disable(&errorString); |
+ m_profilerAgent->disable(&errorString); |
+ m_heapProfilerAgent->disable(&errorString); |
+ m_debuggerAgent->disable(&errorString); |
+ m_runtimeAgent->disable(&errorString); |
+ |
+ discardInjectedScripts(); |
+ m_inspector->disconnect(this); |
+} |
+ |
+protocol::DictionaryValue* V8InspectorSessionImpl::agentState( |
+ const String16& name) { |
+ protocol::DictionaryValue* state = m_state->getObject(name); |
+ if (!state) { |
+ std::unique_ptr<protocol::DictionaryValue> newState = |
+ protocol::DictionaryValue::create(); |
+ state = newState.get(); |
+ m_state->setObject(name, std::move(newState)); |
+ } |
+ return state; |
+} |
+ |
+void V8InspectorSessionImpl::sendProtocolResponse(int callId, |
+ const String16& message) { |
+ m_channel->sendProtocolResponse(callId, toStringView(message)); |
+} |
+ |
+void V8InspectorSessionImpl::sendProtocolNotification(const String16& message) { |
+ m_channel->sendProtocolNotification(toStringView(message)); |
+} |
+ |
+void V8InspectorSessionImpl::flushProtocolNotifications() { |
+ m_channel->flushProtocolNotifications(); |
+} |
+ |
+void V8InspectorSessionImpl::reset() { |
+ m_debuggerAgent->reset(); |
+ m_runtimeAgent->reset(); |
+ discardInjectedScripts(); |
+} |
+ |
+void V8InspectorSessionImpl::discardInjectedScripts() { |
+ m_inspectedObjects.clear(); |
+ const V8InspectorImpl::ContextByIdMap* contexts = |
+ m_inspector->contextGroup(m_contextGroupId); |
+ if (!contexts) return; |
+ |
+ std::vector<int> keys; |
+ keys.reserve(contexts->size()); |
+ for (auto& idContext : *contexts) keys.push_back(idContext.first); |
+ for (auto& key : keys) { |
+ contexts = m_inspector->contextGroup(m_contextGroupId); |
+ if (!contexts) continue; |
+ auto contextIt = contexts->find(key); |
+ if (contextIt != contexts->end()) |
+ contextIt->second |
+ ->discardInjectedScript(); // This may destroy some contexts. |
+ } |
+} |
+ |
+InjectedScript* V8InspectorSessionImpl::findInjectedScript( |
+ ErrorString* errorString, int contextId) { |
+ if (!contextId) { |
+ *errorString = "Cannot find context with specified id"; |
+ return nullptr; |
+ } |
+ |
+ const V8InspectorImpl::ContextByIdMap* contexts = |
+ m_inspector->contextGroup(m_contextGroupId); |
+ if (!contexts) { |
+ *errorString = "Cannot find context with specified id"; |
+ return nullptr; |
+ } |
+ |
+ auto contextsIt = contexts->find(contextId); |
+ if (contextsIt == contexts->end()) { |
+ *errorString = "Cannot find context with specified id"; |
+ return nullptr; |
+ } |
+ |
+ const std::unique_ptr<InspectedContext>& context = contextsIt->second; |
+ if (!context->getInjectedScript()) { |
+ context->createInjectedScript(); |
+ if (!context->getInjectedScript()) { |
+ *errorString = "Cannot access specified execution context"; |
+ return nullptr; |
+ } |
+ if (m_customObjectFormatterEnabled) |
+ context->getInjectedScript()->setCustomObjectFormatterEnabled(true); |
+ } |
+ return context->getInjectedScript(); |
+} |
+ |
+InjectedScript* V8InspectorSessionImpl::findInjectedScript( |
+ ErrorString* errorString, RemoteObjectIdBase* objectId) { |
+ return objectId ? findInjectedScript(errorString, objectId->contextId()) |
+ : nullptr; |
+} |
+ |
+void V8InspectorSessionImpl::releaseObjectGroup(const StringView& objectGroup) { |
+ releaseObjectGroup(toString16(objectGroup)); |
+} |
+ |
+void V8InspectorSessionImpl::releaseObjectGroup(const String16& objectGroup) { |
+ const V8InspectorImpl::ContextByIdMap* contexts = |
+ m_inspector->contextGroup(m_contextGroupId); |
+ if (!contexts) return; |
+ |
+ std::vector<int> keys; |
+ for (auto& idContext : *contexts) keys.push_back(idContext.first); |
+ for (auto& key : keys) { |
+ contexts = m_inspector->contextGroup(m_contextGroupId); |
+ if (!contexts) continue; |
+ auto contextsIt = contexts->find(key); |
+ if (contextsIt == contexts->end()) continue; |
+ InjectedScript* injectedScript = contextsIt->second->getInjectedScript(); |
+ if (injectedScript) |
+ injectedScript->releaseObjectGroup( |
+ objectGroup); // This may destroy some contexts. |
+ } |
+} |
+ |
+bool V8InspectorSessionImpl::unwrapObject( |
+ std::unique_ptr<StringBuffer>* error, const StringView& objectId, |
+ v8::Local<v8::Value>* object, v8::Local<v8::Context>* context, |
+ std::unique_ptr<StringBuffer>* objectGroup) { |
+ ErrorString errorString; |
+ String16 objectGroupString; |
+ bool result = |
+ unwrapObject(&errorString, toString16(objectId), object, context, |
+ objectGroup ? &objectGroupString : nullptr); |
+ if (error) *error = StringBufferImpl::adopt(errorString); |
+ if (objectGroup) *objectGroup = StringBufferImpl::adopt(objectGroupString); |
+ return result; |
+} |
+ |
+bool V8InspectorSessionImpl::unwrapObject(ErrorString* errorString, |
+ const String16& objectId, |
+ v8::Local<v8::Value>* object, |
+ v8::Local<v8::Context>* context, |
+ String16* objectGroup) { |
+ std::unique_ptr<RemoteObjectId> remoteId = |
+ RemoteObjectId::parse(errorString, objectId); |
+ if (!remoteId) return false; |
+ InjectedScript* injectedScript = |
+ findInjectedScript(errorString, remoteId.get()); |
+ if (!injectedScript) return false; |
+ if (!injectedScript->findObject(errorString, *remoteId, object)) return false; |
+ *context = injectedScript->context()->context(); |
+ if (objectGroup) *objectGroup = injectedScript->objectGroupName(*remoteId); |
+ return true; |
+} |
+ |
+std::unique_ptr<protocol::Runtime::API::RemoteObject> |
+V8InspectorSessionImpl::wrapObject(v8::Local<v8::Context> context, |
+ v8::Local<v8::Value> value, |
+ const StringView& groupName) { |
+ return wrapObject(context, value, toString16(groupName), false); |
+} |
+ |
+std::unique_ptr<protocol::Runtime::RemoteObject> |
+V8InspectorSessionImpl::wrapObject(v8::Local<v8::Context> context, |
+ v8::Local<v8::Value> value, |
+ const String16& groupName, |
+ bool generatePreview) { |
+ ErrorString errorString; |
+ InjectedScript* injectedScript = |
+ findInjectedScript(&errorString, V8Debugger::contextId(context)); |
+ if (!injectedScript) return nullptr; |
+ return injectedScript->wrapObject(&errorString, value, groupName, false, |
+ generatePreview); |
+} |
+ |
+std::unique_ptr<protocol::Runtime::RemoteObject> |
+V8InspectorSessionImpl::wrapTable(v8::Local<v8::Context> context, |
+ v8::Local<v8::Value> table, |
+ v8::Local<v8::Value> columns) { |
+ ErrorString errorString; |
+ InjectedScript* injectedScript = |
+ findInjectedScript(&errorString, V8Debugger::contextId(context)); |
+ if (!injectedScript) return nullptr; |
+ return injectedScript->wrapTable(table, columns); |
+} |
+ |
+void V8InspectorSessionImpl::setCustomObjectFormatterEnabled(bool enabled) { |
+ m_customObjectFormatterEnabled = enabled; |
+ const V8InspectorImpl::ContextByIdMap* contexts = |
+ m_inspector->contextGroup(m_contextGroupId); |
+ if (!contexts) return; |
+ for (auto& idContext : *contexts) { |
+ InjectedScript* injectedScript = idContext.second->getInjectedScript(); |
+ if (injectedScript) |
+ injectedScript->setCustomObjectFormatterEnabled(enabled); |
+ } |
+} |
+ |
+void V8InspectorSessionImpl::reportAllContexts(V8RuntimeAgentImpl* agent) { |
+ const V8InspectorImpl::ContextByIdMap* contexts = |
+ m_inspector->contextGroup(m_contextGroupId); |
+ if (!contexts) return; |
+ for (auto& idContext : *contexts) |
+ agent->reportExecutionContextCreated(idContext.second.get()); |
+} |
+ |
+void V8InspectorSessionImpl::dispatchProtocolMessage( |
+ const StringView& message) { |
+ m_dispatcher.dispatch(protocol::parseJSON(message)); |
+} |
+ |
+std::unique_ptr<StringBuffer> V8InspectorSessionImpl::stateJSON() { |
+ String16 json = m_state->toJSONString(); |
+ return StringBufferImpl::adopt(json); |
+} |
+ |
+std::vector<std::unique_ptr<protocol::Schema::API::Domain>> |
+V8InspectorSessionImpl::supportedDomains() { |
+ std::vector<std::unique_ptr<protocol::Schema::Domain>> domains = |
+ supportedDomainsImpl(); |
+ std::vector<std::unique_ptr<protocol::Schema::API::Domain>> result; |
+ for (size_t i = 0; i < domains.size(); ++i) |
+ result.push_back(std::move(domains[i])); |
+ return result; |
+} |
+ |
+std::vector<std::unique_ptr<protocol::Schema::Domain>> |
+V8InspectorSessionImpl::supportedDomainsImpl() { |
+ std::vector<std::unique_ptr<protocol::Schema::Domain>> result; |
+ result.push_back(protocol::Schema::Domain::create() |
+ .setName(protocol::Runtime::Metainfo::domainName) |
+ .setVersion(protocol::Runtime::Metainfo::version) |
+ .build()); |
+ result.push_back(protocol::Schema::Domain::create() |
+ .setName(protocol::Debugger::Metainfo::domainName) |
+ .setVersion(protocol::Debugger::Metainfo::version) |
+ .build()); |
+ result.push_back(protocol::Schema::Domain::create() |
+ .setName(protocol::Profiler::Metainfo::domainName) |
+ .setVersion(protocol::Profiler::Metainfo::version) |
+ .build()); |
+ result.push_back(protocol::Schema::Domain::create() |
+ .setName(protocol::HeapProfiler::Metainfo::domainName) |
+ .setVersion(protocol::HeapProfiler::Metainfo::version) |
+ .build()); |
+ result.push_back(protocol::Schema::Domain::create() |
+ .setName(protocol::Schema::Metainfo::domainName) |
+ .setVersion(protocol::Schema::Metainfo::version) |
+ .build()); |
+ return result; |
+} |
+ |
+void V8InspectorSessionImpl::addInspectedObject( |
+ std::unique_ptr<V8InspectorSession::Inspectable> inspectable) { |
+ m_inspectedObjects.insert(m_inspectedObjects.begin(), std::move(inspectable)); |
+ if (m_inspectedObjects.size() > kInspectedObjectBufferSize) |
+ m_inspectedObjects.resize(kInspectedObjectBufferSize); |
+} |
+ |
+V8InspectorSession::Inspectable* V8InspectorSessionImpl::inspectedObject( |
+ unsigned num) { |
+ if (num >= m_inspectedObjects.size()) return nullptr; |
+ return m_inspectedObjects[num].get(); |
+} |
+ |
+void V8InspectorSessionImpl::schedulePauseOnNextStatement( |
+ const StringView& breakReason, const StringView& breakDetails) { |
+ m_debuggerAgent->schedulePauseOnNextStatement( |
+ toString16(breakReason), |
+ protocol::DictionaryValue::cast(protocol::parseJSON(breakDetails))); |
+} |
+ |
+void V8InspectorSessionImpl::cancelPauseOnNextStatement() { |
+ m_debuggerAgent->cancelPauseOnNextStatement(); |
+} |
+ |
+void V8InspectorSessionImpl::breakProgram(const StringView& breakReason, |
+ const StringView& breakDetails) { |
+ m_debuggerAgent->breakProgram( |
+ toString16(breakReason), |
+ protocol::DictionaryValue::cast(protocol::parseJSON(breakDetails))); |
+} |
+ |
+void V8InspectorSessionImpl::setSkipAllPauses(bool skip) { |
+ ErrorString errorString; |
+ m_debuggerAgent->setSkipAllPauses(&errorString, skip); |
+} |
+ |
+void V8InspectorSessionImpl::resume() { |
+ ErrorString errorString; |
+ m_debuggerAgent->resume(&errorString); |
+} |
+ |
+void V8InspectorSessionImpl::stepOver() { |
+ ErrorString errorString; |
+ m_debuggerAgent->stepOver(&errorString); |
+} |
+ |
+std::vector<std::unique_ptr<protocol::Debugger::API::SearchMatch>> |
+V8InspectorSessionImpl::searchInTextByLines(const StringView& text, |
+ const StringView& query, |
+ bool caseSensitive, bool isRegex) { |
+ // TODO(dgozman): search may operate on StringView and avoid copying |text|. |
+ std::vector<std::unique_ptr<protocol::Debugger::SearchMatch>> matches = |
+ searchInTextByLinesImpl(this, toString16(text), toString16(query), |
+ caseSensitive, isRegex); |
+ std::vector<std::unique_ptr<protocol::Debugger::API::SearchMatch>> result; |
+ for (size_t i = 0; i < matches.size(); ++i) |
+ result.push_back(std::move(matches[i])); |
+ return result; |
+} |
+ |
+} // namespace v8_inspector |