summaryrefslogtreecommitdiffstats
path: root/WebCore/workers
diff options
context:
space:
mode:
authorFeng Qian <>2009-04-10 18:11:29 -0700
committerThe Android Open Source Project <initial-contribution@android.com>2009-04-10 18:11:29 -0700
commit8f72e70a9fd78eec56623b3a62e68f16b7b27e28 (patch)
tree181bf9a400c30a1bf34ea6d72560e8d00111d549 /WebCore/workers
parent7ed56f225e0ade046e1c2178977f72b2d896f196 (diff)
downloadexternal_webkit-8f72e70a9fd78eec56623b3a62e68f16b7b27e28.zip
external_webkit-8f72e70a9fd78eec56623b3a62e68f16b7b27e28.tar.gz
external_webkit-8f72e70a9fd78eec56623b3a62e68f16b7b27e28.tar.bz2
AI 145796: Land the WebKit merge @r42026.
Automated import of CL 145796
Diffstat (limited to 'WebCore/workers')
-rw-r--r--WebCore/workers/GenericWorkerTask.h415
-rw-r--r--WebCore/workers/Worker.cpp212
-rw-r--r--WebCore/workers/Worker.h111
-rw-r--r--WebCore/workers/Worker.idl48
-rw-r--r--WebCore/workers/WorkerContext.cpp269
-rw-r--r--WebCore/workers/WorkerContext.h134
-rw-r--r--WebCore/workers/WorkerContext.idl71
-rw-r--r--WebCore/workers/WorkerContextProxy.h64
-rw-r--r--WebCore/workers/WorkerImportScriptsClient.cpp96
-rw-r--r--WebCore/workers/WorkerImportScriptsClient.h77
-rw-r--r--WebCore/workers/WorkerLocation.cpp85
-rw-r--r--WebCore/workers/WorkerLocation.h73
-rw-r--r--WebCore/workers/WorkerLocation.idl48
-rw-r--r--WebCore/workers/WorkerMessagingProxy.cpp343
-rw-r--r--WebCore/workers/WorkerMessagingProxy.h104
-rw-r--r--WebCore/workers/WorkerObjectProxy.h64
-rw-r--r--WebCore/workers/WorkerRunLoop.cpp210
-rw-r--r--WebCore/workers/WorkerRunLoop.h82
-rw-r--r--WebCore/workers/WorkerThread.cpp153
-rw-r--r--WebCore/workers/WorkerThread.h78
20 files changed, 2737 insertions, 0 deletions
diff --git a/WebCore/workers/GenericWorkerTask.h b/WebCore/workers/GenericWorkerTask.h
new file mode 100644
index 0000000..96b0e70
--- /dev/null
+++ b/WebCore/workers/GenericWorkerTask.h
@@ -0,0 +1,415 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef GenericWorkerTask_h
+#define GenericWorkerTask_h
+
+#if ENABLE(WORKERS)
+
+#include "CrossThreadCopier.h"
+#include "ScriptExecutionContext.h"
+#include <memory>
+#include <wtf/PassRefPtr.h>
+#include <wtf/TypeTraits.h>
+
+namespace WebCore {
+
+ // Traits for the GenericWorkerTask.
+ template<typename T> struct GenericWorkerTaskTraits {
+ typedef const T& ParamType;
+ };
+
+ template<typename T> struct GenericWorkerTaskTraits<T*> {
+ typedef T* ParamType;
+ };
+
+ template<typename T> struct GenericWorkerTaskTraits<std::auto_ptr<T> > {
+ typedef std::auto_ptr<T> ParamType;
+ };
+
+ template<typename T> struct GenericWorkerTaskTraits<PassRefPtr<T> > {
+ typedef PassRefPtr<T> ParamType;
+ };
+
+ template<typename P1, typename MP1>
+ class GenericWorkerTask1 : public ScriptExecutionContext::Task {
+ public:
+ typedef void (*Method)(ScriptExecutionContext*, MP1);
+ typedef GenericWorkerTask1<P1, MP1> GenericWorkerTask;
+ typedef typename GenericWorkerTaskTraits<P1>::ParamType Param1;
+
+ static PassRefPtr<GenericWorkerTask> create(Method method, Param1 parameter1)
+ {
+ return adoptRef(new GenericWorkerTask(method, parameter1));
+ }
+
+ private:
+ GenericWorkerTask1(Method method, Param1 parameter1)
+ : m_method(method)
+ , m_parameter1(parameter1)
+ {
+ }
+
+ virtual void performTask(ScriptExecutionContext* context)
+ {
+ (*m_method)(context, m_parameter1);
+ }
+
+ private:
+ Method m_method;
+ P1 m_parameter1;
+ };
+
+ template<typename P1, typename MP1, typename P2, typename MP2>
+ class GenericWorkerTask2 : public ScriptExecutionContext::Task {
+ public:
+ typedef void (*Method)(ScriptExecutionContext*, MP1, MP2);
+ typedef GenericWorkerTask2<P1, MP1, P2, MP2> GenericWorkerTask;
+ typedef typename GenericWorkerTaskTraits<P1>::ParamType Param1;
+ typedef typename GenericWorkerTaskTraits<P2>::ParamType Param2;
+
+ static PassRefPtr<GenericWorkerTask> create(Method method, Param1 parameter1, Param2 parameter2)
+ {
+ return adoptRef(new GenericWorkerTask(method, parameter1, parameter2));
+ }
+
+ private:
+ GenericWorkerTask2(Method method, Param1 parameter1, Param2 parameter2)
+ : m_method(method)
+ , m_parameter1(parameter1)
+ , m_parameter2(parameter2)
+ {
+ }
+
+ virtual void performTask(ScriptExecutionContext* context)
+ {
+ (*m_method)(context, m_parameter1, m_parameter2);
+ }
+
+ private:
+ Method m_method;
+ P1 m_parameter1;
+ P2 m_parameter2;
+ };
+
+ template<typename P1, typename MP1, typename P2, typename MP2, typename P3, typename MP3>
+ class GenericWorkerTask3 : public ScriptExecutionContext::Task {
+ public:
+ typedef void (*Method)(ScriptExecutionContext*, MP1, MP2, MP3);
+ typedef GenericWorkerTask3<P1, MP1, P2, MP2, P3, MP3> GenericWorkerTask;
+ typedef typename GenericWorkerTaskTraits<P1>::ParamType Param1;
+ typedef typename GenericWorkerTaskTraits<P2>::ParamType Param2;
+ typedef typename GenericWorkerTaskTraits<P3>::ParamType Param3;
+
+ static PassRefPtr<GenericWorkerTask> create(Method method, Param1 parameter1, Param2 parameter2, Param3 parameter3)
+ {
+ return adoptRef(new GenericWorkerTask(method, parameter1, parameter2, parameter3));
+ }
+
+ private:
+ GenericWorkerTask3(Method method, Param1 parameter1, Param2 parameter2, Param3 parameter3)
+ : m_method(method)
+ , m_parameter1(parameter1)
+ , m_parameter2(parameter2)
+ , m_parameter3(parameter3)
+ {
+ }
+
+ virtual void performTask(ScriptExecutionContext* context)
+ {
+ (*m_method)(context, m_parameter1, m_parameter2, m_parameter3);
+ }
+
+ private:
+ Method m_method;
+ P1 m_parameter1;
+ P2 m_parameter2;
+ P3 m_parameter3;
+ };
+
+ template<typename P1, typename MP1, typename P2, typename MP2, typename P3, typename MP3, typename P4, typename MP4>
+ class GenericWorkerTask4 : public ScriptExecutionContext::Task {
+ public:
+ typedef void (*Method)(ScriptExecutionContext*, MP1, MP2, MP3, MP4);
+ typedef GenericWorkerTask4<P1, MP1, P2, MP2, P3, MP3, P4, MP4> GenericWorkerTask;
+ typedef typename GenericWorkerTaskTraits<P1>::ParamType Param1;
+ typedef typename GenericWorkerTaskTraits<P2>::ParamType Param2;
+ typedef typename GenericWorkerTaskTraits<P3>::ParamType Param3;
+ typedef typename GenericWorkerTaskTraits<P4>::ParamType Param4;
+
+ static PassRefPtr<GenericWorkerTask> create(Method method, Param1 parameter1, Param2 parameter2, Param3 parameter3, Param4 parameter4)
+ {
+ return adoptRef(new GenericWorkerTask(method, parameter1, parameter2, parameter3, parameter4));
+ }
+
+ private:
+ GenericWorkerTask4(Method method, Param1 parameter1, Param2 parameter2, Param3 parameter3, Param4 parameter4)
+ : m_method(method)
+ , m_parameter1(parameter1)
+ , m_parameter2(parameter2)
+ , m_parameter3(parameter3)
+ , m_parameter4(parameter4)
+ {
+ }
+
+ virtual void performTask(ScriptExecutionContext* context)
+ {
+ (*m_method)(context, m_parameter1, m_parameter2, m_parameter3, m_parameter4);
+ }
+
+ private:
+ Method m_method;
+ P1 m_parameter1;
+ P2 m_parameter2;
+ P3 m_parameter3;
+ P4 m_parameter4;
+ };
+
+ template<typename P1, typename MP1, typename P2, typename MP2, typename P3, typename MP3, typename P4, typename MP4, typename P5, typename MP5>
+ class GenericWorkerTask5 : public ScriptExecutionContext::Task {
+ public:
+ typedef void (*Method)(ScriptExecutionContext*, MP1, MP2, MP3, MP4, MP5);
+ typedef GenericWorkerTask5<P1, MP1, P2, MP2, P3, MP3, P4, MP4, P5, MP5> GenericWorkerTask;
+ typedef typename GenericWorkerTaskTraits<P1>::ParamType Param1;
+ typedef typename GenericWorkerTaskTraits<P2>::ParamType Param2;
+ typedef typename GenericWorkerTaskTraits<P3>::ParamType Param3;
+ typedef typename GenericWorkerTaskTraits<P4>::ParamType Param4;
+ typedef typename GenericWorkerTaskTraits<P5>::ParamType Param5;
+
+ static PassRefPtr<GenericWorkerTask> create(Method method, Param1 parameter1, Param2 parameter2, Param3 parameter3, Param4 parameter4, Param5 parameter5)
+ {
+ return adoptRef(new GenericWorkerTask(method, parameter1, parameter2, parameter3, parameter4, parameter5));
+ }
+
+ private:
+ GenericWorkerTask5(Method method, Param1 parameter1, Param2 parameter2, Param3 parameter3, Param4 parameter4, Param5 parameter5)
+ : m_method(method)
+ , m_parameter1(parameter1)
+ , m_parameter2(parameter2)
+ , m_parameter3(parameter3)
+ , m_parameter4(parameter4)
+ , m_parameter5(parameter5)
+ {
+ }
+
+ virtual void performTask(ScriptExecutionContext* context)
+ {
+ (*m_method)(context, m_parameter1, m_parameter2, m_parameter3, m_parameter4, m_parameter5);
+ }
+
+ private:
+ Method m_method;
+ P1 m_parameter1;
+ P2 m_parameter2;
+ P3 m_parameter3;
+ P4 m_parameter4;
+ P5 m_parameter5;
+ };
+
+ template<typename P1, typename MP1, typename P2, typename MP2, typename P3, typename MP3, typename P4, typename MP4, typename P5, typename MP5, typename P6, typename MP6>
+ class GenericWorkerTask6 : public ScriptExecutionContext::Task {
+ public:
+ typedef void (*Method)(ScriptExecutionContext*, MP1, MP2, MP3, MP4, MP5, MP6);
+ typedef GenericWorkerTask6<P1, MP1, P2, MP2, P3, MP3, P4, MP4, P5, MP5, P6, MP6> GenericWorkerTask;
+ typedef typename GenericWorkerTaskTraits<P1>::ParamType Param1;
+ typedef typename GenericWorkerTaskTraits<P2>::ParamType Param2;
+ typedef typename GenericWorkerTaskTraits<P3>::ParamType Param3;
+ typedef typename GenericWorkerTaskTraits<P4>::ParamType Param4;
+ typedef typename GenericWorkerTaskTraits<P5>::ParamType Param5;
+ typedef typename GenericWorkerTaskTraits<P6>::ParamType Param6;
+
+ static PassRefPtr<GenericWorkerTask> create(Method method, Param1 parameter1, Param2 parameter2, Param3 parameter3, Param4 parameter4, Param5 parameter5, Param6 parameter6)
+ {
+ return adoptRef(new GenericWorkerTask(method, parameter1, parameter2, parameter3, parameter4, parameter5, parameter6));
+ }
+
+ private:
+ GenericWorkerTask6(Method method, Param1 parameter1, Param2 parameter2, Param3 parameter3, Param4 parameter4, Param5 parameter5, Param6 parameter6)
+ : m_method(method)
+ , m_parameter1(parameter1)
+ , m_parameter2(parameter2)
+ , m_parameter3(parameter3)
+ , m_parameter4(parameter4)
+ , m_parameter5(parameter5)
+ , m_parameter6(parameter6)
+ {
+ }
+
+ virtual void performTask(ScriptExecutionContext* context)
+ {
+ (*m_method)(context, m_parameter1, m_parameter2, m_parameter3, m_parameter4, m_parameter5, m_parameter6);
+ }
+
+ private:
+ Method m_method;
+ P1 m_parameter1;
+ P2 m_parameter2;
+ P3 m_parameter3;
+ P4 m_parameter4;
+ P5 m_parameter5;
+ P6 m_parameter6;
+ };
+
+ template<typename P1, typename MP1, typename P2, typename MP2, typename P3, typename MP3, typename P4, typename MP4, typename P5, typename MP5, typename P6, typename MP6, typename P7, typename MP7>
+ class GenericWorkerTask7 : public ScriptExecutionContext::Task {
+ public:
+ typedef void (*Method)(ScriptExecutionContext*, MP1, MP2, MP3, MP4, MP5, MP6, MP7);
+ typedef GenericWorkerTask7<P1, MP1, P2, MP2, P3, MP3, P4, MP4, P5, MP5, P6, MP6, P7, MP7> GenericWorkerTask;
+ typedef typename GenericWorkerTaskTraits<P1>::ParamType Param1;
+ typedef typename GenericWorkerTaskTraits<P2>::ParamType Param2;
+ typedef typename GenericWorkerTaskTraits<P3>::ParamType Param3;
+ typedef typename GenericWorkerTaskTraits<P4>::ParamType Param4;
+ typedef typename GenericWorkerTaskTraits<P5>::ParamType Param5;
+ typedef typename GenericWorkerTaskTraits<P6>::ParamType Param6;
+ typedef typename GenericWorkerTaskTraits<P7>::ParamType Param7;
+
+ static PassRefPtr<GenericWorkerTask> create(Method method, Param1 parameter1, Param2 parameter2, Param3 parameter3, Param4 parameter4, Param5 parameter5, Param6 parameter6, Param7 parameter7)
+ {
+ return adoptRef(new GenericWorkerTask(method, parameter1, parameter2, parameter3, parameter4, parameter5, parameter6, parameter7));
+ }
+
+ private:
+ GenericWorkerTask7(Method method, Param1 parameter1, Param2 parameter2, Param3 parameter3, Param4 parameter4, Param5 parameter5, Param6 parameter6, Param7 parameter7)
+ : m_method(method)
+ , m_parameter1(parameter1)
+ , m_parameter2(parameter2)
+ , m_parameter3(parameter3)
+ , m_parameter4(parameter4)
+ , m_parameter5(parameter5)
+ , m_parameter6(parameter6)
+ , m_parameter7(parameter7)
+ {
+ }
+
+ virtual void performTask(ScriptExecutionContext* context)
+ {
+ (*m_method)(context, m_parameter1, m_parameter2, m_parameter3, m_parameter4, m_parameter5, m_parameter6, m_parameter7);
+ }
+
+ private:
+ Method m_method;
+ P1 m_parameter1;
+ P2 m_parameter2;
+ P3 m_parameter3;
+ P4 m_parameter4;
+ P5 m_parameter5;
+ P6 m_parameter6;
+ P7 m_parameter7;
+ };
+
+ template<typename P1, typename MP1>
+ PassRefPtr<ScriptExecutionContext::Task> createCallbackTask(
+ void (*method)(ScriptExecutionContext*, MP1),
+ const P1& parameter1)
+ {
+ return GenericWorkerTask1<typename CrossThreadCopier<P1>::Type, MP1>::create(
+ method,
+ CrossThreadCopier<P1>::copy(parameter1));
+ }
+
+ template<typename P1, typename MP1, typename P2, typename MP2>
+ PassRefPtr<ScriptExecutionContext::Task> createCallbackTask(
+ void (*method)(ScriptExecutionContext*, MP1, MP2),
+ const P1& parameter1, const P2& parameter2)
+ {
+ return GenericWorkerTask2<typename CrossThreadCopier<P1>::Type, MP1, typename CrossThreadCopier<P2>::Type, MP2>::create(
+ method,
+ CrossThreadCopier<P1>::copy(parameter1), CrossThreadCopier<P2>::copy(parameter2));
+ }
+
+ template<typename P1, typename MP1, typename P2, typename MP2, typename P3, typename MP3>
+ PassRefPtr<ScriptExecutionContext::Task> createCallbackTask(
+ void (*method)(ScriptExecutionContext*, MP1, MP2, MP3),
+ const P1& parameter1, const P2& parameter2, const P3& parameter3)
+ {
+ return GenericWorkerTask3<typename CrossThreadCopier<P1>::Type, MP1, typename CrossThreadCopier<P2>::Type, MP2, typename CrossThreadCopier<P3>::Type, MP3>::create(
+ method,
+ CrossThreadCopier<P1>::copy(parameter1), CrossThreadCopier<P2>::copy(parameter2),
+ CrossThreadCopier<P3>::copy(parameter3));
+ }
+
+ template<typename P1, typename MP1, typename P2, typename MP2, typename P3, typename MP3, typename P4, typename MP4>
+ PassRefPtr<ScriptExecutionContext::Task> createCallbackTask(
+ void (*method)(ScriptExecutionContext*, MP1, MP2, MP3, MP4),
+ const P1& parameter1, const P2& parameter2, const P3& parameter3, const P4& parameter4)
+ {
+ return GenericWorkerTask4<typename CrossThreadCopier<P1>::Type, MP1, typename CrossThreadCopier<P2>::Type, MP2, typename CrossThreadCopier<P3>::Type, MP3,
+ typename CrossThreadCopier<P4>::Type, MP4>::create(
+ method,
+ CrossThreadCopier<P1>::copy(parameter1), CrossThreadCopier<P2>::copy(parameter2),
+ CrossThreadCopier<P3>::copy(parameter3), CrossThreadCopier<P4>::copy(parameter4));
+ }
+
+ template<typename P1, typename MP1, typename P2, typename MP2, typename P3, typename MP3, typename P4, typename MP4, typename P5, typename MP5>
+ PassRefPtr<ScriptExecutionContext::Task> createCallbackTask(
+ void (*method)(ScriptExecutionContext*, MP1, MP2, MP3, MP4, MP5),
+ const P1& parameter1, const P2& parameter2, const P3& parameter3, const P4& parameter4, const P5& parameter5)
+ {
+ return GenericWorkerTask5<typename CrossThreadCopier<P1>::Type, MP1, typename CrossThreadCopier<P2>::Type, MP2, typename CrossThreadCopier<P3>::Type, MP3,
+ typename CrossThreadCopier<P4>::Type, MP4, typename CrossThreadCopier<P5>::Type, MP5>::create(
+ method,
+ CrossThreadCopier<P1>::copy(parameter1), CrossThreadCopier<P2>::copy(parameter2),
+ CrossThreadCopier<P3>::copy(parameter3), CrossThreadCopier<P4>::copy(parameter4),
+ CrossThreadCopier<P5>::copy(parameter5));
+ }
+
+ template<typename P1, typename MP1, typename P2, typename MP2, typename P3, typename MP3, typename P4, typename MP4, typename P5, typename MP5, typename P6, typename MP6>
+ PassRefPtr<ScriptExecutionContext::Task> createCallbackTask(
+ void (*method)(ScriptExecutionContext*, MP1, MP2, MP3, MP4, MP5, MP6),
+ const P1& parameter1, const P2& parameter2, const P3& parameter3, const P4& parameter4, const P5& parameter5, const P6& parameter6)
+ {
+ return GenericWorkerTask6<typename CrossThreadCopier<P1>::Type, MP1, typename CrossThreadCopier<P2>::Type, MP2, typename CrossThreadCopier<P3>::Type, MP3,
+ typename CrossThreadCopier<P4>::Type, MP4, typename CrossThreadCopier<P5>::Type, MP5, typename CrossThreadCopier<P6>::Type, MP6>::create(
+ method,
+ CrossThreadCopier<P1>::copy(parameter1), CrossThreadCopier<P2>::copy(parameter2),
+ CrossThreadCopier<P3>::copy(parameter3), CrossThreadCopier<P4>::copy(parameter4),
+ CrossThreadCopier<P5>::copy(parameter5), CrossThreadCopier<P6>::copy(parameter6));
+ }
+
+ template<typename P1, typename MP1, typename P2, typename MP2, typename P3, typename MP3, typename P4, typename MP4, typename P5, typename MP5, typename P6, typename MP6, typename P7, typename MP7>
+ PassRefPtr<ScriptExecutionContext::Task> createCallbackTask(
+ void (*method)(ScriptExecutionContext*, MP1, MP2, MP3, MP4, MP5, MP6, MP7),
+ const P1& parameter1, const P2& parameter2, const P3& parameter3, const P4& parameter4, const P5& parameter5, const P6& parameter6, const P7& parameter7)
+ {
+ return GenericWorkerTask7<typename CrossThreadCopier<P1>::Type, MP1, typename CrossThreadCopier<P2>::Type, MP2, typename CrossThreadCopier<P3>::Type, MP3,
+ typename CrossThreadCopier<P4>::Type, MP4, typename CrossThreadCopier<P5>::Type, MP5, typename CrossThreadCopier<P6>::Type, MP6,
+ typename CrossThreadCopier<P7>::Type, MP7>::create(
+ method,
+ CrossThreadCopier<P1>::copy(parameter1), CrossThreadCopier<P2>::copy(parameter2),
+ CrossThreadCopier<P3>::copy(parameter3), CrossThreadCopier<P4>::copy(parameter4),
+ CrossThreadCopier<P5>::copy(parameter5), CrossThreadCopier<P6>::copy(parameter6),
+ CrossThreadCopier<P7>::copy(parameter7));
+ }
+
+} // namespace WebCore
+
+#endif // ENABLE(WORKERS)
+
+#endif // GenericWorkerTask_h
diff --git a/WebCore/workers/Worker.cpp b/WebCore/workers/Worker.cpp
new file mode 100644
index 0000000..85ba690
--- /dev/null
+++ b/WebCore/workers/Worker.cpp
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2009 Google Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "config.h"
+
+#if ENABLE(WORKERS)
+
+#include "Worker.h"
+
+#include "CachedScript.h"
+#include "DOMWindow.h"
+#include "DocLoader.h"
+#include "Document.h"
+#include "EventException.h"
+#include "EventListener.h"
+#include "EventNames.h"
+#include "ExceptionCode.h"
+#include "Frame.h"
+#include "FrameLoader.h"
+#include "MessageEvent.h"
+#include "SecurityOrigin.h"
+#include "TextEncoding.h"
+#include "WorkerContextProxy.h"
+#include "WorkerThread.h"
+#include <wtf/MainThread.h>
+
+namespace WebCore {
+
+Worker::Worker(const String& url, ScriptExecutionContext* context, ExceptionCode& ec)
+ : ActiveDOMObject(context, this)
+ , m_contextProxy(WorkerContextProxy::create(this))
+{
+ m_scriptURL = context->completeURL(url);
+ if (url.isEmpty() || !m_scriptURL.isValid()) {
+ ec = SYNTAX_ERR;
+ return;
+ }
+
+ if (!context->securityOrigin()->canAccess(SecurityOrigin::create(m_scriptURL).get())) {
+ ec = SECURITY_ERR;
+ return;
+ }
+
+ // FIXME: Nested workers need loading support. Consider adopting ThreadableLoader here.
+ ASSERT(scriptExecutionContext()->isDocument());
+ Document* document = static_cast<Document*>(scriptExecutionContext());
+
+ m_cachedScript = document->docLoader()->requestScript(m_scriptURL, "UTF-8");
+ if (!m_cachedScript) {
+ dispatchErrorEvent();
+ return;
+ }
+
+ setPendingActivity(this); // The worker context does not exist while loading, so we must ensure that the worker object is not collected, as well as its event listeners.
+ m_cachedScript->addClient(this);
+}
+
+Worker::~Worker()
+{
+ ASSERT(isMainThread());
+ ASSERT(scriptExecutionContext()); // The context is protected by worker context proxy, so it cannot be destroyed while a Worker exists.
+ m_contextProxy->workerObjectDestroyed();
+}
+
+void Worker::postMessage(const String& message)
+{
+ m_contextProxy->postMessageToWorkerContext(message);
+}
+
+void Worker::terminate()
+{
+ m_contextProxy->terminateWorkerContext();
+}
+
+bool Worker::canSuspend() const
+{
+ // FIXME: It is not currently possible to suspend a worker, so pages with workers can not go into page cache.
+ return false;
+}
+
+void Worker::stop()
+{
+ terminate();
+}
+
+bool Worker::hasPendingActivity() const
+{
+ return m_contextProxy->hasPendingActivity() || ActiveDOMObject::hasPendingActivity();
+}
+
+void Worker::notifyFinished(CachedResource* unusedResource)
+{
+ ASSERT_UNUSED(unusedResource, unusedResource == m_cachedScript);
+
+ if (m_cachedScript->errorOccurred())
+ dispatchErrorEvent();
+ else
+ m_contextProxy->startWorkerContext(m_scriptURL, scriptExecutionContext()->userAgent(m_scriptURL), m_cachedScript->script());
+
+ m_cachedScript->removeClient(this);
+ m_cachedScript = 0;
+
+ unsetPendingActivity(this);
+}
+
+void Worker::dispatchErrorEvent()
+{
+ RefPtr<Event> evt = Event::create(eventNames().errorEvent, false, true);
+ if (m_onErrorListener) {
+ evt->setTarget(this);
+ evt->setCurrentTarget(this);
+ m_onErrorListener->handleEvent(evt.get(), true);
+ }
+
+ ExceptionCode ec = 0;
+ dispatchEvent(evt.release(), ec);
+ ASSERT(!ec);
+}
+
+void Worker::addEventListener(const AtomicString& eventType, PassRefPtr<EventListener> eventListener, bool)
+{
+ EventListenersMap::iterator iter = m_eventListeners.find(eventType);
+ if (iter == m_eventListeners.end()) {
+ ListenerVector listeners;
+ listeners.append(eventListener);
+ m_eventListeners.add(eventType, listeners);
+ } else {
+ ListenerVector& listeners = iter->second;
+ for (ListenerVector::iterator listenerIter = listeners.begin(); listenerIter != listeners.end(); ++listenerIter) {
+ if (*listenerIter == eventListener)
+ return;
+ }
+
+ listeners.append(eventListener);
+ m_eventListeners.add(eventType, listeners);
+ }
+}
+
+void Worker::removeEventListener(const AtomicString& eventType, EventListener* eventListener, bool)
+{
+ EventListenersMap::iterator iter = m_eventListeners.find(eventType);
+ if (iter == m_eventListeners.end())
+ return;
+
+ ListenerVector& listeners = iter->second;
+ for (ListenerVector::const_iterator listenerIter = listeners.begin(); listenerIter != listeners.end(); ++listenerIter) {
+ if (*listenerIter == eventListener) {
+ listeners.remove(listenerIter - listeners.begin());
+ return;
+ }
+ }
+}
+
+bool Worker::dispatchEvent(PassRefPtr<Event> event, ExceptionCode& ec)
+{
+ if (!event || event->type().isEmpty()) {
+ ec = EventException::UNSPECIFIED_EVENT_TYPE_ERR;
+ return true;
+ }
+
+ ListenerVector listenersCopy = m_eventListeners.get(event->type());
+ for (ListenerVector::const_iterator listenerIter = listenersCopy.begin(); listenerIter != listenersCopy.end(); ++listenerIter) {
+ event->setTarget(this);
+ event->setCurrentTarget(this);
+ listenerIter->get()->handleEvent(event.get(), false);
+ }
+
+ return !event->defaultPrevented();
+}
+
+void Worker::dispatchMessage(const String& message)
+{
+ RefPtr<Event> evt = MessageEvent::create(message, "", "", 0, 0);
+
+ if (m_onMessageListener.get()) {
+ evt->setTarget(this);
+ evt->setCurrentTarget(this);
+ m_onMessageListener->handleEvent(evt.get(), false);
+ }
+
+ ExceptionCode ec = 0;
+ dispatchEvent(evt.release(), ec);
+ ASSERT(!ec);
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(WORKERS)
diff --git a/WebCore/workers/Worker.h b/WebCore/workers/Worker.h
new file mode 100644
index 0000000..d05f9d5
--- /dev/null
+++ b/WebCore/workers/Worker.h
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef Worker_h
+#define Worker_h
+
+#if ENABLE(WORKERS)
+
+#include "AtomicStringHash.h"
+#include "ActiveDOMObject.h"
+#include "CachedResourceClient.h"
+#include "CachedResourceHandle.h"
+#include "EventListener.h"
+#include "EventTarget.h"
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+ class CachedResource;
+ class CachedScript;
+ class ScriptExecutionContext;
+ class String;
+ class WorkerContextProxy;
+
+ typedef int ExceptionCode;
+
+ class Worker : public RefCounted<Worker>, public ActiveDOMObject, private CachedResourceClient, public EventTarget {
+ public:
+ static PassRefPtr<Worker> create(const String& url, ScriptExecutionContext* context, ExceptionCode& ec) { return adoptRef(new Worker(url, context, ec)); }
+ ~Worker();
+
+ virtual ScriptExecutionContext* scriptExecutionContext() const { return ActiveDOMObject::scriptExecutionContext(); }
+
+ virtual Worker* toWorker() { return this; }
+
+ void postMessage(const String& message);
+
+ void terminate();
+
+ void dispatchMessage(const String&);
+ void dispatchErrorEvent();
+
+ virtual bool canSuspend() const;
+ virtual void stop();
+ virtual bool hasPendingActivity() const;
+
+ virtual void addEventListener(const AtomicString& eventType, PassRefPtr<EventListener>, bool useCapture);
+ virtual void removeEventListener(const AtomicString& eventType, EventListener*, bool useCapture);
+ virtual bool dispatchEvent(PassRefPtr<Event>, ExceptionCode&);
+
+ typedef Vector<RefPtr<EventListener> > ListenerVector;
+ typedef HashMap<AtomicString, ListenerVector> EventListenersMap;
+ EventListenersMap& eventListeners() { return m_eventListeners; }
+
+ using RefCounted<Worker>::ref;
+ using RefCounted<Worker>::deref;
+
+ void setOnmessage(PassRefPtr<EventListener> eventListener) { m_onMessageListener = eventListener; }
+ EventListener* onmessage() const { return m_onMessageListener.get(); }
+
+ void setOnerror(PassRefPtr<EventListener> eventListener) { m_onErrorListener = eventListener; }
+ EventListener* onerror() const { return m_onErrorListener.get(); }
+
+ private:
+ Worker(const String&, ScriptExecutionContext*, ExceptionCode&);
+
+ virtual void notifyFinished(CachedResource*);
+
+ virtual void refEventTarget() { ref(); }
+ virtual void derefEventTarget() { deref(); }
+
+ KURL m_scriptURL;
+ CachedResourceHandle<CachedScript> m_cachedScript;
+
+ WorkerContextProxy* m_contextProxy; // The proxy outlives the worker to perform thread shutdown.
+
+ RefPtr<EventListener> m_onMessageListener;
+ RefPtr<EventListener> m_onErrorListener;
+ EventListenersMap m_eventListeners;
+ };
+
+} // namespace WebCore
+
+#endif // ENABLE(WORKERS)
+
+#endif // Worker_h
diff --git a/WebCore/workers/Worker.idl b/WebCore/workers/Worker.idl
new file mode 100644
index 0000000..2ef9b62
--- /dev/null
+++ b/WebCore/workers/Worker.idl
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+module threads {
+
+ interface [CustomMarkFunction, Conditional=WORKERS] Worker {
+
+ attribute EventListener onerror;
+ attribute EventListener onmessage;
+ void postMessage(in DOMString message);
+
+ void terminate();
+
+ // EventTarget interface
+ [Custom] void addEventListener(in DOMString type,
+ in EventListener listener,
+ in boolean useCapture);
+ [Custom] void removeEventListener(in DOMString type,
+ in EventListener listener,
+ in boolean useCapture);
+ boolean dispatchEvent(in Event evt)
+ raises(EventException);
+ };
+
+}
diff --git a/WebCore/workers/WorkerContext.cpp b/WebCore/workers/WorkerContext.cpp
new file mode 100644
index 0000000..69ef472
--- /dev/null
+++ b/WebCore/workers/WorkerContext.cpp
@@ -0,0 +1,269 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2009 Google Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "config.h"
+
+#if ENABLE(WORKERS)
+
+#include "WorkerContext.h"
+
+#include "ActiveDOMObject.h"
+#include "DOMTimer.h"
+#include "DOMWindow.h"
+#include "Event.h"
+#include "EventException.h"
+#include "MessageEvent.h"
+#include "NotImplemented.h"
+#include "ResourceRequest.h"
+#include "ScriptSourceCode.h"
+#include "ScriptValue.h"
+#include "SecurityOrigin.h"
+#include "ThreadableLoader.h"
+#include "WorkerImportScriptsClient.h"
+#include "WorkerLocation.h"
+#include "WorkerNavigator.h"
+#include "WorkerObjectProxy.h"
+#include "WorkerThread.h"
+#include "XMLHttpRequestException.h"
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+WorkerContext::WorkerContext(const KURL& url, const String& userAgent, WorkerThread* thread)
+ : m_url(url)
+ , m_userAgent(userAgent)
+ , m_location(WorkerLocation::create(url))
+ , m_script(new WorkerScriptController(this))
+ , m_thread(thread)
+{
+ setSecurityOrigin(SecurityOrigin::create(url));
+}
+
+WorkerContext::~WorkerContext()
+{
+ ASSERT(currentThread() == m_thread->threadID());
+
+ m_thread->workerObjectProxy()->workerContextDestroyed();
+}
+
+ScriptExecutionContext* WorkerContext::scriptExecutionContext() const
+{
+ return const_cast<WorkerContext*>(this);
+}
+
+const KURL& WorkerContext::virtualURL() const
+{
+ return m_url;
+}
+
+KURL WorkerContext::virtualCompleteURL(const String& url) const
+{
+ return completeURL(url);
+}
+
+KURL WorkerContext::completeURL(const String& url) const
+{
+ // Always return a null URL when passed a null string.
+ // FIXME: Should we change the KURL constructor to have this behavior?
+ if (url.isNull())
+ return KURL();
+ // Always use UTF-8 in Workers.
+ return KURL(m_location->url(), url);
+}
+
+String WorkerContext::userAgent(const KURL&) const
+{
+ return m_userAgent;
+}
+
+WorkerNavigator* WorkerContext::navigator() const
+{
+ if (!m_navigator)
+ m_navigator = WorkerNavigator::create(m_userAgent);
+ return m_navigator.get();
+}
+
+bool WorkerContext::hasPendingActivity() const
+{
+ ActiveDOMObjectsMap& activeObjects = activeDOMObjects();
+ ActiveDOMObjectsMap::const_iterator activeObjectsEnd = activeObjects.end();
+ for (ActiveDOMObjectsMap::const_iterator iter = activeObjects.begin(); iter != activeObjectsEnd; ++iter) {
+ if (iter->first->hasPendingActivity())
+ return true;
+ }
+ return false;
+}
+
+void WorkerContext::reportException(const String& errorMessage, int lineNumber, const String& sourceURL)
+{
+ m_thread->workerObjectProxy()->postExceptionToWorkerObject(errorMessage, lineNumber, sourceURL);
+}
+
+void WorkerContext::addMessage(MessageDestination destination, MessageSource source, MessageLevel level, const String& message, unsigned lineNumber, const String& sourceURL)
+{
+ m_thread->workerObjectProxy()->postConsoleMessageToWorkerObject(destination, source, level, message, lineNumber, sourceURL);
+}
+
+void WorkerContext::resourceRetrievedByXMLHttpRequest(unsigned long, const ScriptString&)
+{
+ // FIXME: The implementation is pending the fixes in https://bugs.webkit.org/show_bug.cgi?id=23175
+ notImplemented();
+}
+
+void WorkerContext::scriptImported(unsigned long, const String&)
+{
+ // FIXME: The implementation is pending the fixes in https://bugs.webkit.org/show_bug.cgi?id=23175
+ notImplemented();
+}
+
+void WorkerContext::postMessage(const String& message)
+{
+ m_thread->workerObjectProxy()->postMessageToWorkerObject(message);
+}
+
+void WorkerContext::addEventListener(const AtomicString& eventType, PassRefPtr<EventListener> eventListener, bool)
+{
+ EventListenersMap::iterator iter = m_eventListeners.find(eventType);
+ if (iter == m_eventListeners.end()) {
+ ListenerVector listeners;
+ listeners.append(eventListener);
+ m_eventListeners.add(eventType, listeners);
+ } else {
+ ListenerVector& listeners = iter->second;
+ for (ListenerVector::iterator listenerIter = listeners.begin(); listenerIter != listeners.end(); ++listenerIter) {
+ if (*listenerIter == eventListener)
+ return;
+ }
+
+ listeners.append(eventListener);
+ m_eventListeners.add(eventType, listeners);
+ }
+}
+
+void WorkerContext::removeEventListener(const AtomicString& eventType, EventListener* eventListener, bool)
+{
+ EventListenersMap::iterator iter = m_eventListeners.find(eventType);
+ if (iter == m_eventListeners.end())
+ return;
+
+ ListenerVector& listeners = iter->second;
+ for (ListenerVector::const_iterator listenerIter = listeners.begin(); listenerIter != listeners.end(); ++listenerIter) {
+ if (*listenerIter == eventListener) {
+ listeners.remove(listenerIter - listeners.begin());
+ return;
+ }
+ }
+}
+
+bool WorkerContext::dispatchEvent(PassRefPtr<Event> event, ExceptionCode& ec)
+{
+ if (!event || event->type().isEmpty()) {
+ ec = EventException::UNSPECIFIED_EVENT_TYPE_ERR;
+ return true;
+ }
+
+ ListenerVector listenersCopy = m_eventListeners.get(event->type());
+ for (ListenerVector::const_iterator listenerIter = listenersCopy.begin(); listenerIter != listenersCopy.end(); ++listenerIter) {
+ event->setTarget(this);
+ event->setCurrentTarget(this);
+ listenerIter->get()->handleEvent(event.get(), false);
+ }
+
+ return !event->defaultPrevented();
+}
+
+void WorkerContext::postTask(PassRefPtr<Task> task)
+{
+ thread()->runLoop().postTask(task);
+}
+
+int WorkerContext::installTimeout(ScheduledAction* action, int timeout, bool singleShot)
+{
+ return DOMTimer::install(scriptExecutionContext(), action, timeout, singleShot);
+}
+
+void WorkerContext::removeTimeout(int timeoutId)
+{
+ DOMTimer::removeById(scriptExecutionContext(), timeoutId);
+}
+
+void WorkerContext::dispatchMessage(const String& message)
+{
+ RefPtr<Event> evt = MessageEvent::create(message, "", "", 0, 0);
+
+ if (m_onmessageListener.get()) {
+ evt->setTarget(this);
+ evt->setCurrentTarget(this);
+ m_onmessageListener->handleEvent(evt.get(), false);
+ }
+
+ ExceptionCode ec = 0;
+ dispatchEvent(evt.release(), ec);
+ ASSERT(!ec);
+}
+
+void WorkerContext::importScripts(const Vector<String>& urls, const String& callerURL, int callerLine, ExceptionCode& ec)
+{
+ ec = 0;
+ Vector<String>::const_iterator urlsEnd = urls.end();
+ Vector<KURL> completedURLs;
+ for (Vector<String>::const_iterator it = urls.begin(); it != urlsEnd; ++it) {
+ const KURL& url = scriptExecutionContext()->completeURL(*it);
+ if (!url.isValid()) {
+ ec = SYNTAX_ERR;
+ return;
+ }
+ completedURLs.append(url);
+ }
+ String securityOrigin = scriptExecutionContext()->securityOrigin()->toString();
+ Vector<KURL>::const_iterator end = completedURLs.end();
+
+ for (Vector<KURL>::const_iterator it = completedURLs.begin(); it != end; ++it) {
+ ResourceRequest request(*it);
+ request.setHTTPMethod("GET");
+ request.setHTTPOrigin(securityOrigin);
+ WorkerImportScriptsClient client(scriptExecutionContext(), *it, callerURL, callerLine);
+ ThreadableLoader::loadResourceSynchronously(scriptExecutionContext(), request, client);
+
+ // If the fetching attempt failed, throw a NETWORK_ERR exception and abort all these steps.
+ if (client.failed()) {
+ ec = XMLHttpRequestException::NETWORK_ERR;
+ return;
+ }
+
+ ScriptValue exception;
+ m_script->evaluate(ScriptSourceCode(client.script(), *it), &exception);
+ if (!exception.hasNoValue()) {
+ m_script->setException(exception);
+ return;
+ }
+ }
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(WORKERS)
diff --git a/WebCore/workers/WorkerContext.h b/WebCore/workers/WorkerContext.h
new file mode 100644
index 0000000..39a5b9b
--- /dev/null
+++ b/WebCore/workers/WorkerContext.h
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef WorkerContext_h
+#define WorkerContext_h
+
+#if ENABLE(WORKERS)
+
+#include "AtomicStringHash.h"
+#include "EventListener.h"
+#include "EventTarget.h"
+#include "ScriptExecutionContext.h"
+#include "WorkerScriptController.h"
+#include <wtf/OwnPtr.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+ class ScheduledAction;
+ class WorkerLocation;
+ class WorkerNavigator;
+ class WorkerThread;
+
+ class WorkerContext : public RefCounted<WorkerContext>, public ScriptExecutionContext, public EventTarget {
+ public:
+ static PassRefPtr<WorkerContext> create(const KURL& url, const String& userAgent, WorkerThread* thread)
+ {
+ return adoptRef(new WorkerContext(url, userAgent, thread));
+ }
+
+ virtual ~WorkerContext();
+
+ virtual bool isWorkerContext() const { return true; }
+
+ virtual ScriptExecutionContext* scriptExecutionContext() const;
+
+ const KURL& url() const { return m_url; }
+ KURL completeURL(const String&) const;
+
+ virtual String userAgent(const KURL&) const;
+
+ WorkerLocation* location() const { return m_location.get(); }
+ WorkerNavigator* navigator() const;
+
+ WorkerScriptController* script() { return m_script.get(); }
+ void clearScript() { return m_script.clear(); }
+ WorkerThread* thread() { return m_thread; }
+
+ bool hasPendingActivity() const;
+
+ virtual void reportException(const String& errorMessage, int lineNumber, const String& sourceURL);
+ virtual void addMessage(MessageDestination, MessageSource, MessageLevel, const String& message, unsigned lineNumber, const String& sourceURL);
+ virtual void resourceRetrievedByXMLHttpRequest(unsigned long identifier, const ScriptString& sourceString);
+ virtual void scriptImported(unsigned long identifier, const String& sourceString);
+
+ virtual WorkerContext* toWorkerContext() { return this; }
+
+ void postMessage(const String& message);
+ virtual void postTask(PassRefPtr<Task>); // Executes the task on context's thread asynchronously.
+
+ int installTimeout(ScheduledAction*, int timeout, bool singleShot);
+ void removeTimeout(int timeoutId);
+
+ void dispatchMessage(const String&);
+
+ virtual void addEventListener(const AtomicString& eventType, PassRefPtr<EventListener>, bool useCapture);
+ virtual void removeEventListener(const AtomicString& eventType, EventListener*, bool useCapture);
+ virtual bool dispatchEvent(PassRefPtr<Event>, ExceptionCode&);
+
+ void setOnmessage(PassRefPtr<EventListener> eventListener) { m_onmessageListener = eventListener; }
+ EventListener* onmessage() const { return m_onmessageListener.get(); }
+
+ typedef Vector<RefPtr<EventListener> > ListenerVector;
+ typedef HashMap<AtomicString, ListenerVector> EventListenersMap;
+ EventListenersMap& eventListeners() { return m_eventListeners; }
+
+ void importScripts(const Vector<String>& urls, const String& callerURL, int callerLine, ExceptionCode&);
+
+ using RefCounted<WorkerContext>::ref;
+ using RefCounted<WorkerContext>::deref;
+
+ private:
+ virtual void refScriptExecutionContext() { ref(); }
+ virtual void derefScriptExecutionContext() { deref(); }
+ virtual void refEventTarget() { ref(); }
+ virtual void derefEventTarget() { deref(); }
+
+ WorkerContext(const KURL&, const String&, WorkerThread*);
+
+ virtual const KURL& virtualURL() const;
+ virtual KURL virtualCompleteURL(const String&) const;
+
+ KURL m_url;
+ String m_userAgent;
+ RefPtr<WorkerLocation> m_location;
+ mutable RefPtr<WorkerNavigator> m_navigator;
+
+ OwnPtr<WorkerScriptController> m_script;
+ WorkerThread* m_thread;
+
+ RefPtr<EventListener> m_onmessageListener;
+ EventListenersMap m_eventListeners;
+ };
+
+} // namespace WebCore
+
+#endif // ENABLE(WORKERS)
+
+#endif // WorkerContext_h
diff --git a/WebCore/workers/WorkerContext.idl b/WebCore/workers/WorkerContext.idl
new file mode 100644
index 0000000..bbfca63
--- /dev/null
+++ b/WebCore/workers/WorkerContext.idl
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+module threads {
+
+ interface [
+ Conditional=WORKERS,
+ CustomGetOwnPropertySlot,
+ CustomMarkFunction,
+ ExtendsDOMGlobalObject,
+ LegacyParent=JSWorkerContextBase,
+ NoStaticTables
+ ] WorkerContext {
+#if defined(LANGUAGE_JAVASCRIPT)
+ attribute [Custom] WorkerContext self;
+#endif
+
+ attribute EventListener onmessage;
+ void postMessage(in DOMString message);
+ [Custom] void importScripts(/* urls */);
+
+ attribute [Replaceable] WorkerLocation location;
+ attribute [Replaceable] WorkerNavigator navigator;
+
+ attribute MessageEventConstructor MessageEvent;
+ attribute WorkerLocationConstructor WorkerLocation;
+
+ // Timers
+ [Custom] long setTimeout(in TimeoutHandler handler, in long timeout);
+ // [Custom] long setTimeout(in DOMString code, in long timeout);
+ [Custom] void clearTimeout(in long handle);
+
+ [Custom] long setInterval(in TimeoutHandler handler, in long timeout);
+ // [Custom] long setInterval(in DOMString code, in long timeout);
+ [Custom] void clearInterval(in long handle);
+
+ // EventTarget interface
+ [Custom] void addEventListener(in DOMString type,
+ in EventListener listener,
+ in boolean useCapture);
+ [Custom] void removeEventListener(in DOMString type,
+ in EventListener listener,
+ in boolean useCapture);
+ boolean dispatchEvent(in Event evt)
+ raises(EventException);
+ };
+
+}
diff --git a/WebCore/workers/WorkerContextProxy.h b/WebCore/workers/WorkerContextProxy.h
new file mode 100644
index 0000000..c8f5761
--- /dev/null
+++ b/WebCore/workers/WorkerContextProxy.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef WorkerContextProxy_h
+#define WorkerContextProxy_h
+
+#if ENABLE(WORKERS)
+
+namespace WebCore {
+
+ class KURL;
+ class String;
+ class Worker;
+
+ // A proxy to talk to the worker context.
+ class WorkerContextProxy {
+ public:
+ static WorkerContextProxy* create(Worker*);
+
+ virtual ~WorkerContextProxy() {}
+
+ virtual void startWorkerContext(const KURL& scriptURL, const String& userAgent, const String& sourceCode) = 0;
+
+ virtual void terminateWorkerContext() = 0;
+
+ virtual void postMessageToWorkerContext(const String&) = 0;
+
+ virtual bool hasPendingActivity() const = 0;
+
+ virtual void workerObjectDestroyed() = 0;
+ };
+
+} // namespace WebCore
+
+#endif // ENABLE(WORKERS)
+
+#endif // WorkerContextProxy_h
diff --git a/WebCore/workers/WorkerImportScriptsClient.cpp b/WebCore/workers/WorkerImportScriptsClient.cpp
new file mode 100644
index 0000000..7b8061b
--- /dev/null
+++ b/WebCore/workers/WorkerImportScriptsClient.cpp
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "config.h"
+
+#if ENABLE(WORKERS)
+
+#include "WorkerImportScriptsClient.h"
+
+#include "ScriptExecutionContext.h"
+
+namespace WebCore {
+
+void WorkerImportScriptsClient::didReceiveResponse(const ResourceResponse& response)
+{
+ if (response.httpStatusCode() / 100 != 2 && response.httpStatusCode() != 0) {
+ m_failed = true;
+ return;
+ }
+ m_responseEncoding = response.textEncodingName();
+}
+
+void WorkerImportScriptsClient::didReceiveData(const char* data, int len)
+{
+ if (m_failed)
+ return;
+
+ if (!m_decoder) {
+ if (!m_responseEncoding.isEmpty())
+ m_decoder = TextResourceDecoder::create("text/javascript", m_responseEncoding);
+ else
+ m_decoder = TextResourceDecoder::create("text/javascript", "UTF-8");
+ }
+
+ if (!len)
+ return;
+
+ if (len == -1)
+ len = strlen(data);
+
+ m_script += m_decoder->decode(data, len);
+}
+
+void WorkerImportScriptsClient::didFinishLoading(unsigned long identifier)
+{
+ if (m_failed)
+ return;
+
+ if (m_decoder)
+ m_script += m_decoder->flush();
+
+ m_scriptExecutionContext->scriptImported(identifier, m_script);
+ m_scriptExecutionContext->addMessage(InspectorControllerDestination, JSMessageSource, LogMessageLevel, "Worker script imported: \"" + m_url + "\".", m_callerLineNumber, m_callerURL);
+}
+
+void WorkerImportScriptsClient::didFail(const ResourceError&)
+{
+ m_failed = true;
+}
+
+void WorkerImportScriptsClient::didFailRedirectCheck()
+{
+ m_failed = true;
+}
+
+void WorkerImportScriptsClient::didReceiveAuthenticationCancellation(const ResourceResponse&)
+{
+ m_failed = true;
+}
+
+}
+
+#endif // ENABLE(WORKERS)
diff --git a/WebCore/workers/WorkerImportScriptsClient.h b/WebCore/workers/WorkerImportScriptsClient.h
new file mode 100644
index 0000000..ec27054
--- /dev/null
+++ b/WebCore/workers/WorkerImportScriptsClient.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef WorkerImportScriptsClient_h
+#define WorkerImportScriptsClient_h
+
+#if ENABLE(WORKERS)
+
+#include "ResourceResponse.h"
+#include "ScriptString.h"
+#include "TextResourceDecoder.h"
+#include "ThreadableLoaderClient.h"
+
+namespace WebCore {
+
+ class ScriptExecutionContext;
+
+ class WorkerImportScriptsClient : public ThreadableLoaderClient {
+ public:
+ WorkerImportScriptsClient(ScriptExecutionContext* scriptExecutionContext, const String& url, const String& callerURL, int callerLineNumber)
+ : m_scriptExecutionContext(scriptExecutionContext)
+ , m_url(url)
+ , m_callerURL(callerURL)
+ , m_callerLineNumber(callerLineNumber)
+ , m_failed(false)
+ {
+ }
+
+ const String& script() const { return m_script; }
+ bool failed() const { return m_failed; }
+
+ virtual void didReceiveResponse(const ResourceResponse& response);
+ virtual void didReceiveData(const char* data, int lengthReceived);
+ virtual void didFinishLoading(unsigned long identifier);
+ virtual void didFail(const ResourceError&);
+ virtual void didFailRedirectCheck();
+ virtual void didReceiveAuthenticationCancellation(const ResourceResponse&);
+
+ private:
+ ScriptExecutionContext* m_scriptExecutionContext;
+ String m_url;
+ String m_callerURL;
+ int m_callerLineNumber;
+ String m_responseEncoding;
+ RefPtr<TextResourceDecoder> m_decoder;
+ String m_script;
+ bool m_failed;
+ };
+
+}
+
+#endif // ENABLE(WORKERS)
+#endif
+
diff --git a/WebCore/workers/WorkerLocation.cpp b/WebCore/workers/WorkerLocation.cpp
new file mode 100644
index 0000000..e84bf93
--- /dev/null
+++ b/WebCore/workers/WorkerLocation.cpp
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "config.h"
+
+#if ENABLE(WORKERS)
+
+#include "WorkerLocation.h"
+
+#include "PlatformString.h"
+
+namespace WebCore {
+
+String WorkerLocation::href() const
+{
+ return m_url.hasPath() ? m_url.prettyURL() : m_url.prettyURL() + "/";
+}
+
+String WorkerLocation::protocol() const
+{
+ return m_url.protocol() + ":";
+}
+
+String WorkerLocation::host() const
+{
+ return m_url.port() ? m_url.host() + ":" + String::number((static_cast<int>(m_url.port()))) : m_url.host();
+}
+
+String WorkerLocation::hostname() const
+{
+ return m_url.host();
+}
+
+String WorkerLocation::port() const
+{
+ return m_url.port() ? String::number(static_cast<int>(m_url.port())) : "";
+}
+
+String WorkerLocation::pathname() const
+{
+ return m_url.path().isEmpty() ? "/" : m_url.path();
+}
+
+String WorkerLocation::search() const
+{
+ return m_url.query().isEmpty() ? "" : "?" + m_url.query();
+}
+
+String WorkerLocation::hash() const
+{
+ return m_url.ref().isEmpty() ? "" : "#" + m_url.ref();
+}
+
+String WorkerLocation::toString() const
+{
+ return m_url.hasPath() ? m_url.prettyURL() : m_url.prettyURL() + "/";
+}
+
+
+} // namespace WebCore
+
+#endif // ENABLE(WORKERS)
diff --git a/WebCore/workers/WorkerLocation.h b/WebCore/workers/WorkerLocation.h
new file mode 100644
index 0000000..52c31ad
--- /dev/null
+++ b/WebCore/workers/WorkerLocation.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef WorkerLocation_h
+#define WorkerLocation_h
+
+#if ENABLE(WORKERS)
+
+#include "KURL.h"
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+ class String;
+
+ class WorkerLocation : public RefCounted<WorkerLocation> {
+ public:
+ static PassRefPtr<WorkerLocation> create(const KURL& url)
+ {
+ return adoptRef(new WorkerLocation(url));
+ }
+
+ const KURL& url() const { return m_url; }
+
+ String href() const;
+
+ // URI decomposition attributes
+ String protocol() const;
+ String host() const;
+ String hostname() const;
+ String port() const;
+ String pathname() const;
+ String search() const;
+ String hash() const;
+
+ String toString() const;
+
+ private:
+ WorkerLocation(const KURL& url) : m_url(url) { }
+
+ KURL m_url;
+ };
+
+} // namespace WebCore
+
+#endif // ENABLE(WORKERS)
+
+#endif // WorkerLocation_h
diff --git a/WebCore/workers/WorkerLocation.idl b/WebCore/workers/WorkerLocation.idl
new file mode 100644
index 0000000..5551f18
--- /dev/null
+++ b/WebCore/workers/WorkerLocation.idl
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+module threads {
+
+ interface [
+ Conditional=WORKERS,
+ GenerateConstructor,
+ NoStaticTables
+ ] WorkerLocation {
+ readonly attribute DOMString href;
+ readonly attribute DOMString protocol;
+ readonly attribute DOMString host;
+ readonly attribute DOMString hostname;
+ readonly attribute DOMString port;
+ readonly attribute DOMString pathname;
+ readonly attribute DOMString search;
+ readonly attribute DOMString hash;
+
+ [DontEnum] DOMString toString();
+ };
+
+}
diff --git a/WebCore/workers/WorkerMessagingProxy.cpp b/WebCore/workers/WorkerMessagingProxy.cpp
new file mode 100644
index 0000000..4b34658
--- /dev/null
+++ b/WebCore/workers/WorkerMessagingProxy.cpp
@@ -0,0 +1,343 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2009 Google Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "config.h"
+
+#if ENABLE(WORKERS)
+
+#include "WorkerMessagingProxy.h"
+
+#include "DOMWindow.h"
+#include "Document.h"
+#include "GenericWorkerTask.h"
+#include "MessageEvent.h"
+#include "ScriptExecutionContext.h"
+#include "Worker.h"
+#include "WorkerContext.h"
+#include "WorkerThread.h"
+
+namespace WebCore {
+
+class MessageWorkerContextTask : public ScriptExecutionContext::Task {
+public:
+ static PassRefPtr<MessageWorkerContextTask> create(const String& message)
+ {
+ return adoptRef(new MessageWorkerContextTask(message));
+ }
+
+private:
+ MessageWorkerContextTask(const String& message)
+ : m_message(message.copy())
+ {
+ }
+
+ virtual void performTask(ScriptExecutionContext* scriptContext)
+ {
+ ASSERT(scriptContext->isWorkerContext());
+ WorkerContext* context = static_cast<WorkerContext*>(scriptContext);
+
+ context->dispatchMessage(m_message);
+
+ context->thread()->workerObjectProxy()->confirmMessageFromWorkerObject(context->hasPendingActivity());
+ }
+
+private:
+ String m_message;
+};
+
+class MessageWorkerTask : public ScriptExecutionContext::Task {
+public:
+ static PassRefPtr<MessageWorkerTask> create(const String& message, WorkerMessagingProxy* messagingProxy)
+ {
+ return adoptRef(new MessageWorkerTask(message, messagingProxy));
+ }
+
+private:
+ MessageWorkerTask(const String& message, WorkerMessagingProxy* messagingProxy)
+ : m_message(message.copy())
+ , m_messagingProxy(messagingProxy)
+ {
+ }
+
+ virtual void performTask(ScriptExecutionContext*)
+ {
+ Worker* workerObject = m_messagingProxy->workerObject();
+ if (!workerObject || m_messagingProxy->askedToTerminate())
+ return;
+
+ workerObject->dispatchMessage(m_message);
+ }
+
+private:
+ String m_message;
+ WorkerMessagingProxy* m_messagingProxy;
+};
+
+class WorkerExceptionTask : public ScriptExecutionContext::Task {
+public:
+ static PassRefPtr<WorkerExceptionTask> create(const String& errorMessage, int lineNumber, const String& sourceURL, WorkerMessagingProxy* messagingProxy)
+ {
+ return adoptRef(new WorkerExceptionTask(errorMessage, lineNumber, sourceURL, messagingProxy));
+ }
+
+private:
+ WorkerExceptionTask(const String& errorMessage, int lineNumber, const String& sourceURL, WorkerMessagingProxy* messagingProxy)
+ : m_errorMessage(errorMessage.copy())
+ , m_lineNumber(lineNumber)
+ , m_sourceURL(sourceURL.copy())
+ , m_messagingProxy(messagingProxy)
+ {
+ }
+
+ virtual void performTask(ScriptExecutionContext* context)
+ {
+ if (!m_messagingProxy->askedToTerminate())
+ context->reportException(m_errorMessage, m_lineNumber, m_sourceURL);
+ }
+
+ String m_errorMessage;
+ int m_lineNumber;
+ String m_sourceURL;
+ WorkerMessagingProxy* m_messagingProxy;
+};
+
+class WorkerContextDestroyedTask : public ScriptExecutionContext::Task {
+public:
+ static PassRefPtr<WorkerContextDestroyedTask> create(WorkerMessagingProxy* messagingProxy)
+ {
+ return adoptRef(new WorkerContextDestroyedTask(messagingProxy));
+ }
+
+private:
+ WorkerContextDestroyedTask(WorkerMessagingProxy* messagingProxy)
+ : m_messagingProxy(messagingProxy)
+ {
+ }
+
+ virtual void performTask(ScriptExecutionContext*)
+ {
+ m_messagingProxy->workerContextDestroyedInternal();
+ }
+
+ WorkerMessagingProxy* m_messagingProxy;
+};
+
+class WorkerThreadActivityReportTask : public ScriptExecutionContext::Task {
+public:
+ static PassRefPtr<WorkerThreadActivityReportTask> create(WorkerMessagingProxy* messagingProxy, bool confirmingMessage, bool hasPendingActivity)
+ {
+ return adoptRef(new WorkerThreadActivityReportTask(messagingProxy, confirmingMessage, hasPendingActivity));
+ }
+
+private:
+ WorkerThreadActivityReportTask(WorkerMessagingProxy* messagingProxy, bool confirmingMessage, bool hasPendingActivity)
+ : m_messagingProxy(messagingProxy)
+ , m_confirmingMessage(confirmingMessage)
+ , m_hasPendingActivity(hasPendingActivity)
+ {
+ }
+
+ virtual void performTask(ScriptExecutionContext*)
+ {
+ m_messagingProxy->reportPendingActivityInternal(m_confirmingMessage, m_hasPendingActivity);
+ }
+
+ WorkerMessagingProxy* m_messagingProxy;
+ bool m_confirmingMessage;
+ bool m_hasPendingActivity;
+};
+
+
+#if !PLATFORM(CHROMIUM)
+WorkerContextProxy* WorkerContextProxy::create(Worker* worker)
+{
+ return new WorkerMessagingProxy(worker);
+}
+#endif
+
+WorkerMessagingProxy::WorkerMessagingProxy(Worker* workerObject)
+ : m_scriptExecutionContext(workerObject->scriptExecutionContext())
+ , m_workerObject(workerObject)
+ , m_unconfirmedMessageCount(0)
+ , m_workerThreadHadPendingActivity(false)
+ , m_askedToTerminate(false)
+{
+ ASSERT(m_workerObject);
+ ASSERT((m_scriptExecutionContext->isDocument() && isMainThread())
+ || (m_scriptExecutionContext->isWorkerContext() && currentThread() == static_cast<WorkerContext*>(m_scriptExecutionContext.get())->thread()->threadID()));
+}
+
+WorkerMessagingProxy::~WorkerMessagingProxy()
+{
+ ASSERT(!m_workerObject);
+ ASSERT((m_scriptExecutionContext->isDocument() && isMainThread())
+ || (m_scriptExecutionContext->isWorkerContext() && currentThread() == static_cast<WorkerContext*>(m_scriptExecutionContext.get())->thread()->threadID()));
+}
+
+void WorkerMessagingProxy::startWorkerContext(const KURL& scriptURL, const String& userAgent, const String& sourceCode)
+{
+ RefPtr<WorkerThread> thread = WorkerThread::create(scriptURL, userAgent, sourceCode, this);
+ workerThreadCreated(thread);
+ thread->start();
+}
+
+void WorkerMessagingProxy::postMessageToWorkerObject(const String& message)
+{
+ m_scriptExecutionContext->postTask(MessageWorkerTask::create(message, this));
+}
+
+void WorkerMessagingProxy::postMessageToWorkerContext(const String& message)
+{
+ if (m_askedToTerminate)
+ return;
+
+ if (m_workerThread) {
+ ++m_unconfirmedMessageCount;
+ m_workerThread->runLoop().postTask(MessageWorkerContextTask::create(message));
+ } else
+ m_queuedEarlyTasks.append(MessageWorkerContextTask::create(message));
+}
+
+void WorkerMessagingProxy::postTaskToWorkerContext(PassRefPtr<ScriptExecutionContext::Task> task)
+{
+ postTaskForModeToWorkerContext(task, WorkerRunLoop::defaultMode());
+}
+
+void WorkerMessagingProxy::postTaskForModeToWorkerContext(PassRefPtr<ScriptExecutionContext::Task> task, const String& mode)
+{
+ if (m_askedToTerminate)
+ return;
+
+ ASSERT(m_workerThread);
+ m_workerThread->runLoop().postTaskForMode(task, mode);
+}
+
+void WorkerMessagingProxy::postTaskToWorkerObject(PassRefPtr<ScriptExecutionContext::Task> task)
+{
+ m_scriptExecutionContext->postTask(task);
+}
+
+void WorkerMessagingProxy::postExceptionToWorkerObject(const String& errorMessage, int lineNumber, const String& sourceURL)
+{
+ m_scriptExecutionContext->postTask(WorkerExceptionTask::create(errorMessage, lineNumber, sourceURL, this));
+}
+
+static void postConsoleMessageTask(ScriptExecutionContext* context, WorkerMessagingProxy* messagingProxy, MessageDestination destination, MessageSource source, MessageLevel level, const String& message, unsigned lineNumber, const String& sourceURL)
+{
+ if (messagingProxy->askedToTerminate())
+ return;
+ context->addMessage(destination, source, level, message, lineNumber, sourceURL);
+}
+
+void WorkerMessagingProxy::postConsoleMessageToWorkerObject(MessageDestination destination, MessageSource source, MessageLevel level, const String& message, int lineNumber, const String& sourceURL)
+{
+ m_scriptExecutionContext->postTask(createCallbackTask(&postConsoleMessageTask, this, destination, source, level, message, lineNumber, sourceURL));
+}
+
+void WorkerMessagingProxy::workerThreadCreated(PassRefPtr<WorkerThread> workerThread)
+{
+ m_workerThread = workerThread;
+
+ if (m_askedToTerminate) {
+ // Worker.terminate() could be called from JS before the thread was created.
+ m_workerThread->stop();
+ } else {
+ unsigned taskCount = m_queuedEarlyTasks.size();
+ ASSERT(!m_unconfirmedMessageCount);
+ m_unconfirmedMessageCount = taskCount;
+ m_workerThreadHadPendingActivity = true; // Worker initialization means a pending activity.
+
+ for (unsigned i = 0; i < taskCount; ++i)
+ m_workerThread->runLoop().postTask(m_queuedEarlyTasks[i]);
+ m_queuedEarlyTasks.clear();
+ }
+}
+
+void WorkerMessagingProxy::workerObjectDestroyed()
+{
+ m_workerObject = 0;
+ if (m_workerThread)
+ terminateWorkerContext();
+ else
+ workerContextDestroyedInternal();
+}
+
+void WorkerMessagingProxy::workerContextDestroyed()
+{
+ m_scriptExecutionContext->postTask(WorkerContextDestroyedTask::create(this));
+ // Will execute workerContextDestroyedInternal() on context's thread.
+}
+
+void WorkerMessagingProxy::workerContextDestroyedInternal()
+{
+ // WorkerContextDestroyedTask is always the last to be performed, so the proxy is not needed for communication
+ // in either side any more. However, the Worker object may still exist, and it assumes that the proxy exists, too.
+ m_workerThread = 0;
+ if (!m_workerObject)
+ delete this;
+}
+
+void WorkerMessagingProxy::terminateWorkerContext()
+{
+ if (m_askedToTerminate)
+ return;
+ m_askedToTerminate = true;
+
+ if (m_workerThread)
+ m_workerThread->stop();
+}
+
+void WorkerMessagingProxy::confirmMessageFromWorkerObject(bool hasPendingActivity)
+{
+ m_scriptExecutionContext->postTask(WorkerThreadActivityReportTask::create(this, true, hasPendingActivity));
+ // Will execute reportPendingActivityInternal() on context's thread.
+}
+
+void WorkerMessagingProxy::reportPendingActivity(bool hasPendingActivity)
+{
+ m_scriptExecutionContext->postTask(WorkerThreadActivityReportTask::create(this, false, hasPendingActivity));
+ // Will execute reportPendingActivityInternal() on context's thread.
+}
+
+void WorkerMessagingProxy::reportPendingActivityInternal(bool confirmingMessage, bool hasPendingActivity)
+{
+ if (confirmingMessage && !m_askedToTerminate) {
+ ASSERT(m_unconfirmedMessageCount);
+ --m_unconfirmedMessageCount;
+ }
+
+ m_workerThreadHadPendingActivity = hasPendingActivity;
+}
+
+bool WorkerMessagingProxy::hasPendingActivity() const
+{
+ return (m_unconfirmedMessageCount || m_workerThreadHadPendingActivity) && !m_askedToTerminate;
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(WORKERS)
diff --git a/WebCore/workers/WorkerMessagingProxy.h b/WebCore/workers/WorkerMessagingProxy.h
new file mode 100644
index 0000000..8d81deb
--- /dev/null
+++ b/WebCore/workers/WorkerMessagingProxy.h
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef WorkerMessagingProxy_h
+#define WorkerMessagingProxy_h
+
+#if ENABLE(WORKERS)
+
+#include "ScriptExecutionContext.h"
+#include "WorkerContextProxy.h"
+#include "WorkerObjectProxy.h"
+#include <wtf/Noncopyable.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefPtr.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+ class ScriptExecutionContext;
+ class String;
+ class Worker;
+ class WorkerThread;
+
+ class WorkerMessagingProxy : public WorkerContextProxy, public WorkerObjectProxy, Noncopyable {
+ public:
+ WorkerMessagingProxy(Worker*);
+
+ // Implementations of WorkerContextProxy.
+ // (Only use these methods in the worker object thread.)
+ virtual void startWorkerContext(const KURL& scriptURL, const String& userAgent, const String& sourceCode);
+ virtual void terminateWorkerContext();
+ virtual void postMessageToWorkerContext(const String& message);
+ virtual bool hasPendingActivity() const;
+ virtual void workerObjectDestroyed();
+
+ // Implementations of WorkerObjectProxy.
+ // (Only use these methods in the worker context thread.)
+ virtual void postMessageToWorkerObject(const String& message);
+ virtual void postExceptionToWorkerObject(const String& errorMessage, int lineNumber, const String& sourceURL);
+ virtual void postConsoleMessageToWorkerObject(MessageDestination, MessageSource, MessageLevel, const String& message, int lineNumber, const String& sourceURL);
+ virtual void confirmMessageFromWorkerObject(bool hasPendingActivity);
+ virtual void reportPendingActivity(bool hasPendingActivity);
+ virtual void workerContextDestroyed();
+
+ void postTaskToWorkerObject(PassRefPtr<ScriptExecutionContext::Task>);
+ void postTaskToWorkerContext(PassRefPtr<ScriptExecutionContext::Task>);
+ void postTaskForModeToWorkerContext(PassRefPtr<ScriptExecutionContext::Task>, const String& mode);
+
+ void workerThreadCreated(PassRefPtr<WorkerThread>);
+
+ // Only use this method on the worker object thread.
+ bool askedToTerminate() const { return m_askedToTerminate; }
+
+ private:
+ friend class MessageWorkerTask;
+ friend class WorkerContextDestroyedTask;
+ friend class WorkerThreadActivityReportTask;
+
+ virtual ~WorkerMessagingProxy();
+
+ void workerContextDestroyedInternal();
+ void reportPendingActivityInternal(bool confirmingMessage, bool hasPendingActivity);
+ Worker* workerObject() const { return m_workerObject; }
+
+ RefPtr<ScriptExecutionContext> m_scriptExecutionContext;
+ Worker* m_workerObject;
+ RefPtr<WorkerThread> m_workerThread;
+
+ unsigned m_unconfirmedMessageCount; // Unconfirmed messages from worker object to worker thread.
+ bool m_workerThreadHadPendingActivity; // The latest confirmation from worker thread reported that it was still active.
+
+ bool m_askedToTerminate;
+
+ Vector<RefPtr<ScriptExecutionContext::Task> > m_queuedEarlyTasks; // Tasks are queued here until there's a thread object created.
+ };
+
+} // namespace WebCore
+
+#endif // ENABLE(WORKERS)
+
+#endif // WorkerMessagingProxy_h
diff --git a/WebCore/workers/WorkerObjectProxy.h b/WebCore/workers/WorkerObjectProxy.h
new file mode 100644
index 0000000..3b86028
--- /dev/null
+++ b/WebCore/workers/WorkerObjectProxy.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef WorkerObjectProxy_h
+#define WorkerObjectProxy_h
+
+#if ENABLE(WORKERS)
+
+#include "Console.h"
+
+namespace WebCore {
+
+ class String;
+
+ // A proxy to talk to the worker object.
+ class WorkerObjectProxy {
+ public:
+ virtual ~WorkerObjectProxy() {}
+
+ virtual void postMessageToWorkerObject(const String&) = 0;
+
+ virtual void postExceptionToWorkerObject(const String& errorMessage, int lineNumber, const String& sourceURL) = 0;
+
+ virtual void postConsoleMessageToWorkerObject(MessageDestination, MessageSource, MessageLevel, const String& message, int lineNumber, const String& sourceURL) = 0;
+
+ virtual void confirmMessageFromWorkerObject(bool hasPendingActivity) = 0;
+
+ virtual void reportPendingActivity(bool hasPendingActivity) = 0;
+
+ virtual void workerContextDestroyed() = 0;
+ };
+
+} // namespace WebCore
+
+#endif // ENABLE(WORKERS)
+
+#endif // WorkerObjectProxy_h
diff --git a/WebCore/workers/WorkerRunLoop.cpp b/WebCore/workers/WorkerRunLoop.cpp
new file mode 100644
index 0000000..1e5e510
--- /dev/null
+++ b/WebCore/workers/WorkerRunLoop.cpp
@@ -0,0 +1,210 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(WORKERS)
+
+#include "ScriptExecutionContext.h"
+#include "SharedTimer.h"
+#include "ThreadGlobalData.h"
+#include "ThreadTimers.h"
+#include "WorkerRunLoop.h"
+#include "WorkerContext.h"
+#include "WorkerThread.h"
+
+namespace WebCore {
+
+class WorkerSharedTimer : public SharedTimer {
+public:
+ WorkerSharedTimer()
+ : m_sharedTimerFunction(0)
+ , m_nextFireTime(0)
+ {
+ }
+
+ // SharedTimer interface.
+ virtual void setFiredFunction(void (*function)()) { m_sharedTimerFunction = function; }
+ virtual void setFireTime(double fireTime) { m_nextFireTime = fireTime; }
+ virtual void stop() { m_nextFireTime = 0; }
+
+ bool isActive() { return m_sharedTimerFunction && m_nextFireTime; }
+ double fireTime() { return m_nextFireTime; }
+ void fire() { m_sharedTimerFunction(); }
+
+private:
+ void (*m_sharedTimerFunction)();
+ double m_nextFireTime;
+};
+
+class WorkerRunLoop::Task : public RefCounted<Task> {
+public:
+ static PassRefPtr<Task> create(PassRefPtr<ScriptExecutionContext::Task> task, const String& mode)
+ {
+ return adoptRef(new Task(task, mode));
+ }
+
+ const String& mode() const { return m_mode; }
+ void performTask(ScriptExecutionContext* context) { m_task->performTask(context); }
+
+private:
+ Task(PassRefPtr<ScriptExecutionContext::Task> task, const String& mode)
+ : m_task(task)
+ , m_mode(mode.copy())
+ {
+ }
+
+ RefPtr<ScriptExecutionContext::Task> m_task;
+ String m_mode;
+};
+
+class ModePredicate {
+public:
+ ModePredicate(const String& mode)
+ : m_mode(mode)
+ , m_defaultMode(mode == WorkerRunLoop::defaultMode())
+ {
+ }
+
+ bool isDefaultMode() const
+ {
+ return m_defaultMode;
+ }
+
+ bool operator()(PassRefPtr<WorkerRunLoop::Task> task) const
+ {
+ return m_defaultMode || m_mode == task->mode();
+ }
+
+private:
+ String m_mode;
+ bool m_defaultMode;
+};
+
+WorkerRunLoop::WorkerRunLoop()
+ : m_sharedTimer(new WorkerSharedTimer)
+ , m_nestedCount(0)
+ , m_uniqueId(0)
+{
+}
+
+WorkerRunLoop::~WorkerRunLoop()
+{
+ ASSERT(!m_nestedCount);
+}
+
+String WorkerRunLoop::defaultMode()
+{
+ return String();
+}
+
+class RunLoopSetup : Noncopyable
+{
+public:
+ RunLoopSetup(WorkerRunLoop& runLoop)
+ : m_runLoop(runLoop)
+ {
+ if (!m_runLoop.m_nestedCount)
+ threadGlobalData().threadTimers().setSharedTimer(m_runLoop.m_sharedTimer.get());
+ m_runLoop.m_nestedCount++;
+ }
+
+ ~RunLoopSetup()
+ {
+ m_runLoop.m_nestedCount--;
+ if (!m_runLoop.m_nestedCount)
+ threadGlobalData().threadTimers().setSharedTimer(0);
+ }
+private:
+ WorkerRunLoop& m_runLoop;
+};
+
+void WorkerRunLoop::run(WorkerContext* context)
+{
+ RunLoopSetup setup(*this);
+ ModePredicate modePredicate(defaultMode());
+ MessageQueueWaitResult result;
+ do {
+ result = runInMode(context, modePredicate);
+ } while (result != MessageQueueTerminated);
+}
+
+MessageQueueWaitResult WorkerRunLoop::runInMode(WorkerContext* context, const String& mode)
+{
+ RunLoopSetup setup(*this);
+ ModePredicate modePredicate(mode);
+ MessageQueueWaitResult result = runInMode(context, modePredicate);
+ return result;
+}
+
+MessageQueueWaitResult WorkerRunLoop::runInMode(WorkerContext* context, const ModePredicate& predicate)
+{
+ ASSERT(context);
+ ASSERT(context->thread());
+ ASSERT(context->thread()->threadID() == currentThread());
+
+ double absoluteTime = (predicate.isDefaultMode() && m_sharedTimer->isActive()) ? m_sharedTimer->fireTime() : MessageQueue<RefPtr<Task> >::infiniteTime();
+ RefPtr<Task> task;
+ MessageQueueWaitResult result = m_messageQueue.waitForMessageFilteredWithTimeout(task, predicate, absoluteTime);
+
+ switch (result) {
+ case MessageQueueTerminated:
+ break;
+
+ case MessageQueueMessageReceived:
+ task->performTask(context);
+ break;
+
+ case MessageQueueTimeout:
+ m_sharedTimer->fire();
+ break;
+ }
+
+ return result;
+}
+
+void WorkerRunLoop::terminate()
+{
+ m_messageQueue.kill();
+}
+
+void WorkerRunLoop::postTask(PassRefPtr<ScriptExecutionContext::Task> task)
+{
+ postTaskForMode(task, defaultMode());
+}
+
+void WorkerRunLoop::postTaskForMode(PassRefPtr<ScriptExecutionContext::Task> task, const String& mode)
+{
+ m_messageQueue.append(Task::create(task, mode.copy()));
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(WORKERS)
diff --git a/WebCore/workers/WorkerRunLoop.h b/WebCore/workers/WorkerRunLoop.h
new file mode 100644
index 0000000..5f74f01
--- /dev/null
+++ b/WebCore/workers/WorkerRunLoop.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef WorkerRunLoop_h
+#define WorkerRunLoop_h
+
+#if ENABLE(WORKERS)
+
+#include "ScriptExecutionContext.h"
+#include <wtf/MessageQueue.h>
+#include <wtf/OwnPtr.h>
+#include <wtf/PassRefPtr.h>
+
+namespace WebCore {
+
+ class ModePredicate;
+ class WorkerContext;
+ class WorkerSharedTimer;
+
+ class WorkerRunLoop {
+ public:
+ WorkerRunLoop();
+ ~WorkerRunLoop();
+
+ // Blocking call. Waits for tasks and timers, invokes the callbacks.
+ void run(WorkerContext*);
+
+ // Waits for a single task and returns.
+ MessageQueueWaitResult runInMode(WorkerContext*, const String& mode);
+
+ void terminate();
+ bool terminated() { return m_messageQueue.killed(); }
+
+ void postTask(PassRefPtr<ScriptExecutionContext::Task>);
+ void postTaskForMode(PassRefPtr<ScriptExecutionContext::Task>, const String& mode);
+
+ unsigned long createUniqueId() { return ++m_uniqueId; }
+
+ static String defaultMode();
+ class Task;
+ private:
+ friend class RunLoopSetup;
+ MessageQueueWaitResult runInMode(WorkerContext*, const ModePredicate&);
+
+ MessageQueue<RefPtr<Task> > m_messageQueue;
+ OwnPtr<WorkerSharedTimer> m_sharedTimer;
+ int m_nestedCount;
+ unsigned long m_uniqueId;
+ };
+
+} // namespace WebCore
+
+#endif // ENABLE(WORKERS)
+
+#endif // WorkerRunLoop_h
diff --git a/WebCore/workers/WorkerThread.cpp b/WebCore/workers/WorkerThread.cpp
new file mode 100644
index 0000000..d1026b1
--- /dev/null
+++ b/WebCore/workers/WorkerThread.cpp
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "config.h"
+
+#if ENABLE(WORKERS)
+
+#include "WorkerThread.h"
+
+#include "KURL.h"
+#include "PlatformString.h"
+#include "ScriptSourceCode.h"
+#include "ScriptValue.h"
+#include "WorkerContext.h"
+#include "WorkerObjectProxy.h"
+
+#include <utility>
+#include <wtf/Noncopyable.h>
+
+namespace WebCore {
+struct WorkerThreadStartupData : Noncopyable {
+public:
+ static std::auto_ptr<WorkerThreadStartupData> create(const KURL& scriptURL, const String& userAgent, const String& sourceCode)
+ {
+ return std::auto_ptr<WorkerThreadStartupData>(new WorkerThreadStartupData(scriptURL, userAgent, sourceCode));
+ }
+
+ KURL m_scriptURL;
+ String m_userAgent;
+ String m_sourceCode;
+private:
+ WorkerThreadStartupData(const KURL& scriptURL, const String& userAgent, const String& sourceCode);
+};
+
+WorkerThreadStartupData::WorkerThreadStartupData(const KURL& scriptURL, const String& userAgent, const String& sourceCode)
+ : m_scriptURL(scriptURL.copy())
+ , m_userAgent(userAgent.copy())
+ , m_sourceCode(sourceCode.copy())
+{
+}
+
+PassRefPtr<WorkerThread> WorkerThread::create(const KURL& scriptURL, const String& userAgent, const String& sourceCode, WorkerObjectProxy* workerObjectProxy)
+{
+ return adoptRef(new WorkerThread(scriptURL, userAgent, sourceCode, workerObjectProxy));
+}
+
+WorkerThread::WorkerThread(const KURL& scriptURL, const String& userAgent, const String& sourceCode, WorkerObjectProxy* workerObjectProxy)
+ : m_threadID(0)
+ , m_workerObjectProxy(workerObjectProxy)
+ , m_startupData(WorkerThreadStartupData::create(scriptURL, userAgent, sourceCode))
+{
+}
+
+WorkerThread::~WorkerThread()
+{
+}
+
+bool WorkerThread::start()
+{
+ // Mutex protection is necessary to ensure that m_threadID is initialized when the thread starts.
+ MutexLocker lock(m_threadCreationMutex);
+
+ if (m_threadID)
+ return true;
+
+ m_threadID = createThread(WorkerThread::workerThreadStart, this, "WebCore: Worker");
+
+ return m_threadID;
+}
+
+void* WorkerThread::workerThreadStart(void* thread)
+{
+ return static_cast<WorkerThread*>(thread)->workerThread();
+}
+
+void* WorkerThread::workerThread()
+{
+ {
+ MutexLocker lock(m_threadCreationMutex);
+ m_workerContext = WorkerContext::create(m_startupData->m_scriptURL, m_startupData->m_userAgent, this);
+ if (m_runLoop.terminated()) {
+ // The worker was terminated before the thread had a chance to run. Since the context didn't exist yet,
+ // forbidExecution() couldn't be called from stop().
+ m_workerContext->script()->forbidExecution();
+ }
+ }
+
+ WorkerScriptController* script = m_workerContext->script();
+ script->evaluate(ScriptSourceCode(m_startupData->m_sourceCode, m_startupData->m_scriptURL));
+ // Free the startup data to cause its member variable deref's happen on the worker's thread (since
+ // all ref/derefs of these objects are happening on the thread at this point). Note that
+ // WorkerThread::~WorkerThread happens on a different thread where it was created.
+ m_startupData.clear();
+
+ m_workerObjectProxy->reportPendingActivity(m_workerContext->hasPendingActivity());
+
+ // Blocks until terminated.
+ m_runLoop.run(m_workerContext.get());
+
+ ThreadIdentifier threadID = m_threadID;
+
+ m_workerContext->stopActiveDOMObjects();
+ m_workerContext->clearScript();
+ ASSERT(m_workerContext->hasOneRef());
+ // The below assignment will destroy the context, which will in turn notify messaging proxy.
+ // We cannot let any objects survive past thread exit, because no other thread will run GC or otherwise destroy them.
+ m_workerContext = 0;
+
+ // The thread object may be already destroyed from notification now, don't try to access "this".
+ detachThread(threadID);
+
+ return 0;
+}
+
+void WorkerThread::stop()
+{
+ // Mutex protection is necessary because stop() can be called before the context is fully created.
+ MutexLocker lock(m_threadCreationMutex);
+
+ // Ensure that tasks are being handled by thread event loop. If script execution weren't forbidden, a while(1) loop in JS could keep the thread alive forever.
+ if (m_workerContext)
+ m_workerContext->script()->forbidExecution();
+
+ // FIXME: Rudely killing the thread won't work when we allow nested workers, because they will try to post notifications of their destruction.
+ m_runLoop.terminate();
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(WORKERS)
diff --git a/WebCore/workers/WorkerThread.h b/WebCore/workers/WorkerThread.h
new file mode 100644
index 0000000..f1a8a52
--- /dev/null
+++ b/WebCore/workers/WorkerThread.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef WorkerThread_h
+#define WorkerThread_h
+
+#if ENABLE(WORKERS)
+
+#include "WorkerRunLoop.h"
+#include <wtf/OwnPtr.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+
+namespace WebCore {
+
+ class KURL;
+ class String;
+ class WorkerContext;
+ class WorkerObjectProxy;
+ struct WorkerThreadStartupData;
+
+ class WorkerThread : public RefCounted<WorkerThread> {
+ public:
+ static PassRefPtr<WorkerThread> create(const KURL& scriptURL, const String& userAgent, const String& sourceCode, WorkerObjectProxy*);
+ ~WorkerThread();
+
+ bool start();
+ void stop();
+
+ ThreadIdentifier threadID() const { return m_threadID; }
+ WorkerRunLoop& runLoop() { return m_runLoop; }
+ WorkerObjectProxy* workerObjectProxy() const { return m_workerObjectProxy; }
+
+ private:
+ WorkerThread(const KURL&, const String& userAgent, const String& sourceCode, WorkerObjectProxy*);
+
+ static void* workerThreadStart(void*);
+ void* workerThread();
+
+ ThreadIdentifier m_threadID;
+ WorkerRunLoop m_runLoop;
+ WorkerObjectProxy* m_workerObjectProxy;
+
+ RefPtr<WorkerContext> m_workerContext;
+ Mutex m_threadCreationMutex;
+
+ OwnPtr<WorkerThreadStartupData> m_startupData;
+ };
+
+} // namespace WebCore
+
+#endif // ENABLE(WORKERS)
+
+#endif // WorkerThread_h
+