| // 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/ExecutionContextTask.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( |
| MessageLevel level, |
| const String& message, |
| std::unique_ptr<SourceLocation> location) { |
| if (LocalFrame* frame = m_document->frame()) |
| frame->console().addMessageFromWorker(level, message, std::move(location), |
| m_inspectorId); |
| } |
| |
| static void connectToWorkerGlobalScopeInspectorTask( |
| WorkerThread* workerThread) { |
| if (WorkerInspectorController* inspector = |
| workerThread->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) { |
| if (WorkerInspectorController* inspector = |
| workerThread->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) { |
| if (WorkerInspectorController* inspector = |
| workerThread->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 |