• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2011 Google 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 are
6  * met:
7  *
8  *     * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *     * Redistributions in binary form must reproduce the above
11  * copyright notice, this list of conditions and the following disclaimer
12  * in the documentation and/or other materials provided with the
13  * distribution.
14  *     * Neither the name of Google Inc. nor the names of its
15  * contributors may be used to endorse or promote products derived from
16  * this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 #include "config.h"
32 
33 #include "core/inspector/InspectorWorkerAgent.h"
34 
35 #include "core/InspectorFrontend.h"
36 #include "core/inspector/InspectorState.h"
37 #include "core/inspector/InstrumentingAgents.h"
38 #include "core/inspector/JSONParser.h"
39 #include "core/workers/WorkerGlobalScopeProxy.h"
40 #include "platform/JSONValues.h"
41 #include "platform/weborigin/KURL.h"
42 #include "wtf/PassOwnPtr.h"
43 #include "wtf/RefPtr.h"
44 
45 namespace WebCore {
46 
47 namespace WorkerAgentState {
48 static const char workerInspectionEnabled[] = "workerInspectionEnabled";
49 static const char autoconnectToWorkers[] = "autoconnectToWorkers";
50 };
51 
52 class InspectorWorkerAgent::WorkerFrontendChannel FINAL : public WorkerGlobalScopeProxy::PageInspector {
53     WTF_MAKE_FAST_ALLOCATED;
54 public:
WorkerFrontendChannel(InspectorFrontend * frontend,WorkerGlobalScopeProxy * proxy)55     explicit WorkerFrontendChannel(InspectorFrontend* frontend, WorkerGlobalScopeProxy* proxy)
56         : m_frontend(frontend)
57         , m_proxy(proxy)
58         , m_id(s_nextId++)
59         , m_connected(false)
60     {
61     }
~WorkerFrontendChannel()62     virtual ~WorkerFrontendChannel()
63     {
64         disconnectFromWorkerGlobalScope();
65     }
66 
id() const67     int id() const { return m_id; }
proxy() const68     WorkerGlobalScopeProxy* proxy() const { return m_proxy; }
69 
connectToWorkerGlobalScope()70     void connectToWorkerGlobalScope()
71     {
72         if (m_connected)
73             return;
74         m_connected = true;
75         m_proxy->connectToInspector(this);
76     }
77 
disconnectFromWorkerGlobalScope()78     void disconnectFromWorkerGlobalScope()
79     {
80         if (!m_connected)
81             return;
82         m_connected = false;
83         m_proxy->disconnectFromInspector();
84     }
85 
86 private:
87     // WorkerGlobalScopeProxy::PageInspector implementation
dispatchMessageFromWorker(const String & message)88     virtual void dispatchMessageFromWorker(const String& message) OVERRIDE
89     {
90         RefPtr<JSONValue> value = parseJSON(message);
91         if (!value)
92             return;
93         RefPtr<JSONObject> messageObject = value->asObject();
94         if (!messageObject)
95             return;
96         m_frontend->worker()->dispatchMessageFromWorker(m_id, messageObject);
97     }
98 
99     InspectorFrontend* m_frontend;
100     WorkerGlobalScopeProxy* m_proxy;
101     int m_id;
102     bool m_connected;
103     static int s_nextId;
104 };
105 
106 int InspectorWorkerAgent::WorkerFrontendChannel::s_nextId = 1;
107 
create()108 PassOwnPtr<InspectorWorkerAgent> InspectorWorkerAgent::create()
109 {
110     return adoptPtr(new InspectorWorkerAgent());
111 }
112 
InspectorWorkerAgent()113 InspectorWorkerAgent::InspectorWorkerAgent()
114     : InspectorBaseAgent<InspectorWorkerAgent>("Worker")
115     , m_inspectorFrontend(0)
116 {
117 }
118 
~InspectorWorkerAgent()119 InspectorWorkerAgent::~InspectorWorkerAgent()
120 {
121     m_instrumentingAgents->setInspectorWorkerAgent(0);
122 }
123 
init()124 void InspectorWorkerAgent::init()
125 {
126     m_instrumentingAgents->setInspectorWorkerAgent(this);
127 }
128 
setFrontend(InspectorFrontend * frontend)129 void InspectorWorkerAgent::setFrontend(InspectorFrontend* frontend)
130 {
131     m_inspectorFrontend = frontend;
132 }
133 
restore()134 void InspectorWorkerAgent::restore()
135 {
136     if (m_state->getBoolean(WorkerAgentState::workerInspectionEnabled))
137         createWorkerFrontendChannelsForExistingWorkers();
138 }
139 
clearFrontend()140 void InspectorWorkerAgent::clearFrontend()
141 {
142     m_state->setBoolean(WorkerAgentState::autoconnectToWorkers, false);
143     disable(0);
144     m_inspectorFrontend = 0;
145 }
146 
enable(ErrorString *)147 void InspectorWorkerAgent::enable(ErrorString*)
148 {
149     m_state->setBoolean(WorkerAgentState::workerInspectionEnabled, true);
150     if (!m_inspectorFrontend)
151         return;
152     createWorkerFrontendChannelsForExistingWorkers();
153 }
154 
disable(ErrorString *)155 void InspectorWorkerAgent::disable(ErrorString*)
156 {
157     m_state->setBoolean(WorkerAgentState::workerInspectionEnabled, false);
158     if (!m_inspectorFrontend)
159         return;
160     destroyWorkerFrontendChannels();
161 }
162 
canInspectWorkers(ErrorString *,bool * result)163 void InspectorWorkerAgent::canInspectWorkers(ErrorString*, bool* result)
164 {
165     *result = true;
166 }
167 
connectToWorker(ErrorString * error,int workerId)168 void InspectorWorkerAgent::connectToWorker(ErrorString* error, int workerId)
169 {
170     WorkerFrontendChannel* channel = m_idToChannel.get(workerId);
171     if (channel)
172         channel->connectToWorkerGlobalScope();
173     else
174         *error = "Worker is gone";
175 }
176 
disconnectFromWorker(ErrorString * error,int workerId)177 void InspectorWorkerAgent::disconnectFromWorker(ErrorString* error, int workerId)
178 {
179     WorkerFrontendChannel* channel = m_idToChannel.get(workerId);
180     if (channel)
181         channel->disconnectFromWorkerGlobalScope();
182     else
183         *error = "Worker is gone";
184 }
185 
sendMessageToWorker(ErrorString * error,int workerId,const RefPtr<JSONObject> & message)186 void InspectorWorkerAgent::sendMessageToWorker(ErrorString* error, int workerId, const RefPtr<JSONObject>& message)
187 {
188     WorkerFrontendChannel* channel = m_idToChannel.get(workerId);
189     if (channel)
190         channel->proxy()->sendMessageToInspector(message->toJSONString());
191     else
192         *error = "Worker is gone";
193 }
194 
setAutoconnectToWorkers(ErrorString *,bool value)195 void InspectorWorkerAgent::setAutoconnectToWorkers(ErrorString*, bool value)
196 {
197     m_state->setBoolean(WorkerAgentState::autoconnectToWorkers, value);
198 }
199 
shouldPauseDedicatedWorkerOnStart()200 bool InspectorWorkerAgent::shouldPauseDedicatedWorkerOnStart()
201 {
202     return m_state->getBoolean(WorkerAgentState::autoconnectToWorkers);
203 }
204 
didStartWorkerGlobalScope(WorkerGlobalScopeProxy * workerGlobalScopeProxy,const KURL & url)205 void InspectorWorkerAgent::didStartWorkerGlobalScope(WorkerGlobalScopeProxy* workerGlobalScopeProxy, const KURL& url)
206 {
207     m_dedicatedWorkers.set(workerGlobalScopeProxy, url.string());
208     if (m_inspectorFrontend && m_state->getBoolean(WorkerAgentState::workerInspectionEnabled))
209         createWorkerFrontendChannel(workerGlobalScopeProxy, url.string());
210 }
211 
workerGlobalScopeTerminated(WorkerGlobalScopeProxy * proxy)212 void InspectorWorkerAgent::workerGlobalScopeTerminated(WorkerGlobalScopeProxy* proxy)
213 {
214     m_dedicatedWorkers.remove(proxy);
215     for (WorkerChannels::iterator it = m_idToChannel.begin(); it != m_idToChannel.end(); ++it) {
216         if (proxy == it->value->proxy()) {
217             m_inspectorFrontend->worker()->workerTerminated(it->key);
218             delete it->value;
219             m_idToChannel.remove(it);
220             return;
221         }
222     }
223 }
224 
createWorkerFrontendChannelsForExistingWorkers()225 void InspectorWorkerAgent::createWorkerFrontendChannelsForExistingWorkers()
226 {
227     for (DedicatedWorkers::iterator it = m_dedicatedWorkers.begin(); it != m_dedicatedWorkers.end(); ++it)
228         createWorkerFrontendChannel(it->key, it->value);
229 }
230 
destroyWorkerFrontendChannels()231 void InspectorWorkerAgent::destroyWorkerFrontendChannels()
232 {
233     for (WorkerChannels::iterator it = m_idToChannel.begin(); it != m_idToChannel.end(); ++it) {
234         it->value->disconnectFromWorkerGlobalScope();
235         delete it->value;
236     }
237     m_idToChannel.clear();
238 }
239 
createWorkerFrontendChannel(WorkerGlobalScopeProxy * workerGlobalScopeProxy,const String & url)240 void InspectorWorkerAgent::createWorkerFrontendChannel(WorkerGlobalScopeProxy* workerGlobalScopeProxy, const String& url)
241 {
242     WorkerFrontendChannel* channel = new WorkerFrontendChannel(m_inspectorFrontend, workerGlobalScopeProxy);
243     m_idToChannel.set(channel->id(), channel);
244 
245     ASSERT(m_inspectorFrontend);
246     bool autoconnectToWorkers = m_state->getBoolean(WorkerAgentState::autoconnectToWorkers);
247     if (autoconnectToWorkers)
248         channel->connectToWorkerGlobalScope();
249     m_inspectorFrontend->worker()->workerCreated(channel->id(), url, autoconnectToWorkers);
250 }
251 
252 } // namespace WebCore
253