| 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
|
|
|