blob: 266d0f2ac30af2b5412f985e26323c83cd82cd84 [file] [log] [blame]
/*
* Copyright (C) 2011 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include "core/inspector/InspectorWorkerAgent.h"
#include "core/InspectorFrontend.h"
#include "core/inspector/IdentifiersFactory.h"
#include "core/inspector/InspectorState.h"
#include "core/inspector/InstrumentingAgents.h"
#include "core/inspector/PageConsoleAgent.h"
#include "core/workers/WorkerInspectorProxy.h"
#include "platform/weborigin/KURL.h"
#include "wtf/PassOwnPtr.h"
#include "wtf/RefPtr.h"
#include "wtf/text/WTFString.h"
namespace blink {
namespace WorkerAgentState {
static const char workerInspectionEnabled[] = "workerInspectionEnabled";
static const char autoconnectToWorkers[] = "autoconnectToWorkers";
};
class InspectorWorkerAgent::WorkerAgentClient final : public WorkerInspectorProxy::PageInspector {
WTF_MAKE_FAST_ALLOCATED(InspectorWorkerAgent::WorkerAgentClient);
public:
WorkerAgentClient(InspectorFrontend::Worker* frontend, WorkerInspectorProxy* proxy, const String& id, PageConsoleAgent* consoleAgent)
: m_frontend(frontend)
, m_proxy(proxy)
, m_id(id)
, m_connected(false)
, m_consoleAgent(consoleAgent)
{
ASSERT(!proxy->pageInspector());
}
virtual ~WorkerAgentClient()
{
disconnectFromWorker();
}
String id() const { return m_id; }
WorkerInspectorProxy* proxy() const { return m_proxy; }
void connectToWorker()
{
if (m_connected)
return;
m_connected = true;
m_proxy->connectToInspector(this);
}
void disconnectFromWorker()
{
if (!m_connected)
return;
m_connected = false;
m_proxy->disconnectFromInspector();
}
private:
// WorkerInspectorProxy::PageInspector implementation
virtual void dispatchMessageFromWorker(const String& message) override
{
m_frontend->dispatchMessageFromWorker(m_id, message);
}
// WorkerInspectorProxy::PageInspector implementation
virtual void workerConsoleAgentEnabled(WorkerGlobalScopeProxy* proxy) override
{
m_consoleAgent->workerConsoleAgentEnabled(proxy);
}
InspectorFrontend::Worker* m_frontend;
WorkerInspectorProxy* m_proxy;
String m_id;
bool m_connected;
PageConsoleAgent* m_consoleAgent;
};
PassOwnPtrWillBeRawPtr<InspectorWorkerAgent> InspectorWorkerAgent::create(PageConsoleAgent* consoleAgent)
{
return adoptPtrWillBeNoop(new InspectorWorkerAgent(consoleAgent));
}
InspectorWorkerAgent::InspectorWorkerAgent(PageConsoleAgent* consoleAgent)
: InspectorBaseAgent<InspectorWorkerAgent, InspectorFrontend::Worker>("Worker")
, m_consoleAgent(consoleAgent)
{
}
InspectorWorkerAgent::~InspectorWorkerAgent()
{
#if !ENABLE(OILPAN)
m_instrumentingAgents->setInspectorWorkerAgent(0);
#endif
}
void InspectorWorkerAgent::init()
{
m_instrumentingAgents->setInspectorWorkerAgent(this);
}
void InspectorWorkerAgent::restore()
{
if (m_state->getBoolean(WorkerAgentState::workerInspectionEnabled))
createWorkerAgentClientsForExistingWorkers();
}
void InspectorWorkerAgent::enable(ErrorString*)
{
m_state->setBoolean(WorkerAgentState::workerInspectionEnabled, true);
createWorkerAgentClientsForExistingWorkers();
}
void InspectorWorkerAgent::disable(ErrorString*)
{
m_state->setBoolean(WorkerAgentState::workerInspectionEnabled, false);
m_state->setBoolean(WorkerAgentState::autoconnectToWorkers, false);
destroyWorkerAgentClients();
}
void InspectorWorkerAgent::connectToWorker(ErrorString* error, const String& workerId)
{
WorkerAgentClient* client = m_idToClient.get(workerId);
if (client)
client->connectToWorker();
else
*error = "Worker is gone";
}
void InspectorWorkerAgent::disconnectFromWorker(ErrorString* error, const String& workerId)
{
WorkerAgentClient* client = m_idToClient.get(workerId);
if (client)
client->disconnectFromWorker();
else
*error = "Worker is gone";
}
void InspectorWorkerAgent::sendMessageToWorker(ErrorString* error, const String& workerId, const String& message)
{
WorkerAgentClient* client = m_idToClient.get(workerId);
if (client)
client->proxy()->sendMessageToInspector(message);
else
*error = "Worker is gone";
}
void InspectorWorkerAgent::setAutoconnectToWorkers(ErrorString*, bool value)
{
m_state->setBoolean(WorkerAgentState::autoconnectToWorkers, value);
}
void InspectorWorkerAgent::setTracingSessionId(const String& sessionId)
{
m_tracingSessionId = sessionId;
if (sessionId.isEmpty())
return;
for (auto& info : m_workerInfos)
info.key->writeTimelineStartedEvent(sessionId, info.value.id);
}
bool InspectorWorkerAgent::shouldPauseDedicatedWorkerOnStart()
{
return m_state->getBoolean(WorkerAgentState::autoconnectToWorkers);
}
void InspectorWorkerAgent::didStartWorker(WorkerInspectorProxy* workerInspectorProxy, const KURL& url)
{
String id = "dedicated:" + IdentifiersFactory::createIdentifier();
m_workerInfos.set(workerInspectorProxy, WorkerInfo(url.string(), id));
if (frontend() && m_state->getBoolean(WorkerAgentState::workerInspectionEnabled))
createWorkerAgentClient(workerInspectorProxy, url.string(), id);
if (!m_tracingSessionId.isEmpty())
workerInspectorProxy->writeTimelineStartedEvent(m_tracingSessionId, id);
}
void InspectorWorkerAgent::workerTerminated(WorkerInspectorProxy* proxy)
{
m_workerInfos.remove(proxy);
for (WorkerClients::iterator it = m_idToClient.begin(); it != m_idToClient.end(); ++it) {
if (proxy == it->value->proxy()) {
frontend()->workerTerminated(it->key);
delete it->value;
m_idToClient.remove(it);
return;
}
}
}
void InspectorWorkerAgent::createWorkerAgentClientsForExistingWorkers()
{
for (auto& info : m_workerInfos)
createWorkerAgentClient(info.key, info.value.url, info.value.id);
}
void InspectorWorkerAgent::destroyWorkerAgentClients()
{
for (auto& client : m_idToClient) {
client.value->disconnectFromWorker();
delete client.value;
}
m_idToClient.clear();
}
void InspectorWorkerAgent::createWorkerAgentClient(WorkerInspectorProxy* workerInspectorProxy, const String& url, const String& id)
{
WorkerAgentClient* client = new WorkerAgentClient(frontend(), workerInspectorProxy, id, m_consoleAgent);
m_idToClient.set(id, client);
ASSERT(frontend());
bool autoconnectToWorkers = m_state->getBoolean(WorkerAgentState::autoconnectToWorkers);
if (autoconnectToWorkers)
client->connectToWorker();
frontend()->workerCreated(id, url, autoconnectToWorkers);
}
} // namespace blink