Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / inspector / InspectorWorkerAgent.cpp
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/WorkerInspectorProxy.h"
40 #include "platform/JSONValues.h"
41 #include "platform/weborigin/KURL.h"
42 #include "wtf/PassOwnPtr.h"
43 #include "wtf/RefPtr.h"
44 #include "wtf/text/WTFString.h"
45
46 namespace blink {
47
48 namespace WorkerAgentState {
49 static const char workerInspectionEnabled[] = "workerInspectionEnabled";
50 static const char autoconnectToWorkers[] = "autoconnectToWorkers";
51 };
52
53 class InspectorWorkerAgent::WorkerFrontendChannel final : public WorkerInspectorProxy::PageInspector {
54     WTF_MAKE_FAST_ALLOCATED;
55 public:
56     explicit WorkerFrontendChannel(InspectorFrontend::Worker* frontend, WorkerInspectorProxy* proxy)
57         : m_frontend(frontend)
58         , m_proxy(proxy)
59         , m_id(s_nextId++)
60         , m_connected(false)
61     {
62         ASSERT(!proxy->pageInspector());
63     }
64     virtual ~WorkerFrontendChannel()
65     {
66         disconnectFromWorker();
67     }
68
69     int id() const { return m_id; }
70     WorkerInspectorProxy* proxy() const { return m_proxy; }
71
72     void connectToWorker()
73     {
74         if (m_connected)
75             return;
76         m_connected = true;
77         m_proxy->connectToInspector(this);
78     }
79
80     void disconnectFromWorker()
81     {
82         if (!m_connected)
83             return;
84         m_connected = false;
85         m_proxy->disconnectFromInspector();
86     }
87
88 private:
89     // WorkerInspectorProxy::PageInspector implementation
90     virtual void dispatchMessageFromWorker(const String& message) override
91     {
92         RefPtr<JSONValue> value = parseJSON(message);
93         if (!value)
94             return;
95         RefPtr<JSONObject> messageObject = value->asObject();
96         if (!messageObject)
97             return;
98         m_frontend->dispatchMessageFromWorker(m_id, messageObject);
99     }
100
101     InspectorFrontend::Worker* m_frontend;
102     WorkerInspectorProxy* m_proxy;
103     int m_id;
104     bool m_connected;
105     static int s_nextId;
106 };
107
108 int InspectorWorkerAgent::WorkerFrontendChannel::s_nextId = 1;
109
110 PassOwnPtrWillBeRawPtr<InspectorWorkerAgent> InspectorWorkerAgent::create()
111 {
112     return adoptPtrWillBeNoop(new InspectorWorkerAgent());
113 }
114
115 InspectorWorkerAgent::InspectorWorkerAgent()
116     : InspectorBaseAgent<InspectorWorkerAgent>("Worker")
117     , m_frontend(0)
118 {
119 }
120
121 InspectorWorkerAgent::~InspectorWorkerAgent()
122 {
123 #if !ENABLE(OILPAN)
124     m_instrumentingAgents->setInspectorWorkerAgent(0);
125 #endif
126 }
127
128 void InspectorWorkerAgent::init()
129 {
130     m_instrumentingAgents->setInspectorWorkerAgent(this);
131 }
132
133 void InspectorWorkerAgent::setFrontend(InspectorFrontend* frontend)
134 {
135     m_frontend = frontend->worker();
136 }
137
138 void InspectorWorkerAgent::restore()
139 {
140     if (m_state->getBoolean(WorkerAgentState::workerInspectionEnabled))
141         createWorkerFrontendChannelsForExistingWorkers();
142 }
143
144 void InspectorWorkerAgent::clearFrontend()
145 {
146     m_state->setBoolean(WorkerAgentState::autoconnectToWorkers, false);
147     disable(0);
148     m_frontend = 0;
149 }
150
151 void InspectorWorkerAgent::enable(ErrorString*)
152 {
153     m_state->setBoolean(WorkerAgentState::workerInspectionEnabled, true);
154     if (!m_frontend)
155         return;
156     createWorkerFrontendChannelsForExistingWorkers();
157 }
158
159 void InspectorWorkerAgent::disable(ErrorString*)
160 {
161     m_state->setBoolean(WorkerAgentState::workerInspectionEnabled, false);
162     if (!m_frontend)
163         return;
164     destroyWorkerFrontendChannels();
165 }
166
167 void InspectorWorkerAgent::canInspectWorkers(ErrorString*, bool* result)
168 {
169     *result = true;
170 }
171
172 void InspectorWorkerAgent::connectToWorker(ErrorString* error, int workerId)
173 {
174     WorkerFrontendChannel* channel = m_idToChannel.get(workerId);
175     if (channel)
176         channel->connectToWorker();
177     else
178         *error = "Worker is gone";
179 }
180
181 void InspectorWorkerAgent::disconnectFromWorker(ErrorString* error, int workerId)
182 {
183     WorkerFrontendChannel* channel = m_idToChannel.get(workerId);
184     if (channel)
185         channel->disconnectFromWorker();
186     else
187         *error = "Worker is gone";
188 }
189
190 void InspectorWorkerAgent::sendMessageToWorker(ErrorString* error, int workerId, const RefPtr<JSONObject>& message)
191 {
192     WorkerFrontendChannel* channel = m_idToChannel.get(workerId);
193     if (channel)
194         channel->proxy()->sendMessageToInspector(message->toJSONString());
195     else
196         *error = "Worker is gone";
197 }
198
199 void InspectorWorkerAgent::setAutoconnectToWorkers(ErrorString*, bool value)
200 {
201     m_state->setBoolean(WorkerAgentState::autoconnectToWorkers, value);
202 }
203
204 void InspectorWorkerAgent::setTracingSessionId(const String& sessionId)
205 {
206     m_tracingSessionId = sessionId;
207     if (sessionId.isEmpty())
208         return;
209     for (WorkerIds::iterator it = m_workerIds.begin(); it != m_workerIds.end(); ++it)
210         it->key->writeTimelineStartedEvent(sessionId);
211 }
212
213 bool InspectorWorkerAgent::shouldPauseDedicatedWorkerOnStart()
214 {
215     return m_state->getBoolean(WorkerAgentState::autoconnectToWorkers);
216 }
217
218 void InspectorWorkerAgent::didStartWorker(WorkerInspectorProxy* workerInspectorProxy, const KURL& url)
219 {
220     m_workerIds.set(workerInspectorProxy, url.string());
221     if (m_frontend && m_state->getBoolean(WorkerAgentState::workerInspectionEnabled))
222         createWorkerFrontendChannel(workerInspectorProxy, url.string());
223     if (!m_tracingSessionId.isEmpty())
224         workerInspectorProxy->writeTimelineStartedEvent(m_tracingSessionId);
225 }
226
227 void InspectorWorkerAgent::workerTerminated(WorkerInspectorProxy* proxy)
228 {
229     m_workerIds.remove(proxy);
230     for (WorkerChannels::iterator it = m_idToChannel.begin(); it != m_idToChannel.end(); ++it) {
231         if (proxy == it->value->proxy()) {
232             m_frontend->workerTerminated(it->key);
233             delete it->value;
234             m_idToChannel.remove(it);
235             return;
236         }
237     }
238 }
239
240 void InspectorWorkerAgent::createWorkerFrontendChannelsForExistingWorkers()
241 {
242     for (WorkerIds::iterator it = m_workerIds.begin(); it != m_workerIds.end(); ++it)
243         createWorkerFrontendChannel(it->key, it->value);
244 }
245
246 void InspectorWorkerAgent::destroyWorkerFrontendChannels()
247 {
248     for (WorkerChannels::iterator it = m_idToChannel.begin(); it != m_idToChannel.end(); ++it) {
249         it->value->disconnectFromWorker();
250         delete it->value;
251     }
252     m_idToChannel.clear();
253 }
254
255 void InspectorWorkerAgent::createWorkerFrontendChannel(WorkerInspectorProxy* workerInspectorProxy, const String& url)
256 {
257     WorkerFrontendChannel* channel = new WorkerFrontendChannel(m_frontend, workerInspectorProxy);
258     m_idToChannel.set(channel->id(), channel);
259
260     ASSERT(m_frontend);
261     bool autoconnectToWorkers = m_state->getBoolean(WorkerAgentState::autoconnectToWorkers);
262     if (autoconnectToWorkers)
263         channel->connectToWorker();
264     m_frontend->workerCreated(channel->id(), url, autoconnectToWorkers);
265 }
266
267 } // namespace blink