| OLD | NEW |
| 1 // Copyright 2016 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "test/inspector/inspector-impl.h" | 5 #include "test/inspector/inspector-impl.h" |
| 6 | 6 |
| 7 #include "include/v8.h" | 7 #include "include/v8.h" |
| 8 | 8 |
| 9 #include "src/vector.h" | 9 #include "src/vector.h" |
| 10 #include "test/inspector/isolate-data.h" |
| 11 #include "test/inspector/task-runner.h" |
| 10 | 12 |
| 11 namespace { | 13 namespace { |
| 12 | 14 |
| 13 const int kInspectorClientIndex = 0; | |
| 14 | |
| 15 class ChannelImpl final : public v8_inspector::V8Inspector::Channel { | 15 class ChannelImpl final : public v8_inspector::V8Inspector::Channel { |
| 16 public: | 16 public: |
| 17 explicit ChannelImpl(InspectorClientImpl::FrontendChannel* frontend_channel) | 17 ChannelImpl(InspectorClientImpl::FrontendChannel* frontend_channel, |
| 18 : frontend_channel_(frontend_channel) {} | 18 int session_id) |
| 19 : frontend_channel_(frontend_channel), session_id_(session_id) {} |
| 19 virtual ~ChannelImpl() = default; | 20 virtual ~ChannelImpl() = default; |
| 20 | 21 |
| 21 private: | 22 private: |
| 22 void sendResponse( | 23 void sendResponse( |
| 23 int callId, | 24 int callId, |
| 24 std::unique_ptr<v8_inspector::StringBuffer> message) override { | 25 std::unique_ptr<v8_inspector::StringBuffer> message) override { |
| 25 frontend_channel_->SendMessageToFrontend(message->string()); | 26 frontend_channel_->SendMessageToFrontend(session_id_, message->string()); |
| 26 } | 27 } |
| 27 void sendNotification( | 28 void sendNotification( |
| 28 std::unique_ptr<v8_inspector::StringBuffer> message) override { | 29 std::unique_ptr<v8_inspector::StringBuffer> message) override { |
| 29 frontend_channel_->SendMessageToFrontend(message->string()); | 30 frontend_channel_->SendMessageToFrontend(session_id_, message->string()); |
| 30 } | 31 } |
| 31 void flushProtocolNotifications() override {} | 32 void flushProtocolNotifications() override {} |
| 32 | 33 |
| 33 InspectorClientImpl::FrontendChannel* frontend_channel_; | 34 InspectorClientImpl::FrontendChannel* frontend_channel_; |
| 35 int session_id_; |
| 34 DISALLOW_COPY_AND_ASSIGN(ChannelImpl); | 36 DISALLOW_COPY_AND_ASSIGN(ChannelImpl); |
| 35 }; | 37 }; |
| 36 | 38 |
| 37 InspectorClientImpl* InspectorClientFromContext( | |
| 38 v8::Local<v8::Context> context) { | |
| 39 InspectorClientImpl* inspector_client = static_cast<InspectorClientImpl*>( | |
| 40 context->GetAlignedPointerFromEmbedderData(kInspectorClientIndex)); | |
| 41 CHECK(inspector_client); | |
| 42 return inspector_client; | |
| 43 } | |
| 44 | |
| 45 v8::internal::Vector<uint16_t> ToVector(v8::Local<v8::String> str) { | 39 v8::internal::Vector<uint16_t> ToVector(v8::Local<v8::String> str) { |
| 46 v8::internal::Vector<uint16_t> buffer = | 40 v8::internal::Vector<uint16_t> buffer = |
| 47 v8::internal::Vector<uint16_t>::New(str->Length()); | 41 v8::internal::Vector<uint16_t>::New(str->Length()); |
| 48 str->Write(buffer.start(), 0, str->Length()); | 42 str->Write(buffer.start(), 0, str->Length()); |
| 49 return buffer; | 43 return buffer; |
| 50 } | 44 } |
| 51 | 45 |
| 52 void MessageHandler(v8::Local<v8::Message> message, | 46 void MessageHandler(v8::Local<v8::Message> message, |
| 53 v8::Local<v8::Value> exception) { | 47 v8::Local<v8::Value> exception) { |
| 54 v8::Isolate* isolate = v8::Isolate::GetCurrent(); | 48 v8::Isolate* isolate = v8::Isolate::GetCurrent(); |
| 55 v8::Local<v8::Context> context = isolate->GetEnteredContext(); | 49 v8::Local<v8::Context> context = isolate->GetEnteredContext(); |
| 56 if (context.IsEmpty()) return; | 50 if (context.IsEmpty()) return; |
| 57 v8_inspector::V8Inspector* inspector = | 51 v8_inspector::V8Inspector* inspector = |
| 58 InspectorClientImpl::InspectorFromContext(context); | 52 IsolateData::FromContext(context)->inspector()->inspector(); |
| 59 | 53 |
| 60 v8::Local<v8::StackTrace> stack = message->GetStackTrace(); | 54 v8::Local<v8::StackTrace> stack = message->GetStackTrace(); |
| 61 int script_id = | 55 int script_id = |
| 62 static_cast<int>(message->GetScriptOrigin().ScriptID()->Value()); | 56 static_cast<int>(message->GetScriptOrigin().ScriptID()->Value()); |
| 63 if (!stack.IsEmpty() && stack->GetFrameCount() > 0) { | 57 if (!stack.IsEmpty() && stack->GetFrameCount() > 0) { |
| 64 int top_script_id = stack->GetFrame(0)->GetScriptId(); | 58 int top_script_id = stack->GetFrame(0)->GetScriptId(); |
| 65 if (top_script_id == script_id) script_id = 0; | 59 if (top_script_id == script_id) script_id = 0; |
| 66 } | 60 } |
| 67 int line_number = message->GetLineNumber(context).FromMaybe(0); | 61 int line_number = message->GetLineNumber(context).FromMaybe(0); |
| 68 int column_number = 0; | 62 int column_number = 0; |
| (...skipping 30 matching lines...) Expand all Loading... |
| 99 .ToLocalChecked(); | 93 .ToLocalChecked(); |
| 100 } | 94 } |
| 101 | 95 |
| 102 void Print(v8::Isolate* isolate, const v8_inspector::StringView& string) { | 96 void Print(v8::Isolate* isolate, const v8_inspector::StringView& string) { |
| 103 v8::Local<v8::String> v8_string = ToString(isolate, string); | 97 v8::Local<v8::String> v8_string = ToString(isolate, string); |
| 104 v8::String::Utf8Value utf8_string(v8_string); | 98 v8::String::Utf8Value utf8_string(v8_string); |
| 105 fwrite(*utf8_string, sizeof(**utf8_string), utf8_string.length(), stdout); | 99 fwrite(*utf8_string, sizeof(**utf8_string), utf8_string.length(), stdout); |
| 106 } | 100 } |
| 107 } // namespace | 101 } // namespace |
| 108 | 102 |
| 109 class ConnectTask : public TaskRunner::Task { | 103 InspectorClientImpl::InspectorClientImpl(v8::Isolate* isolate, |
| 110 public: | 104 TaskRunner* task_runner, |
| 111 ConnectTask(InspectorClientImpl* client, v8::base::Semaphore* ready_semaphore) | 105 FrontendChannel* frontend_channel) |
| 112 : client_(client), ready_semaphore_(ready_semaphore) {} | 106 : task_runner_(task_runner), |
| 113 virtual ~ConnectTask() = default; | 107 isolate_(isolate), |
| 114 | |
| 115 bool is_inspector_task() final { return true; } | |
| 116 | |
| 117 private: | |
| 118 void Run() override { | |
| 119 v8::HandleScope handle_scope(isolate()); | |
| 120 client_->connect(); | |
| 121 if (ready_semaphore_) ready_semaphore_->Signal(); | |
| 122 } | |
| 123 | |
| 124 InspectorClientImpl* client_; | |
| 125 v8::base::Semaphore* ready_semaphore_; | |
| 126 }; | |
| 127 | |
| 128 class DisconnectTask : public TaskRunner::Task { | |
| 129 public: | |
| 130 explicit DisconnectTask(InspectorClientImpl* client, bool reset_inspector, | |
| 131 v8::base::Semaphore* ready_semaphore) | |
| 132 : client_(client), | |
| 133 reset_inspector_(reset_inspector), | |
| 134 ready_semaphore_(ready_semaphore) {} | |
| 135 virtual ~DisconnectTask() = default; | |
| 136 | |
| 137 bool is_inspector_task() final { return true; } | |
| 138 | |
| 139 private: | |
| 140 void Run() override { | |
| 141 client_->disconnect(reset_inspector_); | |
| 142 if (ready_semaphore_) ready_semaphore_->Signal(); | |
| 143 } | |
| 144 | |
| 145 InspectorClientImpl* client_; | |
| 146 bool reset_inspector_; | |
| 147 v8::base::Semaphore* ready_semaphore_; | |
| 148 }; | |
| 149 | |
| 150 class CreateContextGroupTask : public TaskRunner::Task { | |
| 151 public: | |
| 152 CreateContextGroupTask(InspectorClientImpl* client, | |
| 153 IsolateData::SetupGlobalTasks setup_global_tasks, | |
| 154 v8::base::Semaphore* ready_semaphore, | |
| 155 int* context_group_id) | |
| 156 : client_(client), | |
| 157 setup_global_tasks_(std::move(setup_global_tasks)), | |
| 158 ready_semaphore_(ready_semaphore), | |
| 159 context_group_id_(context_group_id) {} | |
| 160 virtual ~CreateContextGroupTask() = default; | |
| 161 | |
| 162 bool is_inspector_task() final { return true; } | |
| 163 | |
| 164 private: | |
| 165 void Run() override { | |
| 166 *context_group_id_ = client_->createContextGroup(setup_global_tasks_); | |
| 167 if (ready_semaphore_) ready_semaphore_->Signal(); | |
| 168 } | |
| 169 | |
| 170 InspectorClientImpl* client_; | |
| 171 IsolateData::SetupGlobalTasks setup_global_tasks_; | |
| 172 v8::base::Semaphore* ready_semaphore_; | |
| 173 int* context_group_id_; | |
| 174 }; | |
| 175 | |
| 176 InspectorClientImpl::InspectorClientImpl(TaskRunner* task_runner, | |
| 177 FrontendChannel* frontend_channel, | |
| 178 v8::base::Semaphore* ready_semaphore) | |
| 179 : isolate_(nullptr), | |
| 180 task_runner_(task_runner), | |
| 181 frontend_channel_(frontend_channel) { | 108 frontend_channel_(frontend_channel) { |
| 182 task_runner_->Append(new ConnectTask(this, ready_semaphore)); | 109 isolate_->AddMessageListener(MessageHandler); |
| 110 inspector_ = v8_inspector::V8Inspector::create(isolate_, this); |
| 183 } | 111 } |
| 184 | 112 |
| 185 InspectorClientImpl::~InspectorClientImpl() {} | 113 InspectorClientImpl::~InspectorClientImpl() {} |
| 186 | 114 |
| 187 void InspectorClientImpl::connect() { | 115 int InspectorClientImpl::ConnectSession(int context_group_id, |
| 188 isolate_ = task_runner_->data()->isolate(); | 116 const v8_inspector::StringView& state) { |
| 189 isolate_->AddMessageListener(MessageHandler); | 117 int session_id = ++last_session_id_; |
| 190 channel_.reset(new ChannelImpl(frontend_channel_)); | 118 channels_[session_id].reset(new ChannelImpl(frontend_channel_, session_id)); |
| 191 inspector_ = v8_inspector::V8Inspector::create(isolate_, this); | 119 sessions_[session_id] = |
| 192 | 120 inspector_->connect(context_group_id, channels_[session_id].get(), state); |
| 193 if (states_.empty()) { | 121 context_group_by_session_[sessions_[session_id].get()] = context_group_id; |
| 194 ConnectToContextGroup(task_runner_->default_context_group_id(), | 122 return session_id; |
| 195 v8_inspector::StringView()); | |
| 196 } else { | |
| 197 for (const auto& it : states_) | |
| 198 ConnectToContextGroup(it.first, it.second->string()); | |
| 199 } | |
| 200 states_.clear(); | |
| 201 } | 123 } |
| 202 | 124 |
| 203 void InspectorClientImpl::ConnectToContextGroup( | 125 std::unique_ptr<v8_inspector::StringBuffer> |
| 204 int context_group_id, v8_inspector::StringView state) { | 126 InspectorClientImpl::DisconnectSession(int session_id) { |
| 205 v8::Local<v8::Context> context = | 127 auto it = sessions_.find(session_id); |
| 206 task_runner_->data()->GetContext(context_group_id); | 128 CHECK(it != sessions_.end()); |
| 207 sessions_[context_group_id] = | 129 context_group_by_session_.erase(it->second.get()); |
| 208 inspector_->connect(context_group_id, channel_.get(), state); | 130 std::unique_ptr<v8_inspector::StringBuffer> result = it->second->stateJSON(); |
| 209 context->SetAlignedPointerInEmbedderData(kInspectorClientIndex, this); | 131 sessions_.erase(it); |
| 132 channels_.erase(session_id); |
| 133 return result; |
| 134 } |
| 135 |
| 136 void InspectorClientImpl::SendMessage(int session_id, |
| 137 const v8_inspector::StringView& message) { |
| 138 auto it = sessions_.find(session_id); |
| 139 if (it != sessions_.end()) it->second->dispatchProtocolMessage(message); |
| 140 } |
| 141 |
| 142 void InspectorClientImpl::BreakProgram( |
| 143 int context_group_id, const v8_inspector::StringView& reason, |
| 144 const v8_inspector::StringView& details) { |
| 145 for (int session_id : GetSessionIds(context_group_id)) { |
| 146 auto it = sessions_.find(session_id); |
| 147 if (it != sessions_.end()) it->second->breakProgram(reason, details); |
| 148 } |
| 149 } |
| 150 |
| 151 void InspectorClientImpl::SchedulePauseOnNextStatement( |
| 152 int context_group_id, const v8_inspector::StringView& reason, |
| 153 const v8_inspector::StringView& details) { |
| 154 for (int session_id : GetSessionIds(context_group_id)) { |
| 155 auto it = sessions_.find(session_id); |
| 156 if (it != sessions_.end()) |
| 157 it->second->schedulePauseOnNextStatement(reason, details); |
| 158 } |
| 159 } |
| 160 |
| 161 void InspectorClientImpl::CancelPauseOnNextStatement(int context_group_id) { |
| 162 for (int session_id : GetSessionIds(context_group_id)) { |
| 163 auto it = sessions_.find(session_id); |
| 164 if (it != sessions_.end()) it->second->cancelPauseOnNextStatement(); |
| 165 } |
| 166 } |
| 167 |
| 168 void InspectorClientImpl::ContextCreated(v8::Local<v8::Context> context, |
| 169 int context_group_id) { |
| 210 v8_inspector::V8ContextInfo info(context, context_group_id, | 170 v8_inspector::V8ContextInfo info(context, context_group_id, |
| 211 v8_inspector::StringView()); | 171 v8_inspector::StringView()); |
| 212 info.hasMemoryOnConsole = true; | 172 info.hasMemoryOnConsole = true; |
| 213 inspector_->contextCreated(info); | 173 inspector_->contextCreated(info); |
| 214 } | 174 } |
| 215 | 175 |
| 216 void InspectorClientImpl::scheduleReconnect( | 176 void InspectorClientImpl::ContextDestroyed(v8::Local<v8::Context> context) { |
| 217 v8::base::Semaphore* ready_semaphore) { | 177 inspector_->contextDestroyed(context); |
| 218 task_runner_->Append( | |
| 219 new DisconnectTask(this, /* reset_inspector */ true, nullptr)); | |
| 220 task_runner_->Append(new ConnectTask(this, ready_semaphore)); | |
| 221 } | 178 } |
| 222 | 179 |
| 223 void InspectorClientImpl::scheduleDisconnect( | 180 std::vector<int> InspectorClientImpl::GetSessionIds(int context_group_id) { |
| 224 v8::base::Semaphore* ready_semaphore) { | 181 std::vector<int> result; |
| 225 task_runner_->Append( | 182 for (auto& it : sessions_) { |
| 226 new DisconnectTask(this, /* reset_inspector */ false, ready_semaphore)); | 183 if (context_group_by_session_[it.second.get()] == context_group_id) |
| 227 } | 184 result.push_back(it.first); |
| 228 | |
| 229 void InspectorClientImpl::disconnect(bool reset_inspector) { | |
| 230 for (const auto& it : sessions_) { | |
| 231 states_[it.first] = it.second->stateJSON(); | |
| 232 } | 185 } |
| 233 sessions_.clear(); | 186 return result; |
| 234 if (reset_inspector) inspector_.reset(); | |
| 235 } | |
| 236 | |
| 237 void InspectorClientImpl::scheduleCreateContextGroup( | |
| 238 IsolateData::SetupGlobalTasks setup_global_tasks, | |
| 239 v8::base::Semaphore* ready_semaphore, int* context_group_id) { | |
| 240 task_runner_->Append(new CreateContextGroupTask( | |
| 241 this, std::move(setup_global_tasks), ready_semaphore, context_group_id)); | |
| 242 } | |
| 243 | |
| 244 int InspectorClientImpl::createContextGroup( | |
| 245 const IsolateData::SetupGlobalTasks& setup_global_tasks) { | |
| 246 v8::HandleScope handle_scope(isolate_); | |
| 247 int context_group_id = task_runner_->data()->CreateContextGroup(); | |
| 248 v8::Local<v8::Context> context = | |
| 249 task_runner_->data()->GetContext(context_group_id); | |
| 250 context->SetAlignedPointerInEmbedderData(kInspectorClientIndex, this); | |
| 251 v8_inspector::StringView state; | |
| 252 sessions_[context_group_id] = | |
| 253 inspector_->connect(context_group_id, channel_.get(), state); | |
| 254 inspector_->contextCreated(v8_inspector::V8ContextInfo( | |
| 255 context, context_group_id, v8_inspector::StringView())); | |
| 256 return context_group_id; | |
| 257 } | 187 } |
| 258 | 188 |
| 259 bool InspectorClientImpl::formatAccessorsAsProperties( | 189 bool InspectorClientImpl::formatAccessorsAsProperties( |
| 260 v8::Local<v8::Value> object) { | 190 v8::Local<v8::Value> object) { |
| 261 v8::Isolate* isolate = v8::Isolate::GetCurrent(); | 191 v8::Isolate* isolate = v8::Isolate::GetCurrent(); |
| 262 v8::Local<v8::Context> context = isolate->GetCurrentContext(); | 192 v8::Local<v8::Context> context = isolate->GetCurrentContext(); |
| 263 v8::Local<v8::Private> shouldFormatAccessorsPrivate = v8::Private::ForApi( | 193 v8::Local<v8::Private> shouldFormatAccessorsPrivate = v8::Private::ForApi( |
| 264 isolate, v8::String::NewFromUtf8(isolate, "allowAccessorFormatting", | 194 isolate, v8::String::NewFromUtf8(isolate, "allowAccessorFormatting", |
| 265 v8::NewStringType::kNormal) | 195 v8::NewStringType::kNormal) |
| 266 .ToLocalChecked()); | 196 .ToLocalChecked()); |
| 267 CHECK(object->IsObject()); | 197 CHECK(object->IsObject()); |
| 268 return object.As<v8::Object>() | 198 return object.As<v8::Object>() |
| 269 ->HasPrivate(context, shouldFormatAccessorsPrivate) | 199 ->HasPrivate(context, shouldFormatAccessorsPrivate) |
| 270 .FromMaybe(false); | 200 .FromMaybe(false); |
| 271 } | 201 } |
| 272 | 202 |
| 273 v8::Local<v8::Context> InspectorClientImpl::ensureDefaultContextInGroup( | 203 v8::Local<v8::Context> InspectorClientImpl::ensureDefaultContextInGroup( |
| 274 int context_group_id) { | 204 int context_group_id) { |
| 275 CHECK(isolate_); | 205 CHECK(isolate_); |
| 276 return task_runner_->data()->GetContext(context_group_id); | 206 return task_runner_->data()->GetContext(context_group_id); |
| 277 } | 207 } |
| 278 | 208 |
| 279 void InspectorClientImpl::setCurrentTimeMSForTest(double time) { | 209 void InspectorClientImpl::SetCurrentTimeMSForTest(double time) { |
| 280 current_time_ = time; | 210 current_time_ = time; |
| 281 current_time_set_for_test_ = true; | 211 current_time_set_for_test_ = true; |
| 282 } | 212 } |
| 283 | 213 |
| 284 double InspectorClientImpl::currentTimeMS() { | 214 double InspectorClientImpl::currentTimeMS() { |
| 285 if (current_time_set_for_test_) return current_time_; | 215 if (current_time_set_for_test_) return current_time_; |
| 286 return v8::base::OS::TimeCurrentMillis(); | 216 return v8::base::OS::TimeCurrentMillis(); |
| 287 } | 217 } |
| 288 | 218 |
| 289 void InspectorClientImpl::setMemoryInfoForTest( | 219 void InspectorClientImpl::SetMemoryInfoForTest( |
| 290 v8::Local<v8::Value> memory_info) { | 220 v8::Local<v8::Value> memory_info) { |
| 291 memory_info_.Reset(isolate_, memory_info); | 221 memory_info_.Reset(isolate_, memory_info); |
| 292 } | 222 } |
| 293 | 223 |
| 294 void InspectorClientImpl::setLogConsoleApiMessageCalls(bool log) { | 224 void InspectorClientImpl::SetLogConsoleApiMessageCalls(bool log) { |
| 295 log_console_api_message_calls_ = log; | 225 log_console_api_message_calls_ = log; |
| 296 } | 226 } |
| 297 | 227 |
| 298 v8::MaybeLocal<v8::Value> InspectorClientImpl::memoryInfo( | 228 v8::MaybeLocal<v8::Value> InspectorClientImpl::memoryInfo( |
| 299 v8::Isolate* isolate, v8::Local<v8::Context>) { | 229 v8::Isolate* isolate, v8::Local<v8::Context>) { |
| 300 if (memory_info_.IsEmpty()) return v8::MaybeLocal<v8::Value>(); | 230 if (memory_info_.IsEmpty()) return v8::MaybeLocal<v8::Value>(); |
| 301 return memory_info_.Get(isolate); | 231 return memory_info_.Get(isolate); |
| 302 } | 232 } |
| 303 | 233 |
| 304 void InspectorClientImpl::runMessageLoopOnPause(int) { | 234 void InspectorClientImpl::runMessageLoopOnPause(int) { |
| (...skipping 10 matching lines...) Expand all Loading... |
| 315 const v8_inspector::StringView& url, unsigned lineNumber, | 245 const v8_inspector::StringView& url, unsigned lineNumber, |
| 316 unsigned columnNumber, v8_inspector::V8StackTrace* stack) { | 246 unsigned columnNumber, v8_inspector::V8StackTrace* stack) { |
| 317 if (!log_console_api_message_calls_) return; | 247 if (!log_console_api_message_calls_) return; |
| 318 Print(isolate_, message); | 248 Print(isolate_, message); |
| 319 fprintf(stdout, " ("); | 249 fprintf(stdout, " ("); |
| 320 Print(isolate_, url); | 250 Print(isolate_, url); |
| 321 fprintf(stdout, ":%d:%d)", lineNumber, columnNumber); | 251 fprintf(stdout, ":%d:%d)", lineNumber, columnNumber); |
| 322 Print(isolate_, stack->toString()->string()); | 252 Print(isolate_, stack->toString()->string()); |
| 323 fprintf(stdout, "\n"); | 253 fprintf(stdout, "\n"); |
| 324 } | 254 } |
| 325 | |
| 326 v8_inspector::V8Inspector* InspectorClientImpl::InspectorFromContext( | |
| 327 v8::Local<v8::Context> context) { | |
| 328 return InspectorClientFromContext(context)->inspector_.get(); | |
| 329 } | |
| 330 | |
| 331 v8_inspector::V8InspectorSession* InspectorClientImpl::SessionFromContext( | |
| 332 v8::Local<v8::Context> context) { | |
| 333 InspectorClientImpl* client = InspectorClientFromContext(context); | |
| 334 for (auto& it : client->sessions_) { | |
| 335 if (client->task_runner_->data()->GetContext(it.first) == context) | |
| 336 return it.second.get(); | |
| 337 } | |
| 338 return nullptr; | |
| 339 } | |
| 340 | |
| 341 v8_inspector::V8InspectorSession* InspectorClientImpl::session( | |
| 342 int context_group_id) { | |
| 343 if (context_group_id) { | |
| 344 return sessions_[context_group_id].get(); | |
| 345 } else { | |
| 346 return sessions_.begin()->second.get(); | |
| 347 } | |
| 348 } | |
| 349 | |
| 350 class SendMessageToBackendTask : public TaskRunner::Task { | |
| 351 public: | |
| 352 explicit SendMessageToBackendTask( | |
| 353 const v8::internal::Vector<uint16_t>& message, int context_group_id) | |
| 354 : message_(message), context_group_id_(context_group_id) {} | |
| 355 | |
| 356 bool is_inspector_task() final { return true; } | |
| 357 | |
| 358 private: | |
| 359 void Run() override { | |
| 360 v8_inspector::V8InspectorSession* session = nullptr; | |
| 361 { | |
| 362 v8::HandleScope handle_scope(isolate()); | |
| 363 if (!context_group_id_) { | |
| 364 session = InspectorClientImpl::SessionFromContext(default_context()); | |
| 365 } else { | |
| 366 session = InspectorClientFromContext(default_context()) | |
| 367 ->sessions_[context_group_id_] | |
| 368 .get(); | |
| 369 } | |
| 370 if (!session) return; | |
| 371 } | |
| 372 v8_inspector::StringView message_view(message_.start(), message_.length()); | |
| 373 session->dispatchProtocolMessage(message_view); | |
| 374 } | |
| 375 | |
| 376 v8::internal::Vector<uint16_t> message_; | |
| 377 int context_group_id_; | |
| 378 }; | |
| 379 | |
| 380 TaskRunner* SendMessageToBackendExtension::backend_task_runner_ = nullptr; | |
| 381 | |
| 382 void SendMessageToBackendExtension::Run(v8::Isolate* isolate, | |
| 383 v8::Local<v8::ObjectTemplate> global) { | |
| 384 global->Set( | |
| 385 v8::String::NewFromUtf8(isolate, "sendMessageToBackend", | |
| 386 v8::NewStringType::kNormal) | |
| 387 .ToLocalChecked(), | |
| 388 v8::FunctionTemplate::New( | |
| 389 isolate, &SendMessageToBackendExtension::SendMessageToBackend)); | |
| 390 } | |
| 391 | |
| 392 void SendMessageToBackendExtension::SendMessageToBackend( | |
| 393 const v8::FunctionCallbackInfo<v8::Value>& args) { | |
| 394 CHECK(backend_task_runner_); | |
| 395 CHECK(args.Length() == 2 && args[0]->IsString() && args[1]->IsInt32()); | |
| 396 v8::Local<v8::String> message = args[0].As<v8::String>(); | |
| 397 backend_task_runner_->Append(new SendMessageToBackendTask( | |
| 398 ToVector(message), args[1].As<v8::Int32>()->Value())); | |
| 399 } | |
| OLD | NEW |