2 * Copyright (C) 2008 Apple Inc. All Rights Reserved.
3 * Copyright (C) 2009 Google Inc. All Rights Reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 #include "DOMWindow.h"
35 #include "DocLoader.h"
37 #include "EventException.h"
38 #include "EventListener.h"
39 #include "EventNames.h"
40 #include "ExceptionCode.h"
42 #include "FrameLoader.h"
43 #include "MessageEvent.h"
44 #include "SecurityOrigin.h"
45 #include "TextEncoding.h"
46 #include "WorkerContextProxy.h"
47 #include "WorkerScriptLoader.h"
48 #include "WorkerThread.h"
49 #include <wtf/MainThread.h>
53 Worker::Worker(const String& url, ScriptExecutionContext* context, ExceptionCode& ec)
54 : ActiveDOMObject(context, this)
55 , m_contextProxy(WorkerContextProxy::create(this))
57 m_scriptURL = context->completeURL(url);
58 if (url.isEmpty() || !m_scriptURL.isValid()) {
63 if (!context->securityOrigin()->canAccess(SecurityOrigin::create(m_scriptURL).get())) {
68 m_scriptLoader = new WorkerScriptLoader();
69 m_scriptLoader->loadAsynchronously(scriptExecutionContext(), m_scriptURL, DenyCrossOriginRedirect, this);
70 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.
75 ASSERT(isMainThread());
76 ASSERT(scriptExecutionContext()); // The context is protected by worker context proxy, so it cannot be destroyed while a Worker exists.
77 m_contextProxy->workerObjectDestroyed();
80 void Worker::postMessage(const String& message)
82 m_contextProxy->postMessageToWorkerContext(message);
85 void Worker::terminate()
87 m_contextProxy->terminateWorkerContext();
90 bool Worker::canSuspend() const
92 // FIXME: It is not currently possible to suspend a worker, so pages with workers can not go into page cache.
101 bool Worker::hasPendingActivity() const
103 return m_contextProxy->hasPendingActivity() || ActiveDOMObject::hasPendingActivity();
106 void Worker::notifyFinished()
108 if (m_scriptLoader->failed())
109 dispatchErrorEvent();
111 m_contextProxy->startWorkerContext(m_scriptURL, scriptExecutionContext()->userAgent(m_scriptURL), m_scriptLoader->script());
115 unsetPendingActivity(this);
118 void Worker::dispatchErrorEvent()
120 RefPtr<Event> evt = Event::create(eventNames().errorEvent, false, true);
121 if (m_onErrorListener) {
122 evt->setTarget(this);
123 evt->setCurrentTarget(this);
124 m_onErrorListener->handleEvent(evt.get(), true);
127 ExceptionCode ec = 0;
128 dispatchEvent(evt.release(), ec);
132 void Worker::addEventListener(const AtomicString& eventType, PassRefPtr<EventListener> eventListener, bool)
134 EventListenersMap::iterator iter = m_eventListeners.find(eventType);
135 if (iter == m_eventListeners.end()) {
136 ListenerVector listeners;
137 listeners.append(eventListener);
138 m_eventListeners.add(eventType, listeners);
140 ListenerVector& listeners = iter->second;
141 for (ListenerVector::iterator listenerIter = listeners.begin(); listenerIter != listeners.end(); ++listenerIter) {
142 if (*listenerIter == eventListener)
146 listeners.append(eventListener);
147 m_eventListeners.add(eventType, listeners);
151 void Worker::removeEventListener(const AtomicString& eventType, EventListener* eventListener, bool)
153 EventListenersMap::iterator iter = m_eventListeners.find(eventType);
154 if (iter == m_eventListeners.end())
157 ListenerVector& listeners = iter->second;
158 for (ListenerVector::const_iterator listenerIter = listeners.begin(); listenerIter != listeners.end(); ++listenerIter) {
159 if (*listenerIter == eventListener) {
160 listeners.remove(listenerIter - listeners.begin());
166 bool Worker::dispatchEvent(PassRefPtr<Event> event, ExceptionCode& ec)
168 if (!event || event->type().isEmpty()) {
169 ec = EventException::UNSPECIFIED_EVENT_TYPE_ERR;
173 ListenerVector listenersCopy = m_eventListeners.get(event->type());
174 for (ListenerVector::const_iterator listenerIter = listenersCopy.begin(); listenerIter != listenersCopy.end(); ++listenerIter) {
175 event->setTarget(this);
176 event->setCurrentTarget(this);
177 listenerIter->get()->handleEvent(event.get(), false);
180 return !event->defaultPrevented();
183 void Worker::dispatchMessage(const String& message)
185 RefPtr<Event> evt = MessageEvent::create(message, "", "", 0, 0);
187 if (m_onMessageListener.get()) {
188 evt->setTarget(this);
189 evt->setCurrentTarget(this);
190 m_onMessageListener->handleEvent(evt.get(), false);
193 ExceptionCode ec = 0;
194 dispatchEvent(evt.release(), ec);
198 } // namespace WebCore
200 #endif // ENABLE(WORKERS)