blob: 67c9e8c0816348d5254ff7440cd11b2a10e90f5f [file] [log] [blame]
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "third_party/blink/renderer/core/workers/worker_inspector_proxy.h"
#include "base/location.h"
#include "third_party/blink/renderer/core/frame/frame_console.h"
#include "third_party/blink/renderer/core/inspector/InspectorTraceEvents.h"
#include "third_party/blink/renderer/core/inspector/InspectorWorkerAgent.h"
#include "third_party/blink/renderer/core/inspector/identifiers_factory.h"
#include "third_party/blink/renderer/core/inspector/worker_inspector_controller.h"
#include "third_party/blink/renderer/core/probe/core_probes.h"
#include "third_party/blink/renderer/core/workers/execution_context_worker_registry.h"
#include "third_party/blink/renderer/core/workers/worker_global_scope.h"
#include "third_party/blink/renderer/core/workers/worker_thread.h"
#include "third_party/blink/renderer/platform/cross_thread_functional.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
namespace blink {
WorkerInspectorProxy::WorkerInspectorProxy()
: worker_thread_(nullptr), execution_context_(nullptr) {}
WorkerInspectorProxy* WorkerInspectorProxy::Create() {
return new WorkerInspectorProxy();
}
WorkerInspectorProxy::~WorkerInspectorProxy() = default;
const String& WorkerInspectorProxy::InspectorId() {
if (inspector_id_.IsEmpty() && worker_thread_) {
inspector_id_ = IdentifiersFactory::IdFromToken(
worker_thread_->GetDevToolsWorkerToken());
}
return inspector_id_;
}
WorkerInspectorProxy::PauseOnWorkerStart
WorkerInspectorProxy::ShouldPauseOnWorkerStart(
ExecutionContext* execution_context) {
bool result = false;
probe::shouldWaitForDebuggerOnWorkerStart(execution_context, &result);
return result ? PauseOnWorkerStart::kPause : PauseOnWorkerStart::kDontPause;
}
void WorkerInspectorProxy::WorkerThreadCreated(
ExecutionContext* execution_context,
WorkerThread* worker_thread,
const KURL& url) {
worker_thread_ = worker_thread;
execution_context_ = execution_context;
url_ = url.GetString();
DCHECK(execution_context_);
ExecutionContextWorkerRegistry::From(*execution_context_)
->AddWorkerInspectorProxy(this);
// We expect everyone starting worker thread to synchronously ask for
// ShouldPauseOnWorkerStart() right before.
bool waiting_for_debugger = false;
probe::shouldWaitForDebuggerOnWorkerStart(execution_context_,
&waiting_for_debugger);
probe::didStartWorker(execution_context_, this, waiting_for_debugger);
}
void WorkerInspectorProxy::WorkerThreadTerminated() {
if (worker_thread_) {
ExecutionContextWorkerRegistry::From(*execution_context_)
->RemoveWorkerInspectorProxy(this);
probe::workerTerminated(execution_context_, this);
}
worker_thread_ = nullptr;
page_inspectors_.clear();
execution_context_ = nullptr;
}
void WorkerInspectorProxy::DispatchMessageFromWorker(int session_id,
const String& message) {
auto it = page_inspectors_.find(session_id);
if (it != page_inspectors_.end())
it->value->DispatchMessageFromWorker(this, session_id, message);
}
static void ConnectToWorkerGlobalScopeInspectorTask(WorkerThread* worker_thread,
int session_id) {
if (WorkerInspectorController* inspector =
worker_thread->GetWorkerInspectorController()) {
inspector->ConnectFrontend(session_id);
}
}
void WorkerInspectorProxy::ConnectToInspector(
int session_id,
WorkerInspectorProxy::PageInspector* page_inspector) {
if (!worker_thread_)
return;
DCHECK(page_inspectors_.find(session_id) == page_inspectors_.end());
page_inspectors_.insert(session_id, page_inspector);
worker_thread_->AppendDebuggerTask(
CrossThreadBind(ConnectToWorkerGlobalScopeInspectorTask,
CrossThreadUnretained(worker_thread_), session_id));
}
static void DisconnectFromWorkerGlobalScopeInspectorTask(
WorkerThread* worker_thread,
int session_id) {
if (WorkerInspectorController* inspector =
worker_thread->GetWorkerInspectorController()) {
inspector->DisconnectFrontend(session_id);
}
}
void WorkerInspectorProxy::DisconnectFromInspector(
int session_id,
WorkerInspectorProxy::PageInspector* page_inspector) {
DCHECK(page_inspectors_.at(session_id) == page_inspector);
page_inspectors_.erase(session_id);
if (worker_thread_) {
worker_thread_->AppendDebuggerTask(
CrossThreadBind(DisconnectFromWorkerGlobalScopeInspectorTask,
CrossThreadUnretained(worker_thread_), session_id));
}
}
static void DispatchOnInspectorBackendTask(int session_id,
const String& message,
WorkerThread* worker_thread) {
if (WorkerInspectorController* inspector =
worker_thread->GetWorkerInspectorController()) {
inspector->DispatchMessageFromFrontend(session_id, message);
}
}
void WorkerInspectorProxy::SendMessageToInspector(int session_id,
const String& message) {
if (worker_thread_) {
worker_thread_->AppendDebuggerTask(
CrossThreadBind(DispatchOnInspectorBackendTask, session_id, message,
CrossThreadUnretained(worker_thread_)));
}
}
void WorkerInspectorProxy::Trace(blink::Visitor* visitor) {
visitor->Trace(execution_context_);
}
} // namespace blink