1/*
2 * Copyright (C) 2016 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "config.h"
27#include "InspectorWorkerAgent.h"
28
29#include "Document.h"
30#include "InstrumentingAgents.h"
31
32
33namespace WebCore {
34
35using namespace Inspector;
36
37InspectorWorkerAgent::InspectorWorkerAgent(PageAgentContext& context)
38 : InspectorAgentBase("Worker"_s, context)
39 , m_frontendDispatcher(std::make_unique<Inspector::WorkerFrontendDispatcher>(context.frontendRouter))
40 , m_backendDispatcher(Inspector::WorkerBackendDispatcher::create(context.backendDispatcher, this))
41 , m_page(context.inspectedPage)
42{
43}
44
45void InspectorWorkerAgent::didCreateFrontendAndBackend(FrontendRouter*, BackendDispatcher*)
46{
47 m_instrumentingAgents.setInspectorWorkerAgent(this);
48}
49
50void InspectorWorkerAgent::willDestroyFrontendAndBackend(DisconnectReason)
51{
52 m_instrumentingAgents.setInspectorWorkerAgent(nullptr);
53
54 ErrorString ignored;
55 disable(ignored);
56}
57
58void InspectorWorkerAgent::enable(ErrorString&)
59{
60 if (m_enabled)
61 return;
62
63 m_enabled = true;
64
65 connectToAllWorkerInspectorProxiesForPage();
66}
67
68void InspectorWorkerAgent::disable(ErrorString&)
69{
70 if (!m_enabled)
71 return;
72
73 m_enabled = false;
74
75 disconnectFromAllWorkerInspectorProxies();
76}
77
78void InspectorWorkerAgent::initialized(ErrorString& errorString, const String& workerId)
79{
80 WorkerInspectorProxy* proxy = m_connectedProxies.get(workerId);
81 if (!proxy) {
82 errorString = "Worker not found."_s;
83 return;
84 }
85
86 proxy->resumeWorkerIfPaused();
87}
88
89void InspectorWorkerAgent::sendMessageToWorker(ErrorString& errorString, const String& workerId, const String& message)
90{
91 if (!m_enabled) {
92 errorString = "Worker inspection must be enabled."_s;
93 return;
94 }
95
96 WorkerInspectorProxy* proxy = m_connectedProxies.get(workerId);
97 if (!proxy) {
98 errorString = "Worker not found."_s;
99 return;
100 }
101
102 proxy->sendMessageToWorkerInspectorController(message);
103}
104
105void InspectorWorkerAgent::sendMessageFromWorkerToFrontend(WorkerInspectorProxy* proxy, const String& message)
106{
107 m_frontendDispatcher->dispatchMessageFromWorker(proxy->identifier(), message);
108}
109
110bool InspectorWorkerAgent::shouldWaitForDebuggerOnStart() const
111{
112 return m_enabled;
113}
114
115void InspectorWorkerAgent::workerStarted(WorkerInspectorProxy* proxy, const URL&)
116{
117 if (!m_enabled)
118 return;
119
120 connectToWorkerInspectorProxy(proxy);
121}
122
123void InspectorWorkerAgent::workerTerminated(WorkerInspectorProxy* proxy)
124{
125 if (!m_enabled)
126 return;
127
128 disconnectFromWorkerInspectorProxy(proxy);
129}
130
131void InspectorWorkerAgent::connectToAllWorkerInspectorProxiesForPage()
132{
133 ASSERT(m_connectedProxies.isEmpty());
134
135 for (auto* proxy : WorkerInspectorProxy::allWorkerInspectorProxies()) {
136 if (!is<Document>(proxy->scriptExecutionContext()))
137 continue;
138
139 Document& document = downcast<Document>(*proxy->scriptExecutionContext());
140 if (document.page() != &m_page)
141 continue;
142
143 connectToWorkerInspectorProxy(proxy);
144 }
145}
146
147void InspectorWorkerAgent::disconnectFromAllWorkerInspectorProxies()
148{
149 for (auto* proxy : copyToVector(m_connectedProxies.values()))
150 proxy->disconnectFromWorkerInspectorController();
151
152 m_connectedProxies.clear();
153}
154
155void InspectorWorkerAgent::connectToWorkerInspectorProxy(WorkerInspectorProxy* proxy)
156{
157 proxy->connectToWorkerInspectorController(this);
158
159 m_connectedProxies.set(proxy->identifier(), proxy);
160
161 m_frontendDispatcher->workerCreated(proxy->identifier(), proxy->url());
162}
163
164void InspectorWorkerAgent::disconnectFromWorkerInspectorProxy(WorkerInspectorProxy* proxy)
165{
166 m_frontendDispatcher->workerTerminated(proxy->identifier());
167
168 m_connectedProxies.remove(proxy->identifier());
169
170 proxy->disconnectFromWorkerInspectorController();
171}
172
173} // namespace Inspector
174