| // Copyright 2015 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "core/workers/InProcessWorkerBase.h" |
| |
| #include "bindings/core/v8/ExceptionState.h" |
| #include "core/events/MessageEvent.h" |
| #include "core/fetch/ResourceFetcher.h" |
| #include "core/frame/LocalDOMWindow.h" |
| #include "core/frame/csp/ContentSecurityPolicy.h" |
| #include "core/inspector/InspectorInstrumentation.h" |
| #include "core/workers/InProcessWorkerMessagingProxy.h" |
| #include "core/workers/WorkerScriptLoader.h" |
| #include "core/workers/WorkerThread.h" |
| #include "platform/network/ContentSecurityPolicyResponseHeaders.h" |
| #include <memory> |
| |
| namespace blink { |
| |
| InProcessWorkerBase::InProcessWorkerBase(ExecutionContext* context) |
| : AbstractWorker(context), |
| ActiveScriptWrappable(this), |
| m_contextProxy(nullptr) {} |
| |
| InProcessWorkerBase::~InProcessWorkerBase() { |
| DCHECK(isMainThread()); |
| if (!m_contextProxy) |
| return; |
| m_contextProxy->parentObjectDestroyed(); |
| } |
| |
| void InProcessWorkerBase::postMessage(ExecutionContext* context, |
| PassRefPtr<SerializedScriptValue> message, |
| const MessagePortArray& ports, |
| ExceptionState& exceptionState) { |
| DCHECK(m_contextProxy); |
| // Disentangle the port in preparation for sending it to the remote context. |
| std::unique_ptr<MessagePortChannelArray> channels = |
| MessagePort::disentanglePorts(context, ports, exceptionState); |
| if (exceptionState.hadException()) |
| return; |
| m_contextProxy->postMessageToWorkerGlobalScope(std::move(message), |
| std::move(channels)); |
| } |
| |
| bool InProcessWorkerBase::initialize(ExecutionContext* context, |
| const String& url, |
| ExceptionState& exceptionState) { |
| suspendIfNeeded(); |
| |
| // TODO(mkwst): Revisit the context as |
| // https://drafts.css-houdini.org/worklets/ evolves. |
| KURL scriptURL = |
| resolveURL(url, exceptionState, WebURLRequest::RequestContextScript); |
| if (scriptURL.isEmpty()) |
| return false; |
| |
| m_scriptLoader = WorkerScriptLoader::create(); |
| m_scriptLoader->loadAsynchronously( |
| *context, scriptURL, DenyCrossOriginRequests, |
| context->securityContext().addressSpace(), |
| WTF::bind(&InProcessWorkerBase::onResponse, wrapPersistent(this)), |
| WTF::bind(&InProcessWorkerBase::onFinished, wrapPersistent(this))); |
| |
| m_contextProxy = createInProcessWorkerMessagingProxy(context); |
| |
| return true; |
| } |
| |
| void InProcessWorkerBase::terminate() { |
| if (m_contextProxy) |
| m_contextProxy->terminateGlobalScope(); |
| } |
| |
| void InProcessWorkerBase::stop() { |
| terminate(); |
| } |
| |
| bool InProcessWorkerBase::hasPendingActivity() const { |
| // The worker context does not exist while loading, so we must ensure that the |
| // worker object is not collected, nor are its event listeners. |
| return (m_contextProxy && m_contextProxy->hasPendingActivity()) || |
| m_scriptLoader; |
| } |
| |
| ContentSecurityPolicy* InProcessWorkerBase::contentSecurityPolicy() { |
| if (m_scriptLoader) |
| return m_scriptLoader->contentSecurityPolicy(); |
| return m_contentSecurityPolicy.get(); |
| } |
| |
| String InProcessWorkerBase::referrerPolicy() { |
| if (m_scriptLoader) |
| return m_scriptLoader->referrerPolicy(); |
| return m_referrerPolicy; |
| } |
| |
| void InProcessWorkerBase::onResponse() { |
| InspectorInstrumentation::didReceiveScriptResponse( |
| getExecutionContext(), m_scriptLoader->identifier()); |
| } |
| |
| void InProcessWorkerBase::onFinished() { |
| if (m_scriptLoader->failed()) { |
| dispatchEvent(Event::createCancelable(EventTypeNames::error)); |
| } else { |
| DCHECK(m_contextProxy); |
| m_contextProxy->startWorkerGlobalScope(m_scriptLoader->url(), |
| getExecutionContext()->userAgent(), |
| m_scriptLoader->script()); |
| InspectorInstrumentation::scriptImported(getExecutionContext(), |
| m_scriptLoader->identifier(), |
| m_scriptLoader->script()); |
| } |
| m_contentSecurityPolicy = m_scriptLoader->releaseContentSecurityPolicy(); |
| m_referrerPolicy = m_scriptLoader->referrerPolicy(); |
| m_scriptLoader = nullptr; |
| } |
| |
| DEFINE_TRACE(InProcessWorkerBase) { |
| visitor->trace(m_contentSecurityPolicy); |
| AbstractWorker::trace(visitor); |
| } |
| |
| } // namespace blink |