LCOV - code coverage report
Current view: top level - src/inspector - v8-inspector-session-impl.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 141 208 67.8 %
Date: 2019-01-20 Functions: 31 43 72.1 %

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

Generated by: LCOV version 1.10