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

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

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