WorkerDebuggerAgent.cpp [plain text]
#include "config.h"
#include "WorkerDebuggerAgent.h"
#if ENABLE(INSPECTOR)
#include "WorkerGlobalScope.h"
#include "WorkerThread.h"
#include <inspector/InjectedScript.h>
#include <inspector/InjectedScriptManager.h>
#include <inspector/ScriptDebugServer.h>
#include <mutex>
#include <wtf/MessageQueue.h>
#include <wtf/NeverDestroyed.h>
using namespace Inspector;
namespace WebCore {
namespace {
std::mutex& workerDebuggerAgentsMutex()
{
static std::once_flag onceFlag;
static LazyNeverDestroyed<std::mutex> mutex;
std::call_once(onceFlag, []{
mutex.construct();
});
return mutex;
}
typedef HashMap<WorkerThread*, WorkerDebuggerAgent*> WorkerDebuggerAgents;
WorkerDebuggerAgents& workerDebuggerAgents()
{
static NeverDestroyed<WorkerDebuggerAgents> agents;
return agents;
}
class RunInspectorCommandsTask : public ScriptDebugServer::Task {
public:
RunInspectorCommandsTask(WorkerThread* thread, WorkerGlobalScope* workerGlobalScope)
: m_thread(thread)
, m_workerGlobalScope(workerGlobalScope) { }
virtual ~RunInspectorCommandsTask() { }
virtual void run() override
{
while (MessageQueueMessageReceived == m_thread->runLoop().runInMode(m_workerGlobalScope, WorkerDebuggerAgent::debuggerTaskMode, WorkerRunLoop::DontWaitForMessage)) { }
}
private:
WorkerThread* m_thread;
WorkerGlobalScope* m_workerGlobalScope;
};
}
const char* WorkerDebuggerAgent::debuggerTaskMode = "debugger";
WorkerDebuggerAgent::WorkerDebuggerAgent(InjectedScriptManager* injectedScriptManager, InstrumentingAgents* instrumentingAgents, WorkerGlobalScope* inspectedWorkerGlobalScope)
: WebDebuggerAgent(injectedScriptManager, instrumentingAgents)
, m_scriptDebugServer(inspectedWorkerGlobalScope, WorkerDebuggerAgent::debuggerTaskMode)
, m_inspectedWorkerGlobalScope(inspectedWorkerGlobalScope)
{
std::lock_guard<std::mutex> lock(workerDebuggerAgentsMutex());
workerDebuggerAgents().set(&inspectedWorkerGlobalScope->thread(), this);
}
WorkerDebuggerAgent::~WorkerDebuggerAgent()
{
std::lock_guard<std::mutex> lock(workerDebuggerAgentsMutex());
ASSERT(workerDebuggerAgents().contains(&m_inspectedWorkerGlobalScope->thread()));
workerDebuggerAgents().remove(&m_inspectedWorkerGlobalScope->thread());
}
void WorkerDebuggerAgent::interruptAndDispatchInspectorCommands(WorkerThread* thread)
{
std::lock_guard<std::mutex> lock(workerDebuggerAgentsMutex());
if (WorkerDebuggerAgent* agent = workerDebuggerAgents().get(thread))
agent->m_scriptDebugServer.interruptAndRunTask(adoptPtr(new RunInspectorCommandsTask(thread, agent->m_inspectedWorkerGlobalScope)));
}
void WorkerDebuggerAgent::startListeningScriptDebugServer()
{
scriptDebugServer().addListener(this);
}
void WorkerDebuggerAgent::stopListeningScriptDebugServer(bool isBeingDestroyed)
{
scriptDebugServer().removeListener(this, isBeingDestroyed);
}
void WorkerDebuggerAgent::breakpointActionLog(JSC::ExecState*, const String& message)
{
m_inspectedWorkerGlobalScope->addConsoleMessage(MessageSource::JS, MessageLevel::Log, message);
}
WorkerScriptDebugServer& WorkerDebuggerAgent::scriptDebugServer()
{
return m_scriptDebugServer;
}
InjectedScript WorkerDebuggerAgent::injectedScriptForEval(ErrorString* error, const int* executionContextId)
{
if (executionContextId) {
*error = ASCIILiteral("Execution context id is not supported for workers as there is only one execution context.");
return InjectedScript();
}
JSC::ExecState* scriptState = execStateFromWorkerGlobalScope(m_inspectedWorkerGlobalScope);
return injectedScriptManager()->injectedScriptFor(scriptState);
}
void WorkerDebuggerAgent::muteConsole()
{
}
void WorkerDebuggerAgent::unmuteConsole()
{
}
}
#endif // ENABLE(INSPECTOR)