LCOV - code coverage report
Current view: top level - src/inspector - v8-inspector-session-impl.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 161 244 66.0 %
Date: 2019-04-19 Functions: 30 42 71.4 %

          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           0 :   return stringViewStartsWith(method,
      27           0 :                               protocol::Runtime::Metainfo::commandPrefix) ||
      28           0 :          stringViewStartsWith(method,
      29           0 :                               protocol::Debugger::Metainfo::commandPrefix) ||
      30           0 :          stringViewStartsWith(method,
      31           0 :                               protocol::Profiler::Metainfo::commandPrefix) ||
      32           0 :          stringViewStartsWith(
      33           0 :              method, protocol::HeapProfiler::Metainfo::commandPrefix) ||
      34           0 :          stringViewStartsWith(method,
      35           0 :                               protocol::Console::Metainfo::commandPrefix) ||
      36           0 :          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        3879 : std::unique_ptr<V8InspectorSessionImpl> V8InspectorSessionImpl::create(
      46             :     V8InspectorImpl* inspector, int contextGroupId, int sessionId,
      47             :     V8Inspector::Channel* channel, const StringView& state) {
      48             :   return std::unique_ptr<V8InspectorSessionImpl>(new V8InspectorSessionImpl(
      49        7758 :       inspector, contextGroupId, sessionId, channel, state));
      50             : }
      51             : 
      52        3879 : V8InspectorSessionImpl::V8InspectorSessionImpl(V8InspectorImpl* inspector,
      53             :                                                int contextGroupId,
      54             :                                                int sessionId,
      55             :                                                V8Inspector::Channel* channel,
      56             :                                                const StringView& savedState)
      57             :     : m_contextGroupId(contextGroupId),
      58             :       m_sessionId(sessionId),
      59             :       m_inspector(inspector),
      60             :       m_channel(channel),
      61             :       m_customObjectFormatterEnabled(false),
      62             :       m_dispatcher(this),
      63             :       m_state(nullptr),
      64             :       m_runtimeAgent(nullptr),
      65             :       m_debuggerAgent(nullptr),
      66             :       m_heapProfilerAgent(nullptr),
      67             :       m_profilerAgent(nullptr),
      68             :       m_consoleAgent(nullptr),
      69        7758 :       m_schemaAgent(nullptr) {
      70        3879 :   if (savedState.length()) {
      71             :     std::unique_ptr<protocol::Value> state =
      72         110 :         protocol::StringUtil::parseJSON(toString16(savedState));
      73          55 :     if (state) m_state = protocol::DictionaryValue::cast(std::move(state));
      74          55 :     if (!m_state) m_state = protocol::DictionaryValue::create();
      75             :   } else {
      76             :     m_state = protocol::DictionaryValue::create();
      77             :   }
      78             : 
      79       11637 :   m_state->getBoolean("use_binary_protocol", &use_binary_protocol_);
      80             : 
      81        3879 :   m_runtimeAgent.reset(new V8RuntimeAgentImpl(
      82       11637 :       this, this, agentState(protocol::Runtime::Metainfo::domainName)));
      83        3879 :   protocol::Runtime::Dispatcher::wire(&m_dispatcher, m_runtimeAgent.get());
      84             : 
      85        3879 :   m_debuggerAgent.reset(new V8DebuggerAgentImpl(
      86       11637 :       this, this, agentState(protocol::Debugger::Metainfo::domainName)));
      87        3879 :   protocol::Debugger::Dispatcher::wire(&m_dispatcher, m_debuggerAgent.get());
      88             : 
      89        3879 :   m_profilerAgent.reset(new V8ProfilerAgentImpl(
      90       11637 :       this, this, agentState(protocol::Profiler::Metainfo::domainName)));
      91        3879 :   protocol::Profiler::Dispatcher::wire(&m_dispatcher, m_profilerAgent.get());
      92             : 
      93        3879 :   m_heapProfilerAgent.reset(new V8HeapProfilerAgentImpl(
      94       11637 :       this, this, agentState(protocol::HeapProfiler::Metainfo::domainName)));
      95             :   protocol::HeapProfiler::Dispatcher::wire(&m_dispatcher,
      96        3879 :                                            m_heapProfilerAgent.get());
      97             : 
      98        3879 :   m_consoleAgent.reset(new V8ConsoleAgentImpl(
      99       11637 :       this, this, agentState(protocol::Console::Metainfo::domainName)));
     100        3879 :   protocol::Console::Dispatcher::wire(&m_dispatcher, m_consoleAgent.get());
     101             : 
     102        3879 :   m_schemaAgent.reset(new V8SchemaAgentImpl(
     103       11637 :       this, this, agentState(protocol::Schema::Metainfo::domainName)));
     104        3879 :   protocol::Schema::Dispatcher::wire(&m_dispatcher, m_schemaAgent.get());
     105             : 
     106        3879 :   if (savedState.length()) {
     107          55 :     m_runtimeAgent->restore();
     108          55 :     m_debuggerAgent->restore();
     109          55 :     m_heapProfilerAgent->restore();
     110          55 :     m_profilerAgent->restore();
     111          55 :     m_consoleAgent->restore();
     112             :   }
     113        3879 : }
     114             : 
     115       19395 : V8InspectorSessionImpl::~V8InspectorSessionImpl() {
     116        3879 :   discardInjectedScripts();
     117        7758 :   m_consoleAgent->disable();
     118        7758 :   m_profilerAgent->disable();
     119        7758 :   m_heapProfilerAgent->disable();
     120        7758 :   m_debuggerAgent->disable();
     121        7758 :   m_runtimeAgent->disable();
     122        3879 :   m_inspector->disconnect(this);
     123        7758 : }
     124             : 
     125       23274 : protocol::DictionaryValue* V8InspectorSessionImpl::agentState(
     126             :     const String16& name) {
     127       23274 :   protocol::DictionaryValue* state = m_state->getObject(name);
     128       23274 :   if (!state) {
     129             :     std::unique_ptr<protocol::DictionaryValue> newState =
     130             :         protocol::DictionaryValue::create();
     131             :     state = newState.get();
     132       45948 :     m_state->setObject(name, std::move(newState));
     133             :   }
     134       23274 :   return state;
     135             : }
     136             : 
     137             : namespace {
     138             : 
     139      990015 : class MessageBuffer : public StringBuffer {
     140             :  public:
     141             :   static std::unique_ptr<MessageBuffer> create(
     142             :       std::unique_ptr<protocol::Serializable> message, bool binary) {
     143             :     return std::unique_ptr<MessageBuffer>(
     144      330005 :         new MessageBuffer(std::move(message), binary));
     145             :   }
     146             : 
     147      330005 :   const StringView& string() override {
     148      330005 :     if (!m_serialized) {
     149      330005 :       if (m_binary) {
     150             :         // Encode binary response as an 8bit string buffer.
     151           0 :         m_serialized.reset(
     152           0 :             new BinaryStringBuffer(m_message->serializeToBinary()));
     153             :       } else {
     154             :         m_serialized =
     155      990015 :             StringBuffer::create(toStringView(m_message->serializeToJSON()));
     156             :       }
     157             :       m_message.reset(nullptr);
     158             :     }
     159      330005 :     return m_serialized->string();
     160             :   }
     161             : 
     162             :  private:
     163             :   explicit MessageBuffer(std::unique_ptr<protocol::Serializable> message,
     164             :                          bool binary)
     165      660010 :       : m_message(std::move(message)), m_binary(binary) {}
     166             : 
     167             :   std::unique_ptr<protocol::Serializable> m_message;
     168             :   std::unique_ptr<StringBuffer> m_serialized;
     169             :   bool m_binary;
     170             : };
     171             : 
     172             : }  // namespace
     173             : 
     174      154950 : void V8InspectorSessionImpl::sendProtocolResponse(
     175             :     int callId, std::unique_ptr<protocol::Serializable> message) {
     176      464850 :   m_channel->sendResponse(
     177      464850 :       callId, MessageBuffer::create(std::move(message), use_binary_protocol_));
     178      154950 : }
     179             : 
     180      175055 : void V8InspectorSessionImpl::sendProtocolNotification(
     181             :     std::unique_ptr<protocol::Serializable> message) {
     182      525165 :   m_channel->sendNotification(
     183      525165 :       MessageBuffer::create(std::move(message), use_binary_protocol_));
     184      175055 : }
     185             : 
     186           0 : void V8InspectorSessionImpl::fallThrough(
     187             :     int callId, const String16& method,
     188             :     const protocol::ProtocolMessage& message) {
     189             :   // There's no other layer to handle the command.
     190           0 :   UNREACHABLE();
     191             : }
     192             : 
     193        7095 : void V8InspectorSessionImpl::flushProtocolNotifications() {
     194        7095 :   m_channel->flushProtocolNotifications();
     195        7095 : }
     196             : 
     197           4 : void V8InspectorSessionImpl::reset() {
     198           4 :   m_debuggerAgent->reset();
     199           4 :   m_runtimeAgent->reset();
     200           4 :   discardInjectedScripts();
     201           4 : }
     202             : 
     203        3883 : void V8InspectorSessionImpl::discardInjectedScripts() {
     204        3883 :   m_inspectedObjects.clear();
     205        3883 :   int sessionId = m_sessionId;
     206        7766 :   m_inspector->forEachContext(m_contextGroupId,
     207        3869 :                               [&sessionId](InspectedContext* context) {
     208        3869 :                                 context->discardInjectedScript(sessionId);
     209        3883 :                               });
     210        3883 : }
     211             : 
     212      268791 : Response V8InspectorSessionImpl::findInjectedScript(
     213             :     int contextId, InjectedScript*& injectedScript) {
     214      268791 :   injectedScript = nullptr;
     215             :   InspectedContext* context =
     216      268791 :       m_inspector->getContext(m_contextGroupId, contextId);
     217      268820 :   if (!context) return Response::Error("Cannot find context with specified id");
     218      268762 :   injectedScript = context->getInjectedScript(m_sessionId);
     219      268762 :   if (!injectedScript) {
     220        3358 :     injectedScript = context->createInjectedScript(m_sessionId);
     221        3358 :     if (m_customObjectFormatterEnabled)
     222          10 :       injectedScript->setCustomObjectFormatterEnabled(true);
     223             :   }
     224      268762 :   return Response::OK();
     225             : }
     226             : 
     227       93786 : Response V8InspectorSessionImpl::findInjectedScript(
     228             :     RemoteObjectIdBase* objectId, InjectedScript*& injectedScript) {
     229       93786 :   return findInjectedScript(objectId->contextId(), injectedScript);
     230             : }
     231             : 
     232           0 : void V8InspectorSessionImpl::releaseObjectGroup(const StringView& objectGroup) {
     233           0 :   releaseObjectGroup(toString16(objectGroup));
     234           0 : }
     235             : 
     236       46726 : void V8InspectorSessionImpl::releaseObjectGroup(const String16& objectGroup) {
     237       46726 :   int sessionId = m_sessionId;
     238       93452 :   m_inspector->forEachContext(
     239       93452 :       m_contextGroupId, [&objectGroup, &sessionId](InspectedContext* context) {
     240       46726 :         InjectedScript* injectedScript = context->getInjectedScript(sessionId);
     241       93452 :         if (injectedScript) injectedScript->releaseObjectGroup(objectGroup);
     242       93452 :       });
     243       46726 : }
     244             : 
     245           0 : bool V8InspectorSessionImpl::unwrapObject(
     246             :     std::unique_ptr<StringBuffer>* error, const StringView& objectId,
     247             :     v8::Local<v8::Value>* object, v8::Local<v8::Context>* context,
     248             :     std::unique_ptr<StringBuffer>* objectGroup) {
     249             :   String16 objectGroupString;
     250           0 :   Response response = unwrapObject(toString16(objectId), object, context,
     251           0 :                                    objectGroup ? &objectGroupString : nullptr);
     252           0 :   if (!response.isSuccess()) {
     253           0 :     if (error) {
     254             :       String16 errorMessage = response.errorMessage();
     255           0 :       *error = StringBufferImpl::adopt(errorMessage);
     256             :     }
     257             :     return false;
     258             :   }
     259           0 :   if (objectGroup) *objectGroup = StringBufferImpl::adopt(objectGroupString);
     260             :   return true;
     261             : }
     262             : 
     263           0 : Response V8InspectorSessionImpl::unwrapObject(const String16& objectId,
     264             :                                               v8::Local<v8::Value>* object,
     265             :                                               v8::Local<v8::Context>* context,
     266             :                                               String16* objectGroup) {
     267           0 :   std::unique_ptr<RemoteObjectId> remoteId;
     268           0 :   Response response = RemoteObjectId::parse(objectId, &remoteId);
     269           0 :   if (!response.isSuccess()) return response;
     270           0 :   InjectedScript* injectedScript = nullptr;
     271           0 :   response = findInjectedScript(remoteId.get(), injectedScript);
     272           0 :   if (!response.isSuccess()) return response;
     273           0 :   response = injectedScript->findObject(*remoteId, object);
     274           0 :   if (!response.isSuccess()) return response;
     275           0 :   *context = injectedScript->context()->context();
     276           0 :   if (objectGroup) *objectGroup = injectedScript->objectGroupName(*remoteId);
     277           0 :   return Response::OK();
     278             : }
     279             : 
     280             : std::unique_ptr<protocol::Runtime::API::RemoteObject>
     281           5 : V8InspectorSessionImpl::wrapObject(v8::Local<v8::Context> context,
     282             :                                    v8::Local<v8::Value> value,
     283             :                                    const StringView& groupName,
     284             :                                    bool generatePreview) {
     285          15 :   return wrapObject(context, value, toString16(groupName), generatePreview);
     286             : }
     287             : 
     288             : std::unique_ptr<protocol::Runtime::RemoteObject>
     289        6705 : V8InspectorSessionImpl::wrapObject(v8::Local<v8::Context> context,
     290             :                                    v8::Local<v8::Value> value,
     291             :                                    const String16& groupName,
     292             :                                    bool generatePreview) {
     293        6705 :   InjectedScript* injectedScript = nullptr;
     294       13410 :   findInjectedScript(InspectedContext::contextId(context), injectedScript);
     295        6705 :   if (!injectedScript) return nullptr;
     296        6705 :   std::unique_ptr<protocol::Runtime::RemoteObject> result;
     297             :   injectedScript->wrapObject(
     298             :       value, groupName,
     299       13410 :       generatePreview ? WrapMode::kWithPreview : WrapMode::kNoPreview, &result);
     300             :   return result;
     301             : }
     302             : 
     303             : std::unique_ptr<protocol::Runtime::RemoteObject>
     304         165 : V8InspectorSessionImpl::wrapTable(v8::Local<v8::Context> context,
     305             :                                   v8::Local<v8::Object> table,
     306             :                                   v8::MaybeLocal<v8::Array> columns) {
     307         165 :   InjectedScript* injectedScript = nullptr;
     308         330 :   findInjectedScript(InspectedContext::contextId(context), injectedScript);
     309         165 :   if (!injectedScript) return nullptr;
     310         165 :   return injectedScript->wrapTable(table, columns);
     311             : }
     312             : 
     313         697 : void V8InspectorSessionImpl::setCustomObjectFormatterEnabled(bool enabled) {
     314         697 :   m_customObjectFormatterEnabled = enabled;
     315         697 :   int sessionId = m_sessionId;
     316        1394 :   m_inspector->forEachContext(
     317        1014 :       m_contextGroupId, [&enabled, &sessionId](InspectedContext* context) {
     318         692 :         InjectedScript* injectedScript = context->getInjectedScript(sessionId);
     319         692 :         if (injectedScript)
     320         322 :           injectedScript->setCustomObjectFormatterEnabled(enabled);
     321        1389 :       });
     322         697 : }
     323             : 
     324         682 : void V8InspectorSessionImpl::reportAllContexts(V8RuntimeAgentImpl* agent) {
     325        1364 :   m_inspector->forEachContext(m_contextGroupId,
     326         682 :                               [&agent](InspectedContext* context) {
     327         682 :                                 agent->reportExecutionContextCreated(context);
     328         682 :                               });
     329         682 : }
     330             : 
     331      154955 : void V8InspectorSessionImpl::dispatchProtocolMessage(
     332             :     const StringView& message) {
     333             :   bool binary_protocol =
     334      154955 :       message.is8Bit() && message.length() && message.characters8()[0] == 0xD8;
     335      154955 :   if (binary_protocol) {
     336           0 :     use_binary_protocol_ = true;
     337           0 :     m_state->setBoolean("use_binary_protocol", true);
     338             :   }
     339             : 
     340             :   int callId;
     341             :   std::unique_ptr<protocol::Value> parsed_message;
     342      154955 :   if (binary_protocol) {
     343           0 :     parsed_message = protocol::Value::parseBinary(
     344             :         message.characters8(), static_cast<unsigned>(message.length()));
     345             :   } else {
     346      309910 :     parsed_message = protocol::StringUtil::parseJSON(message);
     347             :   }
     348             :   String16 method;
     349      154955 :   if (m_dispatcher.parseCommand(parsed_message.get(), &callId, &method)) {
     350             :     // Pass empty string instead of the actual message to save on a conversion.
     351             :     // We're allowed to do so because fall-through is not implemented.
     352      309910 :     m_dispatcher.dispatch(callId, method, std::move(parsed_message),
     353      154955 :                           protocol::ProtocolMessage());
     354             :   }
     355      154955 : }
     356             : 
     357         110 : std::unique_ptr<StringBuffer> V8InspectorSessionImpl::stateJSON() {
     358         110 :   String16 json = m_state->toJSONString();
     359         330 :   return StringBufferImpl::adopt(json);
     360             : }
     361             : 
     362             : std::vector<std::unique_ptr<protocol::Schema::API::Domain>>
     363           0 : V8InspectorSessionImpl::supportedDomains() {
     364             :   std::vector<std::unique_ptr<protocol::Schema::Domain>> domains =
     365           0 :       supportedDomainsImpl();
     366             :   std::vector<std::unique_ptr<protocol::Schema::API::Domain>> result;
     367           0 :   for (size_t i = 0; i < domains.size(); ++i)
     368           0 :     result.push_back(std::move(domains[i]));
     369           0 :   return result;
     370             : }
     371             : 
     372             : std::vector<std::unique_ptr<protocol::Schema::Domain>>
     373           0 : V8InspectorSessionImpl::supportedDomainsImpl() {
     374             :   std::vector<std::unique_ptr<protocol::Schema::Domain>> result;
     375           0 :   result.push_back(protocol::Schema::Domain::create()
     376           0 :                        .setName(protocol::Runtime::Metainfo::domainName)
     377           0 :                        .setVersion(protocol::Runtime::Metainfo::version)
     378           0 :                        .build());
     379           0 :   result.push_back(protocol::Schema::Domain::create()
     380           0 :                        .setName(protocol::Debugger::Metainfo::domainName)
     381           0 :                        .setVersion(protocol::Debugger::Metainfo::version)
     382           0 :                        .build());
     383           0 :   result.push_back(protocol::Schema::Domain::create()
     384           0 :                        .setName(protocol::Profiler::Metainfo::domainName)
     385           0 :                        .setVersion(protocol::Profiler::Metainfo::version)
     386           0 :                        .build());
     387           0 :   result.push_back(protocol::Schema::Domain::create()
     388           0 :                        .setName(protocol::HeapProfiler::Metainfo::domainName)
     389           0 :                        .setVersion(protocol::HeapProfiler::Metainfo::version)
     390           0 :                        .build());
     391           0 :   result.push_back(protocol::Schema::Domain::create()
     392           0 :                        .setName(protocol::Schema::Metainfo::domainName)
     393           0 :                        .setVersion(protocol::Schema::Metainfo::version)
     394           0 :                        .build());
     395           0 :   return result;
     396             : }
     397             : 
     398          10 : void V8InspectorSessionImpl::addInspectedObject(
     399             :     std::unique_ptr<V8InspectorSession::Inspectable> inspectable) {
     400          10 :   m_inspectedObjects.insert(m_inspectedObjects.begin(), std::move(inspectable));
     401          10 :   if (m_inspectedObjects.size() > kInspectedObjectBufferSize)
     402           0 :     m_inspectedObjects.resize(kInspectedObjectBufferSize);
     403          10 : }
     404             : 
     405          30 : V8InspectorSession::Inspectable* V8InspectorSessionImpl::inspectedObject(
     406             :     unsigned num) {
     407          60 :   if (num >= m_inspectedObjects.size()) return nullptr;
     408          20 :   return m_inspectedObjects[num].get();
     409             : }
     410             : 
     411         120 : void V8InspectorSessionImpl::schedulePauseOnNextStatement(
     412             :     const StringView& breakReason, const StringView& breakDetails) {
     413             :   m_debuggerAgent->schedulePauseOnNextStatement(
     414         240 :       toString16(breakReason),
     415         120 :       protocol::DictionaryValue::cast(
     416         360 :           protocol::StringUtil::parseJSON(breakDetails)));
     417         120 : }
     418             : 
     419          50 : void V8InspectorSessionImpl::cancelPauseOnNextStatement() {
     420          50 :   m_debuggerAgent->cancelPauseOnNextStatement();
     421          50 : }
     422             : 
     423          65 : void V8InspectorSessionImpl::breakProgram(const StringView& breakReason,
     424             :                                           const StringView& breakDetails) {
     425             :   m_debuggerAgent->breakProgram(
     426         130 :       toString16(breakReason),
     427          65 :       protocol::DictionaryValue::cast(
     428         195 :           protocol::StringUtil::parseJSON(breakDetails)));
     429          65 : }
     430             : 
     431           0 : void V8InspectorSessionImpl::setSkipAllPauses(bool skip) {
     432           0 :   m_debuggerAgent->setSkipAllPauses(skip);
     433           0 : }
     434             : 
     435           0 : void V8InspectorSessionImpl::resume() { m_debuggerAgent->resume(); }
     436             : 
     437           0 : void V8InspectorSessionImpl::stepOver() { m_debuggerAgent->stepOver(); }
     438             : 
     439             : std::vector<std::unique_ptr<protocol::Debugger::API::SearchMatch>>
     440           0 : V8InspectorSessionImpl::searchInTextByLines(const StringView& text,
     441             :                                             const StringView& query,
     442             :                                             bool caseSensitive, bool isRegex) {
     443             :   // TODO(dgozman): search may operate on StringView and avoid copying |text|.
     444             :   std::vector<std::unique_ptr<protocol::Debugger::SearchMatch>> matches =
     445           0 :       searchInTextByLinesImpl(this, toString16(text), toString16(query),
     446           0 :                               caseSensitive, isRegex);
     447             :   std::vector<std::unique_ptr<protocol::Debugger::API::SearchMatch>> result;
     448           0 :   for (size_t i = 0; i < matches.size(); ++i)
     449           0 :     result.push_back(std::move(matches[i]));
     450           0 :   return result;
     451             : }
     452             : 
     453             : }  // namespace v8_inspector

Generated by: LCOV version 1.10