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