LCOV - code coverage report
Current view: top level - src/inspector - v8-inspector-session-impl.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 136 214 63.6 %
Date: 2017-04-26 Functions: 26 40 65.0 %

          Line data    Source code
       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/v8-inspector-session-impl.h"
       6             : 
       7             : #include "src/inspector/injected-script.h"
       8             : #include "src/inspector/inspected-context.h"
       9             : #include "src/inspector/protocol/Protocol.h"
      10             : #include "src/inspector/remote-object-id.h"
      11             : #include "src/inspector/search-util.h"
      12             : #include "src/inspector/string-util.h"
      13             : #include "src/inspector/v8-console-agent-impl.h"
      14             : #include "src/inspector/v8-debugger-agent-impl.h"
      15             : #include "src/inspector/v8-debugger.h"
      16             : #include "src/inspector/v8-heap-profiler-agent-impl.h"
      17             : #include "src/inspector/v8-inspector-impl.h"
      18             : #include "src/inspector/v8-profiler-agent-impl.h"
      19             : #include "src/inspector/v8-runtime-agent-impl.h"
      20             : #include "src/inspector/v8-schema-agent-impl.h"
      21             : 
      22             : namespace v8_inspector {
      23             : 
      24             : // static
      25           0 : bool V8InspectorSession::canDispatchMethod(const StringView& method) {
      26             :   return stringViewStartsWith(method,
      27           0 :                               protocol::Runtime::Metainfo::commandPrefix) ||
      28             :          stringViewStartsWith(method,
      29           0 :                               protocol::Debugger::Metainfo::commandPrefix) ||
      30             :          stringViewStartsWith(method,
      31           0 :                               protocol::Profiler::Metainfo::commandPrefix) ||
      32             :          stringViewStartsWith(
      33           0 :              method, protocol::HeapProfiler::Metainfo::commandPrefix) ||
      34             :          stringViewStartsWith(method,
      35           0 :                               protocol::Console::Metainfo::commandPrefix) ||
      36             :          stringViewStartsWith(method,
      37           0 :                               protocol::Schema::Metainfo::commandPrefix);
      38             : }
      39             : 
      40             : // static
      41           0 : int V8ContextInfo::executionContextId(v8::Local<v8::Context> context) {
      42           0 :   return InspectedContext::contextId(context);
      43             : }
      44             : 
      45        4573 : std::unique_ptr<V8InspectorSessionImpl> V8InspectorSessionImpl::create(
      46             :     V8InspectorImpl* inspector, int contextGroupId,
      47             :     V8Inspector::Channel* channel, const StringView& state) {
      48             :   return std::unique_ptr<V8InspectorSessionImpl>(
      49        9146 :       new V8InspectorSessionImpl(inspector, contextGroupId, channel, state));
      50             : }
      51             : 
      52        4573 : V8InspectorSessionImpl::V8InspectorSessionImpl(V8InspectorImpl* inspector,
      53             :                                                int contextGroupId,
      54             :                                                V8Inspector::Channel* channel,
      55        9146 :                                                const StringView& savedState)
      56             :     : m_contextGroupId(contextGroupId),
      57             :       m_inspector(inspector),
      58             :       m_channel(channel),
      59             :       m_customObjectFormatterEnabled(false),
      60             :       m_dispatcher(this),
      61             :       m_state(nullptr),
      62             :       m_runtimeAgent(nullptr),
      63             :       m_debuggerAgent(nullptr),
      64             :       m_heapProfilerAgent(nullptr),
      65             :       m_profilerAgent(nullptr),
      66             :       m_consoleAgent(nullptr),
      67        4573 :       m_schemaAgent(nullptr) {
      68        4573 :   if (savedState.length()) {
      69             :     std::unique_ptr<protocol::Value> state =
      70          72 :         protocol::StringUtil::parseJSON(toString16(savedState));
      71          36 :     if (state) m_state = protocol::DictionaryValue::cast(std::move(state));
      72          36 :     if (!m_state) m_state = protocol::DictionaryValue::create();
      73             :   } else {
      74        9074 :     m_state = protocol::DictionaryValue::create();
      75             :   }
      76             : 
      77             :   m_runtimeAgent.reset(new V8RuntimeAgentImpl(
      78        9146 :       this, this, agentState(protocol::Runtime::Metainfo::domainName)));
      79        4573 :   protocol::Runtime::Dispatcher::wire(&m_dispatcher, m_runtimeAgent.get());
      80             : 
      81             :   m_debuggerAgent.reset(new V8DebuggerAgentImpl(
      82        9146 :       this, this, agentState(protocol::Debugger::Metainfo::domainName)));
      83        4573 :   protocol::Debugger::Dispatcher::wire(&m_dispatcher, m_debuggerAgent.get());
      84             : 
      85             :   m_profilerAgent.reset(new V8ProfilerAgentImpl(
      86        9146 :       this, this, agentState(protocol::Profiler::Metainfo::domainName)));
      87        4573 :   protocol::Profiler::Dispatcher::wire(&m_dispatcher, m_profilerAgent.get());
      88             : 
      89             :   m_heapProfilerAgent.reset(new V8HeapProfilerAgentImpl(
      90        9146 :       this, this, agentState(protocol::HeapProfiler::Metainfo::domainName)));
      91             :   protocol::HeapProfiler::Dispatcher::wire(&m_dispatcher,
      92        4573 :                                            m_heapProfilerAgent.get());
      93             : 
      94             :   m_consoleAgent.reset(new V8ConsoleAgentImpl(
      95        9146 :       this, this, agentState(protocol::Console::Metainfo::domainName)));
      96        4573 :   protocol::Console::Dispatcher::wire(&m_dispatcher, m_consoleAgent.get());
      97             : 
      98             :   m_schemaAgent.reset(new V8SchemaAgentImpl(
      99        9146 :       this, this, agentState(protocol::Schema::Metainfo::domainName)));
     100        4573 :   protocol::Schema::Dispatcher::wire(&m_dispatcher, m_schemaAgent.get());
     101             : 
     102        4573 :   if (savedState.length()) {
     103          36 :     m_runtimeAgent->restore();
     104          36 :     m_debuggerAgent->restore();
     105          36 :     m_heapProfilerAgent->restore();
     106          36 :     m_profilerAgent->restore();
     107          36 :     m_consoleAgent->restore();
     108             :   }
     109        4573 : }
     110             : 
     111       18292 : V8InspectorSessionImpl::~V8InspectorSessionImpl() {
     112        9146 :   m_consoleAgent->disable();
     113        9146 :   m_profilerAgent->disable();
     114        9146 :   m_heapProfilerAgent->disable();
     115        9146 :   m_debuggerAgent->disable();
     116        9146 :   m_runtimeAgent->disable();
     117             : 
     118        4573 :   discardInjectedScripts();
     119        4573 :   m_inspector->disconnect(this);
     120        4573 : }
     121             : 
     122       27438 : protocol::DictionaryValue* V8InspectorSessionImpl::agentState(
     123             :     const String16& name) {
     124       27438 :   protocol::DictionaryValue* state = m_state->getObject(name);
     125       27438 :   if (!state) {
     126             :     std::unique_ptr<protocol::DictionaryValue> newState =
     127       27222 :         protocol::DictionaryValue::create();
     128             :     state = newState.get();
     129       54444 :     m_state->setObject(name, std::move(newState));
     130             :   }
     131       27438 :   return state;
     132             : }
     133             : 
     134             : namespace {
     135             : 
     136     1225482 : class MessageBuffer : public StringBuffer {
     137             :  public:
     138      408494 :   static std::unique_ptr<MessageBuffer> create(
     139             :       std::unique_ptr<protocol::Serializable> message) {
     140             :     return std::unique_ptr<MessageBuffer>(
     141      816988 :         new MessageBuffer(std::move(message)));
     142             :   }
     143             : 
     144      408494 :   const StringView& string() override {
     145      408494 :     if (!m_serialized) {
     146     1225482 :       m_serialized = StringBuffer::create(toStringView(m_message->serialize()));
     147             :       m_message.reset(nullptr);
     148             :     }
     149      408494 :     return m_serialized->string();
     150             :   }
     151             : 
     152             :  private:
     153             :   explicit MessageBuffer(std::unique_ptr<protocol::Serializable> message)
     154      816988 :       : m_message(std::move(message)) {}
     155             : 
     156             :   std::unique_ptr<protocol::Serializable> m_message;
     157             :   std::unique_ptr<StringBuffer> m_serialized;
     158             : };
     159             : 
     160             : }  // namespace
     161             : 
     162      209613 : void V8InspectorSessionImpl::sendProtocolResponse(
     163             :     int callId, std::unique_ptr<protocol::Serializable> message) {
     164     1257678 :   m_channel->sendResponse(callId, MessageBuffer::create(std::move(message)));
     165      209613 : }
     166             : 
     167      198881 : void V8InspectorSessionImpl::sendProtocolNotification(
     168             :     std::unique_ptr<protocol::Serializable> message) {
     169     1193286 :   m_channel->sendNotification(MessageBuffer::create(std::move(message)));
     170      198881 : }
     171             : 
     172        7580 : void V8InspectorSessionImpl::flushProtocolNotifications() {
     173        7580 :   m_channel->flushProtocolNotifications();
     174        7580 : }
     175             : 
     176           0 : void V8InspectorSessionImpl::reset() {
     177           0 :   m_debuggerAgent->reset();
     178           0 :   m_runtimeAgent->reset();
     179           0 :   discardInjectedScripts();
     180           0 : }
     181             : 
     182        4969 : void V8InspectorSessionImpl::discardInjectedScripts() {
     183             :   m_inspectedObjects.clear();
     184             :   const V8InspectorImpl::ContextByIdMap* contexts =
     185        4969 :       m_inspector->contextGroup(m_contextGroupId);
     186        4969 :   if (!contexts) return;
     187             : 
     188             :   std::vector<int> keys;
     189        4969 :   keys.reserve(contexts->size());
     190       14907 :   for (auto& idContext : *contexts) keys.push_back(idContext.first);
     191       14907 :   for (auto& key : keys) {
     192        4969 :     contexts = m_inspector->contextGroup(m_contextGroupId);
     193        4969 :     if (!contexts) continue;
     194             :     auto contextIt = contexts->find(key);
     195        4969 :     if (contextIt != contexts->end())
     196             :       contextIt->second
     197        4969 :           ->discardInjectedScript();  // This may destroy some contexts.
     198             :   }
     199             : }
     200             : 
     201      347844 : Response V8InspectorSessionImpl::findInjectedScript(
     202             :     int contextId, InjectedScript*& injectedScript) {
     203      347844 :   injectedScript = nullptr;
     204      347844 :   if (!contextId)
     205          12 :     return Response::Error("Cannot find context with specified id");
     206             : 
     207             :   const V8InspectorImpl::ContextByIdMap* contexts =
     208      347838 :       m_inspector->contextGroup(m_contextGroupId);
     209      347838 :   if (!contexts)
     210           0 :     return Response::Error("Cannot find context with specified id");
     211             : 
     212             :   auto contextsIt = contexts->find(contextId);
     213      347838 :   if (contextsIt == contexts->end())
     214          12 :     return Response::Error("Cannot find context with specified id");
     215             : 
     216             :   const std::unique_ptr<InspectedContext>& context = contextsIt->second;
     217      347832 :   if (!context->getInjectedScript()) {
     218        4109 :     if (!context->createInjectedScript())
     219           0 :       return Response::Error("Cannot access specified execution context");
     220        4109 :     if (m_customObjectFormatterEnabled)
     221           6 :       context->getInjectedScript()->setCustomObjectFormatterEnabled(true);
     222             :   }
     223      347832 :   injectedScript = context->getInjectedScript();
     224      347832 :   return Response::OK();
     225             : }
     226             : 
     227      136090 : Response V8InspectorSessionImpl::findInjectedScript(
     228             :     RemoteObjectIdBase* objectId, InjectedScript*& injectedScript) {
     229      136090 :   return findInjectedScript(objectId->contextId(), injectedScript);
     230             : }
     231             : 
     232           0 : void V8InspectorSessionImpl::releaseObjectGroup(const StringView& objectGroup) {
     233           0 :   releaseObjectGroup(toString16(objectGroup));
     234           0 : }
     235             : 
     236       64524 : void V8InspectorSessionImpl::releaseObjectGroup(const String16& objectGroup) {
     237             :   const V8InspectorImpl::ContextByIdMap* contexts =
     238       64524 :       m_inspector->contextGroup(m_contextGroupId);
     239       64524 :   if (!contexts) return;
     240             : 
     241             :   std::vector<int> keys;
     242      193572 :   for (auto& idContext : *contexts) keys.push_back(idContext.first);
     243      193572 :   for (auto& key : keys) {
     244       64524 :     contexts = m_inspector->contextGroup(m_contextGroupId);
     245       64524 :     if (!contexts) continue;
     246             :     auto contextsIt = contexts->find(key);
     247       64524 :     if (contextsIt == contexts->end()) continue;
     248             :     InjectedScript* injectedScript = contextsIt->second->getInjectedScript();
     249       64524 :     if (injectedScript)
     250             :       injectedScript->releaseObjectGroup(
     251       64524 :           objectGroup);  // This may destroy some contexts.
     252             :   }
     253             : }
     254             : 
     255           0 : bool V8InspectorSessionImpl::unwrapObject(
     256             :     std::unique_ptr<StringBuffer>* error, const StringView& objectId,
     257             :     v8::Local<v8::Value>* object, v8::Local<v8::Context>* context,
     258             :     std::unique_ptr<StringBuffer>* objectGroup) {
     259             :   String16 objectGroupString;
     260             :   Response response = unwrapObject(toString16(objectId), object, context,
     261           0 :                                    objectGroup ? &objectGroupString : nullptr);
     262           0 :   if (!response.isSuccess()) {
     263           0 :     if (error) {
     264             :       String16 errorMessage = response.errorMessage();
     265           0 :       *error = StringBufferImpl::adopt(errorMessage);
     266             :     }
     267             :     return false;
     268             :   }
     269           0 :   if (objectGroup) *objectGroup = StringBufferImpl::adopt(objectGroupString);
     270             :   return true;
     271             : }
     272             : 
     273           0 : Response V8InspectorSessionImpl::unwrapObject(const String16& objectId,
     274             :                                               v8::Local<v8::Value>* object,
     275             :                                               v8::Local<v8::Context>* context,
     276             :                                               String16* objectGroup) {
     277           0 :   std::unique_ptr<RemoteObjectId> remoteId;
     278           0 :   Response response = RemoteObjectId::parse(objectId, &remoteId);
     279           0 :   if (!response.isSuccess()) return response;
     280           0 :   InjectedScript* injectedScript = nullptr;
     281           0 :   response = findInjectedScript(remoteId.get(), injectedScript);
     282           0 :   if (!response.isSuccess()) return response;
     283           0 :   response = injectedScript->findObject(*remoteId, object);
     284           0 :   if (!response.isSuccess()) return response;
     285           0 :   *context = injectedScript->context()->context();
     286           0 :   if (objectGroup) *objectGroup = injectedScript->objectGroupName(*remoteId);
     287           0 :   return Response::OK();
     288             : }
     289             : 
     290             : std::unique_ptr<protocol::Runtime::API::RemoteObject>
     291           0 : V8InspectorSessionImpl::wrapObject(v8::Local<v8::Context> context,
     292             :                                    v8::Local<v8::Value> value,
     293             :                                    const StringView& groupName) {
     294           0 :   return wrapObject(context, value, toString16(groupName), false);
     295             : }
     296             : 
     297             : std::unique_ptr<protocol::Runtime::RemoteObject>
     298        7278 : V8InspectorSessionImpl::wrapObject(v8::Local<v8::Context> context,
     299             :                                    v8::Local<v8::Value> value,
     300             :                                    const String16& groupName,
     301             :                                    bool generatePreview) {
     302        7278 :   InjectedScript* injectedScript = nullptr;
     303       14556 :   findInjectedScript(InspectedContext::contextId(context), injectedScript);
     304        7278 :   if (!injectedScript) return nullptr;
     305        7278 :   std::unique_ptr<protocol::Runtime::RemoteObject> result;
     306       14556 :   injectedScript->wrapObject(value, groupName, false, generatePreview, &result);
     307             :   return result;
     308             : }
     309             : 
     310             : std::unique_ptr<protocol::Runtime::RemoteObject>
     311         120 : V8InspectorSessionImpl::wrapTable(v8::Local<v8::Context> context,
     312             :                                   v8::Local<v8::Value> table,
     313             :                                   v8::Local<v8::Value> columns) {
     314         120 :   InjectedScript* injectedScript = nullptr;
     315         240 :   findInjectedScript(InspectedContext::contextId(context), injectedScript);
     316         120 :   if (!injectedScript) return nullptr;
     317         120 :   return injectedScript->wrapTable(table, columns);
     318             : }
     319             : 
     320         408 : void V8InspectorSessionImpl::setCustomObjectFormatterEnabled(bool enabled) {
     321         408 :   m_customObjectFormatterEnabled = enabled;
     322             :   const V8InspectorImpl::ContextByIdMap* contexts =
     323         408 :       m_inspector->contextGroup(m_contextGroupId);
     324         816 :   if (!contexts) return;
     325        1206 :   for (auto& idContext : *contexts) {
     326             :     InjectedScript* injectedScript = idContext.second->getInjectedScript();
     327         402 :     if (injectedScript)
     328           0 :       injectedScript->setCustomObjectFormatterEnabled(enabled);
     329             :   }
     330             : }
     331             : 
     332         396 : void V8InspectorSessionImpl::reportAllContexts(V8RuntimeAgentImpl* agent) {
     333             :   const V8InspectorImpl::ContextByIdMap* contexts =
     334         396 :       m_inspector->contextGroup(m_contextGroupId);
     335         792 :   if (!contexts) return;
     336        1098 :   for (auto& idContext : *contexts)
     337         366 :     agent->reportExecutionContextCreated(idContext.second.get());
     338             : }
     339             : 
     340      209619 : void V8InspectorSessionImpl::dispatchProtocolMessage(
     341             :     const StringView& message) {
     342      419238 :   m_dispatcher.dispatch(protocol::StringUtil::parseJSON(message));
     343      209619 : }
     344             : 
     345          42 : std::unique_ptr<StringBuffer> V8InspectorSessionImpl::stateJSON() {
     346          42 :   String16 json = m_state->serialize();
     347         126 :   return StringBufferImpl::adopt(json);
     348             : }
     349             : 
     350             : std::vector<std::unique_ptr<protocol::Schema::API::Domain>>
     351           0 : V8InspectorSessionImpl::supportedDomains() {
     352             :   std::vector<std::unique_ptr<protocol::Schema::Domain>> domains =
     353           0 :       supportedDomainsImpl();
     354             :   std::vector<std::unique_ptr<protocol::Schema::API::Domain>> result;
     355           0 :   for (size_t i = 0; i < domains.size(); ++i)
     356           0 :     result.push_back(std::move(domains[i]));
     357           0 :   return result;
     358             : }
     359             : 
     360             : std::vector<std::unique_ptr<protocol::Schema::Domain>>
     361           0 : V8InspectorSessionImpl::supportedDomainsImpl() {
     362             :   std::vector<std::unique_ptr<protocol::Schema::Domain>> result;
     363             :   result.push_back(protocol::Schema::Domain::create()
     364           0 :                        .setName(protocol::Runtime::Metainfo::domainName)
     365           0 :                        .setVersion(protocol::Runtime::Metainfo::version)
     366           0 :                        .build());
     367             :   result.push_back(protocol::Schema::Domain::create()
     368           0 :                        .setName(protocol::Debugger::Metainfo::domainName)
     369           0 :                        .setVersion(protocol::Debugger::Metainfo::version)
     370           0 :                        .build());
     371             :   result.push_back(protocol::Schema::Domain::create()
     372           0 :                        .setName(protocol::Profiler::Metainfo::domainName)
     373           0 :                        .setVersion(protocol::Profiler::Metainfo::version)
     374           0 :                        .build());
     375             :   result.push_back(protocol::Schema::Domain::create()
     376           0 :                        .setName(protocol::HeapProfiler::Metainfo::domainName)
     377           0 :                        .setVersion(protocol::HeapProfiler::Metainfo::version)
     378           0 :                        .build());
     379             :   result.push_back(protocol::Schema::Domain::create()
     380           0 :                        .setName(protocol::Schema::Metainfo::domainName)
     381           0 :                        .setVersion(protocol::Schema::Metainfo::version)
     382           0 :                        .build());
     383           0 :   return result;
     384             : }
     385             : 
     386           0 : void V8InspectorSessionImpl::addInspectedObject(
     387             :     std::unique_ptr<V8InspectorSession::Inspectable> inspectable) {
     388           0 :   m_inspectedObjects.insert(m_inspectedObjects.begin(), std::move(inspectable));
     389           0 :   if (m_inspectedObjects.size() > kInspectedObjectBufferSize)
     390           0 :     m_inspectedObjects.resize(kInspectedObjectBufferSize);
     391           0 : }
     392             : 
     393           6 : V8InspectorSession::Inspectable* V8InspectorSessionImpl::inspectedObject(
     394             :     unsigned num) {
     395          12 :   if (num >= m_inspectedObjects.size()) return nullptr;
     396           0 :   return m_inspectedObjects[num].get();
     397             : }
     398             : 
     399         114 : void V8InspectorSessionImpl::schedulePauseOnNextStatement(
     400             :     const StringView& breakReason, const StringView& breakDetails) {
     401             :   m_debuggerAgent->schedulePauseOnNextStatement(
     402             :       toString16(breakReason),
     403             :       protocol::DictionaryValue::cast(
     404         684 :           protocol::StringUtil::parseJSON(breakDetails)));
     405         114 : }
     406             : 
     407          54 : void V8InspectorSessionImpl::cancelPauseOnNextStatement() {
     408          54 :   m_debuggerAgent->cancelPauseOnNextStatement();
     409          54 : }
     410             : 
     411          66 : void V8InspectorSessionImpl::breakProgram(const StringView& breakReason,
     412             :                                           const StringView& breakDetails) {
     413             :   m_debuggerAgent->breakProgram(
     414             :       toString16(breakReason),
     415             :       protocol::DictionaryValue::cast(
     416         396 :           protocol::StringUtil::parseJSON(breakDetails)));
     417          66 : }
     418             : 
     419           0 : void V8InspectorSessionImpl::setSkipAllPauses(bool skip) {
     420           0 :   m_debuggerAgent->setSkipAllPauses(skip);
     421           0 : }
     422             : 
     423           0 : void V8InspectorSessionImpl::resume() { m_debuggerAgent->resume(); }
     424             : 
     425           0 : void V8InspectorSessionImpl::stepOver() { m_debuggerAgent->stepOver(); }
     426             : 
     427             : std::vector<std::unique_ptr<protocol::Debugger::API::SearchMatch>>
     428           0 : V8InspectorSessionImpl::searchInTextByLines(const StringView& text,
     429             :                                             const StringView& query,
     430             :                                             bool caseSensitive, bool isRegex) {
     431             :   // TODO(dgozman): search may operate on StringView and avoid copying |text|.
     432             :   std::vector<std::unique_ptr<protocol::Debugger::SearchMatch>> matches =
     433             :       searchInTextByLinesImpl(this, toString16(text), toString16(query),
     434           0 :                               caseSensitive, isRegex);
     435             :   std::vector<std::unique_ptr<protocol::Debugger::API::SearchMatch>> result;
     436           0 :   for (size_t i = 0; i < matches.size(); ++i)
     437           0 :     result.push_back(std::move(matches[i]));
     438           0 :   return result;
     439             : }
     440             : 
     441             : }  // namespace v8_inspector

Generated by: LCOV version 1.10