InspectorWorkerAgent.cpp [plain text]
#include "config.h"
#include "InspectorWorkerAgent.h"
#include "InspectorForwarding.h"
#include "InstrumentingAgents.h"
#include "URL.h"
#include "WorkerGlobalScopeProxy.h"
#include <inspector/InspectorFrontendDispatchers.h>
#include <inspector/InspectorValues.h>
#include <wtf/RefPtr.h>
using namespace Inspector;
namespace WebCore {
class InspectorWorkerAgent::WorkerFrontendChannel : public WorkerGlobalScopeProxy::PageInspector {
WTF_MAKE_FAST_ALLOCATED;
public:
explicit WorkerFrontendChannel(Inspector::WorkerFrontendDispatcher* frontendDispatcher, WorkerGlobalScopeProxy* proxy)
: m_frontendDispatcher(frontendDispatcher)
, m_proxy(proxy)
, m_id(s_nextId++)
, m_connected(false)
{
}
virtual ~WorkerFrontendChannel()
{
disconnectFromWorkerGlobalScope();
}
int id() const { return m_id; }
WorkerGlobalScopeProxy* proxy() const { return m_proxy; }
void connectToWorkerGlobalScope()
{
if (m_connected)
return;
m_connected = true;
m_proxy->connectToInspector(this);
}
void disconnectFromWorkerGlobalScope()
{
if (!m_connected)
return;
m_connected = false;
m_proxy->disconnectFromInspector();
}
private:
virtual void dispatchMessageFromWorker(const String& messageString) override
{
RefPtr<InspectorValue> parsedMessage;
if (!InspectorValue::parseJSON(messageString, parsedMessage))
return;
RefPtr<InspectorObject> messageObject;
if (!parsedMessage->asObject(messageObject))
return;
m_frontendDispatcher->dispatchMessageFromWorker(m_id, messageObject);
}
Inspector::WorkerFrontendDispatcher* m_frontendDispatcher;
WorkerGlobalScopeProxy* m_proxy;
int m_id;
bool m_connected;
static int s_nextId;
};
int InspectorWorkerAgent::WorkerFrontendChannel::s_nextId = 1;
InspectorWorkerAgent::InspectorWorkerAgent(InstrumentingAgents* instrumentingAgents)
: InspectorAgentBase(ASCIILiteral("Worker"), instrumentingAgents)
, m_enabled(false)
, m_shouldPauseDedicatedWorkerOnStart(false)
{
m_instrumentingAgents->setInspectorWorkerAgent(this);
}
InspectorWorkerAgent::~InspectorWorkerAgent()
{
m_instrumentingAgents->setInspectorWorkerAgent(nullptr);
}
void InspectorWorkerAgent::didCreateFrontendAndBackend(Inspector::FrontendChannel* frontendChannel, Inspector::BackendDispatcher* backendDispatcher)
{
m_frontendDispatcher = std::make_unique<Inspector::WorkerFrontendDispatcher>(frontendChannel);
m_backendDispatcher = Inspector::WorkerBackendDispatcher::create(backendDispatcher, this);
}
void InspectorWorkerAgent::willDestroyFrontendAndBackend(Inspector::DisconnectReason)
{
m_shouldPauseDedicatedWorkerOnStart = false;
ErrorString unused;
disable(unused);
m_frontendDispatcher = nullptr;
m_backendDispatcher = nullptr;
}
void InspectorWorkerAgent::enable(ErrorString&)
{
m_enabled = true;
if (!m_frontendDispatcher)
return;
createWorkerFrontendChannelsForExistingWorkers();
}
void InspectorWorkerAgent::disable(ErrorString&)
{
m_enabled = false;
if (!m_frontendDispatcher)
return;
destroyWorkerFrontendChannels();
}
void InspectorWorkerAgent::canInspectWorkers(ErrorString&, bool* result)
{
*result = true;
}
void InspectorWorkerAgent::connectToWorker(ErrorString& error, int workerId)
{
WorkerFrontendChannel* channel = m_idToChannel.get(workerId);
if (channel)
channel->connectToWorkerGlobalScope();
else
error = ASCIILiteral("Worker is gone");
}
void InspectorWorkerAgent::disconnectFromWorker(ErrorString& error, int workerId)
{
WorkerFrontendChannel* channel = m_idToChannel.get(workerId);
if (channel)
channel->disconnectFromWorkerGlobalScope();
else
error = ASCIILiteral("Worker is gone");
}
void InspectorWorkerAgent::sendMessageToWorker(ErrorString& error, int workerId, const InspectorObject& message)
{
WorkerFrontendChannel* channel = m_idToChannel.get(workerId);
if (channel)
channel->proxy()->sendMessageToInspector(message.toJSONString());
else
error = ASCIILiteral("Worker is gone");
}
void InspectorWorkerAgent::setAutoconnectToWorkers(ErrorString&, bool value)
{
m_shouldPauseDedicatedWorkerOnStart = value;
}
bool InspectorWorkerAgent::shouldPauseDedicatedWorkerOnStart() const
{
return m_shouldPauseDedicatedWorkerOnStart;
}
void InspectorWorkerAgent::didStartWorkerGlobalScope(WorkerGlobalScopeProxy* workerGlobalScopeProxy, const URL& url)
{
m_dedicatedWorkers.set(workerGlobalScopeProxy, url.string());
if (m_frontendDispatcher && m_enabled)
createWorkerFrontendChannel(workerGlobalScopeProxy, url.string());
}
void InspectorWorkerAgent::workerGlobalScopeTerminated(WorkerGlobalScopeProxy* proxy)
{
m_dedicatedWorkers.remove(proxy);
for (WorkerChannels::iterator it = m_idToChannel.begin(); it != m_idToChannel.end(); ++it) {
if (proxy == it->value->proxy()) {
m_frontendDispatcher->workerTerminated(it->key);
delete it->value;
m_idToChannel.remove(it);
return;
}
}
}
void InspectorWorkerAgent::createWorkerFrontendChannelsForExistingWorkers()
{
for (DedicatedWorkers::iterator it = m_dedicatedWorkers.begin(); it != m_dedicatedWorkers.end(); ++it)
createWorkerFrontendChannel(it->key, it->value);
}
void InspectorWorkerAgent::destroyWorkerFrontendChannels()
{
for (WorkerChannels::iterator it = m_idToChannel.begin(); it != m_idToChannel.end(); ++it) {
it->value->disconnectFromWorkerGlobalScope();
delete it->value;
}
m_idToChannel.clear();
}
void InspectorWorkerAgent::createWorkerFrontendChannel(WorkerGlobalScopeProxy* workerGlobalScopeProxy, const String& url)
{
WorkerFrontendChannel* channel = new WorkerFrontendChannel(m_frontendDispatcher.get(), workerGlobalScopeProxy);
m_idToChannel.set(channel->id(), channel);
ASSERT(m_frontendDispatcher);
if (m_shouldPauseDedicatedWorkerOnStart)
channel->connectToWorkerGlobalScope();
m_frontendDispatcher->workerCreated(channel->id(), url, m_shouldPauseDedicatedWorkerOnStart);
}
}