diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
commit | 1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch) | |
tree | 46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/WebCore/workers | |
parent | 32761a6cee1d0dee366b885b7b9c777e67885688 (diff) | |
download | WebKitGtk-tarball-master.tar.gz |
webkitgtk-2.16.5HEADwebkitgtk-2.16.5master
Diffstat (limited to 'Source/WebCore/workers')
48 files changed, 1528 insertions, 2710 deletions
diff --git a/Source/WebCore/workers/AbstractWorker.cpp b/Source/WebCore/workers/AbstractWorker.cpp index 85b9b5408..39b95d0eb 100644 --- a/Source/WebCore/workers/AbstractWorker.cpp +++ b/Source/WebCore/workers/AbstractWorker.cpp @@ -29,55 +29,35 @@ */ #include "config.h" - #include "AbstractWorker.h" #include "ContentSecurityPolicy.h" -#include "ErrorEvent.h" -#include "Event.h" -#include "EventException.h" -#include "EventNames.h" #include "ExceptionCode.h" -#include "InspectorInstrumentation.h" #include "ScriptExecutionContext.h" #include "SecurityOrigin.h" namespace WebCore { -AbstractWorker::AbstractWorker(ScriptExecutionContext& context) - : ActiveDOMObject(&context) -{ -} - -AbstractWorker::~AbstractWorker() +ExceptionOr<URL> AbstractWorker::resolveURL(const String& url, bool shouldBypassMainWorldContentSecurityPolicy) { -} + if (url.isEmpty()) + return Exception { SYNTAX_ERR }; -URL AbstractWorker::resolveURL(const String& url, ExceptionCode& ec) -{ - if (url.isEmpty()) { - ec = SYNTAX_ERR; - return URL(); - } + auto& context = *scriptExecutionContext(); - // FIXME: This should use the dynamic global scope (bug #27887) - URL scriptURL = scriptExecutionContext()->completeURL(url); - if (!scriptURL.isValid()) { - ec = SYNTAX_ERR; - return URL(); - } + // FIXME: This should use the dynamic global scope (bug #27887). + URL scriptURL = context.completeURL(url); + if (!scriptURL.isValid()) + return Exception { SYNTAX_ERR }; - if (!scriptExecutionContext()->securityOrigin()->canRequest(scriptURL)) { - ec = SECURITY_ERR; - return URL(); - } + if (!context.securityOrigin()->canRequest(scriptURL)) + return Exception { SECURITY_ERR }; - if (scriptExecutionContext()->contentSecurityPolicy() && !scriptExecutionContext()->contentSecurityPolicy()->allowScriptFromSource(scriptURL)) { - ec = SECURITY_ERR; - return URL(); - } + ASSERT(context.contentSecurityPolicy()); + if (!shouldBypassMainWorldContentSecurityPolicy && !context.contentSecurityPolicy()->allowChildContextFromSource(scriptURL)) + return Exception { SECURITY_ERR }; - return scriptURL; + return WTFMove(scriptURL); } } // namespace WebCore diff --git a/Source/WebCore/workers/AbstractWorker.h b/Source/WebCore/workers/AbstractWorker.h index 7848332c4..900c2cb40 100644 --- a/Source/WebCore/workers/AbstractWorker.h +++ b/Source/WebCore/workers/AbstractWorker.h @@ -28,46 +28,31 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef AbstractWorker_h -#define AbstractWorker_h +#pragma once -#include "ActiveDOMObject.h" -#include "EventListener.h" -#include "EventNames.h" #include "EventTarget.h" -#include <wtf/PassRefPtr.h> -#include <wtf/RefCounted.h> -#include <wtf/RefPtr.h> -#include <wtf/text/AtomicStringHash.h> +#include "ExceptionOr.h" namespace WebCore { - class URL; +class URL; - class AbstractWorker : public RefCounted<AbstractWorker>, public ActiveDOMObject, public EventTargetWithInlineData { - public: - // EventTarget APIs - virtual ScriptExecutionContext* scriptExecutionContext() const override final { return ActiveDOMObject::scriptExecutionContext(); } +class AbstractWorker : public RefCounted<AbstractWorker>, public EventTargetWithInlineData { +public: + using RefCounted::ref; + using RefCounted::deref; - DEFINE_ATTRIBUTE_EVENT_LISTENER(error); +protected: + AbstractWorker() = default; - using RefCounted<AbstractWorker>::ref; - using RefCounted<AbstractWorker>::deref; + // Helper function that converts a URL to an absolute URL and checks the result for validity. + ExceptionOr<URL> resolveURL(const String& url, bool shouldBypassMainWorldContentSecurityPolicy); - virtual ~AbstractWorker(); + intptr_t asID() const { return reinterpret_cast<intptr_t>(this); } - protected: - explicit AbstractWorker(ScriptExecutionContext&); - - // Helper function that converts a URL to an absolute URL and checks the result for validity. - URL resolveURL(const String& url, ExceptionCode& ec); - intptr_t asID() const { return reinterpret_cast<intptr_t>(this); } - - private: - virtual void refEventTarget() override final { ref(); } - virtual void derefEventTarget() override final { deref(); } - }; +private: + void refEventTarget() final { ref(); } + void derefEventTarget() final { deref(); } +}; } // namespace WebCore - -#endif // AbstractWorker_h diff --git a/Source/WebCore/workers/AbstractWorker.idl b/Source/WebCore/workers/AbstractWorker.idl index b2aee6833..3933b93b5 100644 --- a/Source/WebCore/workers/AbstractWorker.idl +++ b/Source/WebCore/workers/AbstractWorker.idl @@ -32,6 +32,6 @@ [ NoInterfaceObject, ] interface AbstractWorker { - attribute EventListener onerror; + attribute EventHandler onerror; }; diff --git a/Source/WebCore/workers/DedicatedWorkerGlobalScope.cpp b/Source/WebCore/workers/DedicatedWorkerGlobalScope.cpp index 701569f15..cb9b634d0 100644 --- a/Source/WebCore/workers/DedicatedWorkerGlobalScope.cpp +++ b/Source/WebCore/workers/DedicatedWorkerGlobalScope.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2009 Google Inc. All rights reserved. + * Copyright (C) 2016 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 @@ -31,6 +32,7 @@ #include "config.h" #include "DedicatedWorkerGlobalScope.h" +#include "ContentSecurityPolicyResponseHeaders.h" #include "DOMWindow.h" #include "DedicatedWorkerThread.h" #include "MessageEvent.h" @@ -39,15 +41,16 @@ namespace WebCore { -PassRefPtr<DedicatedWorkerGlobalScope> DedicatedWorkerGlobalScope::create(const URL& url, const String& userAgent, std::unique_ptr<GroupSettings> settings, DedicatedWorkerThread* thread, const String& contentSecurityPolicy, ContentSecurityPolicy::HeaderType contentSecurityPolicyType, PassRefPtr<SecurityOrigin> topOrigin) +Ref<DedicatedWorkerGlobalScope> DedicatedWorkerGlobalScope::create(const URL& url, const String& identifier, const String& userAgent, DedicatedWorkerThread& thread, const ContentSecurityPolicyResponseHeaders& contentSecurityPolicyResponseHeaders, bool shouldBypassMainWorldContentSecurityPolicy, Ref<SecurityOrigin>&& topOrigin, MonotonicTime timeOrigin, IDBClient::IDBConnectionProxy* connectionProxy, SocketProvider* socketProvider) { - RefPtr<DedicatedWorkerGlobalScope> context = adoptRef(new DedicatedWorkerGlobalScope(url, userAgent, std::move(settings), thread, topOrigin)); - context->applyContentSecurityPolicyFromString(contentSecurityPolicy, contentSecurityPolicyType); - return context.release(); + auto context = adoptRef(*new DedicatedWorkerGlobalScope(url, identifier, userAgent, thread, shouldBypassMainWorldContentSecurityPolicy, WTFMove(topOrigin), timeOrigin, connectionProxy, socketProvider)); + if (!shouldBypassMainWorldContentSecurityPolicy) + context->applyContentSecurityPolicyResponseHeaders(contentSecurityPolicyResponseHeaders); + return context; } -DedicatedWorkerGlobalScope::DedicatedWorkerGlobalScope(const URL& url, const String& userAgent, std::unique_ptr<GroupSettings> settings, DedicatedWorkerThread* thread, PassRefPtr<SecurityOrigin> topOrigin) - : WorkerGlobalScope(url, userAgent, std::move(settings), thread, topOrigin) +DedicatedWorkerGlobalScope::DedicatedWorkerGlobalScope(const URL& url, const String& identifier, const String& userAgent, DedicatedWorkerThread& thread, bool shouldBypassMainWorldContentSecurityPolicy, Ref<SecurityOrigin>&& topOrigin, MonotonicTime timeOrigin, IDBClient::IDBConnectionProxy* connectionProxy, SocketProvider* socketProvider) + : WorkerGlobalScope(url, identifier, userAgent, thread, shouldBypassMainWorldContentSecurityPolicy, WTFMove(topOrigin), timeOrigin, connectionProxy, socketProvider) { } @@ -60,32 +63,31 @@ EventTargetInterface DedicatedWorkerGlobalScope::eventTargetInterface() const return DedicatedWorkerGlobalScopeEventTargetInterfaceType; } -void DedicatedWorkerGlobalScope::postMessage(PassRefPtr<SerializedScriptValue> message, MessagePort* port, ExceptionCode& ec) +ExceptionOr<void> DedicatedWorkerGlobalScope::postMessage(JSC::ExecState& state, JSC::JSValue messageValue, Vector<JSC::Strong<JSC::JSObject>>&& transfer) { - MessagePortArray ports; - if (port) - ports.append(port); - postMessage(message, &ports, ec); -} + Vector<RefPtr<MessagePort>> ports; + auto message = SerializedScriptValue::create(state, messageValue, WTFMove(transfer), ports, SerializationContext::WorkerPostMessage); + if (message.hasException()) + return message.releaseException(); -void DedicatedWorkerGlobalScope::postMessage(PassRefPtr<SerializedScriptValue> message, const MessagePortArray* ports, ExceptionCode& ec) -{ // Disentangle the port in preparation for sending it to the remote context. - OwnPtr<MessagePortChannelArray> channels = MessagePort::disentanglePorts(ports, ec); - if (ec) - return; - thread()->workerObjectProxy().postMessageToWorkerObject(message, channels.release()); + auto channels = MessagePort::disentanglePorts(WTFMove(ports)); + if (channels.hasException()) + return channels.releaseException(); + thread().workerObjectProxy().postMessageToWorkerObject(message.releaseReturnValue(), channels.releaseReturnValue()); + return { }; } -void DedicatedWorkerGlobalScope::importScripts(const Vector<String>& urls, ExceptionCode& ec) +ExceptionOr<void> DedicatedWorkerGlobalScope::importScripts(const Vector<String>& urls) { - Base::importScripts(urls, ec); - thread()->workerObjectProxy().reportPendingActivity(hasPendingActivity()); + auto result = Base::importScripts(urls); + thread().workerObjectProxy().reportPendingActivity(hasPendingActivity()); + return result; } -DedicatedWorkerThread* DedicatedWorkerGlobalScope::thread() +DedicatedWorkerThread& DedicatedWorkerGlobalScope::thread() { - return static_cast<DedicatedWorkerThread*>(Base::thread()); + return static_cast<DedicatedWorkerThread&>(Base::thread()); } } // namespace WebCore diff --git a/Source/WebCore/workers/DedicatedWorkerGlobalScope.h b/Source/WebCore/workers/DedicatedWorkerGlobalScope.h index 52762c1b9..c86e8de1e 100644 --- a/Source/WebCore/workers/DedicatedWorkerGlobalScope.h +++ b/Source/WebCore/workers/DedicatedWorkerGlobalScope.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2009 Google Inc. All rights reserved. + * Copyright (C) 2016 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 @@ -28,43 +29,40 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef DedicatedWorkerGlobalScope_h -#define DedicatedWorkerGlobalScope_h +#pragma once -#include "ContentSecurityPolicy.h" -#include "MessagePort.h" #include "WorkerGlobalScope.h" -namespace WebCore { - - class DedicatedWorkerThread; +namespace JSC { +class ExecState; +class JSObject; +class JSValue; +} - class DedicatedWorkerGlobalScope : public WorkerGlobalScope { - public: - typedef WorkerGlobalScope Base; - static PassRefPtr<DedicatedWorkerGlobalScope> create(const URL&, const String& userAgent, std::unique_ptr<GroupSettings>, DedicatedWorkerThread*, const String& contentSecurityPolicy, ContentSecurityPolicy::HeaderType contentSecurityPolicyType, PassRefPtr<SecurityOrigin> topOrigin); - virtual ~DedicatedWorkerGlobalScope(); +namespace WebCore { - virtual bool isDedicatedWorkerGlobalScope() const override { return true; } +class ContentSecurityPolicyResponseHeaders; +class DedicatedWorkerThread; +class MessagePort; +class SerializedScriptValue; - // Overridden to allow us to check our pending activity after executing imported script. - virtual void importScripts(const Vector<String>& urls, ExceptionCode&) override; +class DedicatedWorkerGlobalScope final : public WorkerGlobalScope { +public: + static Ref<DedicatedWorkerGlobalScope> create(const URL&, const String& identifier, const String& userAgent, DedicatedWorkerThread&, const ContentSecurityPolicyResponseHeaders&, bool shouldBypassMainWorldContentSecurityPolicy, Ref<SecurityOrigin>&& topOrigin, MonotonicTime timeOrigin, IDBClient::IDBConnectionProxy*, SocketProvider*); + virtual ~DedicatedWorkerGlobalScope(); - // EventTarget - virtual EventTargetInterface eventTargetInterface() const override; + ExceptionOr<void> postMessage(JSC::ExecState&, JSC::JSValue message, Vector<JSC::Strong<JSC::JSObject>>&&); - void postMessage(PassRefPtr<SerializedScriptValue>, const MessagePortArray*, ExceptionCode&); - // Needed for Objective-C bindings (see bug 28774). - void postMessage(PassRefPtr<SerializedScriptValue>, MessagePort*, ExceptionCode&); + DedicatedWorkerThread& thread(); - DEFINE_ATTRIBUTE_EVENT_LISTENER(message); +private: + using Base = WorkerGlobalScope; - DedicatedWorkerThread* thread(); + DedicatedWorkerGlobalScope(const URL&, const String& identifier, const String& userAgent, DedicatedWorkerThread&, bool shouldBypassMainWorldContentSecurityPolicy, Ref<SecurityOrigin>&& topOrigin, MonotonicTime timeOrigin, IDBClient::IDBConnectionProxy*, SocketProvider*); - private: - DedicatedWorkerGlobalScope(const URL&, const String& userAgent, std::unique_ptr<GroupSettings>, DedicatedWorkerThread*, PassRefPtr<SecurityOrigin> topOrigin); - }; + bool isDedicatedWorkerGlobalScope() const final { return true; } + ExceptionOr<void> importScripts(const Vector<String>& urls) final; + EventTargetInterface eventTargetInterface() const final; +}; } // namespace WebCore - -#endif // DedicatedWorkerGlobalScope_h diff --git a/Source/WebCore/workers/DedicatedWorkerGlobalScope.idl b/Source/WebCore/workers/DedicatedWorkerGlobalScope.idl index ce824f662..a080e6847 100644 --- a/Source/WebCore/workers/DedicatedWorkerGlobalScope.idl +++ b/Source/WebCore/workers/DedicatedWorkerGlobalScope.idl @@ -29,21 +29,12 @@ */ [ - GlobalContext=DedicatedWorkerGlobalScope, + CustomProxyToJSObject, + Exposed=DedicatedWorker, + Global=(Worker,DedicatedWorker), JSGenerateToNativeObject, - JSNoStaticTables, ] interface DedicatedWorkerGlobalScope : WorkerGlobalScope { + [CallWith=ScriptState, MayThrowException] void postMessage(any message, optional sequence<object> transfer = []); -#if !defined(LANGUAGE_CPP) || !LANGUAGE_CPP -#if defined(LANGUAGE_JAVASCRIPT) && LANGUAGE_JAVASCRIPT - [Custom, RaisesException] void postMessage(any message, optional Array messagePorts); -#else - // There's no good way to expose an array via the ObjC bindings, so for now just allow passing in a single port. - [RaisesException] void postMessage(DOMString message, optional MessagePort messagePort); -#endif -#endif - - attribute EventListener onmessage; - + attribute EventHandler onmessage; }; - diff --git a/Source/WebCore/workers/DedicatedWorkerThread.cpp b/Source/WebCore/workers/DedicatedWorkerThread.cpp index 1020ce99e..7a51745fe 100644 --- a/Source/WebCore/workers/DedicatedWorkerThread.cpp +++ b/Source/WebCore/workers/DedicatedWorkerThread.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2009 Google Inc. All rights reserved. + * Copyright (C) 2016 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 @@ -29,7 +30,6 @@ */ #include "config.h" - #include "DedicatedWorkerThread.h" #include "DedicatedWorkerGlobalScope.h" @@ -38,13 +38,8 @@ namespace WebCore { -PassRefPtr<DedicatedWorkerThread> DedicatedWorkerThread::create(const URL& scriptURL, const String& userAgent, const GroupSettings* settings, const String& sourceCode, WorkerLoaderProxy& workerLoaderProxy, WorkerObjectProxy& workerObjectProxy, WorkerThreadStartMode startMode, const String& contentSecurityPolicy, ContentSecurityPolicy::HeaderType contentSecurityPolicyType, const SecurityOrigin* topOrigin) -{ - return adoptRef(new DedicatedWorkerThread(scriptURL, userAgent, settings, sourceCode, workerLoaderProxy, workerObjectProxy, startMode, contentSecurityPolicy, contentSecurityPolicyType, topOrigin)); -} - -DedicatedWorkerThread::DedicatedWorkerThread(const URL& url, const String& userAgent, const GroupSettings* settings, const String& sourceCode, WorkerLoaderProxy& workerLoaderProxy, WorkerObjectProxy& workerObjectProxy, WorkerThreadStartMode startMode, const String& contentSecurityPolicy, ContentSecurityPolicy::HeaderType contentSecurityPolicyType, const SecurityOrigin* topOrigin) - : WorkerThread(url, userAgent, settings, sourceCode, workerLoaderProxy, workerObjectProxy, startMode, contentSecurityPolicy, contentSecurityPolicyType, topOrigin) +DedicatedWorkerThread::DedicatedWorkerThread(const URL& url, const String& identifier, const String& userAgent, const String& sourceCode, WorkerLoaderProxy& workerLoaderProxy, WorkerObjectProxy& workerObjectProxy, WorkerThreadStartMode startMode, const ContentSecurityPolicyResponseHeaders& contentSecurityPolicyResponseHeaders, bool shouldBypassMainWorldContentSecurityPolicy, const SecurityOrigin& topOrigin, MonotonicTime timeOrigin, IDBClient::IDBConnectionProxy* connectionProxy, SocketProvider* socketProvider, JSC::RuntimeFlags runtimeFlags) + : WorkerThread(url, identifier, userAgent, sourceCode, workerLoaderProxy, workerObjectProxy, startMode, contentSecurityPolicyResponseHeaders, shouldBypassMainWorldContentSecurityPolicy, topOrigin, timeOrigin, connectionProxy, socketProvider, runtimeFlags) , m_workerObjectProxy(workerObjectProxy) { } @@ -53,9 +48,9 @@ DedicatedWorkerThread::~DedicatedWorkerThread() { } -PassRefPtr<WorkerGlobalScope> DedicatedWorkerThread::createWorkerGlobalScope(const URL& url, const String& userAgent, std::unique_ptr<GroupSettings> settings, const String& contentSecurityPolicy, ContentSecurityPolicy::HeaderType contentSecurityPolicyType, PassRefPtr<SecurityOrigin> topOrigin) +Ref<WorkerGlobalScope> DedicatedWorkerThread::createWorkerGlobalScope(const URL& url, const String& identifier, const String& userAgent, const ContentSecurityPolicyResponseHeaders& contentSecurityPolicyResponseHeaders, bool shouldBypassMainWorldContentSecurityPolicy, Ref<SecurityOrigin>&& topOrigin, MonotonicTime timeOrigin) { - return DedicatedWorkerGlobalScope::create(url, userAgent, std::move(settings), this, contentSecurityPolicy, contentSecurityPolicyType, topOrigin); + return DedicatedWorkerGlobalScope::create(url, identifier, userAgent, *this, contentSecurityPolicyResponseHeaders, shouldBypassMainWorldContentSecurityPolicy, WTFMove(topOrigin), timeOrigin, idbConnectionProxy(), socketProvider()); } void DedicatedWorkerThread::runEventLoop() diff --git a/Source/WebCore/workers/DedicatedWorkerThread.h b/Source/WebCore/workers/DedicatedWorkerThread.h index 4f8750130..7cabd58fd 100644 --- a/Source/WebCore/workers/DedicatedWorkerThread.h +++ b/Source/WebCore/workers/DedicatedWorkerThread.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2009 Google Inc. All rights reserved. + * Copyright (C) 2016 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 @@ -27,31 +28,34 @@ * (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 DedicatedWorkerThread_h -#define DedicatedWorkerThread_h -#include "ContentSecurityPolicy.h" +#pragma once + #include "WorkerThread.h" namespace WebCore { - class WorkerObjectProxy; +class ContentSecurityPolicyResponseHeaders; +class WorkerObjectProxy; - class DedicatedWorkerThread : public WorkerThread { - public: - static PassRefPtr<DedicatedWorkerThread> create(const URL& scriptURL, const String& userAgent, const GroupSettings*, const String& sourceCode, WorkerLoaderProxy&, WorkerObjectProxy&, WorkerThreadStartMode, const String& contentSecurityPolicy, ContentSecurityPolicy::HeaderType, const SecurityOrigin* topOrigin); - WorkerObjectProxy& workerObjectProxy() const { return m_workerObjectProxy; } - virtual ~DedicatedWorkerThread(); +class DedicatedWorkerThread : public WorkerThread { +public: + template<typename... Args> static Ref<DedicatedWorkerThread> create(Args&&... args) + { + return adoptRef(*new DedicatedWorkerThread(std::forward<Args>(args)...)); + } + virtual ~DedicatedWorkerThread(); - protected: - virtual PassRefPtr<WorkerGlobalScope> createWorkerGlobalScope(const URL&, const String& userAgent, std::unique_ptr<GroupSettings>, const String& contentSecurityPolicy, ContentSecurityPolicy::HeaderType, PassRefPtr<SecurityOrigin> topOrigin) override; - virtual void runEventLoop() override; + WorkerObjectProxy& workerObjectProxy() const { return m_workerObjectProxy; } - private: - DedicatedWorkerThread(const URL&, const String& userAgent, const GroupSettings*, const String& sourceCode, WorkerLoaderProxy&, WorkerObjectProxy&, WorkerThreadStartMode, const String& contentSecurityPolicy, ContentSecurityPolicy::HeaderType, const SecurityOrigin* topOrigin); +protected: + Ref<WorkerGlobalScope> createWorkerGlobalScope(const URL&, const String& identifier, const String& userAgent, const ContentSecurityPolicyResponseHeaders&, bool shouldBypassMainWorldContentSecurityPolicy, Ref<SecurityOrigin>&& topOrigin, MonotonicTime timeOrigin) override; + void runEventLoop() override; - WorkerObjectProxy& m_workerObjectProxy; - }; -} // namespace WebCore +private: + DedicatedWorkerThread(const URL&, const String& identifier, const String& userAgent, const String& sourceCode, WorkerLoaderProxy&, WorkerObjectProxy&, WorkerThreadStartMode, const ContentSecurityPolicyResponseHeaders&, bool shouldBypassMainWorldContentSecurityPolicy, const SecurityOrigin& topOrigin, MonotonicTime timeOrigin, IDBClient::IDBConnectionProxy*, SocketProvider*, JSC::RuntimeFlags); -#endif // DedicatedWorkerThread_h + WorkerObjectProxy& m_workerObjectProxy; +}; + +} // namespace WebCore diff --git a/Source/WebCore/workers/DefaultSharedWorkerRepository.cpp b/Source/WebCore/workers/DefaultSharedWorkerRepository.cpp deleted file mode 100644 index a64a4c90c..000000000 --- a/Source/WebCore/workers/DefaultSharedWorkerRepository.cpp +++ /dev/null @@ -1,452 +0,0 @@ -/* - * 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(SHARED_WORKERS) - -#include "DefaultSharedWorkerRepository.h" - -#include "ActiveDOMObject.h" -#include "CrossThreadTask.h" -#include "Document.h" -#include "ExceptionCode.h" -#include "InspectorInstrumentation.h" -#include "MessageEvent.h" -#include "MessagePort.h" -#include "NotImplemented.h" -#include "PageGroup.h" -#include "PlatformStrategies.h" -#include "ScriptCallStack.h" -#include "SecurityOrigin.h" -#include "SecurityOriginHash.h" -#include "SharedWorker.h" -#include "SharedWorkerGlobalScope.h" -#include "SharedWorkerRepository.h" -#include "SharedWorkerStrategy.h" -#include "SharedWorkerThread.h" -#include "WorkerLoaderProxy.h" -#include "WorkerReportingProxy.h" -#include "WorkerScriptLoader.h" -#include "WorkerScriptLoaderClient.h" -#include <mutex> -#include <wtf/HashSet.h> -#include <wtf/Threading.h> -#include <wtf/text/WTFString.h> - -namespace WebCore { - -class SharedWorkerProxy : public ThreadSafeRefCounted<SharedWorkerProxy>, public WorkerLoaderProxy, public WorkerReportingProxy { -public: - static PassRefPtr<SharedWorkerProxy> create(const String& name, const URL& url, PassRefPtr<SecurityOrigin> origin) { return adoptRef(new SharedWorkerProxy(name, url, origin)); } - - void setThread(PassRefPtr<SharedWorkerThread> thread) { m_thread = thread; } - SharedWorkerThread* thread() { return m_thread.get(); } - bool isClosing() const { return m_closing; } - URL url() const - { - // Don't use m_url.copy() because it isn't a threadsafe method. - return URL(ParsedURLString, m_url.string().isolatedCopy()); - } - - String name() const { return m_name.isolatedCopy(); } - bool matches(const String& name, PassRefPtr<SecurityOrigin> origin, const URL& urlToMatch) const; - - // WorkerLoaderProxy - virtual void postTaskToLoader(PassOwnPtr<ScriptExecutionContext::Task>); - virtual bool postTaskForModeToWorkerGlobalScope(PassOwnPtr<ScriptExecutionContext::Task>, const String&); - - // WorkerReportingProxy - virtual void postExceptionToWorkerObject(const String& errorMessage, int lineNumber, int columnNumber, const String& sourceURL); - virtual void postConsoleMessageToWorkerObject(MessageSource, MessageLevel, const String& message, int lineNumber, int columnNumber, const String& sourceURL); -#if ENABLE(INSPECTOR) - virtual void postMessageToPageInspector(const String&); -#endif - virtual void workerGlobalScopeClosed(); - virtual void workerGlobalScopeDestroyed(); - - // Updates the list of the worker's documents, per section 4.5 of the WebWorkers spec. - void addToWorkerDocuments(ScriptExecutionContext*); - - bool isInWorkerDocuments(Document* document) { return m_workerDocuments.contains(document); } - - // Removes a detached document from the list of worker's documents. May set the closing flag if this is the last document in the list. - void documentDetached(Document*); - - GroupSettings* groupSettings() const; // Page GroupSettings used by worker thread. - -private: - SharedWorkerProxy(const String& name, const URL&, PassRefPtr<SecurityOrigin>); - void close(); - - bool m_closing; - String m_name; - URL m_url; - // The thread is freed when the proxy is destroyed, so we need to make sure that the proxy stays around until the SharedWorkerGlobalScope exits. - RefPtr<SharedWorkerThread> m_thread; - RefPtr<SecurityOrigin> m_origin; - HashSet<Document*> m_workerDocuments; - // Ensures exclusive access to the worker documents. Must not grab any other locks (such as the DefaultSharedWorkerRepository lock) while holding this one. - Mutex m_workerDocumentsLock; -}; - -SharedWorkerProxy::SharedWorkerProxy(const String& name, const URL& url, PassRefPtr<SecurityOrigin> origin) - : m_closing(false) - , m_name(name.isolatedCopy()) - , m_url(url.copy()) - , m_origin(origin) -{ - // We should be the sole owner of the SecurityOrigin, as we will free it on another thread. - ASSERT(m_origin->hasOneRef()); -} - -bool SharedWorkerProxy::matches(const String& name, PassRefPtr<SecurityOrigin> origin, const URL& urlToMatch) const -{ - // If the origins don't match, or the names don't match, then this is not the proxy we are looking for. - if (!origin->equal(m_origin.get())) - return false; - - // If the names are both empty, compares the URLs instead per the Web Workers spec. - if (name.isEmpty() && m_name.isEmpty()) - return urlToMatch == url(); - - return name == m_name; -} - -void SharedWorkerProxy::postTaskToLoader(PassOwnPtr<ScriptExecutionContext::Task> task) -{ - MutexLocker lock(m_workerDocumentsLock); - - if (isClosing()) - return; - - // If we aren't closing, then we must have at least one document. - ASSERT(m_workerDocuments.size()); - - // Just pick an arbitrary active document from the HashSet and pass load requests to it. - // FIXME: Do we need to deal with the case where the user closes the document mid-load, via a shadow document or some other solution? - Document* document = *(m_workerDocuments.begin()); - document->postTask(task); -} - -bool SharedWorkerProxy::postTaskForModeToWorkerGlobalScope(PassOwnPtr<ScriptExecutionContext::Task> task, const String& mode) -{ - if (isClosing()) - return false; - ASSERT(m_thread); - m_thread->runLoop().postTaskForMode(task, mode); - return true; -} - -GroupSettings* SharedWorkerProxy::groupSettings() const -{ - if (isClosing()) - return 0; - ASSERT(m_workerDocuments.size()); - // Just pick the first active document, and use the groupsettings of that page. - Document* document = *(m_workerDocuments.begin()); - if (document->page()) - return &document->page()->group().groupSettings(); - - return 0; -} - -static void postExceptionTask(ScriptExecutionContext* context, const String& errorMessage, int lineNumber, int columnNumber, const String& sourceURL) -{ - context->reportException(errorMessage, lineNumber, columnNumber, sourceURL, 0); -} - -void SharedWorkerProxy::postExceptionToWorkerObject(const String& errorMessage, int lineNumber, int columnNumber, const String& sourceURL) -{ - MutexLocker lock(m_workerDocumentsLock); - for (HashSet<Document*>::iterator iter = m_workerDocuments.begin(); iter != m_workerDocuments.end(); ++iter) - (*iter)->postTask(createCallbackTask(&postExceptionTask, errorMessage, lineNumber, columnNumber, sourceURL)); -} - -static void postConsoleMessageTask(ScriptExecutionContext* document, MessageSource source, MessageLevel level, const String& message, const String& sourceURL, unsigned lineNumber, unsigned columnNumber) -{ - document->addConsoleMessage(source, level, message, sourceURL, lineNumber, columnNumber); -} - -void SharedWorkerProxy::postConsoleMessageToWorkerObject(MessageSource source, MessageLevel level, const String& message, int lineNumber, int columnNumber, const String& sourceURL) -{ - MutexLocker lock(m_workerDocumentsLock); - for (HashSet<Document*>::iterator iter = m_workerDocuments.begin(); iter != m_workerDocuments.end(); ++iter) - (*iter)->postTask(createCallbackTask(&postConsoleMessageTask, source, level, message, sourceURL, lineNumber, columnNumber)); -} - -#if ENABLE(INSPECTOR) -void SharedWorkerProxy::postMessageToPageInspector(const String&) -{ - notImplemented(); -} -#endif - -void SharedWorkerProxy::workerGlobalScopeClosed() -{ - if (isClosing()) - return; - close(); -} - -void SharedWorkerProxy::workerGlobalScopeDestroyed() -{ - // The proxy may be freed by this call, so do not reference it any further. - DefaultSharedWorkerRepository::instance().removeProxy(this); -} - -void SharedWorkerProxy::addToWorkerDocuments(ScriptExecutionContext* context) -{ - // Nested workers are not yet supported, so passed-in context should always be a Document. - ASSERT_WITH_SECURITY_IMPLICATION(context->isDocument()); - ASSERT(!isClosing()); - MutexLocker lock(m_workerDocumentsLock); - Document* document = static_cast<Document*>(context); - m_workerDocuments.add(document); -} - -void SharedWorkerProxy::documentDetached(Document* document) -{ - if (isClosing()) - return; - // Remove the document from our set (if it's there) and if that was the last document in the set, mark the proxy as closed. - MutexLocker lock(m_workerDocumentsLock); - m_workerDocuments.remove(document); - if (!m_workerDocuments.size()) - close(); -} - -void SharedWorkerProxy::close() -{ - ASSERT(!isClosing()); - m_closing = true; - // Stop the worker thread - the proxy will stay around until we get workerThreadExited() notification. - if (m_thread) - m_thread->stop(); -} - -class SharedWorkerConnectTask : public ScriptExecutionContext::Task { -public: - static PassOwnPtr<SharedWorkerConnectTask> create(PassOwnPtr<MessagePortChannel> channel) - { - return adoptPtr(new SharedWorkerConnectTask(channel)); - } - -private: - SharedWorkerConnectTask(PassOwnPtr<MessagePortChannel> channel) - : m_channel(channel) - { - } - - virtual void performTask(ScriptExecutionContext* scriptContext) - { - RefPtr<MessagePort> port = MessagePort::create(*scriptContext); - port->entangle(m_channel.release()); - ASSERT_WITH_SECURITY_IMPLICATION(scriptContext->isWorkerGlobalScope()); - WorkerGlobalScope* workerGlobalScope = static_cast<WorkerGlobalScope*>(scriptContext); - // Since close() stops the thread event loop, this should not ever get called while closing. - ASSERT(!workerGlobalScope->isClosing()); - ASSERT_WITH_SECURITY_IMPLICATION(workerGlobalScope->isSharedWorkerGlobalScope()); - workerGlobalScope->dispatchEvent(createConnectEvent(port)); - } - - OwnPtr<MessagePortChannel> m_channel; -}; - -// Loads the script on behalf of a worker. -class SharedWorkerScriptLoader : public RefCounted<SharedWorkerScriptLoader>, private WorkerScriptLoaderClient { -public: - SharedWorkerScriptLoader(PassRefPtr<SharedWorker>, PassOwnPtr<MessagePortChannel>, PassRefPtr<SharedWorkerProxy>); - void load(const URL&); - -private: - // WorkerScriptLoaderClient callbacks - virtual void didReceiveResponse(unsigned long identifier, const ResourceResponse&); - virtual void notifyFinished(); - - RefPtr<SharedWorker> m_worker; - OwnPtr<MessagePortChannel> m_port; - RefPtr<SharedWorkerProxy> m_proxy; - RefPtr<WorkerScriptLoader> m_scriptLoader; -}; - -SharedWorkerScriptLoader::SharedWorkerScriptLoader(PassRefPtr<SharedWorker> worker, PassOwnPtr<MessagePortChannel> port, PassRefPtr<SharedWorkerProxy> proxy) - : m_worker(worker) - , m_port(port) - , m_proxy(proxy) -{ -} - -void SharedWorkerScriptLoader::load(const URL& url) -{ - // Stay alive (and keep the SharedWorker and JS wrapper alive) until the load finishes. - this->ref(); - m_worker->setPendingActivity(m_worker.get()); - - // Mark this object as active for the duration of the load. - m_scriptLoader = WorkerScriptLoader::create(); - m_scriptLoader->loadAsynchronously(m_worker->scriptExecutionContext(), url, DenyCrossOriginRequests, this); -} - -void SharedWorkerScriptLoader::didReceiveResponse(unsigned long identifier, const ResourceResponse&) -{ - InspectorInstrumentation::didReceiveScriptResponse(m_worker->scriptExecutionContext(), identifier); -} - -void SharedWorkerScriptLoader::notifyFinished() -{ - // FIXME: This method is not guaranteed to be invoked if we are loading from WorkerGlobalScope (see comment for WorkerScriptLoaderClient::notifyFinished()). - // We need to address this before supporting nested workers. - - // Hand off the just-loaded code to the repository to start up the worker thread. - if (m_scriptLoader->failed()) - m_worker->dispatchEvent(Event::create(eventNames().errorEvent, false, true)); - else { - InspectorInstrumentation::scriptImported(m_worker->scriptExecutionContext(), m_scriptLoader->identifier(), m_scriptLoader->script()); - DefaultSharedWorkerRepository::instance().workerScriptLoaded(*m_proxy, m_worker->scriptExecutionContext()->userAgent(m_scriptLoader->url()), - m_scriptLoader->script(), m_port.release(), - m_worker->scriptExecutionContext()->contentSecurityPolicy()->deprecatedHeader(), - m_worker->scriptExecutionContext()->contentSecurityPolicy()->deprecatedHeaderType()); - } - m_worker->unsetPendingActivity(m_worker.get()); - this->deref(); // This frees this object - must be the last action in this function. -} - -DefaultSharedWorkerRepository& DefaultSharedWorkerRepository::instance() -{ - static std::once_flag onceFlag; - static DefaultSharedWorkerRepository* instance; - std::call_once(onceFlag, []{ - instance = new DefaultSharedWorkerRepository; - }); - - return *instance; -} - -bool DefaultSharedWorkerRepository::isAvailable() -{ - return platformStrategies()->sharedWorkerStrategy()->isAvailable(); -} - -void DefaultSharedWorkerRepository::workerScriptLoaded(SharedWorkerProxy& proxy, const String& userAgent, const String& workerScript, PassOwnPtr<MessagePortChannel> port, const String& contentSecurityPolicy, ContentSecurityPolicy::HeaderType contentSecurityPolicyType) -{ - MutexLocker lock(m_lock); - if (proxy.isClosing()) - return; - - // Another loader may have already started up a thread for this proxy - if so, just send a connect to the pre-existing thread. - if (!proxy.thread()) { - RefPtr<SharedWorkerThread> thread = SharedWorkerThread::create(proxy.name(), proxy.url(), userAgent, proxy.groupSettings(), workerScript, proxy, proxy, DontPauseWorkerGlobalScopeOnStart, contentSecurityPolicy, contentSecurityPolicyType); - proxy.setThread(thread); - thread->start(); - } - proxy.thread()->runLoop().postTask(SharedWorkerConnectTask::create(port)); -} - -bool DefaultSharedWorkerRepository::hasSharedWorkers(Document* document) -{ - MutexLocker lock(m_lock); - for (unsigned i = 0; i < m_proxies.size(); i++) { - if (m_proxies[i]->isInWorkerDocuments(document)) - return true; - } - return false; -} - -void DefaultSharedWorkerRepository::removeProxy(SharedWorkerProxy* proxy) -{ - MutexLocker lock(m_lock); - for (unsigned i = 0; i < m_proxies.size(); i++) { - if (proxy == m_proxies[i].get()) { - m_proxies.remove(i); - return; - } - } -} - -void DefaultSharedWorkerRepository::documentDetached(Document* document) -{ - MutexLocker lock(m_lock); - for (unsigned i = 0; i < m_proxies.size(); i++) - m_proxies[i]->documentDetached(document); -} - -void DefaultSharedWorkerRepository::connectToWorker(PassRefPtr<SharedWorker> worker, PassOwnPtr<MessagePortChannel> port, const URL& url, const String& name, ExceptionCode& ec) -{ - MutexLocker lock(m_lock); - ASSERT(worker->scriptExecutionContext()->securityOrigin()->canAccess(SecurityOrigin::create(url).get())); - // Fetch a proxy corresponding to this SharedWorker. - RefPtr<SharedWorkerProxy> proxy = getProxy(name, url); - - // FIXME: Why is this done even if we are raising an exception below? - proxy->addToWorkerDocuments(worker->scriptExecutionContext()); - - if (proxy->url() != url) { - // Proxy already existed under alternate URL - return an error. - ec = URL_MISMATCH_ERR; - return; - } - // If proxy is already running, just connect to it - otherwise, kick off a loader to load the script. - if (proxy->thread()) - proxy->thread()->runLoop().postTask(SharedWorkerConnectTask::create(port)); - else { - RefPtr<SharedWorkerScriptLoader> loader = adoptRef(new SharedWorkerScriptLoader(worker, port, proxy.release())); - loader->load(url); - } -} - -// Creates a new SharedWorkerProxy or returns an existing one from the repository. Must only be called while the repository mutex is held. -PassRefPtr<SharedWorkerProxy> DefaultSharedWorkerRepository::getProxy(const String& name, const URL& url) -{ - // Look for an existing worker, and create one if it doesn't exist. - // Items in the cache are freed on another thread, so do a threadsafe copy of the URL before creating the origin, - // to make sure no references to external strings linger. - RefPtr<SecurityOrigin> origin = SecurityOrigin::create(URL(ParsedURLString, url.string().isolatedCopy())); - for (unsigned i = 0; i < m_proxies.size(); i++) { - if (!m_proxies[i]->isClosing() && m_proxies[i]->matches(name, origin, url)) - return m_proxies[i]; - } - // Proxy is not in the repository currently - create a new one. - RefPtr<SharedWorkerProxy> proxy = SharedWorkerProxy::create(name, url, origin.release()); - m_proxies.append(proxy); - return proxy.release(); -} - -DefaultSharedWorkerRepository::DefaultSharedWorkerRepository() -{ -} - -DefaultSharedWorkerRepository::~DefaultSharedWorkerRepository() -{ -} - -} // namespace WebCore - -#endif // ENABLE(SHARED_WORKERS) diff --git a/Source/WebCore/workers/DefaultSharedWorkerRepository.h b/Source/WebCore/workers/DefaultSharedWorkerRepository.h deleted file mode 100644 index d2629524e..000000000 --- a/Source/WebCore/workers/DefaultSharedWorkerRepository.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - * 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 DefaultSharedWorkerRepository_h -#define DefaultSharedWorkerRepository_h - -#if ENABLE(SHARED_WORKERS) - -#include "ContentSecurityPolicy.h" -#include <wtf/Forward.h> -#include <wtf/HashMap.h> -#include <wtf/Noncopyable.h> -#include <wtf/PassOwnPtr.h> -#include <wtf/PassRefPtr.h> -#include <wtf/RefPtr.h> -#include <wtf/Threading.h> -#include <wtf/text/StringHash.h> - -namespace WebCore { - - class Document; - class URL; - class MessagePortChannel; - class ScriptExecutionContext; - class SharedWorker; - class SharedWorkerProxy; - - typedef int ExceptionCode; - - // Platform-specific implementation of the SharedWorkerRepository static interface. - class DefaultSharedWorkerRepository { - WTF_MAKE_NONCOPYABLE(DefaultSharedWorkerRepository); WTF_MAKE_FAST_ALLOCATED; - public: - // Returns true if the platform supports SharedWorkers, otherwise false. - static bool isAvailable(); - - // Invoked once the worker script has been loaded to fire up the worker thread. - void workerScriptLoaded(SharedWorkerProxy&, const String& userAgent, const String& workerScript, PassOwnPtr<MessagePortChannel>, const String& contentSecurityPolicy, ContentSecurityPolicy::HeaderType); - - // Internal implementation of SharedWorkerRepository::connect() - void connectToWorker(PassRefPtr<SharedWorker>, PassOwnPtr<MessagePortChannel>, const URL&, const String& name, ExceptionCode&); - - // Notification that a document has been detached. - void documentDetached(Document*); - - // Removes the passed SharedWorkerProxy from the repository. - void removeProxy(SharedWorkerProxy*); - - bool hasSharedWorkers(Document*); - - static DefaultSharedWorkerRepository& instance(); - private: - DefaultSharedWorkerRepository(); - ~DefaultSharedWorkerRepository(); - - PassRefPtr<SharedWorkerProxy> getProxy(const String& name, const URL&); - // Mutex used to protect internal data structures. - Mutex m_lock; - - // List of shared workers. Expectation is that there will be a limited number of shared workers, and so tracking them in a Vector is more efficient than nested HashMaps. - typedef Vector<RefPtr<SharedWorkerProxy>> SharedWorkerProxyRepository; - SharedWorkerProxyRepository m_proxies; - }; - -} // namespace WebCore - -#endif // ENABLE(SHARED_WORKERS) - -#endif // DefaultSharedWorkerRepository_h diff --git a/Source/WebCore/workers/SharedWorker.cpp b/Source/WebCore/workers/SharedWorker.cpp deleted file mode 100644 index 634b4d012..000000000 --- a/Source/WebCore/workers/SharedWorker.cpp +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (C) 2009 Google Inc. All rights reserved. - * Copyright (C) 2010 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: - * - * * 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(SHARED_WORKERS) - -#include "SharedWorker.h" - -#include "ExceptionCode.h" -#include "FeatureObserver.h" -#include "InspectorInstrumentation.h" -#include "URL.h" -#include "MessageChannel.h" -#include "MessagePort.h" -#include "ScriptExecutionContext.h" -#include "SecurityOrigin.h" -#include "SharedWorkerRepository.h" - -namespace WebCore { - -inline SharedWorker::SharedWorker(ScriptExecutionContext& context) - : AbstractWorker(context) -{ -} - -PassRefPtr<SharedWorker> SharedWorker::create(ScriptExecutionContext& context, const String& url, const String& name, ExceptionCode& ec) -{ - ASSERT(isMainThread()); - - // We don't currently support nested workers, so workers can only be created from documents. - ASSERT_WITH_SECURITY_IMPLICATION(context.isDocument()); - Document& document = static_cast<Document&>(context); - - FeatureObserver::observe(document.domWindow(), FeatureObserver::SharedWorkerStart); - - RefPtr<SharedWorker> worker = adoptRef(new SharedWorker(context)); - - RefPtr<MessageChannel> channel = MessageChannel::create(context); - worker->m_port = channel->port1(); - OwnPtr<MessagePortChannel> remotePort = channel->port2()->disentangle(); - ASSERT(remotePort); - - worker->suspendIfNeeded(); - - URL scriptURL = worker->resolveURL(url, ec); - if (scriptURL.isEmpty()) - return 0; - - if (!document.securityOrigin()->canAccessSharedWorkers(document.topOrigin())) { - ec = SECURITY_ERR; - return 0; - } - - SharedWorkerRepository::connect(worker.get(), remotePort.release(), scriptURL, name, ec); - - return worker.release(); -} - -SharedWorker::~SharedWorker() -{ -} - -} // namespace WebCore - -#endif // ENABLE(SHARED_WORKERS) diff --git a/Source/WebCore/workers/SharedWorker.h b/Source/WebCore/workers/SharedWorker.h deleted file mode 100644 index 96c540a80..000000000 --- a/Source/WebCore/workers/SharedWorker.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (C) 2009 Google Inc. All rights reserved. - * Copyright (C) 2010 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: - * - * * 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 SharedWorker_h -#define SharedWorker_h - -#include "AbstractWorker.h" - -#if ENABLE(SHARED_WORKERS) - -namespace WebCore { - - class SharedWorker final : public AbstractWorker { - public: - static PassRefPtr<SharedWorker> create(ScriptExecutionContext&, const String& url, const String& name, ExceptionCode&); - virtual ~SharedWorker(); - - MessagePort* port() const { return m_port.get(); } - - virtual EventTargetInterface eventTargetInterface() const override { return SharedWorkerEventTargetInterfaceType; } - - private: - explicit SharedWorker(ScriptExecutionContext&); - - RefPtr<MessagePort> m_port; - }; - -} // namespace WebCore - -#endif // ENABLE(SHARED_WORKERS) - -#endif // SharedWorker_h diff --git a/Source/WebCore/workers/SharedWorker.idl b/Source/WebCore/workers/SharedWorker.idl deleted file mode 100644 index afa483164..000000000 --- a/Source/WebCore/workers/SharedWorker.idl +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2009 Google Inc. All rights reserved. - * Copyright (C) 2010 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: - * - * * 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. - */ - -[ - EnabledAtRuntime, - Conditional=SHARED_WORKERS, - CustomConstructor(DOMString scriptURL, [Default=NullString] optional DOMString name), - JSCustomMarkFunction, - JSGenerateToNativeObject, - JSGenerateToJSObject, - ActiveDOMObject -] interface SharedWorker : EventTarget { - readonly attribute MessagePort port; -}; - -SharedWorker implements AbstractWorker; - diff --git a/Source/WebCore/workers/SharedWorkerGlobalScope.cpp b/Source/WebCore/workers/SharedWorkerGlobalScope.cpp deleted file mode 100644 index 138bfac71..000000000 --- a/Source/WebCore/workers/SharedWorkerGlobalScope.cpp +++ /dev/null @@ -1,91 +0,0 @@ -/* - * 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(SHARED_WORKERS) - -#include "SharedWorkerGlobalScope.h" - -#include "DOMWindow.h" -#include "EventNames.h" -#include "MessageEvent.h" -#include "NotImplemented.h" -#include "ScriptCallStack.h" -#include "SecurityOrigin.h" -#include "SharedWorkerThread.h" - -namespace WebCore { - -PassRefPtr<MessageEvent> createConnectEvent(PassRefPtr<MessagePort> prpPort) -{ - RefPtr<MessagePort> port = prpPort; - RefPtr<MessageEvent> event = MessageEvent::create(adoptPtr(new MessagePortArray(1, port)), Deprecated::ScriptValue(), String(), String(), port); - event->initEvent(eventNames().connectEvent, false, false); - return event.release(); -} - -// static -PassRefPtr<SharedWorkerGlobalScope> SharedWorkerGlobalScope::create(const String& name, const URL& url, const String& userAgent, std::unique_ptr<GroupSettings> settings, SharedWorkerThread* thread, const String& contentSecurityPolicy, ContentSecurityPolicy::HeaderType contentSecurityPolicyType) -{ - RefPtr<SharedWorkerGlobalScope> context = adoptRef(new SharedWorkerGlobalScope(name, url, userAgent, std::move(settings), thread)); - context->applyContentSecurityPolicyFromString(contentSecurityPolicy, contentSecurityPolicyType); - return context.release(); -} - -SharedWorkerGlobalScope::SharedWorkerGlobalScope(const String& name, const URL& url, const String& userAgent, std::unique_ptr<GroupSettings> settings, SharedWorkerThread* thread) - : WorkerGlobalScope(url, userAgent, std::move(settings), thread, 0) - , m_name(name) -{ -} - -SharedWorkerGlobalScope::~SharedWorkerGlobalScope() -{ -} - -EventTargetInterface SharedWorkerGlobalScope::eventTargetInterface() const -{ - return SharedWorkerGlobalScopeEventTargetInterfaceType; -} - -SharedWorkerThread* SharedWorkerGlobalScope::thread() -{ - return static_cast<SharedWorkerThread*>(Base::thread()); -} - -void SharedWorkerGlobalScope::logExceptionToConsole(const String& errorMessage, const String& sourceURL, int lineNumber, int columnNumber, PassRefPtr<ScriptCallStack> callStack) -{ - WorkerGlobalScope::logExceptionToConsole(errorMessage, sourceURL, lineNumber, columnNumber, callStack); - addMessageToWorkerConsole(JSMessageSource, ErrorMessageLevel, errorMessage, sourceURL, lineNumber, columnNumber, callStack); -} - -} // namespace WebCore - -#endif // ENABLE(SHARED_WORKERS) diff --git a/Source/WebCore/workers/SharedWorkerGlobalScope.h b/Source/WebCore/workers/SharedWorkerGlobalScope.h deleted file mode 100644 index ce6870267..000000000 --- a/Source/WebCore/workers/SharedWorkerGlobalScope.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * 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 SharedWorkerGlobalScope_h -#define SharedWorkerGlobalScope_h - -#if ENABLE(SHARED_WORKERS) - -#include "ContentSecurityPolicy.h" -#include "WorkerGlobalScope.h" - -namespace WebCore { - - class MessageEvent; - class SharedWorkerThread; - - class SharedWorkerGlobalScope : public WorkerGlobalScope { - public: - typedef WorkerGlobalScope Base; - static PassRefPtr<SharedWorkerGlobalScope> create(const String& name, const URL&, const String& userAgent, std::unique_ptr<GroupSettings>, SharedWorkerThread*, const String& contentSecurityPolicy, ContentSecurityPolicy::HeaderType contentSecurityPolicyType); - virtual ~SharedWorkerGlobalScope(); - - virtual bool isSharedWorkerGlobalScope() const override { return true; } - - // EventTarget - virtual EventTargetInterface eventTargetInterface() const override; - - // Setters/Getters for attributes in SharedWorkerGlobalScope.idl - DEFINE_ATTRIBUTE_EVENT_LISTENER(connect); - String name() const { return m_name; } - - SharedWorkerThread* thread(); - - private: - SharedWorkerGlobalScope(const String& name, const URL&, const String& userAgent, std::unique_ptr<GroupSettings>, SharedWorkerThread*); - virtual void logExceptionToConsole(const String& errorMessage, const String& sourceURL, int lineNumber, int columnNumber, PassRefPtr<ScriptCallStack>) override; - - String m_name; - }; - - PassRefPtr<MessageEvent> createConnectEvent(PassRefPtr<MessagePort>); - -} // namespace WebCore - -#endif // ENABLE(SHARED_WORKERS) - -#endif // SharedWorkerGlobalScope_h diff --git a/Source/WebCore/workers/SharedWorkerGlobalScope.idl b/Source/WebCore/workers/SharedWorkerGlobalScope.idl deleted file mode 100644 index 2a17c4fa7..000000000 --- a/Source/WebCore/workers/SharedWorkerGlobalScope.idl +++ /dev/null @@ -1,42 +0,0 @@ -/* - * 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. - */ - -[ - GlobalContext=SharedWorkerGlobalScope, - Conditional=SHARED_WORKERS, - JSGenerateToNativeObject, - JSNoStaticTables, -] interface SharedWorkerGlobalScope : WorkerGlobalScope { - - readonly attribute DOMString name; - attribute EventListener onconnect; - -}; - diff --git a/Source/WebCore/workers/SharedWorkerRepository.cpp b/Source/WebCore/workers/SharedWorkerRepository.cpp deleted file mode 100644 index a3cda5b50..000000000 --- a/Source/WebCore/workers/SharedWorkerRepository.cpp +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2012 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 INC. 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 INC. 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. - */ - -#include "config.h" - -#if ENABLE(SHARED_WORKERS) - -#include "SharedWorkerRepository.h" - -#include "DefaultSharedWorkerRepository.h" -#include "MessagePortChannel.h" -#include "SharedWorker.h" - -namespace WebCore { - -bool SharedWorkerRepository::isAvailable() -{ - return DefaultSharedWorkerRepository::instance().isAvailable(); -} - -void SharedWorkerRepository::connect(PassRefPtr<SharedWorker> worker, PassOwnPtr<MessagePortChannel> port, const URL& url, const String& name, ExceptionCode& ec) -{ - DefaultSharedWorkerRepository::instance().connectToWorker(worker, port, url, name, ec); -} - -void SharedWorkerRepository::documentDetached(Document* document) -{ - DefaultSharedWorkerRepository::instance().documentDetached(document); -} - -bool SharedWorkerRepository::hasSharedWorkers(Document* document) -{ - return DefaultSharedWorkerRepository::instance().hasSharedWorkers(document); -} - -} - -#endif diff --git a/Source/WebCore/workers/SharedWorkerRepository.h b/Source/WebCore/workers/SharedWorkerRepository.h deleted file mode 100644 index 049f86ac9..000000000 --- a/Source/WebCore/workers/SharedWorkerRepository.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * 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 SharedWorkerRepository_h -#define SharedWorkerRepository_h - -#if ENABLE(SHARED_WORKERS) - -#include <wtf/Forward.h> -#include <wtf/PassOwnPtr.h> -#include <wtf/PassRefPtr.h> - -namespace WebCore { - - class Document; - class URL; - class MessagePortChannel; - class SharedWorker; - - typedef int ExceptionCode; - - // Interface to a repository which manages references to the set of active shared workers. - class SharedWorkerRepository { - public: - // Returns true if the platform supports SharedWorkers, otherwise false. - static bool isAvailable(); - - // Connects the passed SharedWorker object with the specified worker thread, creating a new thread if necessary. - static void connect(PassRefPtr<SharedWorker>, PassOwnPtr<MessagePortChannel>, const URL&, const String& name, ExceptionCode&); - - // Invoked when a document has been detached. - static void documentDetached(Document*); - - // Returns true if the passed document is associated with any SharedWorkers. - static bool hasSharedWorkers(Document*); - private: - SharedWorkerRepository() { } - }; - -} // namespace WebCore - -#endif // ENABLE(SHARED_WORKERS) - -#endif // SharedWorkerRepository_h diff --git a/Source/WebCore/workers/SharedWorkerThread.cpp b/Source/WebCore/workers/SharedWorkerThread.cpp deleted file mode 100644 index 9d6ea5c3b..000000000 --- a/Source/WebCore/workers/SharedWorkerThread.cpp +++ /dev/null @@ -1,63 +0,0 @@ -/* - * 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(SHARED_WORKERS) - -#include "SecurityOrigin.h" -#include "SharedWorkerThread.h" -#include "SharedWorkerGlobalScope.h" - -namespace WebCore { - -PassRefPtr<SharedWorkerThread> SharedWorkerThread::create(const String& name, const URL& scriptURL, const String& userAgent, const GroupSettings* settings, const String& sourceCode, WorkerLoaderProxy& workerLoaderProxy, WorkerReportingProxy& workerReportingProxy, WorkerThreadStartMode startMode, const String& contentSecurityPolicy, ContentSecurityPolicy::HeaderType contentSecurityPolicyType) -{ - return adoptRef(new SharedWorkerThread(name, scriptURL, userAgent, settings, sourceCode, workerLoaderProxy, workerReportingProxy, startMode, contentSecurityPolicy, contentSecurityPolicyType)); -} - -SharedWorkerThread::SharedWorkerThread(const String& name, const URL& url, const String& userAgent, const GroupSettings* settings, const String& sourceCode, WorkerLoaderProxy& workerLoaderProxy, WorkerReportingProxy& workerReportingProxy, WorkerThreadStartMode startMode, const String& contentSecurityPolicy, ContentSecurityPolicy::HeaderType contentSecurityPolicyType) - : WorkerThread(url, userAgent, settings, sourceCode, workerLoaderProxy, workerReportingProxy, startMode, contentSecurityPolicy, contentSecurityPolicyType, 0) - , m_name(name.isolatedCopy()) -{ -} - -SharedWorkerThread::~SharedWorkerThread() -{ -} - -PassRefPtr<WorkerGlobalScope> SharedWorkerThread::createWorkerGlobalScope(const URL& url, const String& userAgent, std::unique_ptr<GroupSettings> settings, const String& contentSecurityPolicy, ContentSecurityPolicy::HeaderType contentSecurityPolicyType, PassRefPtr<SecurityOrigin>) -{ - return SharedWorkerGlobalScope::create(m_name, url, userAgent, std::move(settings), this, contentSecurityPolicy, contentSecurityPolicyType); -} - -} // namespace WebCore - -#endif // ENABLE(SHARED_WORKERS) diff --git a/Source/WebCore/workers/SharedWorkerThread.h b/Source/WebCore/workers/SharedWorkerThread.h deleted file mode 100644 index 1d214a867..000000000 --- a/Source/WebCore/workers/SharedWorkerThread.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * 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 SharedWorkerThread_h -#define SharedWorkerThread_h - -#if ENABLE(SHARED_WORKERS) - -#include "ContentSecurityPolicy.h" -#include "WorkerThread.h" - -namespace WebCore { - - class SharedWorkerThread : public WorkerThread { - public: - static PassRefPtr<SharedWorkerThread> create(const String& name, const URL&, const String& userAgent, const GroupSettings*, const String& sourceCode, WorkerLoaderProxy&, WorkerReportingProxy&, WorkerThreadStartMode, const String& contentSecurityPolicy, ContentSecurityPolicy::HeaderType); - virtual ~SharedWorkerThread(); - - protected: - virtual PassRefPtr<WorkerGlobalScope> createWorkerGlobalScope(const URL&, const String& userAgent, std::unique_ptr<GroupSettings>, const String& contentSecurityPolicy, ContentSecurityPolicy::HeaderType, PassRefPtr<SecurityOrigin> topOrigin) override; - - private: - SharedWorkerThread(const String& name, const URL&, const String& userAgent, const GroupSettings*, const String& sourceCode, WorkerLoaderProxy&, WorkerReportingProxy&, WorkerThreadStartMode, const String& contentSecurityPolicy, ContentSecurityPolicy::HeaderType); - - String m_name; - }; -} // namespace WebCore - -#endif // ENABLE(SHARED_WORKERS) - -#endif // SharedWorkerThread_h diff --git a/Source/WebCore/workers/Worker.cpp b/Source/WebCore/workers/Worker.cpp index 168d13821..51348c278 100644 --- a/Source/WebCore/workers/Worker.cpp +++ b/Source/WebCore/workers/Worker.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008, 2010 Apple Inc. All Rights Reserved. + * Copyright (C) 2008-2017 Apple Inc. All Rights Reserved. * Copyright (C) 2009 Google Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without @@ -11,10 +11,10 @@ * 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 + * THIS SOFTWARE IS PROVIDED BY APPLE 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 + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE 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 @@ -22,30 +22,22 @@ * 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" - #include "Worker.h" -#include "DOMWindow.h" -#include "CachedResourceLoader.h" -#include "Document.h" -#include "EventException.h" -#include "EventListener.h" +#include "ContentSecurityPolicy.h" +#include "Event.h" #include "EventNames.h" -#include "ExceptionCode.h" -#include "FeatureObserver.h" -#include "Frame.h" -#include "FrameLoader.h" #include "InspectorInstrumentation.h" -#include "MessageEvent.h" #include "NetworkStateNotifier.h" -#include "TextEncoding.h" +#include "ResourceResponse.h" +#include "SecurityOrigin.h" #include "WorkerGlobalScopeProxy.h" #include "WorkerScriptLoader.h" #include "WorkerThread.h" +#include <inspector/IdentifiersFactory.h> #include <wtf/HashSet.h> #include <wtf/MainThread.h> @@ -55,49 +47,53 @@ static HashSet<Worker*>* allWorkers; void networkStateChanged(bool isOnLine) { - HashSet<Worker*>::iterator end = allWorkers->end(); - for (HashSet<Worker*>::iterator it = allWorkers->begin(); it != end; ++it) - (*it)->notifyNetworkStateChange(isOnLine); + for (auto& worker : *allWorkers) + worker->notifyNetworkStateChange(isOnLine); } -inline Worker::Worker(ScriptExecutionContext& context) - : AbstractWorker(context) - , m_contextProxy(WorkerGlobalScopeProxy::create(this)) +inline Worker::Worker(ScriptExecutionContext& context, JSC::RuntimeFlags runtimeFlags) + : ActiveDOMObject(&context) + , m_identifier("worker:" + Inspector::IdentifiersFactory::createIdentifier()) + , m_contextProxy(WorkerGlobalScopeProxy::create(*this)) + , m_runtimeFlags(runtimeFlags) { if (!allWorkers) { allWorkers = new HashSet<Worker*>; networkStateNotifier().addNetworkStateChangeListener(networkStateChanged); } - HashSet<Worker*>::AddResult addResult = allWorkers->add(this); + auto addResult = allWorkers->add(this); ASSERT_UNUSED(addResult, addResult.isNewEntry); } -PassRefPtr<Worker> Worker::create(ScriptExecutionContext& context, const String& url, ExceptionCode& ec) +ExceptionOr<Ref<Worker>> Worker::create(ScriptExecutionContext& context, const String& url, JSC::RuntimeFlags runtimeFlags) { ASSERT(isMainThread()); // We don't currently support nested workers, so workers can only be created from documents. ASSERT_WITH_SECURITY_IMPLICATION(context.isDocument()); - Document& document = static_cast<Document&>(context); - - FeatureObserver::observe(document.domWindow(), FeatureObserver::WorkerStart); - RefPtr<Worker> worker = adoptRef(new Worker(context)); + auto worker = adoptRef(*new Worker(context, runtimeFlags)); worker->suspendIfNeeded(); - URL scriptURL = worker->resolveURL(url, ec); - if (scriptURL.isEmpty()) - return 0; + bool shouldBypassMainWorldContentSecurityPolicy = context.shouldBypassMainWorldContentSecurityPolicy(); + auto scriptURL = worker->resolveURL(url, shouldBypassMainWorldContentSecurityPolicy); + if (scriptURL.hasException()) + return scriptURL.releaseException(); + + worker->m_shouldBypassMainWorldContentSecurityPolicy = shouldBypassMainWorldContentSecurityPolicy; // The worker context does not exist while loading, so we must ensure that the worker object is not collected, nor are its event listeners. - worker->setPendingActivity(worker.get()); + worker->setPendingActivity(worker.ptr()); - worker->m_scriptLoader = WorkerScriptLoader::create(); - worker->m_scriptLoader->loadAsynchronously(&context, scriptURL, DenyCrossOriginRequests, worker.get()); + // https://html.spec.whatwg.org/multipage/workers.html#official-moment-of-creation + worker->m_workerCreationTime = MonotonicTime::now(); - return worker.release(); + worker->m_scriptLoader = WorkerScriptLoader::create(); + auto contentSecurityPolicyEnforcement = shouldBypassMainWorldContentSecurityPolicy ? ContentSecurityPolicyEnforcement::DoNotEnforce : ContentSecurityPolicyEnforcement::EnforceChildSrcDirective; + worker->m_scriptLoader->loadAsynchronously(&context, scriptURL.releaseReturnValue(), FetchOptions::Mode::SameOrigin, contentSecurityPolicyEnforcement, worker->m_identifier, worker.ptr()); + return WTFMove(worker); } Worker::~Worker() @@ -105,37 +101,40 @@ Worker::~Worker() ASSERT(isMainThread()); ASSERT(scriptExecutionContext()); // The context is protected by worker context proxy, so it cannot be destroyed while a Worker exists. allWorkers->remove(this); - m_contextProxy->workerObjectDestroyed(); + m_contextProxy.workerObjectDestroyed(); } -void Worker::postMessage(PassRefPtr<SerializedScriptValue> message, MessagePort* port, ExceptionCode& ec) +ExceptionOr<void> Worker::postMessage(JSC::ExecState& state, JSC::JSValue messageValue, Vector<JSC::Strong<JSC::JSObject>>&& transfer) { - MessagePortArray ports; - if (port) - ports.append(port); - postMessage(message, &ports, ec); -} + Vector<RefPtr<MessagePort>> ports; + auto message = SerializedScriptValue::create(state, messageValue, WTFMove(transfer), ports, SerializationContext::WorkerPostMessage); + if (message.hasException()) + return message.releaseException(); -void Worker::postMessage(PassRefPtr<SerializedScriptValue> message, const MessagePortArray* ports, ExceptionCode& ec) -{ // Disentangle the port in preparation for sending it to the remote context. - OwnPtr<MessagePortChannelArray> channels = MessagePort::disentanglePorts(ports, ec); - if (ec) - return; - m_contextProxy->postMessageToWorkerGlobalScope(message, channels.release()); + auto channels = MessagePort::disentanglePorts(WTFMove(ports)); + if (channels.hasException()) + return channels.releaseException(); + m_contextProxy.postMessageToWorkerGlobalScope(message.releaseReturnValue(), channels.releaseReturnValue()); + return { }; } void Worker::terminate() { - m_contextProxy->terminateWorkerGlobalScope(); + m_contextProxy.terminateWorkerGlobalScope(); } -bool Worker::canSuspend() const +bool Worker::canSuspendForDocumentSuspension() const { // FIXME: It is not currently possible to suspend a worker, so pages with workers can not go into page cache. return false; } +const char* Worker::activeDOMObjectName() const +{ + return "Worker"; +} + void Worker::stop() { terminate(); @@ -143,16 +142,19 @@ void Worker::stop() bool Worker::hasPendingActivity() const { - return m_contextProxy->hasPendingActivity() || ActiveDOMObject::hasPendingActivity(); + return m_contextProxy.hasPendingActivity() || ActiveDOMObject::hasPendingActivity(); } void Worker::notifyNetworkStateChange(bool isOnLine) { - m_contextProxy->notifyNetworkStateChange(isOnLine); + m_contextProxy.notifyNetworkStateChange(isOnLine); } -void Worker::didReceiveResponse(unsigned long identifier, const ResourceResponse&) +void Worker::didReceiveResponse(unsigned long identifier, const ResourceResponse& response) { + const URL& responseURL = response.url(); + if (!responseURL.protocolIsBlob() && !responseURL.protocolIs("file") && !SecurityOrigin::create(responseURL)->isUnique()) + m_contentSecurityPolicyResponseHeaders = ContentSecurityPolicyResponseHeaders(response); InspectorInstrumentation::didReceiveScriptResponse(scriptExecutionContext(), identifier); } @@ -161,11 +163,9 @@ void Worker::notifyFinished() if (m_scriptLoader->failed()) dispatchEvent(Event::create(eventNames().errorEvent, false, true)); else { - WorkerThreadStartMode startMode = DontPauseWorkerGlobalScopeOnStart; - if (InspectorInstrumentation::shouldPauseDedicatedWorkerOnStart(scriptExecutionContext())) - startMode = PauseWorkerGlobalScopeOnStart; - m_contextProxy->startWorkerGlobalScope(m_scriptLoader->url(), scriptExecutionContext()->userAgent(m_scriptLoader->url()), m_scriptLoader->script(), startMode); - InspectorInstrumentation::scriptImported(scriptExecutionContext(), m_scriptLoader->identifier(), m_scriptLoader->script()); + const ContentSecurityPolicyResponseHeaders& contentSecurityPolicyResponseHeaders = m_contentSecurityPolicyResponseHeaders ? m_contentSecurityPolicyResponseHeaders.value() : scriptExecutionContext()->contentSecurityPolicy()->responseHeaders(); + m_contextProxy.startWorkerGlobalScope(m_scriptLoader->url(), scriptExecutionContext()->userAgent(m_scriptLoader->url()), m_scriptLoader->script(), contentSecurityPolicyResponseHeaders, m_shouldBypassMainWorldContentSecurityPolicy, m_workerCreationTime, m_runtimeFlags); + InspectorInstrumentation::scriptImported(*scriptExecutionContext(), m_scriptLoader->identifier(), m_scriptLoader->script()); } m_scriptLoader = nullptr; diff --git a/Source/WebCore/workers/Worker.h b/Source/WebCore/workers/Worker.h index c197eef6b..44d86f8e7 100644 --- a/Source/WebCore/workers/Worker.h +++ b/Source/WebCore/workers/Worker.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008, 2010 Apple Inc. All Rights Reserved. + * Copyright (C) 2008, 2010, 2016 Apple Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -10,10 +10,10 @@ * 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 + * THIS SOFTWARE IS PROVIDED BY APPLE 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 + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE 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 @@ -21,66 +21,70 @@ * 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 +#pragma once #include "AbstractWorker.h" #include "ActiveDOMObject.h" -#include "EventListener.h" -#include "EventNames.h" +#include "ContentSecurityPolicyResponseHeaders.h" #include "EventTarget.h" #include "MessagePort.h" #include "WorkerScriptLoaderClient.h" -#include <wtf/Forward.h> -#include <wtf/PassRefPtr.h> -#include <wtf/RefPtr.h> +#include <runtime/RuntimeFlags.h> +#include <wtf/Optional.h> #include <wtf/text/AtomicStringHash.h> +namespace JSC { +class ExecState; +class JSObject; +class JSValue; +} + namespace WebCore { - class ScriptExecutionContext; - class WorkerGlobalScopeProxy; - class WorkerScriptLoader; +class ScriptExecutionContext; +class WorkerGlobalScopeProxy; +class WorkerScriptLoader; - typedef int ExceptionCode; +class Worker final : public AbstractWorker, public ActiveDOMObject, private WorkerScriptLoaderClient { +public: + static ExceptionOr<Ref<Worker>> create(ScriptExecutionContext&, const String& url, JSC::RuntimeFlags); + virtual ~Worker(); - class Worker final : public AbstractWorker, private WorkerScriptLoaderClient { - public: - static PassRefPtr<Worker> create(ScriptExecutionContext&, const String& url, ExceptionCode&); - virtual ~Worker(); + ExceptionOr<void> postMessage(JSC::ExecState&, JSC::JSValue message, Vector<JSC::Strong<JSC::JSObject>>&&); - virtual EventTargetInterface eventTargetInterface() const override { return WorkerEventTargetInterfaceType; } + void terminate(); - void postMessage(PassRefPtr<SerializedScriptValue> message, const MessagePortArray*, ExceptionCode&); - // Needed for Objective-C bindings (see bug 28774). - void postMessage(PassRefPtr<SerializedScriptValue> message, MessagePort*, ExceptionCode&); + bool hasPendingActivity() const final; - void terminate(); + String identifier() const { return m_identifier; } - virtual bool canSuspend() const override; - virtual void stop() override; - virtual bool hasPendingActivity() const override; - - DEFINE_ATTRIBUTE_EVENT_LISTENER(message); + ScriptExecutionContext* scriptExecutionContext() const final { return ActiveDOMObject::scriptExecutionContext(); } - private: - explicit Worker(ScriptExecutionContext&); +private: + explicit Worker(ScriptExecutionContext&, JSC::RuntimeFlags); - void notifyNetworkStateChange(bool isOnline); + EventTargetInterface eventTargetInterface() const final { return WorkerEventTargetInterfaceType; } - // WorkerScriptLoaderClient callbacks - virtual void didReceiveResponse(unsigned long identifier, const ResourceResponse&) override; - virtual void notifyFinished() override; + void notifyNetworkStateChange(bool isOnline); - friend void networkStateChanged(bool isOnLine); + void didReceiveResponse(unsigned long identifier, const ResourceResponse&) final; + void notifyFinished() final; - RefPtr<WorkerScriptLoader> m_scriptLoader; - WorkerGlobalScopeProxy* m_contextProxy; // The proxy outlives the worker to perform thread shutdown. - }; + bool canSuspendForDocumentSuspension() const final; + void stop() final; + const char* activeDOMObjectName() const final; -} // namespace WebCore + friend void networkStateChanged(bool isOnLine); -#endif // Worker_h + RefPtr<WorkerScriptLoader> m_scriptLoader; + String m_identifier; + WorkerGlobalScopeProxy& m_contextProxy; // The proxy outlives the worker to perform thread shutdown. + std::optional<ContentSecurityPolicyResponseHeaders> m_contentSecurityPolicyResponseHeaders; + MonotonicTime m_workerCreationTime; + bool m_shouldBypassMainWorldContentSecurityPolicy { false }; + JSC::RuntimeFlags m_runtimeFlags; +}; + +} // namespace WebCore diff --git a/Source/WebCore/workers/Worker.idl b/Source/WebCore/workers/Worker.idl index 3be80442a..16481a393 100644 --- a/Source/WebCore/workers/Worker.idl +++ b/Source/WebCore/workers/Worker.idl @@ -11,10 +11,10 @@ * 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 + * THIS SOFTWARE IS PROVIDED BY APPLE 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 + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE 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 @@ -22,27 +22,16 @@ * 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. - * */ [ - CustomConstructor(DOMString scriptUrl), - JSGenerateToNativeObject, - JSGenerateToJSObject, ActiveDOMObject, + CustomConstructor(USVString scriptUrl), ] interface Worker : EventTarget { - - attribute EventListener onmessage; - -#if defined(LANGUAGE_JAVASCRIPT) && LANGUAGE_JAVASCRIPT - [Custom, RaisesException] void postMessage(SerializedScriptValue message, optional Array messagePorts); -#else - // There's no good way to expose an array via the ObjC bindings, so for now just allow passing in a single port. - [RaisesException] void postMessage(SerializedScriptValue message, optional MessagePort messagePort); -#endif - void terminate(); + + [CallWith=ScriptState, MayThrowException] void postMessage(any message, optional sequence<object> transfer = []); + attribute EventHandler onmessage; }; Worker implements AbstractWorker; - diff --git a/Source/WebCore/workers/WorkerConsoleClient.cpp b/Source/WebCore/workers/WorkerConsoleClient.cpp new file mode 100644 index 000000000..af99f5ea0 --- /dev/null +++ b/Source/WebCore/workers/WorkerConsoleClient.cpp @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2016 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 INC. 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 INC. 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. + */ + +#include "config.h" +#include "WorkerConsoleClient.h" + +#include "InspectorInstrumentation.h" +#include <inspector/ConsoleMessage.h> +#include <inspector/ScriptArguments.h> +#include <inspector/ScriptCallStack.h> +#include <inspector/ScriptCallStackFactory.h> + +using namespace Inspector; + +namespace WebCore { + +WorkerConsoleClient::WorkerConsoleClient(WorkerGlobalScope& workerGlobalScope) + : m_workerGlobalScope(workerGlobalScope) +{ +} + +WorkerConsoleClient::~WorkerConsoleClient() +{ +} + +void WorkerConsoleClient::messageWithTypeAndLevel(MessageType type, MessageLevel level, JSC::ExecState* exec, Ref<Inspector::ScriptArguments>&& arguments) +{ + String messageText; + arguments->getFirstArgumentAsString(messageText); + auto message = std::make_unique<Inspector::ConsoleMessage>(MessageSource::ConsoleAPI, type, level, messageText, WTFMove(arguments), exec); + m_workerGlobalScope.addConsoleMessage(WTFMove(message)); +} + +void WorkerConsoleClient::count(JSC::ExecState* exec, Ref<ScriptArguments>&& arguments) +{ + InspectorInstrumentation::consoleCount(m_workerGlobalScope, exec, WTFMove(arguments)); +} + +void WorkerConsoleClient::time(JSC::ExecState*, const String& title) +{ + InspectorInstrumentation::startConsoleTiming(m_workerGlobalScope, title); +} + +void WorkerConsoleClient::timeEnd(JSC::ExecState* exec, const String& title) +{ + InspectorInstrumentation::stopConsoleTiming(m_workerGlobalScope, title, createScriptCallStackForConsole(exec, 1)); +} + +// FIXME: <https://webkit.org/b/153499> Web Inspector: console.profile should use the new Sampling Profiler +void WorkerConsoleClient::profile(JSC::ExecState*, const String&) { } +void WorkerConsoleClient::profileEnd(JSC::ExecState*, const String&) { } + +// FIXME: <https://webkit.org/b/127634> Web Inspector: support debugging web workers +void WorkerConsoleClient::takeHeapSnapshot(JSC::ExecState*, const String&) { } +void WorkerConsoleClient::timeStamp(JSC::ExecState*, Ref<ScriptArguments>&&) { } + +} // namespace WebCore diff --git a/Source/WebCore/workers/SharedWorkerStrategy.h b/Source/WebCore/workers/WorkerConsoleClient.h index a75e1b295..a8d122815 100644 --- a/Source/WebCore/workers/SharedWorkerStrategy.h +++ b/Source/WebCore/workers/WorkerConsoleClient.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Apple Inc. All rights reserved. + * Copyright (C) 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -23,21 +23,36 @@ * THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef SharedWorkerStrategy_h -#define SharedWorkerStrategy_h +#pragma once + +#include "WorkerGlobalScope.h" +#include <runtime/ConsoleClient.h> +#include <wtf/Forward.h> + +namespace JSC { +class ExecState; +} namespace WebCore { - -class SharedWorkerStrategy { + +class WorkerConsoleClient final : public JSC::ConsoleClient { + WTF_MAKE_FAST_ALLOCATED; public: - virtual bool isAvailable() const { return true; } + explicit WorkerConsoleClient(WorkerGlobalScope&); + virtual ~WorkerConsoleClient(); protected: - virtual ~SharedWorkerStrategy() - { - } -}; + void messageWithTypeAndLevel(MessageType, MessageLevel, JSC::ExecState*, Ref<Inspector::ScriptArguments>&&) override; + void count(JSC::ExecState*, Ref<Inspector::ScriptArguments>&&) override; + void profile(JSC::ExecState*, const String& title) override; + void profileEnd(JSC::ExecState*, const String& title) override; + void takeHeapSnapshot(JSC::ExecState*, const String& title) override; + void time(JSC::ExecState*, const String& title) override; + void timeEnd(JSC::ExecState*, const String& title) override; + void timeStamp(JSC::ExecState*, Ref<Inspector::ScriptArguments>&&) override; -} +private: + WorkerGlobalScope& m_workerGlobalScope; +}; -#endif // SharedWorkerStrategy_h +} // namespace WebCore diff --git a/Source/WebCore/workers/WorkerEventQueue.cpp b/Source/WebCore/workers/WorkerEventQueue.cpp index fd3b865be..f43bd2a7a 100644 --- a/Source/WebCore/workers/WorkerEventQueue.cpp +++ b/Source/WebCore/workers/WorkerEventQueue.cpp @@ -10,10 +10,10 @@ * 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 + * THIS SOFTWARE IS PROVIDED BY APPLE 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 + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE 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 @@ -21,23 +21,19 @@ * 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" #include "WorkerEventQueue.h" -#include "DOMWindow.h" -#include "Document.h" #include "Event.h" -#include "EventNames.h" +#include "EventTarget.h" #include "ScriptExecutionContext.h" namespace WebCore { WorkerEventQueue::WorkerEventQueue(ScriptExecutionContext& context) : m_scriptExecutionContext(context) - , m_isClosed(false) { } @@ -46,66 +42,60 @@ WorkerEventQueue::~WorkerEventQueue() close(); } -class WorkerEventQueue::EventDispatcherTask final : public ScriptExecutionContext::Task { +class WorkerEventQueue::EventDispatcher +{ public: - static PassOwnPtr<EventDispatcherTask> create(PassRefPtr<Event> event, WorkerEventQueue& eventQueue) + EventDispatcher(RefPtr<Event>&& event, WorkerEventQueue& eventQueue) + : m_event(WTFMove(event)) + , m_eventQueue(eventQueue) { - return adoptPtr(new EventDispatcherTask(event, eventQueue)); } - virtual ~EventDispatcherTask() + ~EventDispatcher() { if (m_event) - m_eventQueue.m_eventTaskMap.remove(m_event.get()); + m_eventQueue.m_eventDispatcherMap.remove(m_event.get()); } - void dispatchEvent(ScriptExecutionContext*, PassRefPtr<Event> event) - { - event->target()->dispatchEvent(event); - } - - virtual void performTask(ScriptExecutionContext* context) override + void dispatch() { if (m_isCancelled) return; - m_eventQueue.m_eventTaskMap.remove(m_event.get()); - dispatchEvent(context, m_event); - m_event.clear(); + m_eventQueue.m_eventDispatcherMap.remove(m_event.get()); + m_event->target()->dispatchEvent(*m_event); + m_event = nullptr; } void cancel() { m_isCancelled = true; - m_event.clear(); + m_event = nullptr; } private: - EventDispatcherTask(PassRefPtr<Event> event, WorkerEventQueue& eventQueue) - : m_event(event) - , m_eventQueue(eventQueue) - , m_isCancelled(false) - { - } - RefPtr<Event> m_event; WorkerEventQueue& m_eventQueue; - bool m_isCancelled; + bool m_isCancelled { false }; }; -bool WorkerEventQueue::enqueueEvent(PassRefPtr<Event> prpEvent) +bool WorkerEventQueue::enqueueEvent(Ref<Event>&& event) { if (m_isClosed) return false; - RefPtr<Event> event = prpEvent; - OwnPtr<EventDispatcherTask> task = EventDispatcherTask::create(event, *this); - m_eventTaskMap.add(event.release(), task.get()); - m_scriptExecutionContext.postTask(task.release()); + + auto* eventPtr = event.ptr(); + auto eventDispatcher = std::make_unique<EventDispatcher>(WTFMove(event), *this); + m_eventDispatcherMap.add(eventPtr, eventDispatcher.get()); + m_scriptExecutionContext.postTask([eventDispatcher = WTFMove(eventDispatcher)] (ScriptExecutionContext&) { + eventDispatcher->dispatch(); + }); + return true; } bool WorkerEventQueue::cancelEvent(Event& event) { - EventDispatcherTask* task = m_eventTaskMap.take(&event); + EventDispatcher* task = m_eventDispatcherMap.take(&event); if (!task) return false; task->cancel(); @@ -115,11 +105,9 @@ bool WorkerEventQueue::cancelEvent(Event& event) void WorkerEventQueue::close() { m_isClosed = true; - for (EventTaskMap::iterator it = m_eventTaskMap.begin(); it != m_eventTaskMap.end(); ++it) { - EventDispatcherTask* task = it->value; - task->cancel(); - } - m_eventTaskMap.clear(); + for (auto& dispatcher : m_eventDispatcherMap.values()) + dispatcher->cancel(); + m_eventDispatcherMap.clear(); } -} +} // namespace WebCore diff --git a/Source/WebCore/workers/WorkerEventQueue.h b/Source/WebCore/workers/WorkerEventQueue.h index 4ac5bfca7..6115ef4a1 100644 --- a/Source/WebCore/workers/WorkerEventQueue.h +++ b/Source/WebCore/workers/WorkerEventQueue.h @@ -10,10 +10,10 @@ * 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 + * THIS SOFTWARE IS PROVIDED BY APPLE 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 + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE 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 @@ -21,15 +21,12 @@ * 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 WorkerEventQueue_h -#define WorkerEventQueue_h +#pragma once #include "EventQueue.h" #include <wtf/HashMap.h> -#include <wtf/PassOwnPtr.h> namespace WebCore { @@ -40,19 +37,17 @@ public: explicit WorkerEventQueue(ScriptExecutionContext&); virtual ~WorkerEventQueue(); - virtual bool enqueueEvent(PassRefPtr<Event>) override; - virtual bool cancelEvent(Event&) override; - virtual void close() override; + bool enqueueEvent(Ref<Event>&&) override; + bool cancelEvent(Event&) override; + void close() override; private: ScriptExecutionContext& m_scriptExecutionContext; - bool m_isClosed; + bool m_isClosed { false }; - class EventDispatcherTask; - typedef HashMap<RefPtr<Event>, EventDispatcherTask*> EventTaskMap; - EventTaskMap m_eventTaskMap; + class EventDispatcher; + typedef HashMap<RefPtr<Event>, EventDispatcher*> EventDispatcherMap; + EventDispatcherMap m_eventDispatcherMap; }; -} - -#endif // WorkerEventQueue_h +} // namespace WebCore diff --git a/Source/WebCore/workers/WorkerGlobalScope.cpp b/Source/WebCore/workers/WorkerGlobalScope.cpp index 2889236f7..9b357096b 100644 --- a/Source/WebCore/workers/WorkerGlobalScope.cpp +++ b/Source/WebCore/workers/WorkerGlobalScope.cpp @@ -11,107 +11,112 @@ * 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 + * THIS SOFTWARE IS PROVIDED BY APPLE 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 + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE 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. + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "config.h" - #include "WorkerGlobalScope.h" -#include "ActiveDOMObject.h" #include "ContentSecurityPolicy.h" -#include "DOMTimer.h" -#include "DOMURL.h" -#include "DOMWindow.h" -#include "ErrorEvent.h" -#include "Event.h" -#include "EventException.h" +#include "Crypto.h" #include "ExceptionCode.h" -#include "InspectorConsoleInstrumentation.h" -#include "URL.h" -#include "MessagePort.h" -#include "NotImplemented.h" +#include "IDBConnectionProxy.h" +#include "InspectorInstrumentation.h" +#include "Performance.h" #include "ScheduledAction.h" -#include "ScriptCallStack.h" #include "ScriptSourceCode.h" #include "SecurityOrigin.h" +#include "SecurityOriginPolicy.h" +#include "SocketProvider.h" #include "WorkerInspectorController.h" +#include "WorkerLoaderProxy.h" #include "WorkerLocation.h" #include "WorkerNavigator.h" -#include "WorkerObjectProxy.h" +#include "WorkerReportingProxy.h" #include "WorkerScriptLoader.h" #include "WorkerThread.h" -#include "WorkerThreadableLoader.h" -#include "XMLHttpRequestException.h" -#include <bindings/ScriptValue.h> -#include <wtf/RefPtr.h> +#include <inspector/ScriptArguments.h> +#include <inspector/ScriptCallStack.h> -#if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS) -#include "NotificationCenter.h" -#endif +using namespace Inspector; namespace WebCore { -class CloseWorkerGlobalScopeTask : public ScriptExecutionContext::Task { -public: - static PassOwnPtr<CloseWorkerGlobalScopeTask> create() - { - return adoptPtr(new CloseWorkerGlobalScopeTask); - } - - virtual void performTask(ScriptExecutionContext *context) - { - ASSERT_WITH_SECURITY_IMPLICATION(context->isWorkerGlobalScope()); - WorkerGlobalScope* workerGlobalScope = static_cast<WorkerGlobalScope*>(context); - // Notify parent that this context is closed. Parent is responsible for calling WorkerThread::stop(). - workerGlobalScope->thread()->workerReportingProxy().workerGlobalScopeClosed(); - } - - virtual bool isCleanupTask() const { return true; } -}; - -WorkerGlobalScope::WorkerGlobalScope(const URL& url, const String& userAgent, std::unique_ptr<GroupSettings> settings, WorkerThread* thread, PassRefPtr<SecurityOrigin> topOrigin) +WorkerGlobalScope::WorkerGlobalScope(const URL& url, const String& identifier, const String& userAgent, WorkerThread& thread, bool shouldBypassMainWorldContentSecurityPolicy, Ref<SecurityOrigin>&& topOrigin, MonotonicTime timeOrigin, IDBClient::IDBConnectionProxy* connectionProxy, SocketProvider* socketProvider) : m_url(url) + , m_identifier(identifier) , m_userAgent(userAgent) - , m_groupSettings(std::move(settings)) - , m_script(adoptPtr(new WorkerScriptController(this))) , m_thread(thread) -#if ENABLE(INSPECTOR) - , m_workerInspectorController(std::make_unique<WorkerInspectorController>(*this)) -#endif - , m_closing(false) + , m_script(std::make_unique<WorkerScriptController>(this)) + , m_inspectorController(std::make_unique<WorkerInspectorController>(*this)) + , m_shouldBypassMainWorldContentSecurityPolicy(shouldBypassMainWorldContentSecurityPolicy) , m_eventQueue(*this) - , m_topOrigin(topOrigin) + , m_topOrigin(WTFMove(topOrigin)) +#if ENABLE(INDEXED_DATABASE) + , m_connectionProxy(connectionProxy) +#endif +#if ENABLE(WEB_SOCKETS) + , m_socketProvider(socketProvider) +#endif +#if ENABLE(WEB_TIMING) + , m_performance(Performance::create(*this, timeOrigin)) +#endif { - setSecurityOrigin(SecurityOrigin::create(url)); +#if !ENABLE(INDEXED_DATABASE) + UNUSED_PARAM(connectionProxy); +#endif +#if !ENABLE(WEB_SOCKETS) + UNUSED_PARAM(socketProvider); +#endif +#if !ENABLE(WEB_TIMING) + UNUSED_PARAM(timeOrigin); +#endif + + auto origin = SecurityOrigin::create(url); + if (m_topOrigin->hasUniversalAccess()) + origin->grantUniversalAccess(); + if (m_topOrigin->needsStorageAccessFromFileURLsQuirk()) + origin->grantStorageAccessFromFileURLsQuirk(); + + setSecurityOriginPolicy(SecurityOriginPolicy::create(WTFMove(origin))); + setContentSecurityPolicy(std::make_unique<ContentSecurityPolicy>(*this)); } WorkerGlobalScope::~WorkerGlobalScope() { - ASSERT(currentThread() == thread()->threadID()); + ASSERT(currentThread() == thread().threadID()); - // Make sure we have no observers. - notifyObserversOfStop(); +#if ENABLE(WEB_TIMING) + m_performance = nullptr; +#endif // Notify proxy that we are going away. This can free the WorkerThread object, so do not access it after this. - thread()->workerReportingProxy().workerGlobalScopeDestroyed(); + thread().workerReportingProxy().workerGlobalScopeDestroyed(); } -void WorkerGlobalScope::applyContentSecurityPolicyFromString(const String& policy, ContentSecurityPolicy::HeaderType contentSecurityPolicyType) +void WorkerGlobalScope::removeAllEventListeners() { - setContentSecurityPolicy(ContentSecurityPolicy::create(this)); - contentSecurityPolicy()->didReceiveHeader(policy, contentSecurityPolicyType); + EventTarget::removeAllEventListeners(); + +#if ENABLE(WEB_TIMING) + m_performance->removeAllEventListeners(); +#endif +} + +void WorkerGlobalScope::applyContentSecurityPolicyResponseHeaders(const ContentSecurityPolicyResponseHeaders& contentSecurityPolicyResponseHeaders) +{ + contentSecurityPolicy()->didReceiveHeaders(contentSecurityPolicyResponseHeaders); } URL WorkerGlobalScope::completeURL(const String& url) const @@ -134,11 +139,41 @@ void WorkerGlobalScope::disableEval(const String& errorMessage) m_script->disableEval(errorMessage); } -WorkerLocation* WorkerGlobalScope::location() const +#if ENABLE(WEB_SOCKETS) + +SocketProvider* WorkerGlobalScope::socketProvider() +{ + return m_socketProvider.get(); +} + +#endif + +#if ENABLE(INDEXED_DATABASE) + +IDBClient::IDBConnectionProxy* WorkerGlobalScope::idbConnectionProxy() +{ +#if ENABLE(INDEXED_DATABASE_IN_WORKERS) + return m_connectionProxy.get(); +#else + return nullptr; +#endif +} + +void WorkerGlobalScope::stopIndexedDatabase() +{ +#if ENABLE(INDEXED_DATABASE_IN_WORKERS) + ASSERT(m_connectionProxy); + m_connectionProxy->forgetActivityForCurrentThread(); +#endif +} + +#endif // ENABLE(INDEXED_DATABASE) + +WorkerLocation& WorkerGlobalScope::location() const { if (!m_location) m_location = WorkerLocation::create(m_url); - return m_location.get(); + return *m_location; } void WorkerGlobalScope::close() @@ -150,93 +185,83 @@ void WorkerGlobalScope::close() // After m_closing is set, all the tasks in the queue continue to be fetched but only // tasks with isCleanupTask()==true will be executed. m_closing = true; - postTask(CloseWorkerGlobalScopeTask::create()); + postTask({ ScriptExecutionContext::Task::CleanupTask, [] (ScriptExecutionContext& context) { + ASSERT_WITH_SECURITY_IMPLICATION(is<WorkerGlobalScope>(context)); + WorkerGlobalScope& workerGlobalScope = downcast<WorkerGlobalScope>(context); + // Notify parent that this context is closed. Parent is responsible for calling WorkerThread::stop(). + workerGlobalScope.thread().workerReportingProxy().workerGlobalScopeClosed(); + } }); } -WorkerNavigator* WorkerGlobalScope::navigator() const +WorkerNavigator& WorkerGlobalScope::navigator() const { if (!m_navigator) m_navigator = WorkerNavigator::create(m_userAgent); - return m_navigator.get(); -} - -bool WorkerGlobalScope::hasPendingActivity() const -{ - ActiveDOMObjectsSet::const_iterator activeObjectsEnd = activeDOMObjects().end(); - for (ActiveDOMObjectsSet::const_iterator iter = activeDOMObjects().begin(); iter != activeObjectsEnd; ++iter) { - if ((*iter)->hasPendingActivity()) - return true; - } - - HashSet<MessagePort*>::const_iterator messagePortsEnd = messagePorts().end(); - for (HashSet<MessagePort*>::const_iterator iter = messagePorts().begin(); iter != messagePortsEnd; ++iter) { - if ((*iter)->hasPendingActivity()) - return true; - } - - return false; + return *m_navigator; } -void WorkerGlobalScope::postTask(PassOwnPtr<Task> task) +void WorkerGlobalScope::postTask(Task&& task) { - thread()->runLoop().postTask(task); + thread().runLoop().postTask(WTFMove(task)); } -int WorkerGlobalScope::setTimeout(PassOwnPtr<ScheduledAction> action, int timeout) +int WorkerGlobalScope::setTimeout(std::unique_ptr<ScheduledAction> action, int timeout) { - return DOMTimer::install(scriptExecutionContext(), action, timeout, true); + return DOMTimer::install(*this, WTFMove(action), std::chrono::milliseconds(timeout), true); } void WorkerGlobalScope::clearTimeout(int timeoutId) { - DOMTimer::removeById(scriptExecutionContext(), timeoutId); + DOMTimer::removeById(*this, timeoutId); } -int WorkerGlobalScope::setInterval(PassOwnPtr<ScheduledAction> action, int timeout) +int WorkerGlobalScope::setInterval(std::unique_ptr<ScheduledAction> action, int timeout) { - return DOMTimer::install(scriptExecutionContext(), action, timeout, false); + return DOMTimer::install(*this, WTFMove(action), std::chrono::milliseconds(timeout), false); } void WorkerGlobalScope::clearInterval(int timeoutId) { - DOMTimer::removeById(scriptExecutionContext(), timeoutId); + DOMTimer::removeById(*this, timeoutId); } -void WorkerGlobalScope::importScripts(const Vector<String>& urls, ExceptionCode& ec) +ExceptionOr<void> WorkerGlobalScope::importScripts(const Vector<String>& urls) { ASSERT(contentSecurityPolicy()); - ec = 0; - Vector<String>::const_iterator urlsEnd = urls.end(); + Vector<URL> completedURLs; - for (Vector<String>::const_iterator it = urls.begin(); it != urlsEnd; ++it) { - const URL& url = scriptExecutionContext()->completeURL(*it); - if (!url.isValid()) { - ec = SYNTAX_ERR; - return; - } - completedURLs.append(url); + completedURLs.reserveInitialCapacity(urls.size()); + for (auto& entry : urls) { + URL url = completeURL(entry); + if (!url.isValid()) + return Exception { SYNTAX_ERR }; + completedURLs.uncheckedAppend(WTFMove(url)); } - Vector<URL>::const_iterator end = completedURLs.end(); - for (Vector<URL>::const_iterator it = completedURLs.begin(); it != end; ++it) { - RefPtr<WorkerScriptLoader> scriptLoader(WorkerScriptLoader::create()); - scriptLoader->loadSynchronously(scriptExecutionContext(), *it, AllowCrossOriginRequests); + for (auto& url : completedURLs) { + // FIXME: Convert this to check the isolated world's Content Security Policy once webkit.org/b/104520 is solved. + bool shouldBypassMainWorldContentSecurityPolicy = this->shouldBypassMainWorldContentSecurityPolicy(); + if (!shouldBypassMainWorldContentSecurityPolicy && !contentSecurityPolicy()->allowScriptFromSource(url)) + return Exception { NETWORK_ERR }; + + auto scriptLoader = WorkerScriptLoader::create(); + scriptLoader->loadSynchronously(this, url, FetchOptions::Mode::NoCors, shouldBypassMainWorldContentSecurityPolicy ? ContentSecurityPolicyEnforcement::DoNotEnforce : ContentSecurityPolicyEnforcement::EnforceScriptSrcDirective, resourceRequestIdentifier()); // If the fetching attempt failed, throw a NETWORK_ERR exception and abort all these steps. - if (scriptLoader->failed()) { - ec = XMLHttpRequestException::NETWORK_ERR; - return; - } + if (scriptLoader->failed()) + return Exception { NETWORK_ERR }; - InspectorInstrumentation::scriptImported(scriptExecutionContext(), scriptLoader->identifier(), scriptLoader->script()); + InspectorInstrumentation::scriptImported(*this, scriptLoader->identifier(), scriptLoader->script()); - Deprecated::ScriptValue exception; - m_script->evaluate(ScriptSourceCode(scriptLoader->script(), scriptLoader->responseURL()), &exception); - if (!exception.hasNoValue()) { + NakedPtr<JSC::Exception> exception; + m_script->evaluate(ScriptSourceCode(scriptLoader->script(), scriptLoader->responseURL()), exception); + if (exception) { m_script->setException(exception); - return; + return { }; } } + + return { }; } EventTarget* WorkerGlobalScope::errorEventTarget() @@ -244,45 +269,44 @@ EventTarget* WorkerGlobalScope::errorEventTarget() return this; } -void WorkerGlobalScope::logExceptionToConsole(const String& errorMessage, const String& sourceURL, int lineNumber, int columnNumber, PassRefPtr<ScriptCallStack>) +void WorkerGlobalScope::logExceptionToConsole(const String& errorMessage, const String& sourceURL, int lineNumber, int columnNumber, RefPtr<ScriptCallStack>&&) { - thread()->workerReportingProxy().postExceptionToWorkerObject(errorMessage, lineNumber, columnNumber, sourceURL); + thread().workerReportingProxy().postExceptionToWorkerObject(errorMessage, lineNumber, columnNumber, sourceURL); } -void WorkerGlobalScope::addConsoleMessage(MessageSource source, MessageLevel level, const String& message, unsigned long requestIdentifier) +void WorkerGlobalScope::addConsoleMessage(std::unique_ptr<Inspector::ConsoleMessage>&& message) { if (!isContextThread()) { - postTask(AddConsoleMessageTask::create(source, level, message)); + postTask(AddConsoleMessageTask(message->source(), message->level(), message->message())); return; } - thread()->workerReportingProxy().postConsoleMessageToWorkerObject(source, level, message, 0, 0, String()); - addMessageToWorkerConsole(source, level, message, String(), 0, 0, 0, 0, requestIdentifier); + InspectorInstrumentation::addMessageToConsole(*this, WTFMove(message)); } -void WorkerGlobalScope::addMessage(MessageSource source, MessageLevel level, const String& message, const String& sourceURL, unsigned lineNumber, unsigned columnNumber, PassRefPtr<ScriptCallStack> callStack, JSC::ExecState* state, unsigned long requestIdentifier) +void WorkerGlobalScope::addConsoleMessage(MessageSource source, MessageLevel level, const String& message, unsigned long requestIdentifier) +{ + addMessage(source, level, message, { }, 0, 0, nullptr, nullptr, requestIdentifier); +} + +void WorkerGlobalScope::addMessage(MessageSource source, MessageLevel level, const String& messageText, const String& sourceURL, unsigned lineNumber, unsigned columnNumber, RefPtr<ScriptCallStack>&& callStack, JSC::ExecState* state, unsigned long requestIdentifier) { if (!isContextThread()) { - postTask(AddConsoleMessageTask::create(source, level, message)); + postTask(AddConsoleMessageTask(source, level, messageText)); return; } - thread()->workerReportingProxy().postConsoleMessageToWorkerObject(source, level, message, lineNumber, columnNumber, sourceURL); - addMessageToWorkerConsole(source, level, message, sourceURL, lineNumber, columnNumber, callStack, state, requestIdentifier); -} - -void WorkerGlobalScope::addMessageToWorkerConsole(MessageSource source, MessageLevel level, const String& message, const String& sourceURL, unsigned lineNumber, unsigned columnNumber, PassRefPtr<ScriptCallStack> callStack, JSC::ExecState* state, unsigned long requestIdentifier) -{ - ASSERT(isContextThread()); + std::unique_ptr<Inspector::ConsoleMessage> message; if (callStack) - InspectorInstrumentation::addMessageToConsole(this, source, LogMessageType, level, message, callStack, requestIdentifier); + message = std::make_unique<Inspector::ConsoleMessage>(source, MessageType::Log, level, messageText, callStack.releaseNonNull(), requestIdentifier); else - InspectorInstrumentation::addMessageToConsole(this, source, LogMessageType, level, message, sourceURL, lineNumber, columnNumber, state, requestIdentifier); + message = std::make_unique<Inspector::ConsoleMessage>(source, MessageType::Log, level, messageText, sourceURL, lineNumber, columnNumber, state, requestIdentifier); + InspectorInstrumentation::addMessageToConsole(*this, WTFMove(message)); } bool WorkerGlobalScope::isContextThread() const { - return currentThread() == thread()->threadID(); + return currentThread() == thread().threadID(); } bool WorkerGlobalScope::isJSExecutionForbidden() const @@ -290,56 +314,66 @@ bool WorkerGlobalScope::isJSExecutionForbidden() const return m_script->isExecutionForbidden(); } -WorkerGlobalScope::Observer::Observer(WorkerGlobalScope* context) - : m_context(context) +WorkerEventQueue& WorkerGlobalScope::eventQueue() const { - ASSERT(m_context && m_context->isContextThread()); - m_context->registerObserver(this); + return m_eventQueue; } -WorkerGlobalScope::Observer::~Observer() -{ - if (!m_context) - return; - ASSERT(m_context->isContextThread()); - m_context->unregisterObserver(this); -} +#if ENABLE(SUBTLE_CRYPTO) -void WorkerGlobalScope::Observer::stopObserving() +bool WorkerGlobalScope::wrapCryptoKey(const Vector<uint8_t>& key, Vector<uint8_t>& wrappedKey) { - if (!m_context) - return; - ASSERT(m_context->isContextThread()); - m_context->unregisterObserver(this); - m_context = 0; + bool result = false; + bool done = false; + m_thread.workerLoaderProxy().postTaskToLoader([&result, &key, &wrappedKey, &done, workerGlobalScope = this](ScriptExecutionContext& context) { + result = context.wrapCryptoKey(key, wrappedKey); + done = true; + workerGlobalScope->postTask([](ScriptExecutionContext& context) { + ASSERT_UNUSED(context, context.isWorkerGlobalScope()); + }); + }); + + auto waitResult = MessageQueueMessageReceived; + while (!done && waitResult != MessageQueueTerminated) + waitResult = m_thread.runLoop().runInMode(this, WorkerRunLoop::defaultMode()); + + return result; } -void WorkerGlobalScope::registerObserver(Observer* observer) +bool WorkerGlobalScope::unwrapCryptoKey(const Vector<uint8_t>& wrappedKey, Vector<uint8_t>& key) { - ASSERT(observer); - m_workerObservers.add(observer); + bool result = false, done = false; + m_thread.workerLoaderProxy().postTaskToLoader([&result, &wrappedKey, &key, &done, workerGlobalScope = this](ScriptExecutionContext& context) { + result = context.unwrapCryptoKey(wrappedKey, key); + done = true; + workerGlobalScope->postTask([](ScriptExecutionContext& context) { + ASSERT_UNUSED(context, context.isWorkerGlobalScope()); + }); + }); + + auto waitResult = MessageQueueMessageReceived; + while (!done && waitResult != MessageQueueTerminated) + waitResult = m_thread.runLoop().runInMode(this, WorkerRunLoop::defaultMode()); + + return result; } -void WorkerGlobalScope::unregisterObserver(Observer* observer) -{ - ASSERT(observer); - m_workerObservers.remove(observer); -} +#endif // ENABLE(SUBTLE_CRYPTO) -void WorkerGlobalScope::notifyObserversOfStop() +Crypto& WorkerGlobalScope::crypto() { - HashSet<Observer*>::iterator iter = m_workerObservers.begin(); - while (iter != m_workerObservers.end()) { - WorkerGlobalScope::Observer* observer = *iter; - observer->stopObserving(); - observer->notifyStop(); - iter = m_workerObservers.begin(); - } + if (!m_crypto) + m_crypto = Crypto::create(*this); + return *m_crypto; } -WorkerEventQueue& WorkerGlobalScope::eventQueue() const +#if ENABLE(WEB_TIMING) + +Performance& WorkerGlobalScope::performance() const { - return m_eventQueue; + return *m_performance; } +#endif + } // namespace WebCore diff --git a/Source/WebCore/workers/WorkerGlobalScope.h b/Source/WebCore/workers/WorkerGlobalScope.h index 5819965bf..ebe812342 100644 --- a/Source/WebCore/workers/WorkerGlobalScope.h +++ b/Source/WebCore/workers/WorkerGlobalScope.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2008-2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -10,10 +10,10 @@ * 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 + * THIS SOFTWARE IS PROVIDED BY APPLE 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 + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE 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 @@ -24,159 +24,169 @@ * */ -#ifndef WorkerGlobalScope_h -#define WorkerGlobalScope_h +#pragma once -#include "ContentSecurityPolicy.h" -#include "EventListener.h" -#include "EventNames.h" +#include "Base64Utilities.h" #include "EventTarget.h" -#include "GroupSettings.h" #include "ScriptExecutionContext.h" +#include "URL.h" #include "WorkerEventQueue.h" #include "WorkerScriptController.h" -#include <wtf/Assertions.h> -#include <wtf/HashMap.h> -#include <wtf/OwnPtr.h> -#include <wtf/PassRefPtr.h> -#include <wtf/RefCounted.h> -#include <wtf/RefPtr.h> -#include <wtf/text/AtomicStringHash.h> +#include <inspector/ConsoleMessage.h> +#include <memory> namespace WebCore { - class Blob; - class ScheduledAction; - class WorkerInspectorController; - class WorkerLocation; - class WorkerNavigator; - class WorkerThread; +class ContentSecurityPolicyResponseHeaders; +class Crypto; +class Performance; +class ScheduledAction; +class WorkerInspectorController; +class WorkerLocation; +class WorkerNavigator; +class WorkerThread; - class WorkerGlobalScope : public RefCounted<WorkerGlobalScope>, public ScriptExecutionContext, public EventTargetWithInlineData { - public: - virtual ~WorkerGlobalScope(); +namespace IDBClient { +class IDBConnectionProxy; +} - virtual bool isWorkerGlobalScope() const override { return true; } +class WorkerGlobalScope : public RefCounted<WorkerGlobalScope>, public Supplementable<WorkerGlobalScope>, public ScriptExecutionContext, public EventTargetWithInlineData, public Base64Utilities { +public: + virtual ~WorkerGlobalScope(); - virtual ScriptExecutionContext* scriptExecutionContext() const override final { return const_cast<WorkerGlobalScope*>(this); } + virtual bool isDedicatedWorkerGlobalScope() const { return false; } - virtual bool isSharedWorkerGlobalScope() const { return false; } - virtual bool isDedicatedWorkerGlobalScope() const { return false; } + const URL& url() const final { return m_url; } - virtual const URL& url() const override final { return m_url; } - virtual URL completeURL(const String&) const override final; +#if ENABLE(INDEXED_DATABASE) + IDBClient::IDBConnectionProxy* idbConnectionProxy() final; + void stopIndexedDatabase(); +#endif + + WorkerScriptController* script() { return m_script.get(); } + void clearScript() { m_script = nullptr; } + + WorkerInspectorController& inspectorController() const { return *m_inspectorController; } - const GroupSettings* groupSettings() { return m_groupSettings.get(); } - virtual String userAgent(const URL&) const override; + WorkerThread& thread() const { return m_thread; } - virtual void disableEval(const String& errorMessage) override; + using ScriptExecutionContext::hasPendingActivity; - WorkerScriptController* script() { return m_script.get(); } - void clearScript() { m_script.clear(); } + void postTask(Task&&) final; // Executes the task on context's thread asynchronously. - WorkerThread* thread() const { return m_thread; } + WorkerGlobalScope& self() { return *this; } + WorkerLocation& location() const; + void close(); - bool hasPendingActivity() const; + virtual ExceptionOr<void> importScripts(const Vector<String>& urls); + WorkerNavigator& navigator() const; - virtual void postTask(PassOwnPtr<Task>) override; // Executes the task on context's thread asynchronously. + int setTimeout(std::unique_ptr<ScheduledAction>, int timeout); + void clearTimeout(int timeoutId); + int setInterval(std::unique_ptr<ScheduledAction>, int timeout); + void clearInterval(int timeoutId); - // WorkerGlobalScope - WorkerGlobalScope* self() { return this; } - WorkerLocation* location() const; - void close(); + bool isContextThread() const final; - DEFINE_ATTRIBUTE_EVENT_LISTENER(error); - DEFINE_ATTRIBUTE_EVENT_LISTENER(offline); - DEFINE_ATTRIBUTE_EVENT_LISTENER(online); + WorkerNavigator* optionalNavigator() const { return m_navigator.get(); } + WorkerLocation* optionalLocation() const { return m_location.get(); } - // WorkerUtils - virtual void importScripts(const Vector<String>& urls, ExceptionCode&); - WorkerNavigator* navigator() const; + using RefCounted::ref; + using RefCounted::deref; - // Timers - int setTimeout(PassOwnPtr<ScheduledAction>, int timeout); - void clearTimeout(int timeoutId); - int setInterval(PassOwnPtr<ScheduledAction>, int timeout); - void clearInterval(int timeoutId); + bool isClosing() { return m_closing; } - virtual bool isContextThread() const override; - virtual bool isJSExecutionForbidden() const override; + void addConsoleMessage(std::unique_ptr<Inspector::ConsoleMessage>&&); -#if ENABLE(INSPECTOR) - WorkerInspectorController& workerInspectorController() { return *m_workerInspectorController; } + Crypto& crypto(); + +#if ENABLE(WEB_TIMING) + Performance& performance() const; #endif - // These methods are used for GC marking. See JSWorkerGlobalScope::visitChildrenVirtual(SlotVisitor&) in - // JSWorkerGlobalScopeCustom.cpp. - WorkerNavigator* optionalNavigator() const { return m_navigator.get(); } - WorkerLocation* optionalLocation() const { return m_location.get(); } - using RefCounted<WorkerGlobalScope>::ref; - using RefCounted<WorkerGlobalScope>::deref; + void removeAllEventListeners() final; - bool isClosing() { return m_closing; } +protected: + WorkerGlobalScope(const URL&, const String& identifier, const String& userAgent, WorkerThread&, bool shouldBypassMainWorldContentSecurityPolicy, Ref<SecurityOrigin>&& topOrigin, MonotonicTime timeOrigin, IDBClient::IDBConnectionProxy*, SocketProvider*); - // An observer interface to be notified when the worker thread is getting stopped. - class Observer { - WTF_MAKE_NONCOPYABLE(Observer); - public: - Observer(WorkerGlobalScope*); - virtual ~Observer(); - virtual void notifyStop() = 0; - void stopObserving(); - private: - WorkerGlobalScope* m_context; - }; - friend class Observer; - void registerObserver(Observer*); - void unregisterObserver(Observer*); - void notifyObserversOfStop(); + void applyContentSecurityPolicyResponseHeaders(const ContentSecurityPolicyResponseHeaders&); - virtual SecurityOrigin* topOrigin() const override { return m_topOrigin.get(); } +private: + void refScriptExecutionContext() final { ref(); } + void derefScriptExecutionContext() final { deref(); } - virtual void addConsoleMessage(MessageSource, MessageLevel, const String& message, unsigned long requestIdentifier = 0) override; + void refEventTarget() final { ref(); } + void derefEventTarget() final { deref(); } - protected: - WorkerGlobalScope(const URL&, const String& userAgent, std::unique_ptr<GroupSettings>, WorkerThread*, PassRefPtr<SecurityOrigin> topOrigin); - void applyContentSecurityPolicyFromString(const String& contentSecurityPolicy, ContentSecurityPolicy::HeaderType); + void logExceptionToConsole(const String& errorMessage, const String& sourceURL, int lineNumber, int columnNumber, RefPtr<Inspector::ScriptCallStack>&&) final; + void addMessage(MessageSource, MessageLevel, const String& message, const String& sourceURL, unsigned lineNumber, unsigned columnNumber, RefPtr<Inspector::ScriptCallStack>&&, JSC::ExecState*, unsigned long requestIdentifier) final; + void addConsoleMessage(MessageSource, MessageLevel, const String& message, unsigned long requestIdentifier) final; - virtual void logExceptionToConsole(const String& errorMessage, const String& sourceURL, int lineNumber, int columnNumber, PassRefPtr<ScriptCallStack>) override; - void addMessageToWorkerConsole(MessageSource, MessageLevel, const String& message, const String& sourceURL, unsigned lineNumber, unsigned columnNumber, PassRefPtr<ScriptCallStack>, JSC::ExecState* = 0, unsigned long requestIdentifier = 0); + bool isWorkerGlobalScope() const final { return true; } - private: - virtual void refScriptExecutionContext() override { ref(); } - virtual void derefScriptExecutionContext() override { deref(); } + ScriptExecutionContext* scriptExecutionContext() const final { return const_cast<WorkerGlobalScope*>(this); } + URL completeURL(const String&) const final; + String userAgent(const URL&) const final; + void disableEval(const String& errorMessage) final; + EventTarget* errorEventTarget() final; + WorkerEventQueue& eventQueue() const final; + String resourceRequestIdentifier() const final { return m_identifier; } - virtual void refEventTarget() override final { ref(); } - virtual void derefEventTarget() override final { deref(); } +#if ENABLE(WEB_SOCKETS) + SocketProvider* socketProvider() final; +#endif - virtual void addMessage(MessageSource, MessageLevel, const String& message, const String& sourceURL, unsigned lineNumber, unsigned columnNumber, PassRefPtr<ScriptCallStack>, JSC::ExecState* = 0, unsigned long requestIdentifier = 0) override; + bool shouldBypassMainWorldContentSecurityPolicy() const final { return m_shouldBypassMainWorldContentSecurityPolicy; } + bool isJSExecutionForbidden() const final; + SecurityOrigin& topOrigin() const final { return m_topOrigin.get(); } + +#if ENABLE(SUBTLE_CRYPTO) + // The following two functions are side effects of providing extra protection to serialized + // CryptoKey data that went through the structured clone algorithm to local storage such as + // IndexedDB. They don't provide any proctection against communications between mainThread + // and workerThreads. In fact, they cause extra expense as workerThreads cannot talk to clients + // to unwrap/wrap crypto keys. Hence, workerThreads must always ask mainThread to unwrap/wrap + // keys, which results in a second communication and plain keys being transferred between + // workerThreads and the mainThread. + bool wrapCryptoKey(const Vector<uint8_t>& key, Vector<uint8_t>& wrappedKey) final; + bool unwrapCryptoKey(const Vector<uint8_t>& wrappedKey, Vector<uint8_t>& key) final; +#endif + + URL m_url; + String m_identifier; + String m_userAgent; - virtual EventTarget* errorEventTarget() override; + mutable RefPtr<WorkerLocation> m_location; + mutable RefPtr<WorkerNavigator> m_navigator; - virtual WorkerEventQueue& eventQueue() const override final; + WorkerThread& m_thread; + std::unique_ptr<WorkerScriptController> m_script; + std::unique_ptr<WorkerInspectorController> m_inspectorController; - URL m_url; - String m_userAgent; - std::unique_ptr<GroupSettings> m_groupSettings; + bool m_closing { false }; + bool m_shouldBypassMainWorldContentSecurityPolicy; - mutable RefPtr<WorkerLocation> m_location; - mutable RefPtr<WorkerNavigator> m_navigator; + mutable WorkerEventQueue m_eventQueue; - OwnPtr<WorkerScriptController> m_script; - WorkerThread* m_thread; + Ref<SecurityOrigin> m_topOrigin; -#if ENABLE(INSPECTOR) - const std::unique_ptr<WorkerInspectorController> m_workerInspectorController; +#if ENABLE(INDEXED_DATABASE) + RefPtr<IDBClient::IDBConnectionProxy> m_connectionProxy; #endif - bool m_closing; - HashSet<Observer*> m_workerObservers; +#if ENABLE(WEB_SOCKETS) + RefPtr<SocketProvider> m_socketProvider; +#endif - mutable WorkerEventQueue m_eventQueue; +#if ENABLE(WEB_TIMING) + RefPtr<Performance> m_performance; +#endif - RefPtr<SecurityOrigin> m_topOrigin; - }; + mutable RefPtr<Crypto> m_crypto; +}; } // namespace WebCore -#endif // WorkerGlobalScope_h +SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::WorkerGlobalScope) + static bool isType(const WebCore::ScriptExecutionContext& context) { return context.isWorkerGlobalScope(); } +SPECIALIZE_TYPE_TRAITS_END() diff --git a/Source/WebCore/workers/WorkerGlobalScope.idl b/Source/WebCore/workers/WorkerGlobalScope.idl index 1dc9054d2..16a5e0a0b 100644 --- a/Source/WebCore/workers/WorkerGlobalScope.idl +++ b/Source/WebCore/workers/WorkerGlobalScope.idl @@ -10,10 +10,10 @@ * 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 + * THIS SOFTWARE IS PROVIDED BY APPLE 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 + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE 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 @@ -21,43 +21,46 @@ * 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. - * */ [ - GlobalContext=WorkerGlobalScope, + CustomProxyToJSObject, + Exposed=Worker, JSCustomMarkFunction, - JSCustomGetOwnPropertySlotAndDescriptor, - EventTarget, JSLegacyParent=JSWorkerGlobalScopeBase, - JSNoStaticTables, -] interface WorkerGlobalScope { - - // WorkerGlobalScope -#if defined(LANGUAGE_JAVASCRIPT) && LANGUAGE_JAVASCRIPT - [Replaceable] readonly attribute WorkerGlobalScope self; -#endif - [Replaceable] readonly attribute WorkerLocation location; +] interface WorkerGlobalScope : EventTarget { + + readonly attribute WorkerGlobalScope self; + readonly attribute WorkerLocation location; void close(); - attribute EventListener onerror; - attribute EventListener onoffline; - attribute EventListener ononline; + + attribute EventHandler onerror; + attribute EventHandler onoffline; + attribute EventHandler ononline; // WorkerUtils - [Custom] void importScripts(/*[Variadic] DOMString urls */); - [Replaceable] readonly attribute WorkerNavigator navigator; - - // EventTarget interface - void addEventListener(DOMString type, - EventListener listener, - optional boolean useCapture); - void removeEventListener(DOMString type, - EventListener listener, - optional boolean useCapture); - [RaisesException] boolean dispatchEvent(Event evt); + + [MayThrowException] void importScripts(USVString... urls); + readonly attribute WorkerNavigator navigator; // Additional constructors - [Conditional=BLOB] attribute DOMURLConstructor webkitURL; // FIXME: deprecate this. + + attribute DOMURLConstructor webkitURL; // FIXME: deprecate this. + + // FIXME: Automatically generate these once we can drop the IndexedDBWorkers runtime flag. + [Conditional=INDEXED_DATABASE_IN_WORKERS, EnabledAtRuntime=IndexedDBWorkers] attribute IDBCursorConstructor IDBCursor; + [Conditional=INDEXED_DATABASE_IN_WORKERS, EnabledAtRuntime=IndexedDBWorkers] attribute IDBCursorWithValueConstructor IDBCursorWithValue; + [Conditional=INDEXED_DATABASE_IN_WORKERS, EnabledAtRuntime=IndexedDBWorkers] attribute IDBDatabaseConstructor IDBDatabase; + [Conditional=INDEXED_DATABASE_IN_WORKERS, EnabledAtRuntime=IndexedDBWorkers] attribute IDBFactoryConstructor IDBFactory; + [Conditional=INDEXED_DATABASE_IN_WORKERS, EnabledAtRuntime=IndexedDBWorkers] attribute IDBIndexConstructor IDBIndex; + [Conditional=INDEXED_DATABASE_IN_WORKERS, EnabledAtRuntime=IndexedDBWorkers] attribute IDBKeyRangeConstructor IDBKeyRange; + [Conditional=INDEXED_DATABASE_IN_WORKERS, EnabledAtRuntime=IndexedDBWorkers] attribute IDBObjectStoreConstructor IDBObjectStore; + [Conditional=INDEXED_DATABASE_IN_WORKERS, EnabledAtRuntime=IndexedDBWorkers] attribute IDBOpenDBRequestConstructor IDBOpenDBRequest; + [Conditional=INDEXED_DATABASE_IN_WORKERS, EnabledAtRuntime=IndexedDBWorkers] attribute IDBRequestConstructor IDBRequest; + [Conditional=INDEXED_DATABASE_IN_WORKERS, EnabledAtRuntime=IndexedDBWorkers] attribute IDBTransactionConstructor IDBTransaction; + [Conditional=INDEXED_DATABASE_IN_WORKERS, EnabledAtRuntime=IndexedDBWorkers] attribute IDBVersionChangeEventConstructor IDBVersionChangeEvent; }; -WorkerGlobalScope implements WindowTimers; +WorkerGlobalScope implements GlobalCrypto; +WorkerGlobalScope implements GlobalPerformance; +WorkerGlobalScope implements WindowOrWorkerGlobalScope; diff --git a/Source/WebCore/workers/WorkerGlobalScopeProxy.h b/Source/WebCore/workers/WorkerGlobalScopeProxy.h index 0a300710a..1cff6b7dc 100644 --- a/Source/WebCore/workers/WorkerGlobalScopeProxy.h +++ b/Source/WebCore/workers/WorkerGlobalScopeProxy.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2009 Google Inc. All rights reserved. + * Copyright (C) 2017 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 @@ -28,50 +29,31 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef WorkerGlobalScopeProxy_h -#define WorkerGlobalScopeProxy_h +#pragma once -#include "MessagePort.h" -#include "WorkerThread.h" -#include <wtf/Forward.h> -#include <wtf/PassOwnPtr.h> +#include "MessagePortChannel.h" +#include <runtime/RuntimeFlags.h> namespace WebCore { - class URL; - class Worker; +class ContentSecurityPolicyResponseHeaders; +class URL; +class Worker; - // A proxy to talk to the worker context. - class WorkerGlobalScopeProxy { - public: - static WorkerGlobalScopeProxy* create(Worker*); +// A proxy to talk to the worker context. +class WorkerGlobalScopeProxy { +public: + static WorkerGlobalScopeProxy& create(Worker&); - virtual ~WorkerGlobalScopeProxy() { } + virtual void startWorkerGlobalScope(const URL& scriptURL, const String& userAgent, const String& sourceCode, const ContentSecurityPolicyResponseHeaders&, bool shouldBypassMainWorldContentSecurityPolicy, MonotonicTime timeOrigin, JSC::RuntimeFlags) = 0; + virtual void terminateWorkerGlobalScope() = 0; + virtual void postMessageToWorkerGlobalScope(RefPtr<SerializedScriptValue>&&, std::unique_ptr<MessagePortChannelArray>) = 0; + virtual bool hasPendingActivity() const = 0; + virtual void workerObjectDestroyed() = 0; + virtual void notifyNetworkStateChange(bool isOnline) = 0; - virtual void startWorkerGlobalScope(const URL& scriptURL, const String& userAgent, const String& sourceCode, WorkerThreadStartMode) = 0; - - virtual void terminateWorkerGlobalScope() = 0; - - virtual void postMessageToWorkerGlobalScope(PassRefPtr<SerializedScriptValue>, PassOwnPtr<MessagePortChannelArray>) = 0; - - virtual bool hasPendingActivity() const = 0; - - virtual void workerObjectDestroyed() = 0; - - virtual void notifyNetworkStateChange(bool isOnline) = 0; - -#if ENABLE(INSPECTOR) - class PageInspector { - public: - virtual ~PageInspector() { } - virtual void dispatchMessageFromWorker(const String&) = 0; - }; - virtual void connectToInspector(PageInspector*) { } - virtual void disconnectFromInspector() { } - virtual void sendMessageToInspector(const String&) { } -#endif - }; +protected: + virtual ~WorkerGlobalScopeProxy() { } +}; } // namespace WebCore - -#endif // WorkerGlobalScopeProxy_h diff --git a/Source/WebCore/workers/WorkerInspectorProxy.cpp b/Source/WebCore/workers/WorkerInspectorProxy.cpp new file mode 100644 index 000000000..ab566caa3 --- /dev/null +++ b/Source/WebCore/workers/WorkerInspectorProxy.cpp @@ -0,0 +1,147 @@ +/* + * Copyright (C) 2016 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 INC. 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 INC. 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. + */ + +#include "config.h" +#include "WorkerInspectorProxy.h" + +#include "InspectorInstrumentation.h" +#include "ScriptExecutionContext.h" +#include "WorkerGlobalScope.h" +#include "WorkerInspectorController.h" +#include "WorkerRunLoop.h" +#include <inspector/InspectorAgentBase.h> +#include <wtf/NeverDestroyed.h> + +using namespace Inspector; + +namespace WebCore { + +HashSet<WorkerInspectorProxy*>& WorkerInspectorProxy::allWorkerInspectorProxies() +{ + static NeverDestroyed<HashSet<WorkerInspectorProxy*>> proxies; + return proxies; +} + +WorkerInspectorProxy::WorkerInspectorProxy(const String& identifier) + : m_identifier(identifier) +{ +} + +WorkerInspectorProxy::~WorkerInspectorProxy() +{ + ASSERT(!m_workerThread); + ASSERT(!m_pageChannel); +} + +WorkerThreadStartMode WorkerInspectorProxy::workerStartMode(ScriptExecutionContext& scriptExecutionContext) +{ + bool pauseOnStart = InspectorInstrumentation::shouldWaitForDebuggerOnStart(scriptExecutionContext); + return pauseOnStart ? WorkerThreadStartMode::WaitForInspector : WorkerThreadStartMode::Normal; +} + +void WorkerInspectorProxy::workerStarted(ScriptExecutionContext* scriptExecutionContext, WorkerThread* thread, const URL& url) +{ + ASSERT(!m_workerThread); + + m_scriptExecutionContext = scriptExecutionContext; + m_workerThread = thread; + m_url = url; + + allWorkerInspectorProxies().add(this); + + InspectorInstrumentation::workerStarted(*m_scriptExecutionContext.get(), this, m_url); +} + +void WorkerInspectorProxy::workerTerminated() +{ + if (!m_workerThread) + return; + + InspectorInstrumentation::workerTerminated(*m_scriptExecutionContext.get(), this); + + allWorkerInspectorProxies().remove(this); + + m_scriptExecutionContext = nullptr; + m_workerThread = nullptr; + m_pageChannel = nullptr; +} + +void WorkerInspectorProxy::resumeWorkerIfPaused() +{ + m_workerThread->runLoop().postTaskForMode([] (ScriptExecutionContext& context) { + downcast<WorkerGlobalScope>(context).thread().stopRunningDebuggerTasks(); + }, WorkerRunLoop::debuggerMode()); +} + +void WorkerInspectorProxy::connectToWorkerInspectorController(PageChannel* channel) +{ + ASSERT(m_workerThread); + if (!m_workerThread) + return; + + m_pageChannel = channel; + + m_workerThread->runLoop().postTaskForMode([] (ScriptExecutionContext& context) { + downcast<WorkerGlobalScope>(context).inspectorController().connectFrontend(); + }, WorkerRunLoop::debuggerMode()); +} + +void WorkerInspectorProxy::disconnectFromWorkerInspectorController() +{ + ASSERT(m_workerThread); + if (!m_workerThread) + return; + + m_pageChannel = nullptr; + + m_workerThread->runLoop().postTaskForMode([] (ScriptExecutionContext& context) { + downcast<WorkerGlobalScope>(context).inspectorController().disconnectFrontend(DisconnectReason::InspectorDestroyed); + + // In case the worker is paused running debugger tasks, ensure we break out of + // the pause since this will be the last debugger task we send to the worker. + downcast<WorkerGlobalScope>(context).thread().stopRunningDebuggerTasks(); + }, WorkerRunLoop::debuggerMode()); +} + +void WorkerInspectorProxy::sendMessageToWorkerInspectorController(const String& message) +{ + ASSERT(m_workerThread); + if (!m_workerThread) + return; + + m_workerThread->runLoop().postTaskForMode([message = message.isolatedCopy()] (ScriptExecutionContext& context) { + downcast<WorkerGlobalScope>(context).inspectorController().dispatchMessageFromFrontend(message); + }, WorkerRunLoop::debuggerMode()); +} + +void WorkerInspectorProxy::sendMessageFromWorkerToFrontend(const String& message) +{ + if (!m_pageChannel) + return; + + m_pageChannel->sendMessageFromWorkerToFrontend(this, message); +} + +} // namespace WebCore diff --git a/Source/WebCore/workers/WorkerInspectorProxy.h b/Source/WebCore/workers/WorkerInspectorProxy.h new file mode 100644 index 000000000..0c5aa4bd4 --- /dev/null +++ b/Source/WebCore/workers/WorkerInspectorProxy.h @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2016 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 INC. 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 INC. 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. + */ + +#pragma once + +#include "URL.h" +#include "WorkerThread.h" +#include <wtf/HashSet.h> +#include <wtf/text/WTFString.h> + +// All of these methods should be called on the Main Thread. +// Used to send messages to the WorkerInspector on the WorkerThread. + +namespace WebCore { + +class ScriptExecutionContext; +class WorkerThread; + +class WorkerInspectorProxy { + WTF_MAKE_NONCOPYABLE(WorkerInspectorProxy); + WTF_MAKE_FAST_ALLOCATED; +public: + WorkerInspectorProxy(const String& identifier); + ~WorkerInspectorProxy(); + + // A Worker's inspector messages come in and go out through the Page's WorkerAgent. + class PageChannel { + public: + virtual ~PageChannel() { } + virtual void sendMessageFromWorkerToFrontend(WorkerInspectorProxy*, const String&) = 0; + }; + + static HashSet<WorkerInspectorProxy*>& allWorkerInspectorProxies(); + + const URL& url() const { return m_url; } + const String& identifier() const { return m_identifier; } + ScriptExecutionContext* scriptExecutionContext() const { return m_scriptExecutionContext.get(); } + + WorkerThreadStartMode workerStartMode(ScriptExecutionContext&); + void workerStarted(ScriptExecutionContext*, WorkerThread*, const URL&); + void workerTerminated(); + + void resumeWorkerIfPaused(); + void connectToWorkerInspectorController(PageChannel*); + void disconnectFromWorkerInspectorController(); + void sendMessageToWorkerInspectorController(const String&); + void sendMessageFromWorkerToFrontend(const String&); + +private: + RefPtr<ScriptExecutionContext> m_scriptExecutionContext; + RefPtr<WorkerThread> m_workerThread; + String m_identifier; + URL m_url; + PageChannel* m_pageChannel { nullptr }; +}; + +} // namespace WebCore diff --git a/Source/WebCore/workers/WorkerLoaderProxy.h b/Source/WebCore/workers/WorkerLoaderProxy.h index 62931248d..b88f82ac0 100644 --- a/Source/WebCore/workers/WorkerLoaderProxy.h +++ b/Source/WebCore/workers/WorkerLoaderProxy.h @@ -28,12 +28,9 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef WorkerLoaderProxy_h -#define WorkerLoaderProxy_h +#pragma once #include "ScriptExecutionContext.h" -#include <wtf/Forward.h> -#include <wtf/PassOwnPtr.h> namespace WebCore { @@ -47,14 +44,12 @@ namespace WebCore { virtual ~WorkerLoaderProxy() { } // Posts a task to the thread which runs the loading code (normally, the main thread). - virtual void postTaskToLoader(PassOwnPtr<ScriptExecutionContext::Task>) = 0; + virtual void postTaskToLoader(ScriptExecutionContext::Task&&) = 0; // Posts callbacks from loading code to the WorkerGlobalScope. The 'mode' is used to differentiate // specific synchronous loading requests so they can be 'nested', per spec. // Returns true if the task was posted successfully. - virtual bool postTaskForModeToWorkerGlobalScope(PassOwnPtr<ScriptExecutionContext::Task>, const String& mode) = 0; + virtual bool postTaskForModeToWorkerGlobalScope(ScriptExecutionContext::Task&&, const String& mode) = 0; }; } // namespace WebCore - -#endif // WorkerLoaderProxy_h diff --git a/Source/WebCore/workers/WorkerLocation.cpp b/Source/WebCore/workers/WorkerLocation.cpp index 3a637c2c4..def41ffc1 100644 --- a/Source/WebCore/workers/WorkerLocation.cpp +++ b/Source/WebCore/workers/WorkerLocation.cpp @@ -10,10 +10,10 @@ * 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 + * THIS SOFTWARE IS PROVIDED BY APPLE 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 + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE 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 @@ -21,13 +21,12 @@ * 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" - #include "WorkerLocation.h" +#include "SecurityOrigin.h" #include <wtf/text/WTFString.h> namespace WebCore { @@ -39,12 +38,12 @@ String WorkerLocation::href() const String WorkerLocation::protocol() const { - return m_url.protocol() + ":"; + return makeString(m_url.protocol(), ":"); } String WorkerLocation::host() const { - return m_url.port() ? m_url.host() + ":" + String::number(m_url.port()) : m_url.host(); + return m_url.hostAndPort(); } String WorkerLocation::hostname() const @@ -54,7 +53,7 @@ String WorkerLocation::hostname() const String WorkerLocation::port() const { - return m_url.port() ? String::number(m_url.port()) : ""; + return m_url.port() ? String::number(m_url.port().value()) : emptyString(); } String WorkerLocation::pathname() const @@ -72,5 +71,9 @@ String WorkerLocation::hash() const return m_url.fragmentIdentifier().isEmpty() ? emptyString() : "#" + m_url.fragmentIdentifier(); } +String WorkerLocation::origin() const +{ + return SecurityOrigin::create(m_url)->toString(); +} } // namespace WebCore diff --git a/Source/WebCore/workers/WorkerLocation.h b/Source/WebCore/workers/WorkerLocation.h index d3d3b2884..53c776156 100644 --- a/Source/WebCore/workers/WorkerLocation.h +++ b/Source/WebCore/workers/WorkerLocation.h @@ -10,10 +10,10 @@ * 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 + * THIS SOFTWARE IS PROVIDED BY APPLE 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 + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE 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 @@ -21,25 +21,21 @@ * 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 +#pragma once #include "URL.h" -#include <wtf/PassRefPtr.h> #include <wtf/RefCounted.h> -#include <wtf/RefPtr.h> #include <wtf/text/WTFString.h> namespace WebCore { class WorkerLocation : public RefCounted<WorkerLocation> { public: - static PassRefPtr<WorkerLocation> create(const URL& url) + static Ref<WorkerLocation> create(const URL& url) { - return adoptRef(new WorkerLocation(url)); + return adoptRef(*new WorkerLocation(url)); } const URL& url() const { return m_url; } @@ -54,8 +50,7 @@ namespace WebCore { String pathname() const; String search() const; String hash() const; - - String toString() const { return href(); } + String origin() const; private: explicit WorkerLocation(const URL& url) : m_url(url) { } @@ -64,5 +59,3 @@ namespace WebCore { }; } // namespace WebCore - -#endif // WorkerLocation_h diff --git a/Source/WebCore/workers/WorkerLocation.idl b/Source/WebCore/workers/WorkerLocation.idl index ff54aa7c1..f025ebffb 100644 --- a/Source/WebCore/workers/WorkerLocation.idl +++ b/Source/WebCore/workers/WorkerLocation.idl @@ -10,7 +10,7 @@ * 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 + * 3. Neither the name of Apple 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. * @@ -27,20 +27,18 @@ */ [ - GlobalContext=WorkerGlobalScope, + Exposed=Worker, GenerateIsReachable=Impl, - JSNoStaticTables, ImplementationLacksVTable, ] interface 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; - - [NotEnumerable] DOMString toString(); + stringifier readonly attribute USVString href; + readonly attribute USVString protocol; + readonly attribute USVString host; + readonly attribute USVString hostname; + readonly attribute USVString port; + readonly attribute USVString pathname; + readonly attribute USVString search; + readonly attribute USVString hash; + readonly attribute USVString origin; }; diff --git a/Source/WebCore/workers/WorkerMessagingProxy.cpp b/Source/WebCore/workers/WorkerMessagingProxy.cpp index 324cd8944..d212f6c1f 100644 --- a/Source/WebCore/workers/WorkerMessagingProxy.cpp +++ b/Source/WebCore/workers/WorkerMessagingProxy.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Apple Inc. All Rights Reserved. + * Copyright (C) 2008-2017 Apple Inc. All Rights Reserved. * Copyright (C) 2009 Google Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without @@ -11,10 +11,10 @@ * 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 + * THIS SOFTWARE IS PROVIDED BY APPLE 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 + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE 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 @@ -26,363 +26,179 @@ */ #include "config.h" - #include "WorkerMessagingProxy.h" #include "ContentSecurityPolicy.h" -#include "CrossThreadTask.h" +#include "DOMWindow.h" #include "DedicatedWorkerGlobalScope.h" #include "DedicatedWorkerThread.h" -#include "DOMWindow.h" #include "Document.h" #include "ErrorEvent.h" -#include "Event.h" #include "EventNames.h" -#include "ExceptionCode.h" -#include "InspectorInstrumentation.h" #include "MessageEvent.h" -#include "NotImplemented.h" -#include "PageGroup.h" -#include "ScriptCallStack.h" #include "ScriptExecutionContext.h" #include "Worker.h" -#include "WorkerDebuggerAgent.h" -#include "WorkerInspectorController.h" -#include <inspector/InspectorAgentBase.h> +#include "WorkerInspectorProxy.h" +#include <inspector/ScriptCallStack.h> +#include <runtime/ConsoleTypes.h> #include <wtf/MainThread.h> +#include <wtf/RunLoop.h> namespace WebCore { -class MessageWorkerGlobalScopeTask : public ScriptExecutionContext::Task { -public: - static PassOwnPtr<MessageWorkerGlobalScopeTask> create(PassRefPtr<SerializedScriptValue> message, PassOwnPtr<MessagePortChannelArray> channels) - { - return adoptPtr(new MessageWorkerGlobalScopeTask(message, channels)); - } - -private: - MessageWorkerGlobalScopeTask(PassRefPtr<SerializedScriptValue> message, PassOwnPtr<MessagePortChannelArray> channels) - : m_message(message) - , m_channels(channels) - { - } - - virtual void performTask(ScriptExecutionContext* scriptContext) - { - ASSERT_WITH_SECURITY_IMPLICATION(scriptContext->isWorkerGlobalScope()); - DedicatedWorkerGlobalScope* context = static_cast<DedicatedWorkerGlobalScope*>(scriptContext); - OwnPtr<MessagePortArray> ports = MessagePort::entanglePorts(*scriptContext, m_channels.release()); - context->dispatchEvent(MessageEvent::create(ports.release(), m_message)); - context->thread()->workerObjectProxy().confirmMessageFromWorkerObject(context->hasPendingActivity()); - } - -private: - RefPtr<SerializedScriptValue> m_message; - OwnPtr<MessagePortChannelArray> m_channels; -}; - -class MessageWorkerTask : public ScriptExecutionContext::Task { -public: - static PassOwnPtr<MessageWorkerTask> create(PassRefPtr<SerializedScriptValue> message, PassOwnPtr<MessagePortChannelArray> channels, WorkerMessagingProxy* messagingProxy) - { - return adoptPtr(new MessageWorkerTask(message, channels, messagingProxy)); - } - -private: - MessageWorkerTask(PassRefPtr<SerializedScriptValue> message, PassOwnPtr<MessagePortChannelArray> channels, WorkerMessagingProxy* messagingProxy) - : m_message(message) - , m_channels(channels) - , m_messagingProxy(messagingProxy) - { - } - - virtual void performTask(ScriptExecutionContext* scriptContext) - { - Worker* workerObject = m_messagingProxy->workerObject(); - if (!workerObject || m_messagingProxy->askedToTerminate()) - return; - - OwnPtr<MessagePortArray> ports = MessagePort::entanglePorts(*scriptContext, m_channels.release()); - workerObject->dispatchEvent(MessageEvent::create(ports.release(), m_message)); - } - -private: - RefPtr<SerializedScriptValue> m_message; - OwnPtr<MessagePortChannelArray> m_channels; - WorkerMessagingProxy* m_messagingProxy; -}; - -class WorkerExceptionTask : public ScriptExecutionContext::Task { -public: - static PassOwnPtr<WorkerExceptionTask> create(const String& errorMessage, int lineNumber, int columnNumber, const String& sourceURL, WorkerMessagingProxy* messagingProxy) - { - return adoptPtr(new WorkerExceptionTask(errorMessage, lineNumber, columnNumber, sourceURL, messagingProxy)); - } - -private: - WorkerExceptionTask(const String& errorMessage, int lineNumber, int columnNumber, const String& sourceURL, WorkerMessagingProxy* messagingProxy) - : m_errorMessage(errorMessage.isolatedCopy()) - , m_lineNumber(lineNumber) - , m_columnNumber(columnNumber) - , m_sourceURL(sourceURL.isolatedCopy()) - , m_messagingProxy(messagingProxy) - { - } - - virtual void performTask(ScriptExecutionContext* context) - { - Worker* workerObject = m_messagingProxy->workerObject(); - if (!workerObject) - return; - - // We don't bother checking the askedToTerminate() flag here, because exceptions should *always* be reported even if the thread is terminated. - // This is intentionally different than the behavior in MessageWorkerTask, because terminated workers no longer deliver messages (section 4.6 of the WebWorker spec), but they do report exceptions. - - bool errorHandled = !workerObject->dispatchEvent(ErrorEvent::create(m_errorMessage, m_sourceURL, m_lineNumber, m_columnNumber)); - if (!errorHandled) - context->reportException(m_errorMessage, m_lineNumber, m_columnNumber, m_sourceURL, 0); - } - - String m_errorMessage; - int m_lineNumber; - int m_columnNumber; - String m_sourceURL; - WorkerMessagingProxy* m_messagingProxy; -}; - -class WorkerGlobalScopeDestroyedTask : public ScriptExecutionContext::Task { -public: - static PassOwnPtr<WorkerGlobalScopeDestroyedTask> create(WorkerMessagingProxy* messagingProxy) - { - return adoptPtr(new WorkerGlobalScopeDestroyedTask(messagingProxy)); - } - -private: - WorkerGlobalScopeDestroyedTask(WorkerMessagingProxy* messagingProxy) - : m_messagingProxy(messagingProxy) - { - } - - virtual void performTask(ScriptExecutionContext*) - { - m_messagingProxy->workerGlobalScopeDestroyedInternal(); - } - - WorkerMessagingProxy* m_messagingProxy; -}; - -class WorkerTerminateTask : public ScriptExecutionContext::Task { -public: - static PassOwnPtr<WorkerTerminateTask> create(WorkerMessagingProxy* messagingProxy) - { - return adoptPtr(new WorkerTerminateTask(messagingProxy)); - } - -private: - WorkerTerminateTask(WorkerMessagingProxy* messagingProxy) - : m_messagingProxy(messagingProxy) - { - } - - virtual void performTask(ScriptExecutionContext*) - { - m_messagingProxy->terminateWorkerGlobalScope(); - } - - WorkerMessagingProxy* m_messagingProxy; -}; - -class WorkerThreadActivityReportTask : public ScriptExecutionContext::Task { -public: - static PassOwnPtr<WorkerThreadActivityReportTask> create(WorkerMessagingProxy* messagingProxy, bool confirmingMessage, bool hasPendingActivity) - { - return adoptPtr(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; -}; - -class PostMessageToPageInspectorTask : public ScriptExecutionContext::Task { -public: - static PassOwnPtr<PostMessageToPageInspectorTask> create(WorkerMessagingProxy* messagingProxy, const String& message) - { - return adoptPtr(new PostMessageToPageInspectorTask(messagingProxy, message)); - } - -private: - PostMessageToPageInspectorTask(WorkerMessagingProxy* messagingProxy, const String& message) - : m_messagingProxy(messagingProxy) - , m_message(message.isolatedCopy()) - { - } - - virtual void performTask(ScriptExecutionContext*) - { -#if ENABLE(INSPECTOR) - if (WorkerGlobalScopeProxy::PageInspector* pageInspector = m_messagingProxy->m_pageInspector) - pageInspector->dispatchMessageFromWorker(m_message); -#endif - } - - WorkerMessagingProxy* m_messagingProxy; - String m_message; -}; - -class NotifyNetworkStateChangeTask : public ScriptExecutionContext::Task { -public: - static PassOwnPtr<NotifyNetworkStateChangeTask> create(bool isOnLine) - { - return adoptPtr(new NotifyNetworkStateChangeTask(isOnLine)); - } - -private: - NotifyNetworkStateChangeTask(bool isOnLine) - : m_isOnLine(isOnLine) - { - } - - virtual void performTask(ScriptExecutionContext *context) - { - AtomicString eventName = m_isOnLine ? eventNames().onlineEvent : eventNames().offlineEvent; - WorkerGlobalScope* workerGlobalScope = static_cast<WorkerGlobalScope*>(context); - workerGlobalScope->dispatchEvent(Event::create(eventName, false, false)); - } - - bool m_isOnLine; -}; - - -WorkerGlobalScopeProxy* WorkerGlobalScopeProxy::create(Worker* worker) +WorkerGlobalScopeProxy& WorkerGlobalScopeProxy::create(Worker& worker) { - return new WorkerMessagingProxy(worker); + return *new WorkerMessagingProxy(worker); } -WorkerMessagingProxy::WorkerMessagingProxy(Worker* workerObject) - : m_scriptExecutionContext(workerObject->scriptExecutionContext()) - , m_workerObject(workerObject) - , m_mayBeDestroyed(false) - , m_unconfirmedMessageCount(0) - , m_workerThreadHadPendingActivity(false) - , m_askedToTerminate(false) -#if ENABLE(INSPECTOR) - , m_pageInspector(0) -#endif +WorkerMessagingProxy::WorkerMessagingProxy(Worker& workerObject) + : m_scriptExecutionContext(workerObject.scriptExecutionContext()) + , m_inspectorProxy(std::make_unique<WorkerInspectorProxy>(workerObject.identifier())) + , m_workerObject(&workerObject) { - ASSERT(m_workerObject); - ASSERT((m_scriptExecutionContext->isDocument() && isMainThread()) - || (m_scriptExecutionContext->isWorkerGlobalScope() && currentThread() == static_cast<WorkerGlobalScope*>(m_scriptExecutionContext.get())->thread()->threadID())); + ASSERT((is<Document>(*m_scriptExecutionContext) && isMainThread()) + || (is<WorkerGlobalScope>(*m_scriptExecutionContext) && currentThread() == downcast<WorkerGlobalScope>(*m_scriptExecutionContext).thread().threadID())); + + // Nobody outside this class ref counts this object. The original ref + // is balanced by the deref in workerGlobalScopeDestroyedInternal. } WorkerMessagingProxy::~WorkerMessagingProxy() { ASSERT(!m_workerObject); - ASSERT((m_scriptExecutionContext->isDocument() && isMainThread()) - || (m_scriptExecutionContext->isWorkerGlobalScope() && currentThread() == static_cast<WorkerGlobalScope*>(m_scriptExecutionContext.get())->thread()->threadID())); + ASSERT((is<Document>(*m_scriptExecutionContext) && isMainThread()) + || (is<WorkerGlobalScope>(*m_scriptExecutionContext) && currentThread() == downcast<WorkerGlobalScope>(*m_scriptExecutionContext).thread().threadID())); } -void WorkerMessagingProxy::startWorkerGlobalScope(const URL& scriptURL, const String& userAgent, const String& sourceCode, WorkerThreadStartMode startMode) +void WorkerMessagingProxy::startWorkerGlobalScope(const URL& scriptURL, const String& userAgent, const String& sourceCode, const ContentSecurityPolicyResponseHeaders& contentSecurityPolicyResponseHeaders, bool shouldBypassMainWorldContentSecurityPolicy, MonotonicTime timeOrigin, JSC::RuntimeFlags runtimeFlags) { // FIXME: This need to be revisited when we support nested worker one day - ASSERT_WITH_SECURITY_IMPLICATION(m_scriptExecutionContext->isDocument()); - Document* document = static_cast<Document*>(m_scriptExecutionContext.get()); - GroupSettings* settings = 0; - if (document->page()) - settings = &document->page()->group().groupSettings(); - RefPtr<DedicatedWorkerThread> thread = DedicatedWorkerThread::create(scriptURL, userAgent, settings, sourceCode, *this, *this, startMode, document->contentSecurityPolicy()->deprecatedHeader(), document->contentSecurityPolicy()->deprecatedHeaderType(), document->topOrigin()); - workerThreadCreated(thread); + ASSERT(m_scriptExecutionContext); + Document& document = downcast<Document>(*m_scriptExecutionContext); + WorkerThreadStartMode startMode = m_inspectorProxy->workerStartMode(*m_scriptExecutionContext.get()); + String identifier = m_inspectorProxy->identifier(); + +#if ENABLE(INDEXED_DATABASE) + IDBClient::IDBConnectionProxy* proxy = document.idbConnectionProxy(); +#else + IDBClient::IDBConnectionProxy* proxy = nullptr; +#endif + +#if ENABLE(WEB_SOCKETS) + SocketProvider* socketProvider = document.socketProvider(); +#else + SocketProvider* socketProvider = nullptr; +#endif + + auto thread = DedicatedWorkerThread::create(scriptURL, identifier, userAgent, sourceCode, *this, *this, startMode, contentSecurityPolicyResponseHeaders, shouldBypassMainWorldContentSecurityPolicy, document.topOrigin(), timeOrigin, proxy, socketProvider, runtimeFlags); + + workerThreadCreated(thread.get()); thread->start(); - InspectorInstrumentation::didStartWorkerGlobalScope(m_scriptExecutionContext.get(), this, scriptURL); + + m_inspectorProxy->workerStarted(m_scriptExecutionContext.get(), thread.ptr(), scriptURL); } -void WorkerMessagingProxy::postMessageToWorkerObject(PassRefPtr<SerializedScriptValue> message, PassOwnPtr<MessagePortChannelArray> channels) +void WorkerMessagingProxy::postMessageToWorkerObject(RefPtr<SerializedScriptValue>&& message, std::unique_ptr<MessagePortChannelArray> channels) { - m_scriptExecutionContext->postTask(MessageWorkerTask::create(message, channels, this)); + m_scriptExecutionContext->postTask([this, channels = WTFMove(channels), message = WTFMove(message)] (ScriptExecutionContext& context) mutable { + Worker* workerObject = this->workerObject(); + if (!workerObject || askedToTerminate()) + return; + + auto ports = MessagePort::entanglePorts(context, WTFMove(channels)); + workerObject->dispatchEvent(MessageEvent::create(WTFMove(ports), WTFMove(message))); + }); } -void WorkerMessagingProxy::postMessageToWorkerGlobalScope(PassRefPtr<SerializedScriptValue> message, PassOwnPtr<MessagePortChannelArray> channels) +void WorkerMessagingProxy::postMessageToWorkerGlobalScope(RefPtr<SerializedScriptValue>&& message, std::unique_ptr<MessagePortChannelArray> channels) { if (m_askedToTerminate) return; + ScriptExecutionContext::Task task([channels = WTFMove(channels), message = WTFMove(message)] (ScriptExecutionContext& scriptContext) mutable { + ASSERT_WITH_SECURITY_IMPLICATION(scriptContext.isWorkerGlobalScope()); + auto& context = static_cast<DedicatedWorkerGlobalScope&>(scriptContext); + auto ports = MessagePort::entanglePorts(scriptContext, WTFMove(channels)); + context.dispatchEvent(MessageEvent::create(WTFMove(ports), WTFMove(message))); + context.thread().workerObjectProxy().confirmMessageFromWorkerObject(context.hasPendingActivity()); + }); + if (m_workerThread) { ++m_unconfirmedMessageCount; - m_workerThread->runLoop().postTask(MessageWorkerGlobalScopeTask::create(message, channels)); + m_workerThread->runLoop().postTask(WTFMove(task)); } else - m_queuedEarlyTasks.append(MessageWorkerGlobalScopeTask::create(message, channels)); + m_queuedEarlyTasks.append(std::make_unique<ScriptExecutionContext::Task>(WTFMove(task))); +} + +void WorkerMessagingProxy::postTaskToLoader(ScriptExecutionContext::Task&& task) +{ + // FIXME: In case of nested workers, this should go directly to the root Document context. + ASSERT(m_scriptExecutionContext->isDocument()); + m_scriptExecutionContext->postTask(WTFMove(task)); } -bool WorkerMessagingProxy::postTaskForModeToWorkerGlobalScope(PassOwnPtr<ScriptExecutionContext::Task> task, const String& mode) +bool WorkerMessagingProxy::postTaskForModeToWorkerGlobalScope(ScriptExecutionContext::Task&& task, const String& mode) { if (m_askedToTerminate) return false; ASSERT(m_workerThread); - m_workerThread->runLoop().postTaskForMode(task, mode); + m_workerThread->runLoop().postTaskForMode(WTFMove(task), mode); return true; } -void WorkerMessagingProxy::postTaskToLoader(PassOwnPtr<ScriptExecutionContext::Task> task) -{ - // FIXME: In case of nested workers, this should go directly to the root Document context. - ASSERT(m_scriptExecutionContext->isDocument()); - m_scriptExecutionContext->postTask(task); -} - void WorkerMessagingProxy::postExceptionToWorkerObject(const String& errorMessage, int lineNumber, int columnNumber, const String& sourceURL) { - m_scriptExecutionContext->postTask(WorkerExceptionTask::create(errorMessage, lineNumber, columnNumber, sourceURL, this)); -} + m_scriptExecutionContext->postTask([this, errorMessage = errorMessage.isolatedCopy(), sourceURL = sourceURL.isolatedCopy(), lineNumber, columnNumber] (ScriptExecutionContext& context) { + Worker* workerObject = this->workerObject(); + if (!workerObject) + return; -static void postConsoleMessageTask(ScriptExecutionContext* context, WorkerMessagingProxy* messagingProxy, MessageSource source, MessageLevel level, const String& message, unsigned lineNumber, unsigned columnNumber, const String& sourceURL) -{ - if (messagingProxy->askedToTerminate()) - return; - context->addConsoleMessage(source, level, message, sourceURL, lineNumber, columnNumber); + // We don't bother checking the askedToTerminate() flag here, because exceptions should *always* be reported even if the thread is terminated. + // This is intentionally different than the behavior in MessageWorkerTask, because terminated workers no longer deliver messages (section 4.6 of the WebWorker spec), but they do report exceptions. + + bool errorHandled = !workerObject->dispatchEvent(ErrorEvent::create(errorMessage, sourceURL, lineNumber, columnNumber, { })); + if (!errorHandled) + context.reportException(errorMessage, lineNumber, columnNumber, sourceURL, nullptr, nullptr); + }); } -void WorkerMessagingProxy::postConsoleMessageToWorkerObject(MessageSource source, MessageLevel level, const String& message, int lineNumber, int columnNumber, const String& sourceURL) +void WorkerMessagingProxy::postMessageToPageInspector(const String& message) { - m_scriptExecutionContext->postTask(createCallbackTask(&postConsoleMessageTask, AllowCrossThreadAccess(this), source, level, message, lineNumber, columnNumber, sourceURL)); + RunLoop::main().dispatch([this, protectedThis = makeRef(*this), message = message.isolatedCopy()] { + if (!m_mayBeDestroyed) + m_inspectorProxy->sendMessageFromWorkerToFrontend(message); + }); } -void WorkerMessagingProxy::workerThreadCreated(PassRefPtr<DedicatedWorkerThread> workerThread) +void WorkerMessagingProxy::workerThreadCreated(DedicatedWorkerThread& workerThread) { - m_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_unconfirmedMessageCount = m_queuedEarlyTasks.size(); m_workerThreadHadPendingActivity = true; // Worker initialization means a pending activity. - for (unsigned i = 0; i < taskCount; ++i) - m_workerThread->runLoop().postTask(m_queuedEarlyTasks[i].release()); - m_queuedEarlyTasks.clear(); + auto queuedEarlyTasks = WTFMove(m_queuedEarlyTasks); + for (auto& task : queuedEarlyTasks) + m_workerThread->runLoop().postTask(WTFMove(*task)); } } void WorkerMessagingProxy::workerObjectDestroyed() { - m_workerObject = 0; - m_scriptExecutionContext->postTask(createCallbackTask(&workerObjectDestroyedInternal, AllowCrossThreadAccess(this))); + m_workerObject = nullptr; + m_scriptExecutionContext->postTask([this] (ScriptExecutionContext&) { + m_mayBeDestroyed = true; + if (m_workerThread) + terminateWorkerGlobalScope(); + else + workerGlobalScopeDestroyedInternal(); + }); } void WorkerMessagingProxy::notifyNetworkStateChange(bool isOnline) @@ -393,86 +209,37 @@ void WorkerMessagingProxy::notifyNetworkStateChange(bool isOnline) if (!m_workerThread) return; - m_workerThread->runLoop().postTask(NotifyNetworkStateChangeTask::create(isOnline)); + m_workerThread->runLoop().postTask([isOnline] (ScriptExecutionContext& context) { + downcast<WorkerGlobalScope>(context).dispatchEvent(Event::create(isOnline ? eventNames().onlineEvent : eventNames().offlineEvent, false, false)); + }); } -void WorkerMessagingProxy::workerObjectDestroyedInternal(ScriptExecutionContext*, WorkerMessagingProxy* proxy) -{ - proxy->m_mayBeDestroyed = true; - if (proxy->m_workerThread) - proxy->terminateWorkerGlobalScope(); - else - proxy->workerGlobalScopeDestroyedInternal(); -} - -#if ENABLE(INSPECTOR) -static void connectToWorkerGlobalScopeInspectorTask(ScriptExecutionContext* context, bool) -{ - ASSERT_WITH_SECURITY_IMPLICATION(context->isWorkerGlobalScope()); - static_cast<WorkerGlobalScope*>(context)->workerInspectorController().connectFrontend(); -} - -void WorkerMessagingProxy::connectToInspector(WorkerGlobalScopeProxy::PageInspector* pageInspector) -{ - if (m_askedToTerminate) - return; - ASSERT(!m_pageInspector); - m_pageInspector = pageInspector; - m_workerThread->runLoop().postTaskForMode(createCallbackTask(connectToWorkerGlobalScopeInspectorTask, true), WorkerDebuggerAgent::debuggerTaskMode); -} - -static void disconnectFromWorkerGlobalScopeInspectorTask(ScriptExecutionContext* context, bool) -{ - ASSERT_WITH_SECURITY_IMPLICATION(context->isWorkerGlobalScope()); - static_cast<WorkerGlobalScope*>(context)->workerInspectorController().disconnectFrontend(Inspector::InspectorDisconnectReason::InspectorDestroyed); -} - -void WorkerMessagingProxy::disconnectFromInspector() -{ - m_pageInspector = 0; - if (m_askedToTerminate) - return; - m_workerThread->runLoop().postTaskForMode(createCallbackTask(disconnectFromWorkerGlobalScopeInspectorTask, true), WorkerDebuggerAgent::debuggerTaskMode); -} - -static void dispatchOnInspectorBackendTask(ScriptExecutionContext* context, const String& message) -{ - ASSERT_WITH_SECURITY_IMPLICATION(context->isWorkerGlobalScope()); - static_cast<WorkerGlobalScope*>(context)->workerInspectorController().dispatchMessageFromFrontend(message); -} - -void WorkerMessagingProxy::sendMessageToInspector(const String& message) -{ - if (m_askedToTerminate) - return; - m_workerThread->runLoop().postTaskForMode(createCallbackTask(dispatchOnInspectorBackendTask, String(message)), WorkerDebuggerAgent::debuggerTaskMode); - WorkerDebuggerAgent::interruptAndDispatchInspectorCommands(m_workerThread.get()); -} -#endif - void WorkerMessagingProxy::workerGlobalScopeDestroyed() { - m_scriptExecutionContext->postTask(WorkerGlobalScopeDestroyedTask::create(this)); - // Will execute workerGlobalScopeDestroyedInternal() on context's thread. + m_scriptExecutionContext->postTask([this] (ScriptExecutionContext&) { + workerGlobalScopeDestroyedInternal(); + }); } void WorkerMessagingProxy::workerGlobalScopeClosed() { - // Executes terminateWorkerGlobalScope() on parent context's thread. - m_scriptExecutionContext->postTask(WorkerTerminateTask::create(this)); + m_scriptExecutionContext->postTask([this] (ScriptExecutionContext&) { + terminateWorkerGlobalScope(); + }); } void WorkerMessagingProxy::workerGlobalScopeDestroyedInternal() { - // WorkerGlobalScopeDestroyedTask is always the last to be performed, so the proxy is not needed for communication + // This is always the last task 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_askedToTerminate = true; - m_workerThread = 0; + m_workerThread = nullptr; - InspectorInstrumentation::workerGlobalScopeTerminated(m_scriptExecutionContext.get(), this); + m_inspectorProxy->workerTerminated(); + // This balances the original ref in construction. if (m_mayBeDestroyed) - delete this; + deref(); } void WorkerMessagingProxy::terminateWorkerGlobalScope() @@ -481,29 +248,24 @@ void WorkerMessagingProxy::terminateWorkerGlobalScope() return; m_askedToTerminate = true; + m_inspectorProxy->workerTerminated(); + if (m_workerThread) m_workerThread->stop(); - - InspectorInstrumentation::workerGlobalScopeTerminated(m_scriptExecutionContext.get(), this); -} - -#if ENABLE(INSPECTOR) -void WorkerMessagingProxy::postMessageToPageInspector(const String& message) -{ - m_scriptExecutionContext->postTask(PostMessageToPageInspectorTask::create(this, message)); } -#endif void WorkerMessagingProxy::confirmMessageFromWorkerObject(bool hasPendingActivity) { - m_scriptExecutionContext->postTask(WorkerThreadActivityReportTask::create(this, true, hasPendingActivity)); - // Will execute reportPendingActivityInternal() on context's thread. + m_scriptExecutionContext->postTask([this, hasPendingActivity] (ScriptExecutionContext&) { + reportPendingActivityInternal(true, hasPendingActivity); + }); } void WorkerMessagingProxy::reportPendingActivity(bool hasPendingActivity) { - m_scriptExecutionContext->postTask(WorkerThreadActivityReportTask::create(this, false, hasPendingActivity)); - // Will execute reportPendingActivityInternal() on context's thread. + m_scriptExecutionContext->postTask([this, hasPendingActivity] (ScriptExecutionContext&) { + reportPendingActivityInternal(false, hasPendingActivity); + }); } void WorkerMessagingProxy::reportPendingActivityInternal(bool confirmingMessage, bool hasPendingActivity) diff --git a/Source/WebCore/workers/WorkerMessagingProxy.h b/Source/WebCore/workers/WorkerMessagingProxy.h index bf607f582..8fd3cd6a3 100644 --- a/Source/WebCore/workers/WorkerMessagingProxy.h +++ b/Source/WebCore/workers/WorkerMessagingProxy.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Apple Inc. All Rights Reserved. + * Copyright (C) 2008-2017 Apple Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -10,10 +10,10 @@ * 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 + * THIS SOFTWARE IS PROVIDED BY APPLE 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 + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE 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 @@ -21,103 +21,73 @@ * 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 +#pragma once -#include "ScriptExecutionContext.h" #include "WorkerGlobalScopeProxy.h" #include "WorkerLoaderProxy.h" #include "WorkerObjectProxy.h" -#include <wtf/Forward.h> -#include <wtf/Noncopyable.h> -#include <wtf/PassOwnPtr.h> -#include <wtf/PassRefPtr.h> -#include <wtf/RefPtr.h> -#include <wtf/Vector.h> +#include <wtf/ThreadSafeRefCounted.h> namespace WebCore { - class DedicatedWorkerThread; - class ScriptExecutionContext; - class Worker; - - class WorkerMessagingProxy : public WorkerGlobalScopeProxy, public WorkerObjectProxy, public WorkerLoaderProxy { - WTF_MAKE_NONCOPYABLE(WorkerMessagingProxy); WTF_MAKE_FAST_ALLOCATED; - public: - explicit WorkerMessagingProxy(Worker*); - - // Implementations of WorkerGlobalScopeProxy. - // (Only use these methods in the worker object thread.) - virtual void startWorkerGlobalScope(const URL& scriptURL, const String& userAgent, const String& sourceCode, WorkerThreadStartMode) override; - virtual void terminateWorkerGlobalScope() override; - virtual void postMessageToWorkerGlobalScope(PassRefPtr<SerializedScriptValue>, PassOwnPtr<MessagePortChannelArray>) override; - virtual bool hasPendingActivity() const override; - virtual void workerObjectDestroyed() override; - virtual void notifyNetworkStateChange(bool isOnline) override; -#if ENABLE(INSPECTOR) - virtual void connectToInspector(WorkerGlobalScopeProxy::PageInspector*) override; - virtual void disconnectFromInspector() override; - virtual void sendMessageToInspector(const String&) override; -#endif - - // Implementations of WorkerObjectProxy. - // (Only use these methods in the worker context thread.) - virtual void postMessageToWorkerObject(PassRefPtr<SerializedScriptValue>, PassOwnPtr<MessagePortChannelArray>) override; - virtual void postExceptionToWorkerObject(const String& errorMessage, int lineNumber, int columnNumber, const String& sourceURL) override; - virtual void postConsoleMessageToWorkerObject(MessageSource, MessageLevel, const String& message, int lineNumber, int columnNumber, const String& sourceURL) override; -#if ENABLE(INSPECTOR) - virtual void postMessageToPageInspector(const String&) override; -#endif - virtual void confirmMessageFromWorkerObject(bool hasPendingActivity) override; - virtual void reportPendingActivity(bool hasPendingActivity) override; - virtual void workerGlobalScopeClosed() override; - virtual void workerGlobalScopeDestroyed() override; - - // Implementation of WorkerLoaderProxy. - // These methods are called on different threads to schedule loading - // requests and to send callbacks back to WorkerGlobalScope. - virtual void postTaskToLoader(PassOwnPtr<ScriptExecutionContext::Task>) override; - virtual bool postTaskForModeToWorkerGlobalScope(PassOwnPtr<ScriptExecutionContext::Task>, const String& mode) override; - - void workerThreadCreated(PassRefPtr<DedicatedWorkerThread>); - - // Only use this method on the worker object thread. - bool askedToTerminate() const { return m_askedToTerminate; } - - protected: - virtual ~WorkerMessagingProxy(); - - private: - friend class MessageWorkerTask; - friend class PostMessageToPageInspectorTask; - friend class WorkerGlobalScopeDestroyedTask; - friend class WorkerExceptionTask; - friend class WorkerThreadActivityReportTask; - - void workerGlobalScopeDestroyedInternal(); - static void workerObjectDestroyedInternal(ScriptExecutionContext*, WorkerMessagingProxy*); - void reportPendingActivityInternal(bool confirmingMessage, bool hasPendingActivity); - Worker* workerObject() const { return m_workerObject; } - - RefPtr<ScriptExecutionContext> m_scriptExecutionContext; - Worker* m_workerObject; - bool m_mayBeDestroyed; - RefPtr<DedicatedWorkerThread> 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<OwnPtr<ScriptExecutionContext::Task>> m_queuedEarlyTasks; // Tasks are queued here until there's a thread object created. -#if ENABLE(INSPECTOR) - WorkerGlobalScopeProxy::PageInspector* m_pageInspector; -#endif - }; +class DedicatedWorkerThread; +class WorkerInspectorProxy; + +class WorkerMessagingProxy final : public ThreadSafeRefCounted<WorkerMessagingProxy>, public WorkerGlobalScopeProxy, public WorkerObjectProxy, public WorkerLoaderProxy { + WTF_MAKE_FAST_ALLOCATED; +public: + explicit WorkerMessagingProxy(Worker&); + virtual ~WorkerMessagingProxy(); + +private: + // Implementations of WorkerGlobalScopeProxy. + // (Only use these functions in the worker object thread.) + void startWorkerGlobalScope(const URL& scriptURL, const String& userAgent, const String& sourceCode, const ContentSecurityPolicyResponseHeaders&, bool shouldBypassMainWorldContentSecurityPolicy, MonotonicTime timeOrigin, JSC::RuntimeFlags) final; + void terminateWorkerGlobalScope() final; + void postMessageToWorkerGlobalScope(RefPtr<SerializedScriptValue>&&, std::unique_ptr<MessagePortChannelArray>) final; + bool hasPendingActivity() const final; + void workerObjectDestroyed() final; + void notifyNetworkStateChange(bool isOnline) final; + + // Implementations of WorkerObjectProxy. + // (Only use these functions in the worker context thread.) + void postMessageToWorkerObject(RefPtr<SerializedScriptValue>&&, std::unique_ptr<MessagePortChannelArray>) final; + void postExceptionToWorkerObject(const String& errorMessage, int lineNumber, int columnNumber, const String& sourceURL) final; + void postMessageToPageInspector(const String&) final; + void confirmMessageFromWorkerObject(bool hasPendingActivity) final; + void reportPendingActivity(bool hasPendingActivity) final; + void workerGlobalScopeClosed() final; + void workerGlobalScopeDestroyed() final; + + // Implementation of WorkerLoaderProxy. + // These functions are called on different threads to schedule loading + // requests and to send callbacks back to WorkerGlobalScope. + void postTaskToLoader(ScriptExecutionContext::Task&&) final; + bool postTaskForModeToWorkerGlobalScope(ScriptExecutionContext::Task&&, const String& mode) final; + + void workerThreadCreated(DedicatedWorkerThread&); + + // Only use this method on the worker object thread. + bool askedToTerminate() const { return m_askedToTerminate; } + + void workerGlobalScopeDestroyedInternal(); + void reportPendingActivityInternal(bool confirmingMessage, bool hasPendingActivity); + Worker* workerObject() const { return m_workerObject; } + + RefPtr<ScriptExecutionContext> m_scriptExecutionContext; + std::unique_ptr<WorkerInspectorProxy> m_inspectorProxy; + Worker* m_workerObject; + bool m_mayBeDestroyed { false }; + RefPtr<DedicatedWorkerThread> m_workerThread; + + unsigned m_unconfirmedMessageCount { 0 }; // Unconfirmed messages from worker object to worker thread. + bool m_workerThreadHadPendingActivity { false }; // The latest confirmation from worker thread reported that it was still active. + + bool m_askedToTerminate { false }; + + Vector<std::unique_ptr<ScriptExecutionContext::Task>> m_queuedEarlyTasks; // Tasks are queued here until there's a thread object created. +}; } // namespace WebCore - -#endif // WorkerMessagingProxy_h diff --git a/Source/WebCore/workers/WorkerObjectProxy.h b/Source/WebCore/workers/WorkerObjectProxy.h index e6a4b7d73..e89c84cef 100644 --- a/Source/WebCore/workers/WorkerObjectProxy.h +++ b/Source/WebCore/workers/WorkerObjectProxy.h @@ -28,12 +28,11 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef WorkerObjectProxy_h -#define WorkerObjectProxy_h +#pragma once #include "WorkerReportingProxy.h" #include "MessagePort.h" -#include <wtf/PassOwnPtr.h> +#include <memory> namespace WebCore { @@ -42,15 +41,13 @@ namespace WebCore { // A proxy to talk to the worker object. class WorkerObjectProxy : public WorkerReportingProxy { public: - virtual void postMessageToWorkerObject(PassRefPtr<SerializedScriptValue>, PassOwnPtr<MessagePortChannelArray>) = 0; + virtual void postMessageToWorkerObject(RefPtr<SerializedScriptValue>&&, std::unique_ptr<MessagePortChannelArray>) = 0; virtual void confirmMessageFromWorkerObject(bool hasPendingActivity) = 0; virtual void reportPendingActivity(bool hasPendingActivity) = 0; // No need to notify the parent page context when dedicated workers are closing. - virtual void workerGlobalScopeClosed() override { } + void workerGlobalScopeClosed() override { } }; } // namespace WebCore - -#endif // WorkerObjectProxy_h diff --git a/Source/WebCore/workers/WorkerReportingProxy.h b/Source/WebCore/workers/WorkerReportingProxy.h index 61a6611e2..68519cd7b 100644 --- a/Source/WebCore/workers/WorkerReportingProxy.h +++ b/Source/WebCore/workers/WorkerReportingProxy.h @@ -28,11 +28,9 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef WorkerReportingProxy_h -#define WorkerReportingProxy_h +#pragma once -#include "ConsoleTypes.h" -#include <wtf/Forward.h> +#include <runtime/ConsoleTypes.h> namespace WebCore { @@ -43,10 +41,8 @@ namespace WebCore { virtual void postExceptionToWorkerObject(const String& errorMessage, int lineNumber, int columnNumber, const String& sourceURL) = 0; - virtual void postConsoleMessageToWorkerObject(MessageSource, MessageLevel, const String& message, int lineNumber, int columnNumber, const String& sourceURL) = 0; -#if ENABLE(INSPECTOR) virtual void postMessageToPageInspector(const String&) = 0; -#endif + // Invoked when close() is invoked on the worker context. virtual void workerGlobalScopeClosed() = 0; @@ -55,5 +51,3 @@ namespace WebCore { }; } // namespace WebCore - -#endif // WorkerReportingProxy_h diff --git a/Source/WebCore/workers/WorkerRunLoop.cpp b/Source/WebCore/workers/WorkerRunLoop.cpp index 9a9f556f7..b32b2598c 100644 --- a/Source/WebCore/workers/WorkerRunLoop.cpp +++ b/Source/WebCore/workers/WorkerRunLoop.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2009 Google Inc. All rights reserved. + * Copyright (C) 2016 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 @@ -39,28 +40,26 @@ #include "WorkerThread.h" #include <wtf/CurrentTime.h> +#if PLATFORM(GTK) +#include <glib.h> +#endif + namespace WebCore { -class WorkerSharedTimer : public SharedTimer { +class WorkerSharedTimer final : public SharedTimer { public: - WorkerSharedTimer() - : m_sharedTimerFunction(0) - , m_nextFireTime(0) - { - } - // SharedTimer interface. - virtual void setFiredFunction(void (*function)()) { m_sharedTimerFunction = function; } - virtual void setFireInterval(double interval) { m_nextFireTime = interval + currentTime(); } - virtual void stop() { m_nextFireTime = 0; } + void setFiredFunction(std::function<void()>&& function) override { m_sharedTimerFunction = WTFMove(function); } + void setFireInterval(Seconds interval) override { m_nextFireTime = interval + WallTime::now(); } + void stop() override { m_nextFireTime = WallTime(); } bool isActive() { return m_sharedTimerFunction && m_nextFireTime; } - double fireTime() { return m_nextFireTime; } + WallTime fireTime() { return m_nextFireTime; } void fire() { m_sharedTimerFunction(); } private: - void (*m_sharedTimerFunction)(); - double m_nextFireTime; + std::function<void()> m_sharedTimerFunction; + WallTime m_nextFireTime; }; class ModePredicate { @@ -87,7 +86,7 @@ private: }; WorkerRunLoop::WorkerRunLoop() - : m_sharedTimer(adoptPtr(new WorkerSharedTimer)) + : m_sharedTimer(std::make_unique<WorkerSharedTimer>()) , m_nestedCount(0) , m_uniqueId(0) { @@ -103,6 +102,11 @@ String WorkerRunLoop::defaultMode() return String(); } +String WorkerRunLoop::debuggerMode() +{ + return ASCIILiteral("debugger"); +} + class RunLoopSetup { WTF_MAKE_NONCOPYABLE(RunLoopSetup); public: @@ -118,7 +122,7 @@ public: { m_runLoop.m_nestedCount--; if (!m_runLoop.m_nestedCount) - threadGlobalData().threadTimers().setSharedTimer(0); + threadGlobalData().threadTimers().setSharedTimer(nullptr); } private: WorkerRunLoop& m_runLoop; @@ -146,14 +150,35 @@ MessageQueueWaitResult WorkerRunLoop::runInMode(WorkerGlobalScope* context, cons MessageQueueWaitResult WorkerRunLoop::runInMode(WorkerGlobalScope* context, const ModePredicate& predicate, WaitMode waitMode) { ASSERT(context); - ASSERT(context->thread()); - ASSERT(context->thread()->threadID() == currentThread()); - - double absoluteTime = 0.0; - if (waitMode == WaitForMessage) - absoluteTime = (predicate.isDefaultMode() && m_sharedTimer->isActive()) ? m_sharedTimer->fireTime() : MessageQueue<Task>::infiniteTime(); + ASSERT(context->thread().threadID() == currentThread()); + +#if PLATFORM(GTK) + GMainContext* mainContext = g_main_context_get_thread_default(); + if (g_main_context_pending(mainContext)) + g_main_context_iteration(mainContext, FALSE); +#endif + + WallTime deadline = WallTime::infinity(); + +#if USE(CF) + CFAbsoluteTime nextCFRunLoopTimerFireDate = CFRunLoopGetNextTimerFireDate(CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); + double timeUntilNextCFRunLoopTimerInSeconds = nextCFRunLoopTimerFireDate - CFAbsoluteTimeGetCurrent(); + deadline = WallTime::now() + std::max(0_s, Seconds(timeUntilNextCFRunLoopTimerInSeconds)); +#endif + + WallTime absoluteTime; + if (waitMode == WaitForMessage) { + if (predicate.isDefaultMode() && m_sharedTimer->isActive()) + absoluteTime = std::min(deadline, m_sharedTimer->fireTime()); + else + absoluteTime = deadline; + } MessageQueueWaitResult result; + if (WorkerScriptController* script = context->script()) + script->releaseHeapAccess(); auto task = m_messageQueue.waitForMessageFilteredWithTimeout(result, predicate, absoluteTime); + if (WorkerScriptController* script = context->script()) + script->acquireHeapAccess(); // If the context is closing, don't execute any further JavaScript tasks (per section 4.1.1 of the Web Workers spec). However, there may be implementation cleanup tasks in the queue, so keep running through it. @@ -166,8 +191,12 @@ MessageQueueWaitResult WorkerRunLoop::runInMode(WorkerGlobalScope* context, cons break; case MessageQueueTimeout: - if (!context->isClosing()) + if (!context->isClosing() && !isNested()) m_sharedTimer->fire(); +#if USE(CF) + if (nextCFRunLoopTimerFireDate <= CFAbsoluteTimeGetCurrent()) + CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, /*returnAfterSourceHandled*/ false); +#endif break; } @@ -177,8 +206,7 @@ MessageQueueWaitResult WorkerRunLoop::runInMode(WorkerGlobalScope* context, cons void WorkerRunLoop::runCleanupTasks(WorkerGlobalScope* context) { ASSERT(context); - ASSERT(context->thread()); - ASSERT(context->thread()->threadID() == currentThread()); + ASSERT(context->thread().threadID() == currentThread()); ASSERT(m_messageQueue.killed()); while (true) { @@ -194,35 +222,29 @@ void WorkerRunLoop::terminate() m_messageQueue.kill(); } -void WorkerRunLoop::postTask(PassOwnPtr<ScriptExecutionContext::Task> task) -{ - postTaskForMode(task, defaultMode()); -} - -void WorkerRunLoop::postTaskAndTerminate(PassOwnPtr<ScriptExecutionContext::Task> task) +void WorkerRunLoop::postTask(ScriptExecutionContext::Task&& task) { - m_messageQueue.appendAndKill(Task::create(task, defaultMode().isolatedCopy())); + postTaskForMode(WTFMove(task), defaultMode()); } -void WorkerRunLoop::postTaskForMode(PassOwnPtr<ScriptExecutionContext::Task> task, const String& mode) +void WorkerRunLoop::postTaskAndTerminate(ScriptExecutionContext::Task&& task) { - m_messageQueue.append(Task::create(task, mode.isolatedCopy())); + m_messageQueue.appendAndKill(std::make_unique<Task>(WTFMove(task), defaultMode())); } -std::unique_ptr<WorkerRunLoop::Task> WorkerRunLoop::Task::create(PassOwnPtr<ScriptExecutionContext::Task> task, const String& mode) +void WorkerRunLoop::postTaskForMode(ScriptExecutionContext::Task&& task, const String& mode) { - return std::unique_ptr<Task>(new Task(task, mode)); + m_messageQueue.append(std::make_unique<Task>(WTFMove(task), mode)); } -void WorkerRunLoop::Task::performTask(const WorkerRunLoop& runLoop, ScriptExecutionContext* context) +void WorkerRunLoop::Task::performTask(const WorkerRunLoop& runLoop, WorkerGlobalScope* context) { - WorkerGlobalScope* workerGlobalScope = static_cast<WorkerGlobalScope*>(context); - if ((!workerGlobalScope->isClosing() && !runLoop.terminated()) || m_task->isCleanupTask()) - m_task->performTask(context); + if ((!context->isClosing() && !runLoop.terminated()) || m_task.isCleanupTask()) + m_task.performTask(*context); } -WorkerRunLoop::Task::Task(PassOwnPtr<ScriptExecutionContext::Task> task, const String& mode) - : m_task(task) +WorkerRunLoop::Task::Task(ScriptExecutionContext::Task&& task, const String& mode) + : m_task(WTFMove(task)) , m_mode(mode.isolatedCopy()) { } diff --git a/Source/WebCore/workers/WorkerRunLoop.h b/Source/WebCore/workers/WorkerRunLoop.h index 10aa81b54..317dfbd03 100644 --- a/Source/WebCore/workers/WorkerRunLoop.h +++ b/Source/WebCore/workers/WorkerRunLoop.h @@ -28,13 +28,11 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef WorkerRunLoop_h -#define WorkerRunLoop_h +#pragma once #include "ScriptExecutionContext.h" +#include <memory> #include <wtf/MessageQueue.h> -#include <wtf/OwnPtr.h> -#include <wtf/PassOwnPtr.h> namespace WebCore { @@ -58,26 +56,24 @@ namespace WebCore { void terminate(); bool terminated() const { return m_messageQueue.killed(); } - void postTask(PassOwnPtr<ScriptExecutionContext::Task>); - void postTaskAndTerminate(PassOwnPtr<ScriptExecutionContext::Task>); - void postTaskForMode(PassOwnPtr<ScriptExecutionContext::Task>, const String& mode); + void postTask(ScriptExecutionContext::Task&&); + void postTaskAndTerminate(ScriptExecutionContext::Task&&); + void postTaskForMode(ScriptExecutionContext::Task&&, const String& mode); unsigned long createUniqueId() { return ++m_uniqueId; } static String defaultMode(); + static String debuggerMode(); class Task { WTF_MAKE_NONCOPYABLE(Task); WTF_MAKE_FAST_ALLOCATED; public: - static std::unique_ptr<Task> create(PassOwnPtr<ScriptExecutionContext::Task>, const String& mode); - ~Task() { } + Task(ScriptExecutionContext::Task&&, const String& mode); const String& mode() const { return m_mode; } - void performTask(const WorkerRunLoop&, ScriptExecutionContext*); + void performTask(const WorkerRunLoop&, WorkerGlobalScope*); private: - Task(PassOwnPtr<ScriptExecutionContext::Task> task, const String& mode); - - OwnPtr<ScriptExecutionContext::Task> m_task; + ScriptExecutionContext::Task m_task; String m_mode; }; @@ -89,12 +85,12 @@ namespace WebCore { // This should only be called when the context is closed or loop has been terminated. void runCleanupTasks(WorkerGlobalScope*); + bool isNested() const { return m_nestedCount > 1; } + MessageQueue<Task> m_messageQueue; - OwnPtr<WorkerSharedTimer> m_sharedTimer; + std::unique_ptr<WorkerSharedTimer> m_sharedTimer; int m_nestedCount; unsigned long m_uniqueId; }; } // namespace WebCore - -#endif // WorkerRunLoop_h diff --git a/Source/WebCore/workers/WorkerScriptLoader.cpp b/Source/WebCore/workers/WorkerScriptLoader.cpp index aec3e84d2..b6aa26755 100644 --- a/Source/WebCore/workers/WorkerScriptLoader.cpp +++ b/Source/WebCore/workers/WorkerScriptLoader.cpp @@ -11,10 +11,10 @@ * 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 + * THIS SOFTWARE IS PROVIDED BY APPLE 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 + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE 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 @@ -22,32 +22,23 @@ * 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" - #include "WorkerScriptLoader.h" -#include "CrossThreadTask.h" +#include "ContentSecurityPolicy.h" #include "ResourceResponse.h" #include "ScriptExecutionContext.h" -#include "SecurityOrigin.h" #include "TextResourceDecoder.h" #include "WorkerGlobalScope.h" #include "WorkerScriptLoaderClient.h" #include "WorkerThreadableLoader.h" -#include <wtf/OwnPtr.h> #include <wtf/Ref.h> -#include <wtf/RefPtr.h> namespace WebCore { WorkerScriptLoader::WorkerScriptLoader() - : m_client(0) - , m_failed(false) - , m_identifier(0) - , m_finishing(false) { } @@ -55,42 +46,55 @@ WorkerScriptLoader::~WorkerScriptLoader() { } -void WorkerScriptLoader::loadSynchronously(ScriptExecutionContext* scriptExecutionContext, const URL& url, CrossOriginRequestPolicy crossOriginRequestPolicy) +void WorkerScriptLoader::loadSynchronously(ScriptExecutionContext* scriptExecutionContext, const URL& url, FetchOptions::Mode mode, ContentSecurityPolicyEnforcement contentSecurityPolicyEnforcement, const String& initiatorIdentifier) { + ASSERT(scriptExecutionContext); + m_url = url; - OwnPtr<ResourceRequest> request(createResourceRequest()); + std::unique_ptr<ResourceRequest> request(createResourceRequest(initiatorIdentifier)); if (!request) return; - ASSERT_WITH_SECURITY_IMPLICATION(scriptExecutionContext->isWorkerGlobalScope()); + ASSERT_WITH_SECURITY_IMPLICATION(is<WorkerGlobalScope>(scriptExecutionContext)); + + // Only used for importScripts that prescribes NoCors mode. + ASSERT(mode == FetchOptions::Mode::NoCors); ThreadableLoaderOptions options; - options.allowCredentials = AllowStoredCredentials; - options.crossOriginRequestPolicy = crossOriginRequestPolicy; + options.credentials = FetchOptions::Credentials::Include; + options.mode = mode; options.sendLoadCallbacks = SendCallbacks; + options.contentSecurityPolicyEnforcement = contentSecurityPolicyEnforcement; - WorkerThreadableLoader::loadResourceSynchronously(static_cast<WorkerGlobalScope*>(scriptExecutionContext), *request, *this, options); + WorkerThreadableLoader::loadResourceSynchronously(downcast<WorkerGlobalScope>(*scriptExecutionContext), WTFMove(*request), *this, options); } - -void WorkerScriptLoader::loadAsynchronously(ScriptExecutionContext* scriptExecutionContext, const URL& url, CrossOriginRequestPolicy crossOriginRequestPolicy, WorkerScriptLoaderClient* client) + +void WorkerScriptLoader::loadAsynchronously(ScriptExecutionContext* scriptExecutionContext, const URL& url, FetchOptions::Mode mode, ContentSecurityPolicyEnforcement contentSecurityPolicyEnforcement, const String& initiatorIdentifier, WorkerScriptLoaderClient* client) { ASSERT(client); + ASSERT(scriptExecutionContext); + m_client = client; m_url = url; - OwnPtr<ResourceRequest> request(createResourceRequest()); + std::unique_ptr<ResourceRequest> request(createResourceRequest(initiatorIdentifier)); if (!request) return; + // Only used for loading worker scripts in classic mode. + // FIXME: We should add an option to set credential mode. + ASSERT(mode == FetchOptions::Mode::SameOrigin); + ThreadableLoaderOptions options; - options.allowCredentials = AllowStoredCredentials; - options.crossOriginRequestPolicy = crossOriginRequestPolicy; + options.credentials = FetchOptions::Credentials::SameOrigin; + options.mode = mode; options.sendLoadCallbacks = SendCallbacks; + options.contentSecurityPolicyEnforcement = contentSecurityPolicyEnforcement; // During create, callbacks may happen which remove the last reference to this object. - Ref<WorkerScriptLoader> protect(*this); - m_threadableLoader = ThreadableLoader::create(scriptExecutionContext, this, *request, options); + Ref<WorkerScriptLoader> protectedThis(*this); + m_threadableLoader = ThreadableLoader::create(*scriptExecutionContext, *this, WTFMove(*request), options); } const URL& WorkerScriptLoader::responseURL() const @@ -99,11 +103,12 @@ const URL& WorkerScriptLoader::responseURL() const return m_responseURL; } -PassOwnPtr<ResourceRequest> WorkerScriptLoader::createResourceRequest() +std::unique_ptr<ResourceRequest> WorkerScriptLoader::createResourceRequest(const String& initiatorIdentifier) { - OwnPtr<ResourceRequest> request = adoptPtr(new ResourceRequest(m_url)); - request->setHTTPMethod("GET"); - return request.release(); + auto request = std::make_unique<ResourceRequest>(m_url); + request->setHTTPMethod(ASCIILiteral("GET")); + request->setInitiatorIdentifier(initiatorIdentifier); + return request; } void WorkerScriptLoader::didReceiveResponse(unsigned long identifier, const ResourceResponse& response) @@ -125,9 +130,9 @@ void WorkerScriptLoader::didReceiveData(const char* data, int len) if (!m_decoder) { if (!m_responseEncoding.isEmpty()) - m_decoder = TextResourceDecoder::create("text/javascript", m_responseEncoding); + m_decoder = TextResourceDecoder::create(ASCIILiteral("text/javascript"), m_responseEncoding); else - m_decoder = TextResourceDecoder::create("text/javascript", "UTF-8"); + m_decoder = TextResourceDecoder::create(ASCIILiteral("text/javascript"), "UTF-8"); } if (!len) @@ -158,11 +163,6 @@ void WorkerScriptLoader::didFail(const ResourceError&) notifyError(); } -void WorkerScriptLoader::didFailRedirectCheck() -{ - notifyError(); -} - void WorkerScriptLoader::notifyError() { m_failed = true; diff --git a/Source/WebCore/workers/WorkerScriptLoader.h b/Source/WebCore/workers/WorkerScriptLoader.h index 7b8051a13..77ce0fd7f 100644 --- a/Source/WebCore/workers/WorkerScriptLoader.h +++ b/Source/WebCore/workers/WorkerScriptLoader.h @@ -11,10 +11,10 @@ * 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 + * THIS SOFTWARE IS PROVIDED BY APPLE 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 + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE 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 @@ -22,25 +22,22 @@ * 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 WorkerScriptLoader_h -#define WorkerScriptLoader_h +#pragma once #include "URL.h" #include "ResourceRequest.h" #include "ThreadableLoader.h" #include "ThreadableLoaderClient.h" - +#include <memory> #include <wtf/FastMalloc.h> -#include <wtf/PassRefPtr.h> #include <wtf/RefCounted.h> +#include <wtf/RefPtr.h> #include <wtf/text/StringBuilder.h> namespace WebCore { - class ResourceRequest; class ResourceResponse; class ScriptExecutionContext; class TextResourceDecoder; @@ -49,13 +46,13 @@ namespace WebCore { class WorkerScriptLoader : public RefCounted<WorkerScriptLoader>, public ThreadableLoaderClient { WTF_MAKE_FAST_ALLOCATED; public: - static PassRefPtr<WorkerScriptLoader> create() + static Ref<WorkerScriptLoader> create() { - return adoptRef(new WorkerScriptLoader()); + return adoptRef(*new WorkerScriptLoader); } - void loadSynchronously(ScriptExecutionContext*, const URL&, CrossOriginRequestPolicy); - void loadAsynchronously(ScriptExecutionContext*, const URL&, CrossOriginRequestPolicy, WorkerScriptLoaderClient*); + void loadSynchronously(ScriptExecutionContext*, const URL&, FetchOptions::Mode, ContentSecurityPolicyEnforcement, const String& initiatorIdentifier); + void loadAsynchronously(ScriptExecutionContext*, const URL&, FetchOptions::Mode, ContentSecurityPolicyEnforcement, const String& initiatorIdentifier, WorkerScriptLoaderClient*); void notifyError(); @@ -65,11 +62,10 @@ namespace WebCore { bool failed() const { return m_failed; } unsigned long identifier() const { return m_identifier; } - virtual void didReceiveResponse(unsigned long /*identifier*/, const ResourceResponse&) override; - virtual void didReceiveData(const char* data, int dataLength) override; - virtual void didFinishLoading(unsigned long identifier, double) override; - virtual void didFail(const ResourceError&) override; - virtual void didFailRedirectCheck() override; + void didReceiveResponse(unsigned long identifier, const ResourceResponse&) override; + void didReceiveData(const char* data, int dataLength) override; + void didFinishLoading(unsigned long identifier, double) override; + void didFail(const ResourceError&) override; private: friend class WTF::RefCounted<WorkerScriptLoader>; @@ -77,21 +73,19 @@ namespace WebCore { WorkerScriptLoader(); ~WorkerScriptLoader(); - PassOwnPtr<ResourceRequest> createResourceRequest(); + std::unique_ptr<ResourceRequest> createResourceRequest(const String& initiatorIdentifier); void notifyFinished(); - WorkerScriptLoaderClient* m_client; + WorkerScriptLoaderClient* m_client { nullptr }; RefPtr<ThreadableLoader> m_threadableLoader; String m_responseEncoding; RefPtr<TextResourceDecoder> m_decoder; StringBuilder m_script; URL m_url; URL m_responseURL; - bool m_failed; - unsigned long m_identifier; - bool m_finishing; + unsigned long m_identifier { 0 }; + bool m_failed { false }; + bool m_finishing { false }; }; } // namespace WebCore - -#endif // WorkerScriptLoader_h diff --git a/Source/WebCore/workers/WorkerScriptLoaderClient.h b/Source/WebCore/workers/WorkerScriptLoaderClient.h index 4112cf27a..10d06c762 100644 --- a/Source/WebCore/workers/WorkerScriptLoaderClient.h +++ b/Source/WebCore/workers/WorkerScriptLoaderClient.h @@ -11,10 +11,10 @@ * 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 + * THIS SOFTWARE IS PROVIDED BY APPLE 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 + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE 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 @@ -22,11 +22,9 @@ * 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 WorkerScriptLoaderClient_h -#define WorkerScriptLoaderClient_h +#pragma once namespace WebCore { @@ -45,5 +43,3 @@ namespace WebCore { }; } // namespace WebCore - -#endif // WorkerScriptLoaderClient_h diff --git a/Source/WebCore/workers/WorkerThread.cpp b/Source/WebCore/workers/WorkerThread.cpp index fca606ec2..8b1e9234b 100644 --- a/Source/WebCore/workers/WorkerThread.cpp +++ b/Source/WebCore/workers/WorkerThread.cpp @@ -10,10 +10,10 @@ * 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 + * THIS SOFTWARE IS PROVIDED BY APPLE 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 + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE 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 @@ -25,42 +25,35 @@ */ #include "config.h" - #include "WorkerThread.h" -#include "DedicatedWorkerGlobalScope.h" -#include "InspectorInstrumentation.h" +#include "ContentSecurityPolicyResponseHeaders.h" +#include "IDBConnectionProxy.h" #include "ScriptSourceCode.h" #include "SecurityOrigin.h" +#include "SocketProvider.h" #include "ThreadGlobalData.h" #include "URL.h" +#include "WorkerGlobalScope.h" +#include "WorkerInspectorController.h" #include <utility> +#include <wtf/Lock.h> #include <wtf/NeverDestroyed.h> #include <wtf/Noncopyable.h> #include <wtf/text/WTFString.h> -#if ENABLE(SQL_DATABASE) -#include "DatabaseManager.h" -#include "DatabaseTask.h" -#endif - #if PLATFORM(IOS) +#include "FloatingPointEnvironment.h" #include "WebCoreThread.h" #endif -namespace WebCore { - -static std::mutex& threadSetMutex() -{ - static std::once_flag onceFlag; - static std::mutex* mutex; +#if PLATFORM(GTK) +#include <wtf/glib/GRefPtr.h> +#endif - std::call_once(onceFlag, []{ - mutex = std::make_unique<std::mutex>().release(); - }); +namespace WebCore { - return *mutex; -} +static StaticLock threadSetMutex; static HashSet<WorkerThread*>& workerThreads() { @@ -71,7 +64,7 @@ static HashSet<WorkerThread*>& workerThreads() unsigned WorkerThread::workerThreadCount() { - std::lock_guard<std::mutex> lock(threadSetMutex()); + std::lock_guard<StaticLock> lock(threadSetMutex); return workerThreads().size(); } @@ -79,58 +72,60 @@ unsigned WorkerThread::workerThreadCount() struct WorkerThreadStartupData { WTF_MAKE_NONCOPYABLE(WorkerThreadStartupData); WTF_MAKE_FAST_ALLOCATED; public: - static PassOwnPtr<WorkerThreadStartupData> create(const URL& scriptURL, const String& userAgent, const GroupSettings* settings, const String& sourceCode, WorkerThreadStartMode startMode, const String& contentSecurityPolicy, ContentSecurityPolicy::HeaderType contentSecurityPolicyType, const SecurityOrigin* topOrigin) - { - return adoptPtr(new WorkerThreadStartupData(scriptURL, userAgent, settings, sourceCode, startMode, contentSecurityPolicy, contentSecurityPolicyType, topOrigin)); - } + WorkerThreadStartupData(const URL& scriptURL, const String& identifier, const String& userAgent, const String& sourceCode, WorkerThreadStartMode, const ContentSecurityPolicyResponseHeaders&, bool shouldBypassMainWorldContentSecurityPolicy, const SecurityOrigin& topOrigin, MonotonicTime timeOrigin); URL m_scriptURL; + String m_identifier; String m_userAgent; - std::unique_ptr<GroupSettings> m_groupSettings; String m_sourceCode; WorkerThreadStartMode m_startMode; - String m_contentSecurityPolicy; - ContentSecurityPolicy::HeaderType m_contentSecurityPolicyType; - RefPtr<SecurityOrigin> m_topOrigin; -private: - WorkerThreadStartupData(const URL& scriptURL, const String& userAgent, const GroupSettings*, const String& sourceCode, WorkerThreadStartMode, const String& contentSecurityPolicy, ContentSecurityPolicy::HeaderType contentSecurityPolicyType, const SecurityOrigin* topOrigin); + ContentSecurityPolicyResponseHeaders m_contentSecurityPolicyResponseHeaders; + bool m_shouldBypassMainWorldContentSecurityPolicy; + Ref<SecurityOrigin> m_topOrigin; + MonotonicTime m_timeOrigin; }; -WorkerThreadStartupData::WorkerThreadStartupData(const URL& scriptURL, const String& userAgent, const GroupSettings* settings, const String& sourceCode, WorkerThreadStartMode startMode, const String& contentSecurityPolicy, ContentSecurityPolicy::HeaderType contentSecurityPolicyType, const SecurityOrigin* topOrigin) - : m_scriptURL(scriptURL.copy()) +WorkerThreadStartupData::WorkerThreadStartupData(const URL& scriptURL, const String& identifier, const String& userAgent, const String& sourceCode, WorkerThreadStartMode startMode, const ContentSecurityPolicyResponseHeaders& contentSecurityPolicyResponseHeaders, bool shouldBypassMainWorldContentSecurityPolicy, const SecurityOrigin& topOrigin, MonotonicTime timeOrigin) + : m_scriptURL(scriptURL.isolatedCopy()) + , m_identifier(identifier.isolatedCopy()) , m_userAgent(userAgent.isolatedCopy()) , m_sourceCode(sourceCode.isolatedCopy()) , m_startMode(startMode) - , m_contentSecurityPolicy(contentSecurityPolicy.isolatedCopy()) - , m_contentSecurityPolicyType(contentSecurityPolicyType) - , m_topOrigin(topOrigin ? topOrigin->isolatedCopy() : 0) + , m_contentSecurityPolicyResponseHeaders(contentSecurityPolicyResponseHeaders.isolatedCopy()) + , m_shouldBypassMainWorldContentSecurityPolicy(shouldBypassMainWorldContentSecurityPolicy) + , m_topOrigin(topOrigin.isolatedCopy()) + , m_timeOrigin(timeOrigin) { - if (!settings) - return; - - m_groupSettings = std::make_unique<GroupSettings>(); - m_groupSettings->setLocalStorageQuotaBytes(settings->localStorageQuotaBytes()); - m_groupSettings->setIndexedDBQuotaBytes(settings->indexedDBQuotaBytes()); - m_groupSettings->setIndexedDBDatabasePath(settings->indexedDBDatabasePath().isolatedCopy()); } -WorkerThread::WorkerThread(const URL& scriptURL, const String& userAgent, const GroupSettings* settings, const String& sourceCode, WorkerLoaderProxy& workerLoaderProxy, WorkerReportingProxy& workerReportingProxy, WorkerThreadStartMode startMode, const String& contentSecurityPolicy, ContentSecurityPolicy::HeaderType contentSecurityPolicyType, const SecurityOrigin* topOrigin) +WorkerThread::WorkerThread(const URL& scriptURL, const String& identifier, const String& userAgent, const String& sourceCode, WorkerLoaderProxy& workerLoaderProxy, WorkerReportingProxy& workerReportingProxy, WorkerThreadStartMode startMode, const ContentSecurityPolicyResponseHeaders& contentSecurityPolicyResponseHeaders, bool shouldBypassMainWorldContentSecurityPolicy, const SecurityOrigin& topOrigin, MonotonicTime timeOrigin, IDBClient::IDBConnectionProxy* connectionProxy, SocketProvider* socketProvider, JSC::RuntimeFlags runtimeFlags) : m_threadID(0) , m_workerLoaderProxy(workerLoaderProxy) , m_workerReportingProxy(workerReportingProxy) - , m_startupData(WorkerThreadStartupData::create(scriptURL, userAgent, settings, sourceCode, startMode, contentSecurityPolicy, contentSecurityPolicyType, topOrigin)) -#if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS) - , m_notificationClient(0) + , m_runtimeFlags(runtimeFlags) + , m_startupData(std::make_unique<WorkerThreadStartupData>(scriptURL, identifier, userAgent, sourceCode, startMode, contentSecurityPolicyResponseHeaders, shouldBypassMainWorldContentSecurityPolicy, topOrigin, timeOrigin)) +#if ENABLE(INDEXED_DATABASE) + , m_idbConnectionProxy(connectionProxy) +#endif +#if ENABLE(WEB_SOCKETS) + , m_socketProvider(socketProvider) #endif { - std::lock_guard<std::mutex> lock(threadSetMutex()); +#if !ENABLE(INDEXED_DATABASE) + UNUSED_PARAM(connectionProxy); +#endif +#if !ENABLE(WEB_SOCKETS) + UNUSED_PARAM(socketProvider); +#endif + + std::lock_guard<StaticLock> lock(threadSetMutex); workerThreads().add(this); } WorkerThread::~WorkerThread() { - std::lock_guard<std::mutex> lock(threadSetMutex()); + std::lock_guard<StaticLock> lock(threadSetMutex); ASSERT(workerThreads().contains(this)); workerThreads().remove(this); @@ -139,7 +134,7 @@ WorkerThread::~WorkerThread() bool WorkerThread::start() { // Mutex protection is necessary to ensure that m_threadID is initialized when the thread starts. - MutexLocker lock(m_threadCreationMutex); + LockHolder lock(m_threadCreationMutex); if (m_threadID) return true; @@ -158,12 +153,17 @@ void WorkerThread::workerThread() { // Propagate the mainThread's fenv to workers. #if PLATFORM(IOS) - fesetenv(&mainThreadFEnv); + FloatingPointEnvironment::singleton().propagateMainThreadEnvironment(); +#endif + +#if PLATFORM(GTK) + GRefPtr<GMainContext> mainContext = adoptGRef(g_main_context_new()); + g_main_context_push_thread_default(mainContext.get()); #endif { - MutexLocker lock(m_threadCreationMutex); - m_workerGlobalScope = createWorkerGlobalScope(m_startupData->m_scriptURL, m_startupData->m_userAgent, std::move(m_startupData->m_groupSettings), m_startupData->m_contentSecurityPolicy, m_startupData->m_contentSecurityPolicyType, m_startupData->m_topOrigin.release()); + LockHolder lock(m_threadCreationMutex); + m_workerGlobalScope = createWorkerGlobalScope(m_startupData->m_scriptURL, m_startupData->m_identifier, m_startupData->m_userAgent, m_startupData->m_contentSecurityPolicyResponseHeaders, m_startupData->m_shouldBypassMainWorldContentSecurityPolicy, WTFMove(m_startupData->m_topOrigin), m_startupData->m_timeOrigin); if (m_runLoop.terminated()) { // The worker was terminated before the thread had a chance to run. Since the context didn't exist yet, @@ -172,25 +172,34 @@ void WorkerThread::workerThread() } } + if (m_startupData->m_startMode == WorkerThreadStartMode::WaitForInspector) { + startRunningDebuggerTasks(); + + // If the worker was somehow terminated while processing debugger commands. + if (m_runLoop.terminated()) + m_workerGlobalScope->script()->forbidExecution(); + } + WorkerScriptController* script = m_workerGlobalScope->script(); -#if ENABLE(INSPECTOR) - InspectorInstrumentation::willEvaluateWorkerScript(workerGlobalScope(), m_startupData->m_startMode); -#endif 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_startupData = nullptr; runEventLoop(); +#if PLATFORM(GTK) + g_main_context_pop_thread_default(mainContext.get()); +#endif + ThreadIdentifier threadID = m_threadID; ASSERT(m_workerGlobalScope->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_workerGlobalScope = 0; + m_workerGlobalScope = nullptr; // Clean up WebCore::ThreadGlobalData before WTF::WTFThreadData goes away! threadGlobalData().destroy(); @@ -199,98 +208,93 @@ void WorkerThread::workerThread() detachThread(threadID); } +void WorkerThread::startRunningDebuggerTasks() +{ + ASSERT(!m_pausedForDebugger); + m_pausedForDebugger = true; + + MessageQueueWaitResult result; + do { + result = m_runLoop.runInMode(m_workerGlobalScope.get(), WorkerRunLoop::debuggerMode()); + } while (result != MessageQueueTerminated && m_pausedForDebugger); +} + +void WorkerThread::stopRunningDebuggerTasks() +{ + m_pausedForDebugger = false; +} + void WorkerThread::runEventLoop() { // Does not return until terminated. m_runLoop.run(m_workerGlobalScope.get()); } -class WorkerThreadShutdownFinishTask : public ScriptExecutionContext::Task { -public: - static PassOwnPtr<WorkerThreadShutdownFinishTask> create() - { - return adoptPtr(new WorkerThreadShutdownFinishTask()); - } - - virtual void performTask(ScriptExecutionContext *context) - { - ASSERT_WITH_SECURITY_IMPLICATION(context->isWorkerGlobalScope()); - WorkerGlobalScope* workerGlobalScope = static_cast<WorkerGlobalScope*>(context); - // It's not safe to call clearScript until all the cleanup tasks posted by functions initiated by WorkerThreadShutdownStartTask have completed. - workerGlobalScope->clearScript(); - } - - virtual bool isCleanupTask() const { return true; } -}; +void WorkerThread::stop() +{ + // Mutex protection is necessary because stop() can be called before the context is fully created. + LockHolder lock(m_threadCreationMutex); -class WorkerThreadShutdownStartTask : public ScriptExecutionContext::Task { -public: - static PassOwnPtr<WorkerThreadShutdownStartTask> create() - { - return adoptPtr(new WorkerThreadShutdownStartTask()); - } + // 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_workerGlobalScope) { + m_workerGlobalScope->script()->scheduleExecutionTermination(); - virtual void performTask(ScriptExecutionContext *context) - { - ASSERT_WITH_SECURITY_IMPLICATION(context->isWorkerGlobalScope()); - WorkerGlobalScope* workerGlobalScope = static_cast<WorkerGlobalScope*>(context); + m_runLoop.postTaskAndTerminate({ ScriptExecutionContext::Task::CleanupTask, [] (ScriptExecutionContext& context ) { + WorkerGlobalScope& workerGlobalScope = downcast<WorkerGlobalScope>(context); -#if ENABLE(SQL_DATABASE) - // FIXME: Should we stop the databases as part of stopActiveDOMObjects() below? - DatabaseTaskSynchronizer cleanupSync; - DatabaseManager::manager().stopDatabases(workerGlobalScope, &cleanupSync); +#if ENABLE(INDEXED_DATABASE) + workerGlobalScope.stopIndexedDatabase(); #endif - workerGlobalScope->stopActiveDOMObjects(); + workerGlobalScope.stopActiveDOMObjects(); - workerGlobalScope->notifyObserversOfStop(); + workerGlobalScope.inspectorController().workerTerminating(); - // Event listeners would keep DOMWrapperWorld objects alive for too long. Also, they have references to JS objects, - // which become dangling once Heap is destroyed. - workerGlobalScope->removeAllEventListeners(); + // Event listeners would keep DOMWrapperWorld objects alive for too long. Also, they have references to JS objects, + // which become dangling once Heap is destroyed. + workerGlobalScope.removeAllEventListeners(); -#if ENABLE(SQL_DATABASE) - // We wait for the database thread to clean up all its stuff so that we - // can do more stringent leak checks as we exit. - cleanupSync.waitForTaskCompletion(); -#endif + // Stick a shutdown command at the end of the queue, so that we deal + // with all the cleanup tasks the databases post first. + workerGlobalScope.postTask({ ScriptExecutionContext::Task::CleanupTask, [] (ScriptExecutionContext& context) { + WorkerGlobalScope& workerGlobalScope = downcast<WorkerGlobalScope>(context); + // It's not safe to call clearScript until all the cleanup tasks posted by functions initiated by WorkerThreadShutdownStartTask have completed. + workerGlobalScope.clearScript(); + } }); - // Stick a shutdown command at the end of the queue, so that we deal - // with all the cleanup tasks the databases post first. - workerGlobalScope->postTask(WorkerThreadShutdownFinishTask::create()); + } }); + return; } + m_runLoop.terminate(); +} - virtual bool isCleanupTask() const { return true; } -}; - -void WorkerThread::stop() +void WorkerThread::releaseFastMallocFreeMemoryInAllThreads() { - // Mutex protection is necessary because stop() can be called before the context is fully created. - MutexLocker lock(m_threadCreationMutex); + std::lock_guard<StaticLock> lock(threadSetMutex); - // 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_workerGlobalScope) { - m_workerGlobalScope->script()->scheduleExecutionTermination(); - -#if ENABLE(SQL_DATABASE) - DatabaseManager::manager().interruptAllDatabasesForContext(m_workerGlobalScope.get()); -#endif - m_runLoop.postTaskAndTerminate(WorkerThreadShutdownStartTask::create()); - return; + for (auto* workerThread : workerThreads()) { + workerThread->runLoop().postTask([] (ScriptExecutionContext&) { + WTF::releaseFastMallocFreeMemory(); + }); } - m_runLoop.terminate(); } -class ReleaseFastMallocFreeMemoryTask : public ScriptExecutionContext::Task { - virtual void performTask(ScriptExecutionContext*) override { WTF::releaseFastMallocFreeMemory(); } -}; - -void WorkerThread::releaseFastMallocFreeMemoryInAllThreads() +IDBClient::IDBConnectionProxy* WorkerThread::idbConnectionProxy() { - std::lock_guard<std::mutex> lock(threadSetMutex()); +#if ENABLE(INDEXED_DATABASE) + return m_idbConnectionProxy.get(); +#else + return nullptr; +#endif +} - for (auto* workerThread : workerThreads()) - workerThread->runLoop().postTask(adoptPtr(new ReleaseFastMallocFreeMemoryTask)); +SocketProvider* WorkerThread::socketProvider() +{ +#if ENABLE(WEB_SOCKETS) + return m_socketProvider.get(); +#else + return nullptr; +#endif } } // namespace WebCore diff --git a/Source/WebCore/workers/WorkerThread.h b/Source/WebCore/workers/WorkerThread.h index 96d9b07cd..07ad3ce78 100644 --- a/Source/WebCore/workers/WorkerThread.h +++ b/Source/WebCore/workers/WorkerThread.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Apple Inc. All Rights Reserved. + * Copyright (C) 2008, 2016 Apple Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -10,10 +10,10 @@ * 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 + * THIS SOFTWARE IS PROVIDED BY APPLE 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 + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE 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 @@ -21,85 +21,105 @@ * 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 +#pragma once -#include "ContentSecurityPolicy.h" -#include "GroupSettings.h" #include "WorkerRunLoop.h" +#include <memory> +#include <runtime/RuntimeFlags.h> #include <wtf/Forward.h> -#include <wtf/OwnPtr.h> -#include <wtf/PassRefPtr.h> #include <wtf/RefCounted.h> namespace WebCore { - class URL; - class NotificationClient; - class SecurityOrigin; - class WorkerGlobalScope; - class WorkerLoaderProxy; - class WorkerReportingProxy; - struct WorkerThreadStartupData; +class ContentSecurityPolicyResponseHeaders; +class URL; +class NotificationClient; +class SecurityOrigin; +class SocketProvider; +class WorkerGlobalScope; +class WorkerLoaderProxy; +class WorkerReportingProxy; + +enum class WorkerThreadStartMode { + Normal, + WaitForInspector, +}; + +namespace IDBClient { +class IDBConnectionProxy; +} - enum WorkerThreadStartMode { DontPauseWorkerGlobalScopeOnStart, PauseWorkerGlobalScopeOnStart }; +struct WorkerThreadStartupData; - class WorkerThread : public RefCounted<WorkerThread> { - public: - virtual ~WorkerThread(); +class WorkerThread : public RefCounted<WorkerThread> { +public: + virtual ~WorkerThread(); - bool start(); - void stop(); + bool start(); + void stop(); - ThreadIdentifier threadID() const { return m_threadID; } - WorkerRunLoop& runLoop() { return m_runLoop; } - WorkerLoaderProxy& workerLoaderProxy() const { return m_workerLoaderProxy; } - WorkerReportingProxy& workerReportingProxy() const { return m_workerReportingProxy; } + ThreadIdentifier threadID() const { return m_threadID; } + WorkerRunLoop& runLoop() { return m_runLoop; } + WorkerLoaderProxy& workerLoaderProxy() const { return m_workerLoaderProxy; } + WorkerReportingProxy& workerReportingProxy() const { return m_workerReportingProxy; } - // Number of active worker threads. - static unsigned workerThreadCount(); - static void releaseFastMallocFreeMemoryInAllThreads(); + // Number of active worker threads. + WEBCORE_EXPORT static unsigned workerThreadCount(); + static void releaseFastMallocFreeMemoryInAllThreads(); #if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS) - NotificationClient* getNotificationClient() { return m_notificationClient; } - void setNotificationClient(NotificationClient* client) { m_notificationClient = client; } + NotificationClient* getNotificationClient() { return m_notificationClient; } + void setNotificationClient(NotificationClient* client) { m_notificationClient = client; } #endif - protected: - WorkerThread(const URL&, const String& userAgent, const GroupSettings*, const String& sourceCode, WorkerLoaderProxy&, WorkerReportingProxy&, WorkerThreadStartMode, const String& contentSecurityPolicy, ContentSecurityPolicy::HeaderType, const SecurityOrigin* topOrigin); + void startRunningDebuggerTasks(); + void stopRunningDebuggerTasks(); + + JSC::RuntimeFlags runtimeFlags() const { return m_runtimeFlags; } + +protected: + WorkerThread(const URL&, const String& identifier, const String& userAgent, const String& sourceCode, WorkerLoaderProxy&, WorkerReportingProxy&, WorkerThreadStartMode, const ContentSecurityPolicyResponseHeaders&, bool shouldBypassMainWorldContentSecurityPolicy, const SecurityOrigin& topOrigin, MonotonicTime timeOrigin, IDBClient::IDBConnectionProxy*, SocketProvider*, JSC::RuntimeFlags); + + // Factory method for creating a new worker context for the thread. + virtual Ref<WorkerGlobalScope> createWorkerGlobalScope(const URL&, const String& identifier, const String& userAgent, const ContentSecurityPolicyResponseHeaders&, bool shouldBypassMainWorldContentSecurityPolicy, Ref<SecurityOrigin>&& topOrigin, MonotonicTime timeOrigin) = 0; - // Factory method for creating a new worker context for the thread. - virtual PassRefPtr<WorkerGlobalScope> createWorkerGlobalScope(const URL&, const String& userAgent, std::unique_ptr<GroupSettings>, const String& contentSecurityPolicy, ContentSecurityPolicy::HeaderType, PassRefPtr<SecurityOrigin> topOrigin) = 0; + // Executes the event loop for the worker thread. Derived classes can override to perform actions before/after entering the event loop. + virtual void runEventLoop(); - // Executes the event loop for the worker thread. Derived classes can override to perform actions before/after entering the event loop. - virtual void runEventLoop(); + WorkerGlobalScope* workerGlobalScope() { return m_workerGlobalScope.get(); } - WorkerGlobalScope* workerGlobalScope() { return m_workerGlobalScope.get(); } + IDBClient::IDBConnectionProxy* idbConnectionProxy(); + SocketProvider* socketProvider(); - private: - // Static function executed as the core routine on the new thread. Passed a pointer to a WorkerThread object. - static void workerThreadStart(void*); - void workerThread(); +private: + // Static function executed as the core routine on the new thread. Passed a pointer to a WorkerThread object. + static void workerThreadStart(void*); + void workerThread(); - ThreadIdentifier m_threadID; - WorkerRunLoop m_runLoop; - WorkerLoaderProxy& m_workerLoaderProxy; - WorkerReportingProxy& m_workerReportingProxy; + ThreadIdentifier m_threadID; + WorkerRunLoop m_runLoop; + WorkerLoaderProxy& m_workerLoaderProxy; + WorkerReportingProxy& m_workerReportingProxy; + JSC::RuntimeFlags m_runtimeFlags; + bool m_pausedForDebugger { false }; - RefPtr<WorkerGlobalScope> m_workerGlobalScope; - Mutex m_threadCreationMutex; + RefPtr<WorkerGlobalScope> m_workerGlobalScope; + Lock m_threadCreationMutex; - OwnPtr<WorkerThreadStartupData> m_startupData; + std::unique_ptr<WorkerThreadStartupData> m_startupData; #if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS) - NotificationClient* m_notificationClient; + NotificationClient* m_notificationClient { nullptr }; #endif - }; -} // namespace WebCore - -#endif // WorkerThread_h +#if ENABLE(INDEXED_DATABASE) + RefPtr<IDBClient::IDBConnectionProxy> m_idbConnectionProxy; +#endif +#if ENABLE(WEB_SOCKETS) + RefPtr<SocketProvider> m_socketProvider; +#endif +}; +} // namespace WebCore |