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 |