Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(11)

Side by Side Diff: webkit/api/src/WebWorkerClientImpl.cpp

Issue 337057: Move webworker{client}_impl.{h,cc} into webkit/api/src (Closed)
Patch Set: mulitple workers per process comment fixed Created 11 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « webkit/api/src/WebWorkerClientImpl.h ('k') | webkit/api/src/WebWorkerImpl.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * Copyright (C) 2009 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 #include "WebWorkerClientImpl.h"
33
34 #if ENABLE(WORKERS)
35
36 #include "DedicatedWorkerThread.h"
37 #include "ErrorEvent.h"
38 #include "Frame.h"
39 #include "FrameLoaderClient.h"
40 #include "GenericWorkerTask.h"
41 #include "MessageEvent.h"
42 #include "MessagePort.h"
43 #include "MessagePortChannel.h"
44 #include "ScriptExecutionContext.h"
45 #include "Worker.h"
46 #include "WorkerContext.h"
47 #include "WorkerContextExecutionProxy.h"
48 #include "WorkerMessagingProxy.h"
49 #include <wtf/Threading.h>
50 #undef LOG
51
52 #include "PlatformMessagePortChannel.h"
53 #include "WebFrameClient.h"
54 #include "WebKit.h"
55 #include "WebKitClient.h"
56 #include "WebMessagePortChannel.h"
57 #include "WebString.h"
58 #include "WebURL.h"
59 #include "WebWorker.h"
60 #include "WebWorkerImpl.h"
61 // FIXME: remove the includes below
62 #include "webkit/glue/webframeloaderclient_impl.h"
63 #include "webkit/glue/webframe_impl.h"
64 #include "webkit/glue/webview_impl.h"
65
66 using namespace WebCore;
67
68 namespace WebKit {
69
70 // When WebKit creates a WorkerContextProxy object, we check if we're in the
71 // renderer or worker process. If the latter, then we just use
72 // WorkerMessagingProxy.
73 //
74 // If we're in the renderer process, then we need use the glue provided
75 // WebWorker object to talk to the worker process over IPC. The worker process
76 // talks to Worker* using WorkerObjectProxy, which we implement on
77 // WebWorkerClientImpl.
78 //
79 // Note that if we're running each worker in a separate process, then nested
80 // workers end up using the same codepath as the renderer process.
81
82 // static
83 WorkerContextProxy* WebWorkerClientImpl::createWorkerContextProxy(Worker* worker)
84 {
85 // Special behavior for multiple workers per process.
86 // FIXME: v8 doesn't support more than one workers per process.
87 // if (!worker->scriptExecutionContext()->isDocument())
88 // return new WorkerMessagingProxy(worker);
89
90 WebWorker* webWorker = 0;
91 WebWorkerClientImpl* proxy = new WebWorkerClientImpl(worker);
92
93 if (worker->scriptExecutionContext()->isDocument()) {
94 Document* document = static_cast<Document*>(
95 worker->scriptExecutionContext());
96 WebFrameImpl* webFrame = WebFrameImpl::FromFrame(document->frame());
97 webWorker = webFrame->client()->createWorker(webFrame, proxy);
98 } else {
99 WorkerContextExecutionProxy* currentContext =
100 WorkerContextExecutionProxy::retrieve();
101 if (!currentContext) {
102 ASSERT_NOT_REACHED();
103 return 0;
104 }
105
106 DedicatedWorkerThread* thread =
107 static_cast<DedicatedWorkerThread*>(currentContext->workerContext()->thread());
108 WorkerObjectProxy* workerObjectProxy = &thread->workerObjectProxy();
109 WebWorkerImpl* impl = reinterpret_cast<WebWorkerImpl*>(workerObjectProxy);
110 webWorker = impl->client()->createWorker(proxy);
111 }
112
113 proxy->setWebWorker(webWorker);
114 return proxy;
115 }
116
117 WebWorkerClientImpl::WebWorkerClientImpl(Worker* worker)
118 : m_scriptExecutionContext(worker->scriptExecutionContext())
119 , m_worker(worker)
120 , m_askedToTerminate(false)
121 , m_unconfirmedMessageCount(0)
122 , m_workerContextHadPendingActivity(false)
123 , m_workerThreadId(currentThread())
124 {
125 }
126
127 WebWorkerClientImpl::~WebWorkerClientImpl()
128 {
129 }
130
131 void WebWorkerClientImpl::setWebWorker(WebWorker* webWorker)
132 {
133 m_webWorker = webWorker;
134 }
135
136 void WebWorkerClientImpl::startWorkerContext(const KURL& scriptURL,
137 const String& userAgent,
138 const String& sourceCode)
139 {
140 // Worker.terminate() could be called from JS before the context is started.
141 if (m_askedToTerminate)
142 return;
143 if (!isMainThread()) {
144 WebWorkerImpl::dispatchTaskToMainThread(createCallbackTask(
145 &startWorkerContextTask,
146 this,
147 scriptURL.string(),
148 userAgent,
149 sourceCode));
150 return;
151 }
152 m_webWorker->startWorkerContext(scriptURL, userAgent, sourceCode);
153 }
154
155 void WebWorkerClientImpl::terminateWorkerContext()
156 {
157 if (m_askedToTerminate)
158 return;
159 m_askedToTerminate = true;
160 if (!isMainThread()) {
161 WebWorkerImpl::dispatchTaskToMainThread(createCallbackTask(&terminateWorkerContextTask, this));
162 return;
163 }
164 m_webWorker->terminateWorkerContext();
165 }
166
167 void WebWorkerClientImpl::postMessageToWorkerContext(
168 PassRefPtr<SerializedScriptValue> message,
169 PassOwnPtr<MessagePortChannelArray> channels)
170 {
171 // Worker.terminate() could be called from JS before the context is started.
172 if (m_askedToTerminate)
173 return;
174 ++m_unconfirmedMessageCount;
175 if (!isMainThread()) {
176 WebWorkerImpl::dispatchTaskToMainThread(createCallbackTask(&postMessageToWorkerContextTask,
177 this,
178 message->toString(),
179 channels));
180 return;
181 }
182 WebMessagePortChannelArray webChannels(channels.get() ? channels->size() : 0);
183 for (size_t i = 0; i < webChannels.size(); ++i) {
184 WebMessagePortChannel* webchannel =
185 (*channels)[i]->channel()->webChannelRelease();
186 webchannel->setClient(0);
187 webChannels[i] = webchannel;
188 }
189 m_webWorker->postMessageToWorkerContext(message->toString(), webChannels);
190 }
191
192 bool WebWorkerClientImpl::hasPendingActivity() const
193 {
194 return !m_askedToTerminate
195 && (m_unconfirmedMessageCount || m_workerContextHadPendingActivity);
196 }
197
198 void WebWorkerClientImpl::workerObjectDestroyed()
199 {
200 if (isMainThread()) {
201 m_webWorker->workerObjectDestroyed();
202 m_worker = 0;
203 }
204 // Even if this is called on the main thread, there could be a queued task for
205 // this object, so don't delete it right away.
206 WebWorkerImpl::dispatchTaskToMainThread(createCallbackTask(&workerObjectDestroyedTask,
207 this));
208 }
209
210 void WebWorkerClientImpl::postMessageToWorkerObject(const WebString& message,
211 const WebMessagePortChannelArray& channels)
212 {
213 OwnPtr<MessagePortChannelArray> channels2;
214 if (channels.size()) {
215 channels2 = new MessagePortChannelArray(channels.size());
216 for (size_t i = 0; i < channels.size(); ++i) {
217 RefPtr<PlatformMessagePortChannel> platform_channel =
218 PlatformMessagePortChannel::create(channels[i]);
219 channels[i]->setClient(platform_channel.get());
220 (*channels2)[i] = MessagePortChannel::create(platform_channel);
221 }
222 }
223
224 if (currentThread() != m_workerThreadId) {
225 m_scriptExecutionContext->postTask(createCallbackTask(&postMessageToWorkerObjectTask,
226 this,
227 String(message),
228 channels2.release()));
229 return;
230 }
231
232 postMessageToWorkerObjectTask(m_scriptExecutionContext.get(), this,
233 message, channels2.release());
234 }
235
236 void WebWorkerClientImpl::postExceptionToWorkerObject(const WebString& errorMessage,
237 int lineNumber,
238 const WebString& sourceURL)
239 {
240 if (currentThread() != m_workerThreadId) {
241 m_scriptExecutionContext->postTask(createCallbackTask(&postExceptionToWorkerObjectTask,
242 this,
243 String(errorMessage),
244 lineNumber,
245 String(sourceURL)));
246 return;
247 }
248
249 bool handled = false;
250 handled = m_worker->dispatchEvent(ErrorEvent::create(errorMessage,
251 sourceURL,
252 lineNumber));
253 if (!handled)
254 m_scriptExecutionContext->reportException(errorMessage, lineNumber, sourceURL);
255 }
256
257 void WebWorkerClientImpl::postConsoleMessageToWorkerObject(int destinationId,
258 int sourceId,
259 int messageType,
260 int messageLevel,
261 const WebString& message,
262 int lineNumber,
263 const WebString& sourceURL)
264 {
265 if (currentThread() != m_workerThreadId) {
266 m_scriptExecutionContext->postTask(createCallbackTask(&postConsoleMessageToWorkerObjectTask,
267 this,
268 destinationId,
269 sourceId,
270 messageType,
271 messageLevel,
272 String(message),
273 lineNumber,
274 String(sourceURL)));
275 return;
276 }
277
278 m_scriptExecutionContext->addMessage(static_cast<MessageDestination>(destinationId),
279 static_cast<MessageSource>(sourceId),
280 static_cast<MessageType>(messageType),
281 static_cast<MessageLevel>(messageLevel),
282 String(message), lineNumber,
283 String(sourceURL));
284 }
285
286 void WebWorkerClientImpl::confirmMessageFromWorkerObject(bool hasPendingActivity)
287 {
288 // unconfirmed_message_count_ can only be updated on the thread where it's
289 // accessed. Otherwise there are race conditions with v8's garbage
290 // collection.
291 m_scriptExecutionContext->postTask(createCallbackTask(&confirmMessageFromWorkerObjectTask,
292 this));
293 }
294
295 void WebWorkerClientImpl::reportPendingActivity(bool hasPendingActivity)
296 {
297 // See above comment in confirmMessageFromWorkerObject.
298 m_scriptExecutionContext->postTask(createCallbackTask(&reportPendingActivityTask,
299 this,
300 hasPendingActivity));
301 }
302
303 void WebWorkerClientImpl::workerContextDestroyed()
304 {
305 }
306
307 void WebWorkerClientImpl::startWorkerContextTask(ScriptExecutionContext* context,
308 WebWorkerClientImpl* thisPtr,
309 const String& scriptURL,
310 const String& userAgent,
311 const String& sourceCode)
312 {
313 thisPtr->m_webWorker->startWorkerContext(KURL(ParsedURLString, scriptURL),
314 userAgent, sourceCode);
315 }
316
317 void WebWorkerClientImpl::terminateWorkerContextTask(ScriptExecutionContext* context,
318 WebWorkerClientImpl* thisPtr)
319 {
320 thisPtr->m_webWorker->terminateWorkerContext();
321 }
322
323 void WebWorkerClientImpl::postMessageToWorkerContextTask(ScriptExecutionContext* context,
324 WebWorkerClientImpl* thisPtr,
325 const String& message,
326 PassOwnPtr<MessagePortChannelArray> channels)
327 {
328 WebMessagePortChannelArray webChannels(channels.get() ? channels->size() : 0);
329
330 for (size_t i = 0; i < webChannels.size(); ++i) {
331 webChannels[i] = (*channels)[i]->channel()->webChannelRelease();
332 webChannels[i]->setClient(0);
333 }
334
335 thisPtr->m_webWorker->postMessageToWorkerContext(message, webChannels);
336 }
337
338 void WebWorkerClientImpl::workerObjectDestroyedTask(ScriptExecutionContext* context,
339 WebWorkerClientImpl* thisPtr)
340 {
341 if (thisPtr->m_worker) // Check we haven't alread called this.
342 thisPtr->m_webWorker->workerObjectDestroyed();
343 delete thisPtr;
344 }
345
346 void WebWorkerClientImpl::postMessageToWorkerObjectTask(
347 ScriptExecutionContext* context,
348 WebWorkerClientImpl* thisPtr,
349 const String& message,
350 PassOwnPtr<MessagePortChannelArray> channels)
351 {
352
353 if (thisPtr->m_worker) {
354 OwnPtr<MessagePortArray> ports =
355 MessagePort::entanglePorts(*context, channels.release());
356 RefPtr<SerializedScriptValue> serializedMessage =
357 SerializedScriptValue::create(message);
358 thisPtr->m_worker->dispatchEvent(MessageEvent::create(ports.release(),
359 serializedMessage.release()));
360 }
361 }
362
363 void WebWorkerClientImpl::postExceptionToWorkerObjectTask(
364 ScriptExecutionContext* context,
365 WebWorkerClientImpl* thisPtr,
366 const String& errorMessage,
367 int lineNumber,
368 const String& sourceURL)
369 {
370 bool handled = false;
371 if (thisPtr->m_worker)
372 handled = thisPtr->m_worker->dispatchEvent(ErrorEvent::create(errorMessage,
373 sourceURL,
374 lineNumber));
375 if (!handled)
376 thisPtr->m_scriptExecutionContext->reportException(errorMessage,
377 lineNumber,
378 sourceURL);
379 }
380
381 void WebWorkerClientImpl::postConsoleMessageToWorkerObjectTask(ScriptExecutionContext* context,
382 WebWorkerClientImpl* thisPtr,
383 int destinationId,
384 int sourceId,
385 int messageType,
386 int messageLevel,
387 const String& message,
388 int lineNumber,
389 const String& sourceURL)
390 {
391 thisPtr->m_scriptExecutionContext->addMessage(static_cast<MessageDestination>(destinationId),
392 static_cast<MessageSource>(sourceId),
393 static_cast<MessageType>(messageType),
394 static_cast<MessageLevel>(messageLevel),
395 message, lineNumber,
396 sourceURL);
397 }
398
399 void WebWorkerClientImpl::confirmMessageFromWorkerObjectTask(ScriptExecutionContext* context,
400 WebWorkerClientImpl* thisPtr)
401 {
402 thisPtr->m_unconfirmedMessageCount--;
403 }
404
405 void WebWorkerClientImpl::reportPendingActivityTask(ScriptExecutionContext* context,
406 WebWorkerClientImpl* thisPtr,
407 bool hasPendingActivity)
408 {
409 thisPtr->m_workerContextHadPendingActivity = hasPendingActivity;
410 }
411
412 } // namespace WebKit
413
414 #endif
OLDNEW
« no previous file with comments | « webkit/api/src/WebWorkerClientImpl.h ('k') | webkit/api/src/WebWorkerImpl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698