| // 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 "core/workers/WorkerInspectorProxy.h" |
| |
| #include "core/dom/CrossThreadTask.h" |
| #include "core/frame/FrameConsole.h" |
| #include "core/inspector/IdentifiersFactory.h" |
| #include "core/inspector/InspectorInstrumentation.h" |
| #include "core/inspector/InspectorTraceEvents.h" |
| #include "core/inspector/WorkerInspectorController.h" |
| #include "core/workers/WorkerGlobalScope.h" |
| #include "core/workers/WorkerThread.h" |
| #include "platform/TraceEvent.h" |
| #include "platform/weborigin/KURL.h" |
| #include "public/platform/WebTaskRunner.h" |
| #include "public/platform/WebTraceLocation.h" |
| |
| namespace blink { |
| |
| namespace { |
| |
| static WorkerInspectorProxy::WorkerInspectorProxySet& inspectorProxies() |
| { |
| DEFINE_STATIC_LOCAL(WorkerInspectorProxy::WorkerInspectorProxySet, proxies, ()); |
| return proxies; |
| } |
| |
| } // namespace |
| |
| const WorkerInspectorProxy::WorkerInspectorProxySet& WorkerInspectorProxy::allProxies() |
| { |
| return inspectorProxies(); |
| } |
| |
| WorkerInspectorProxy::WorkerInspectorProxy() |
| : m_workerThread(nullptr) |
| , m_document(nullptr) |
| , m_pageInspector(nullptr) |
| { |
| } |
| |
| WorkerInspectorProxy* WorkerInspectorProxy::create() |
| { |
| return new WorkerInspectorProxy(); |
| } |
| |
| WorkerInspectorProxy::~WorkerInspectorProxy() |
| { |
| } |
| |
| const String& WorkerInspectorProxy::inspectorId() |
| { |
| if (m_inspectorId.isEmpty()) |
| m_inspectorId = "dedicated:" + IdentifiersFactory::createIdentifier(); |
| return m_inspectorId; |
| } |
| |
| WorkerThreadStartMode WorkerInspectorProxy::workerStartMode(Document* document) |
| { |
| if (InspectorInstrumentation::shouldWaitForDebuggerOnWorkerStart(document)) |
| return PauseWorkerGlobalScopeOnStart; |
| return DontPauseWorkerGlobalScopeOnStart; |
| } |
| |
| void WorkerInspectorProxy::workerThreadCreated(Document* document, WorkerThread* workerThread, const KURL& url) |
| { |
| m_workerThread = workerThread; |
| m_document = document; |
| m_url = url.getString(); |
| inspectorProxies().add(this); |
| // We expect everyone starting worker thread to synchronously ask for workerStartMode right before. |
| bool waitingForDebugger = InspectorInstrumentation::shouldWaitForDebuggerOnWorkerStart(document); |
| InspectorInstrumentation::didStartWorker(document, this, waitingForDebugger); |
| } |
| |
| void WorkerInspectorProxy::workerThreadTerminated() |
| { |
| if (m_workerThread) { |
| DCHECK(inspectorProxies().contains(this)); |
| inspectorProxies().remove(this); |
| InspectorInstrumentation::workerTerminated(m_document, this); |
| } |
| |
| m_workerThread = nullptr; |
| m_pageInspector = nullptr; |
| m_document = nullptr; |
| } |
| |
| void WorkerInspectorProxy::dispatchMessageFromWorker(const String& message) |
| { |
| if (m_pageInspector) |
| m_pageInspector->dispatchMessageFromWorker(this, message); |
| } |
| |
| void WorkerInspectorProxy::addConsoleMessageFromWorker(ConsoleMessage* consoleMessage) |
| { |
| if (LocalFrame* frame = m_document->frame()) |
| frame->console().addMessageFromWorker(consoleMessage, m_inspectorId); |
| } |
| |
| static void connectToWorkerGlobalScopeInspectorTask(WorkerThread* workerThread) |
| { |
| WorkerOrWorkletGlobalScope* globalScope = workerThread->globalScope(); |
| if (globalScope->isWorkerGlobalScope()) { |
| if (WorkerInspectorController* inspector = toWorkerGlobalScope(globalScope)->workerInspectorController()) |
| inspector->connectFrontend(); |
| } |
| } |
| |
| void WorkerInspectorProxy::connectToInspector(WorkerInspectorProxy::PageInspector* pageInspector) |
| { |
| if (!m_workerThread) |
| return; |
| DCHECK(!m_pageInspector); |
| m_pageInspector = pageInspector; |
| m_workerThread->appendDebuggerTask(crossThreadBind(connectToWorkerGlobalScopeInspectorTask, crossThreadUnretained(m_workerThread))); |
| } |
| |
| static void disconnectFromWorkerGlobalScopeInspectorTask(WorkerThread* workerThread) |
| { |
| WorkerOrWorkletGlobalScope* globalScope = workerThread->globalScope(); |
| if (globalScope->isWorkerGlobalScope()) { |
| if (WorkerInspectorController* inspector = toWorkerGlobalScope(globalScope)->workerInspectorController()) |
| inspector->disconnectFrontend(); |
| } |
| } |
| |
| void WorkerInspectorProxy::disconnectFromInspector(WorkerInspectorProxy::PageInspector* pageInspector) |
| { |
| DCHECK(m_pageInspector == pageInspector); |
| m_pageInspector = nullptr; |
| if (m_workerThread) |
| m_workerThread->appendDebuggerTask(crossThreadBind(disconnectFromWorkerGlobalScopeInspectorTask, crossThreadUnretained(m_workerThread))); |
| } |
| |
| static void dispatchOnInspectorBackendTask(const String& message, WorkerThread* workerThread) |
| { |
| WorkerOrWorkletGlobalScope* globalScope = workerThread->globalScope(); |
| if (globalScope->isWorkerGlobalScope()) { |
| if (WorkerInspectorController* inspector = toWorkerGlobalScope(globalScope)->workerInspectorController()) |
| inspector->dispatchMessageFromFrontend(message); |
| } |
| } |
| |
| void WorkerInspectorProxy::sendMessageToInspector(const String& message) |
| { |
| if (m_workerThread) |
| m_workerThread->appendDebuggerTask(crossThreadBind(dispatchOnInspectorBackendTask, message, crossThreadUnretained(m_workerThread))); |
| } |
| |
| void WorkerInspectorProxy::writeTimelineStartedEvent(const String& sessionId) |
| { |
| if (!m_workerThread) |
| return; |
| TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "TracingSessionIdForWorker", TRACE_EVENT_SCOPE_THREAD, "data", InspectorTracingSessionIdForWorkerEvent::data(sessionId, inspectorId(), m_workerThread)); |
| } |
| |
| DEFINE_TRACE(WorkerInspectorProxy) |
| { |
| visitor->trace(m_document); |
| } |
| |
| } // namespace blink |