1/* 2 * Copyright (C) 2008, 2010 Apple Inc. All Rights Reserved. 3 * Copyright (C) 2009 Google Inc. All Rights Reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 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. 13 * 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. 25 * 26 */ 27 28#include "config.h" 29 30#if ENABLE(WORKERS) 31 32#include "Worker.h" 33 34#include "DOMWindow.h" 35#include "CachedResourceLoader.h" 36#include "Document.h" 37#include "EventException.h" 38#include "EventListener.h" 39#include "EventNames.h" 40#include "ExceptionCode.h" 41#include "Frame.h" 42#include "FrameLoader.h" 43#include "InspectorInstrumentation.h" 44#include "MessageEvent.h" 45#include "TextEncoding.h" 46#include "WorkerContextProxy.h" 47#include "WorkerScriptLoader.h" 48#include "WorkerThread.h" 49#include <wtf/MainThread.h> 50 51namespace WebCore { 52 53inline Worker::Worker(ScriptExecutionContext* context) 54 : AbstractWorker(context) 55 , m_contextProxy(WorkerContextProxy::create(this)) 56{ 57} 58 59PassRefPtr<Worker> Worker::create(const String& url, ScriptExecutionContext* context, ExceptionCode& ec) 60{ 61 RefPtr<Worker> worker = adoptRef(new Worker(context)); 62 63 KURL scriptURL = worker->resolveURL(url, ec); 64 if (scriptURL.isEmpty()) 65 return 0; 66 67 worker->m_scriptLoader = adoptPtr(new WorkerScriptLoader(ResourceRequestBase::TargetIsWorker)); 68 worker->m_scriptLoader->loadAsynchronously(context, scriptURL, DenyCrossOriginRequests, worker.get()); 69 70 // The worker context does not exist while loading, so we must ensure that the worker object is not collected, nor are its event listeners. 71 worker->setPendingActivity(worker.get()); 72 73 InspectorInstrumentation::didCreateWorker(context, worker->asID(), scriptURL.string(), false); 74 75 return worker.release(); 76} 77 78Worker::~Worker() 79{ 80 ASSERT(isMainThread()); 81 ASSERT(scriptExecutionContext()); // The context is protected by worker context proxy, so it cannot be destroyed while a Worker exists. 82 m_contextProxy->workerObjectDestroyed(); 83} 84 85// FIXME: remove this when we update the ObjC bindings (bug #28774). 86void Worker::postMessage(PassRefPtr<SerializedScriptValue> message, MessagePort* port, ExceptionCode& ec) 87{ 88 MessagePortArray ports; 89 if (port) 90 ports.append(port); 91 postMessage(message, &ports, ec); 92} 93 94void Worker::postMessage(PassRefPtr<SerializedScriptValue> message, ExceptionCode& ec) 95{ 96 postMessage(message, static_cast<MessagePortArray*>(0), ec); 97} 98 99void Worker::postMessage(PassRefPtr<SerializedScriptValue> message, const MessagePortArray* ports, ExceptionCode& ec) 100{ 101 // Disentangle the port in preparation for sending it to the remote context. 102 OwnPtr<MessagePortChannelArray> channels = MessagePort::disentanglePorts(ports, ec); 103 if (ec) 104 return; 105 m_contextProxy->postMessageToWorkerContext(message, channels.release()); 106} 107 108void Worker::terminate() 109{ 110 m_contextProxy->terminateWorkerContext(); 111} 112 113bool Worker::canSuspend() const 114{ 115 // FIXME: It is not currently possible to suspend a worker, so pages with workers can not go into page cache. 116 return false; 117} 118 119void Worker::stop() 120{ 121 terminate(); 122} 123 124bool Worker::hasPendingActivity() const 125{ 126 return m_contextProxy->hasPendingActivity() || ActiveDOMObject::hasPendingActivity(); 127} 128 129void Worker::notifyFinished() 130{ 131 if (m_scriptLoader->failed()) 132 dispatchEvent(Event::create(eventNames().errorEvent, false, true)); 133 else { 134 m_contextProxy->startWorkerContext(m_scriptLoader->url(), scriptExecutionContext()->userAgent(m_scriptLoader->url()), m_scriptLoader->script()); 135 InspectorInstrumentation::scriptImported(scriptExecutionContext(), m_scriptLoader->identifier(), m_scriptLoader->script()); 136 } 137 m_scriptLoader = 0; 138 139 unsetPendingActivity(this); 140} 141 142} // namespace WebCore 143 144#endif // ENABLE(WORKERS) 145