| 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 | 10 |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 117 | 117 |
| 118 void Run(v8::Isolate* isolate, | 118 void Run(v8::Isolate* isolate, |
| 119 const v8::Global<v8::Context>& global_context) { | 119 const v8::Global<v8::Context>& global_context) { |
| 120 client_->disconnect(); | 120 client_->disconnect(); |
| 121 } | 121 } |
| 122 | 122 |
| 123 private: | 123 private: |
| 124 InspectorClientImpl* client_; | 124 InspectorClientImpl* client_; |
| 125 }; | 125 }; |
| 126 | 126 |
| 127 class CreateContextGroupTask : public TaskRunner::Task { |
| 128 public: |
| 129 CreateContextGroupTask(InspectorClientImpl* client, |
| 130 v8::ExtensionConfiguration* extensions, |
| 131 v8::base::Semaphore* ready_semaphore, |
| 132 int* context_group_id) |
| 133 : client_(client), |
| 134 extensions_(extensions), |
| 135 ready_semaphore_(ready_semaphore), |
| 136 context_group_id_(context_group_id) {} |
| 137 virtual ~CreateContextGroupTask() = default; |
| 138 |
| 139 bool is_inspector_task() final { return true; } |
| 140 |
| 141 void Run(v8::Isolate* isolate, |
| 142 const v8::Global<v8::Context>& global_context) { |
| 143 *context_group_id_ = client_->createContextGroup(extensions_); |
| 144 if (ready_semaphore_) ready_semaphore_->Signal(); |
| 145 } |
| 146 |
| 147 private: |
| 148 InspectorClientImpl* client_; |
| 149 v8::ExtensionConfiguration* extensions_; |
| 150 v8::base::Semaphore* ready_semaphore_; |
| 151 int* context_group_id_; |
| 152 }; |
| 153 |
| 127 InspectorClientImpl::InspectorClientImpl(TaskRunner* task_runner, | 154 InspectorClientImpl::InspectorClientImpl(TaskRunner* task_runner, |
| 128 FrontendChannel* frontend_channel, | 155 FrontendChannel* frontend_channel, |
| 129 v8::base::Semaphore* ready_semaphore) | 156 v8::base::Semaphore* ready_semaphore) |
| 130 : isolate_(nullptr), | 157 : isolate_(nullptr), |
| 131 task_runner_(task_runner), | 158 task_runner_(task_runner), |
| 132 frontend_channel_(frontend_channel) { | 159 frontend_channel_(frontend_channel) { |
| 133 task_runner_->Append(new ConnectTask(this, ready_semaphore)); | 160 task_runner_->Append(new ConnectTask(this, ready_semaphore)); |
| 134 } | 161 } |
| 135 | 162 |
| 136 InspectorClientImpl::~InspectorClientImpl() {} | 163 InspectorClientImpl::~InspectorClientImpl() {} |
| 137 | 164 |
| 138 void InspectorClientImpl::connect(v8::Local<v8::Context> context) { | 165 void InspectorClientImpl::connect(v8::Local<v8::Context> context) { |
| 139 isolate_ = context->GetIsolate(); | 166 isolate_ = context->GetIsolate(); |
| 140 isolate_->AddMessageListener(MessageHandler); | 167 isolate_->AddMessageListener(MessageHandler); |
| 141 channel_.reset(new ChannelImpl(frontend_channel_)); | 168 channel_.reset(new ChannelImpl(frontend_channel_)); |
| 169 inspector_ = v8_inspector::V8Inspector::create(isolate_, this); |
| 142 | 170 |
| 143 inspector_ = v8_inspector::V8Inspector::create(isolate_, this); | 171 if (states_.empty()) { |
| 144 v8_inspector::StringView state = | 172 int context_group_id = TaskRunner::GetContextGroupId(context); |
| 145 state_ ? state_->string() : v8_inspector::StringView(); | 173 v8_inspector::StringView state; |
| 146 session_ = inspector_->connect(1, channel_.get(), state); | 174 sessions_[context_group_id] = |
| 147 | 175 inspector_->connect(context_group_id, channel_.get(), state); |
| 148 context->SetAlignedPointerInEmbedderData(kInspectorClientIndex, this); | 176 context->SetAlignedPointerInEmbedderData(kInspectorClientIndex, this); |
| 149 inspector_->contextCreated( | 177 inspector_->contextCreated(v8_inspector::V8ContextInfo( |
| 150 v8_inspector::V8ContextInfo(context, 1, v8_inspector::StringView())); | 178 context, context_group_id, v8_inspector::StringView())); |
| 151 context_.Reset(isolate_, context); | 179 } else { |
| 180 for (const auto& it : states_) { |
| 181 int context_group_id = it.first; |
| 182 v8::Local<v8::Context> context = |
| 183 task_runner_->GetContext(context_group_id); |
| 184 v8_inspector::StringView state = it.second->string(); |
| 185 sessions_[context_group_id] = |
| 186 inspector_->connect(context_group_id, channel_.get(), state); |
| 187 context->SetAlignedPointerInEmbedderData(kInspectorClientIndex, this); |
| 188 inspector_->contextCreated(v8_inspector::V8ContextInfo( |
| 189 context, context_group_id, v8_inspector::StringView())); |
| 190 } |
| 191 } |
| 192 states_.clear(); |
| 152 } | 193 } |
| 153 | 194 |
| 154 void InspectorClientImpl::scheduleReconnect( | 195 void InspectorClientImpl::scheduleReconnect( |
| 155 v8::base::Semaphore* ready_semaphore) { | 196 v8::base::Semaphore* ready_semaphore) { |
| 156 task_runner_->Append(new DisconnectTask(this)); | 197 task_runner_->Append(new DisconnectTask(this)); |
| 157 task_runner_->Append(new ConnectTask(this, ready_semaphore)); | 198 task_runner_->Append(new ConnectTask(this, ready_semaphore)); |
| 158 } | 199 } |
| 159 | 200 |
| 160 void InspectorClientImpl::disconnect() { | 201 void InspectorClientImpl::disconnect() { |
| 161 state_ = session_->stateJSON(); | 202 for (const auto& it : sessions_) { |
| 162 session_.reset(); | 203 states_[it.first] = it.second->stateJSON(); |
| 204 } |
| 205 sessions_.clear(); |
| 206 } |
| 207 |
| 208 void InspectorClientImpl::scheduleCreateContextGroup( |
| 209 v8::ExtensionConfiguration* extensions, |
| 210 v8::base::Semaphore* ready_semaphore, int* context_group_id) { |
| 211 task_runner_->Append(new CreateContextGroupTask( |
| 212 this, extensions, ready_semaphore, context_group_id)); |
| 213 } |
| 214 |
| 215 int InspectorClientImpl::createContextGroup( |
| 216 v8::ExtensionConfiguration* extensions) { |
| 217 v8::HandleScope handle_scope(isolate_); |
| 218 v8::Local<v8::Context> context = task_runner_->NewContextGroup(); |
| 219 context->SetAlignedPointerInEmbedderData(kInspectorClientIndex, this); |
| 220 int context_group_id = TaskRunner::GetContextGroupId(context); |
| 221 v8_inspector::StringView state; |
| 222 sessions_[context_group_id] = |
| 223 inspector_->connect(context_group_id, channel_.get(), state); |
| 224 inspector_->contextCreated(v8_inspector::V8ContextInfo( |
| 225 context, context_group_id, v8_inspector::StringView())); |
| 226 return context_group_id; |
| 163 } | 227 } |
| 164 | 228 |
| 165 bool InspectorClientImpl::formatAccessorsAsProperties( | 229 bool InspectorClientImpl::formatAccessorsAsProperties( |
| 166 v8::Local<v8::Value> object) { | 230 v8::Local<v8::Value> object) { |
| 167 v8::Isolate* isolate = v8::Isolate::GetCurrent(); | 231 v8::Isolate* isolate = v8::Isolate::GetCurrent(); |
| 168 v8::Local<v8::Context> context = isolate->GetCurrentContext(); | 232 v8::Local<v8::Context> context = isolate->GetCurrentContext(); |
| 169 v8::Local<v8::Private> shouldFormatAccessorsPrivate = v8::Private::ForApi( | 233 v8::Local<v8::Private> shouldFormatAccessorsPrivate = v8::Private::ForApi( |
| 170 isolate, v8::String::NewFromUtf8(isolate, "allowAccessorFormatting", | 234 isolate, v8::String::NewFromUtf8(isolate, "allowAccessorFormatting", |
| 171 v8::NewStringType::kNormal) | 235 v8::NewStringType::kNormal) |
| 172 .ToLocalChecked()); | 236 .ToLocalChecked()); |
| 173 CHECK(object->IsObject()); | 237 CHECK(object->IsObject()); |
| 174 return object.As<v8::Object>() | 238 return object.As<v8::Object>() |
| 175 ->HasPrivate(context, shouldFormatAccessorsPrivate) | 239 ->HasPrivate(context, shouldFormatAccessorsPrivate) |
| 176 .FromMaybe(false); | 240 .FromMaybe(false); |
| 177 } | 241 } |
| 178 | 242 |
| 179 v8::Local<v8::Context> InspectorClientImpl::ensureDefaultContextInGroup(int) { | 243 v8::Local<v8::Context> InspectorClientImpl::ensureDefaultContextInGroup( |
| 244 int context_group_id) { |
| 180 CHECK(isolate_); | 245 CHECK(isolate_); |
| 181 return context_.Get(isolate_); | 246 return task_runner_->GetContext(context_group_id); |
| 182 } | 247 } |
| 183 | 248 |
| 184 void InspectorClientImpl::setCurrentTimeMSForTest(double time) { | 249 void InspectorClientImpl::setCurrentTimeMSForTest(double time) { |
| 185 current_time_ = time; | 250 current_time_ = time; |
| 186 current_time_set_for_test_ = true; | 251 current_time_set_for_test_ = true; |
| 187 } | 252 } |
| 188 | 253 |
| 189 double InspectorClientImpl::currentTimeMS() { | 254 double InspectorClientImpl::currentTimeMS() { |
| 190 if (current_time_set_for_test_) return current_time_; | 255 if (current_time_set_for_test_) return current_time_; |
| 191 return v8::base::OS::TimeCurrentMillis(); | 256 return v8::base::OS::TimeCurrentMillis(); |
| 192 } | 257 } |
| 193 | 258 |
| 194 void InspectorClientImpl::runMessageLoopOnPause(int) { | 259 void InspectorClientImpl::runMessageLoopOnPause(int) { |
| 195 task_runner_->RunMessageLoop(true); | 260 task_runner_->RunMessageLoop(true); |
| 196 } | 261 } |
| 197 | 262 |
| 198 void InspectorClientImpl::quitMessageLoopOnPause() { | 263 void InspectorClientImpl::quitMessageLoopOnPause() { |
| 199 task_runner_->QuitMessageLoop(); | 264 task_runner_->QuitMessageLoop(); |
| 200 } | 265 } |
| 201 | 266 |
| 202 v8_inspector::V8Inspector* InspectorClientImpl::InspectorFromContext( | 267 v8_inspector::V8Inspector* InspectorClientImpl::InspectorFromContext( |
| 203 v8::Local<v8::Context> context) { | 268 v8::Local<v8::Context> context) { |
| 204 return InspectorClientFromContext(context)->inspector_.get(); | 269 return InspectorClientFromContext(context)->inspector_.get(); |
| 205 } | 270 } |
| 206 | 271 |
| 207 v8_inspector::V8InspectorSession* InspectorClientImpl::SessionFromContext( | 272 v8_inspector::V8InspectorSession* InspectorClientImpl::SessionFromContext( |
| 208 v8::Local<v8::Context> context) { | 273 v8::Local<v8::Context> context) { |
| 209 return InspectorClientFromContext(context)->session_.get(); | 274 int context_group_id = TaskRunner::GetContextGroupId(context); |
| 275 return InspectorClientFromContext(context)->sessions_[context_group_id].get(); |
| 276 } |
| 277 |
| 278 v8_inspector::V8InspectorSession* InspectorClientImpl::session( |
| 279 int context_group_id) { |
| 280 if (context_group_id) { |
| 281 return sessions_[context_group_id].get(); |
| 282 } else { |
| 283 return sessions_.begin()->second.get(); |
| 284 } |
| 210 } | 285 } |
| 211 | 286 |
| 212 class SendMessageToBackendTask : public TaskRunner::Task { | 287 class SendMessageToBackendTask : public TaskRunner::Task { |
| 213 public: | 288 public: |
| 214 explicit SendMessageToBackendTask( | 289 explicit SendMessageToBackendTask( |
| 215 const v8::internal::Vector<uint16_t>& message) | 290 const v8::internal::Vector<uint16_t>& message, int context_group_id) |
| 216 : message_(message) {} | 291 : message_(message), context_group_id_(context_group_id) {} |
| 217 | 292 |
| 218 bool is_inspector_task() final { return true; } | 293 bool is_inspector_task() final { return true; } |
| 219 | 294 |
| 220 void Run(v8::Isolate* isolate, | 295 void Run(v8::Isolate* isolate, |
| 221 const v8::Global<v8::Context>& global_context) override { | 296 const v8::Global<v8::Context>& global_context) override { |
| 222 v8_inspector::V8InspectorSession* session = nullptr; | 297 v8_inspector::V8InspectorSession* session = nullptr; |
| 223 { | 298 { |
| 224 v8::HandleScope handle_scope(isolate); | 299 v8::HandleScope handle_scope(isolate); |
| 225 v8::Local<v8::Context> context = global_context.Get(isolate); | 300 v8::Local<v8::Context> context = global_context.Get(isolate); |
| 226 session = InspectorClientImpl::SessionFromContext(context); | 301 if (!context_group_id_) { |
| 302 session = InspectorClientImpl::SessionFromContext(context); |
| 303 } else { |
| 304 session = InspectorClientFromContext(context) |
| 305 ->sessions_[context_group_id_] |
| 306 .get(); |
| 307 } |
| 227 CHECK(session); | 308 CHECK(session); |
| 228 } | 309 } |
| 229 v8_inspector::StringView message_view(message_.start(), message_.length()); | 310 v8_inspector::StringView message_view(message_.start(), message_.length()); |
| 230 session->dispatchProtocolMessage(message_view); | 311 session->dispatchProtocolMessage(message_view); |
| 231 } | 312 } |
| 232 | 313 |
| 233 private: | 314 private: |
| 234 v8::internal::Vector<uint16_t> message_; | 315 v8::internal::Vector<uint16_t> message_; |
| 316 int context_group_id_; |
| 235 }; | 317 }; |
| 236 | 318 |
| 237 TaskRunner* SendMessageToBackendExtension::backend_task_runner_ = nullptr; | 319 TaskRunner* SendMessageToBackendExtension::backend_task_runner_ = nullptr; |
| 238 | 320 |
| 239 v8::Local<v8::FunctionTemplate> | 321 v8::Local<v8::FunctionTemplate> |
| 240 SendMessageToBackendExtension::GetNativeFunctionTemplate( | 322 SendMessageToBackendExtension::GetNativeFunctionTemplate( |
| 241 v8::Isolate* isolate, v8::Local<v8::String> name) { | 323 v8::Isolate* isolate, v8::Local<v8::String> name) { |
| 242 return v8::FunctionTemplate::New( | 324 return v8::FunctionTemplate::New( |
| 243 isolate, SendMessageToBackendExtension::SendMessageToBackend); | 325 isolate, SendMessageToBackendExtension::SendMessageToBackend); |
| 244 } | 326 } |
| 245 | 327 |
| 246 void SendMessageToBackendExtension::SendMessageToBackend( | 328 void SendMessageToBackendExtension::SendMessageToBackend( |
| 247 const v8::FunctionCallbackInfo<v8::Value>& args) { | 329 const v8::FunctionCallbackInfo<v8::Value>& args) { |
| 248 CHECK(backend_task_runner_); | 330 CHECK(backend_task_runner_); |
| 249 CHECK(args.Length() == 1 && args[0]->IsString()); | 331 CHECK(args.Length() == 2 && args[0]->IsString() && args[1]->IsInt32()); |
| 250 v8::Local<v8::String> message = args[0].As<v8::String>(); | 332 v8::Local<v8::String> message = args[0].As<v8::String>(); |
| 251 backend_task_runner_->Append(new SendMessageToBackendTask(ToVector(message))); | 333 backend_task_runner_->Append(new SendMessageToBackendTask( |
| 334 ToVector(message), args[1].As<v8::Int32>()->Value())); |
| 252 } | 335 } |
| OLD | NEW |