/*
 * Copyright (C) 2008-2017 Apple Inc. All Rights Reserved.
 * Copyright (C) 2009, 2011 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. ``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
 * 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 "WorkerGlobalScope.h"

#include "CSSFontSelector.h"
#include "CSSValueList.h"
#include "CSSValuePool.h"
#include "ContentSecurityPolicy.h"
#include "Crypto.h"
#include "FontCache.h"
#include "FontCustomPlatformData.h"
#include "FontFaceSet.h"
#include "IDBConnectionProxy.h"
#include "ImageBitmapOptions.h"
#include "InspectorInstrumentation.h"
#include "JSDOMExceptionHandling.h"
#include "Performance.h"
#include "RTCDataChannelRemoteHandlerConnection.h"
#include "RuntimeEnabledFeatures.h"
#include "ScheduledAction.h"
#include "ScriptSourceCode.h"
#include "SecurityOrigin.h"
#include "SecurityOriginPolicy.h"
#include "ServiceWorkerGlobalScope.h"
#include "SocketProvider.h"
#include "WorkerFileSystemStorageConnection.h"
#include "WorkerFontLoadRequest.h"
#include "WorkerLoaderProxy.h"
#include "WorkerLocation.h"
#include "WorkerMessagingProxy.h"
#include "WorkerNavigator.h"
#include "WorkerReportingProxy.h"
#include "WorkerSWClientConnection.h"
#include "WorkerScriptLoader.h"
#include "WorkerStorageConnection.h"
#include <JavaScriptCore/ScriptArguments.h>
#include <JavaScriptCore/ScriptCallStack.h>
#include <wtf/IsoMallocInlines.h>
#include <wtf/Lock.h>
#include <wtf/threads/BinarySemaphore.h>

namespace WebCore {
using namespace Inspector;

static Lock allWorkerGlobalScopeIdentifiersLock;
static HashSet<ScriptExecutionContextIdentifier>& allWorkerGlobalScopeIdentifiers() WTF_REQUIRES_LOCK(allWorkerGlobalScopeIdentifiersLock)
{
    static NeverDestroyed<HashSet<ScriptExecutionContextIdentifier>> identifiers;
    ASSERT(allWorkerGlobalScopeIdentifiersLock.isLocked());
    return identifiers;
}

WTF_MAKE_ISO_ALLOCATED_IMPL(WorkerGlobalScope);

WorkerGlobalScope::WorkerGlobalScope(WorkerThreadType type, const WorkerParameters& params, Ref<SecurityOrigin>&& origin, WorkerThread& thread, Ref<SecurityOrigin>&& topOrigin, IDBClient::IDBConnectionProxy* connectionProxy, SocketProvider* socketProvider)
    : WorkerOrWorkletGlobalScope(type, JSC::VM::create(), &thread)
    , m_url(params.scriptURL)
    , m_identifier(params.identifier)
    , m_userAgent(params.userAgent)
    , m_isOnline(params.isOnline)
    , m_shouldBypassMainWorldContentSecurityPolicy(params.shouldBypassMainWorldContentSecurityPolicy)
    , m_topOrigin(WTFMove(topOrigin))
    , m_connectionProxy(connectionProxy)
    , m_socketProvider(socketProvider)
    , m_performance(Performance::create(this, params.timeOrigin))
    , m_referrerPolicy(params.referrerPolicy)
    , m_settingsValues(params.settingsValues)
    , m_workerType(params.workerType)
    , m_credentials(params.credentials)
{
    {
        Locker locker { allWorkerGlobalScopeIdentifiersLock };
        allWorkerGlobalScopeIdentifiers().add(contextIdentifier());
    }

    if (m_topOrigin->hasUniversalAccess())
        origin->grantUniversalAccess();
    if (m_topOrigin->needsStorageAccessFromFileURLsQuirk())
        origin->grantStorageAccessFromFileURLsQuirk();

    setSecurityOriginPolicy(SecurityOriginPolicy::create(WTFMove(origin)));
    setContentSecurityPolicy(makeUnique<ContentSecurityPolicy>(URL { m_url }, *this));
    setCrossOriginEmbedderPolicy(params.crossOriginEmbedderPolicy);
}

WorkerGlobalScope::~WorkerGlobalScope()
{
    ASSERT(thread().thread() == &Thread::current());
    // We need to remove from the contexts map very early in the destructor so that calling postTask() on this WorkerGlobalScope from another thread is safe.
    removeFromContextsMap();

    {
        Locker locker { allWorkerGlobalScopeIdentifiersLock };
        allWorkerGlobalScopeIdentifiers().remove(contextIdentifier());
    }

    m_performance = nullptr;
    m_crypto = nullptr;

    // Notify proxy that we are going away. This can free the WorkerThread object, so do not access it after this.
    thread().workerReportingProxy().workerGlobalScopeDestroyed();
}

String WorkerGlobalScope::origin() const
{
    auto* securityOrigin = this->securityOrigin();
    return securityOrigin ? securityOrigin->toString() : emptyString();
}

void WorkerGlobalScope::prepareForDestruction()
{
    WorkerOrWorkletGlobalScope::prepareForDestruction();

    stopIndexedDatabase();

    if (m_cacheStorageConnection)
        m_cacheStorageConnection->clearPendingRequests();

    if (m_storageConnection)
        m_storageConnection->scopeClosed();

    if (m_fileSystemStorageConnection)
        m_fileSystemStorageConnection->scopeClosed();
}

void WorkerGlobalScope::removeAllEventListeners()
{
    WorkerOrWorkletGlobalScope::removeAllEventListeners();
    m_performance->removeAllEventListeners();
    m_performance->removeAllObservers();
}

bool WorkerGlobalScope::isSecureContext() const
{
    if (!RuntimeEnabledFeatures::sharedFeatures().secureContextChecksEnabled())
        return true;

    return securityOrigin() && securityOrigin()->isPotentiallyTrustworthy();
}

void WorkerGlobalScope::applyContentSecurityPolicyResponseHeaders(const ContentSecurityPolicyResponseHeaders& contentSecurityPolicyResponseHeaders)
{
    contentSecurityPolicy()->didReceiveHeaders(contentSecurityPolicyResponseHeaders, String { });
}

URL WorkerGlobalScope::completeURL(const String& url, ForceUTF8) const
{
    // Always return a null URL when passed a null string.
    // FIXME: Should we change the URL constructor to have this behavior?
    if (url.isNull())
        return URL();
    // Always use UTF-8 in Workers.
    return URL(m_url, url);
}

String WorkerGlobalScope::userAgent(const URL&) const
{
    return m_userAgent;
}

SocketProvider* WorkerGlobalScope::socketProvider()
{
    return m_socketProvider.get();
}

RefPtr<RTCDataChannelRemoteHandlerConnection> WorkerGlobalScope::createRTCDataChannelRemoteHandlerConnection()
{
    RefPtr<RTCDataChannelRemoteHandlerConnection> connection;
    callOnMainThreadAndWait([workerThread = Ref { thread() }, &connection]() mutable {
        connection = workerThread->workerLoaderProxy().createRTCDataChannelRemoteHandlerConnection();
    });
    ASSERT(connection);

    return connection;
}

IDBClient::IDBConnectionProxy* WorkerGlobalScope::idbConnectionProxy()
{
    return m_connectionProxy.get();
}

void WorkerGlobalScope::stopIndexedDatabase()
{
    if (m_connectionProxy)
        m_connectionProxy->forgetActivityForCurrentThread();
}

void WorkerGlobalScope::suspend()
{
    if (m_connectionProxy)
        m_connectionProxy->setContextSuspended(*this, true);
}

void WorkerGlobalScope::resume()
{
    if (m_connectionProxy)
        m_connectionProxy->setContextSuspended(*this, false);
}

WorkerStorageConnection& WorkerGlobalScope::storageConnection()
{
    if (!m_storageConnection)
        m_storageConnection = WorkerStorageConnection::create(*this);

    return *m_storageConnection;
}

WorkerFileSystemStorageConnection& WorkerGlobalScope::getFileSystemStorageConnection(Ref<FileSystemStorageConnection>&& mainThreadConnection)
{
    if (!m_fileSystemStorageConnection)
        m_fileSystemStorageConnection = WorkerFileSystemStorageConnection::create(*this, WTFMove(mainThreadConnection));
    else if (m_fileSystemStorageConnection->mainThreadConnection() != mainThreadConnection.ptr()) {
        m_fileSystemStorageConnection->connectionClosed();
        m_fileSystemStorageConnection = WorkerFileSystemStorageConnection::create(*this, WTFMove(mainThreadConnection));
    }

    return *m_fileSystemStorageConnection;
}

WorkerFileSystemStorageConnection* WorkerGlobalScope::fileSystemStorageConnection()
{
    return m_fileSystemStorageConnection.get();
}

WorkerLocation& WorkerGlobalScope::location() const
{
    if (!m_location)
        m_location = WorkerLocation::create(URL { m_url }, origin());
    return *m_location;
}

void WorkerGlobalScope::close()
{
    if (isClosing())
        return;

    // Let current script run to completion but prevent future script evaluations.
    // After m_closing is set, all the tasks in the queue continue to be fetched but only
    // tasks with isCleanupTask()==true will be executed.
    markAsClosing();
    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()
{
    if (!m_navigator)
        m_navigator = WorkerNavigator::create(*this, m_userAgent, m_isOnline);
    return *m_navigator;
}

void WorkerGlobalScope::setIsOnline(bool isOnline)
{
    m_isOnline = isOnline;
    if (m_navigator)
        m_navigator->setIsOnline(isOnline);
}

ExceptionOr<int> WorkerGlobalScope::setTimeout(JSC::JSGlobalObject& state, std::unique_ptr<ScheduledAction> action, int timeout, Vector<JSC::Strong<JSC::Unknown>>&& arguments)
{
    // FIXME: Should this check really happen here? Or should it happen when code is about to eval?
    if (action->type() == ScheduledAction::Type::Code) {
        if (!contentSecurityPolicy()->allowEval(&state, LogToConsole::Yes))
            return 0;
    }

    action->addArguments(WTFMove(arguments));

    return DOMTimer::install(*this, WTFMove(action), Seconds::fromMilliseconds(timeout), true);
}

void WorkerGlobalScope::clearTimeout(int timeoutId)
{
    DOMTimer::removeById(*this, timeoutId);
}

ExceptionOr<int> WorkerGlobalScope::setInterval(JSC::JSGlobalObject& state, std::unique_ptr<ScheduledAction> action, int timeout, Vector<JSC::Strong<JSC::Unknown>>&& arguments)
{
    // FIXME: Should this check really happen here? Or should it happen when code is about to eval?
    if (action->type() == ScheduledAction::Type::Code) {
        if (!contentSecurityPolicy()->allowEval(&state, LogToConsole::Yes))
            return 0;
    }

    action->addArguments(WTFMove(arguments));

    return DOMTimer::install(*this, WTFMove(action), Seconds::fromMilliseconds(timeout), false);
}

void WorkerGlobalScope::clearInterval(int timeoutId)
{
    DOMTimer::removeById(*this, timeoutId);
}

ExceptionOr<void> WorkerGlobalScope::importScripts(const Vector<String>& urls)
{
    ASSERT(contentSecurityPolicy());

    // https://html.spec.whatwg.org/multipage/workers.html#importing-scripts-and-libraries
    // 1. If worker global scope's type is "module", throw a TypeError exception.
    if (m_workerType == WorkerType::Module)
        return Exception { TypeError, "importScripts cannot be used if worker type is \"module\""_s };

    Vector<URL> completedURLs;
    completedURLs.reserveInitialCapacity(urls.size());
    for (auto& entry : urls) {
        URL url = completeURL(entry);
        if (!url.isValid())
            return Exception { SyntaxError };
        completedURLs.uncheckedAppend(WTFMove(url));
    }

    FetchOptions::Cache cachePolicy = FetchOptions::Cache::Default;

#if ENABLE(SERVICE_WORKER)
    bool isServiceWorkerGlobalScope = is<ServiceWorkerGlobalScope>(*this);
    if (isServiceWorkerGlobalScope) {
        // FIXME: We need to add support for the 'imported scripts updated' flag as per:
        // https://w3c.github.io/ServiceWorker/#importscripts
        auto& serviceWorkerGlobalScope = downcast<ServiceWorkerGlobalScope>(*this);
        auto& registration = serviceWorkerGlobalScope.registration();
        if (registration.updateViaCache() == ServiceWorkerUpdateViaCache::None || registration.needsUpdate())
            cachePolicy = FetchOptions::Cache::NoCache;
    }
#endif

    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 { NetworkError };

        auto scriptLoader = WorkerScriptLoader::create();
        auto cspEnforcement = shouldBypassMainWorldContentSecurityPolicy ? ContentSecurityPolicyEnforcement::DoNotEnforce : ContentSecurityPolicyEnforcement::EnforceScriptSrcDirective;
        if (auto exception = scriptLoader->loadSynchronously(this, url, FetchOptions::Mode::NoCors, cachePolicy, cspEnforcement, resourceRequestIdentifier()))
            return WTFMove(*exception);

        InspectorInstrumentation::scriptImported(*this, scriptLoader->identifier(), scriptLoader->script().toString());

        WeakPtr<ScriptBufferSourceProvider> sourceProvider;
        {
            NakedPtr<JSC::Exception> exception;
            ScriptSourceCode sourceCode(scriptLoader->script(), URL(scriptLoader->responseURL()));
            sourceProvider = static_cast<ScriptBufferSourceProvider&>(sourceCode.provider());
            script()->evaluate(sourceCode, exception);
            if (exception) {
                script()->setException(exception);
                return { };
            }
        }
        if (sourceProvider)
            addImportedScriptSourceProvider(url, *sourceProvider);
    }

    return { };
}

EventTarget* WorkerGlobalScope::errorEventTarget()
{
    return this;
}

void WorkerGlobalScope::logExceptionToConsole(const String& errorMessage, const String& sourceURL, int lineNumber, int columnNumber, RefPtr<ScriptCallStack>&&)
{
    thread().workerReportingProxy().postExceptionToWorkerObject(errorMessage, lineNumber, columnNumber, sourceURL);
}

void WorkerGlobalScope::addConsoleMessage(std::unique_ptr<Inspector::ConsoleMessage>&& message)
{
    if (!isContextThread()) {
        postTask(AddConsoleMessageTask(message->source(), message->level(), message->message()));
        return;
    }

    InspectorInstrumentation::addMessageToConsole(*this, WTFMove(message));
}

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::JSGlobalObject* state, unsigned long requestIdentifier)
{
    if (!isContextThread()) {
        postTask(AddConsoleMessageTask(source, level, messageText));
        return;
    }

    std::unique_ptr<Inspector::ConsoleMessage> message;
    if (callStack)
        message = makeUnique<Inspector::ConsoleMessage>(source, MessageType::Log, level, messageText, callStack.releaseNonNull(), requestIdentifier);
    else
        message = makeUnique<Inspector::ConsoleMessage>(source, MessageType::Log, level, messageText, sourceURL, lineNumber, columnNumber, state, requestIdentifier);
    InspectorInstrumentation::addMessageToConsole(*this, WTFMove(message));
}

#if ENABLE(WEB_CRYPTO)

bool WorkerGlobalScope::wrapCryptoKey(const Vector<uint8_t>& key, Vector<uint8_t>& wrappedKey)
{
    Ref protectedThis { *this };
    bool success = false;
    BinarySemaphore semaphore;
    thread().workerLoaderProxy().postTaskToLoader([&semaphore, &success, &key, &wrappedKey](auto& context) {
        success = context.wrapCryptoKey(key, wrappedKey);
        semaphore.signal();
    });
    semaphore.wait();
    return success;
}

bool WorkerGlobalScope::unwrapCryptoKey(const Vector<uint8_t>& wrappedKey, Vector<uint8_t>& key)
{
    Ref protectedThis { *this };
    bool success = false;
    BinarySemaphore semaphore;
    thread().workerLoaderProxy().postTaskToLoader([&semaphore, &success, &key, &wrappedKey](auto& context) {
        success = context.unwrapCryptoKey(wrappedKey, key);
        semaphore.signal();
    });
    semaphore.wait();
    return success;
}

#endif // ENABLE(WEB_CRYPTO)

Crypto& WorkerGlobalScope::crypto()
{
    if (!m_crypto)
        m_crypto = Crypto::create(this);
    return *m_crypto;
}

Performance& WorkerGlobalScope::performance() const
{
    return *m_performance;
}

WorkerCacheStorageConnection& WorkerGlobalScope::cacheStorageConnection()
{
    if (!m_cacheStorageConnection)
        m_cacheStorageConnection = WorkerCacheStorageConnection::create(*this);
    return *m_cacheStorageConnection;
}

MessagePortChannelProvider& WorkerGlobalScope::messagePortChannelProvider()
{
    if (!m_messagePortChannelProvider)
        m_messagePortChannelProvider = makeUnique<WorkerMessagePortChannelProvider>(*this);
    return *m_messagePortChannelProvider;
}

#if ENABLE(SERVICE_WORKER)
WorkerSWClientConnection& WorkerGlobalScope::swClientConnection()
{
    if (!m_swClientConnection)
        m_swClientConnection = WorkerSWClientConnection::create(*this);
    return *m_swClientConnection;
}
#endif

void WorkerGlobalScope::createImageBitmap(ImageBitmap::Source&& source, ImageBitmapOptions&& options, ImageBitmap::Promise&& promise)
{
    ImageBitmap::createPromise(*this, WTFMove(source), WTFMove(options), WTFMove(promise));
}

void WorkerGlobalScope::createImageBitmap(ImageBitmap::Source&& source, int sx, int sy, int sw, int sh, ImageBitmapOptions&& options, ImageBitmap::Promise&& promise)
{
    ImageBitmap::createPromise(*this, WTFMove(source), WTFMove(options), sx, sy, sw, sh, WTFMove(promise));
}

CSSValuePool& WorkerGlobalScope::cssValuePool()
{
    if (!m_cssValuePool)
        m_cssValuePool = makeUnique<CSSValuePool>();
    return *m_cssValuePool;
}

CSSFontSelector* WorkerGlobalScope::cssFontSelector()
{
    if (!m_cssFontSelector)
        m_cssFontSelector = CSSFontSelector::create(*this);
    return m_cssFontSelector.get();
}

FontCache& WorkerGlobalScope::fontCache()
{
    if (!m_fontCache)
        m_fontCache = FontCache::create();
    return *m_fontCache;
}

Ref<FontFaceSet> WorkerGlobalScope::fonts()
{
    ASSERT(cssFontSelector());
    return cssFontSelector()->fontFaceSet();
}

std::unique_ptr<FontLoadRequest> WorkerGlobalScope::fontLoadRequest(String& url, bool, bool, LoadedFromOpaqueSource loadedFromOpaqueSource)
{
    return makeUnique<WorkerFontLoadRequest>(completeURL(url), loadedFromOpaqueSource);
}

void WorkerGlobalScope::beginLoadingFontSoon(FontLoadRequest& request)
{
    ASSERT(is<WorkerFontLoadRequest>(request));
    downcast<WorkerFontLoadRequest>(request).load(*this);
}

ReferrerPolicy WorkerGlobalScope::referrerPolicy() const
{
    return m_referrerPolicy;
}

WorkerThread& WorkerGlobalScope::thread() const
{
    return *static_cast<WorkerThread*>(workerOrWorkletThread());
}

void WorkerGlobalScope::releaseMemory(Synchronous synchronous)
{
    ASSERT(isContextThread());
    deleteJSCodeAndGC(synchronous);
    clearDecodedScriptData();
}

void WorkerGlobalScope::deleteJSCodeAndGC(Synchronous synchronous)
{
    ASSERT(isContextThread());

    JSC::JSLockHolder lock(vm());
    vm().deleteAllCode(JSC::DeleteAllCodeIfNotCollecting);

    if (synchronous == Synchronous::Yes) {
        if (!vm().heap.isCurrentThreadBusy()) {
            vm().heap.collectNow(JSC::Sync, JSC::CollectionScope::Full);
            WTF::releaseFastMallocFreeMemory();
            return;
        }
    }
#if PLATFORM(IOS_FAMILY)
    if (!vm().heap.isCurrentThreadBusy()) {
        vm().heap.collectNowFullIfNotDoneRecently(JSC::Async);
        return;
    }
#endif
#if USE(CF) || USE(GLIB)
    vm().heap.reportAbandonedObjectGraph();
#else
    vm().heap.collectNow(JSC::Async, JSC::CollectionScope::Full);
#endif
}

void WorkerGlobalScope::releaseMemoryInWorkers(Synchronous synchronous)
{
    Locker locker { allWorkerGlobalScopeIdentifiersLock };
    for (auto& globalScopeIdentifier : allWorkerGlobalScopeIdentifiers()) {
        postTaskTo(globalScopeIdentifier, [synchronous](auto& context) {
            downcast<WorkerGlobalScope>(context).releaseMemory(synchronous);
        });
    }
}

void WorkerGlobalScope::setMainScriptSourceProvider(ScriptBufferSourceProvider& provider)
{
    ASSERT(!m_mainScriptSourceProvider);
    m_mainScriptSourceProvider = provider;
}

void WorkerGlobalScope::addImportedScriptSourceProvider(const URL& url, ScriptBufferSourceProvider& provider)
{
    m_importedScriptsSourceProviders.ensure(url, [] {
        return WeakHashSet<ScriptBufferSourceProvider> { };
    }).iterator->value.add(provider);
}

void WorkerGlobalScope::clearDecodedScriptData()
{
    ASSERT(isContextThread());

    if (m_mainScriptSourceProvider)
        m_mainScriptSourceProvider->clearDecodedData();

    for (auto& sourceProviders : m_importedScriptsSourceProviders.values()) {
        for (auto& sourceProvider : sourceProviders)
            sourceProvider.clearDecodedData();
    }
}

bool WorkerGlobalScope::crossOriginIsolated() const
{
    return ScriptExecutionContext::crossOriginMode() == CrossOriginMode::Isolated;
}

void WorkerGlobalScope::updateSourceProviderBuffers(const ScriptBuffer& mainScript, const HashMap<URL, ScriptBuffer>& importedScripts)
{
    ASSERT(isContextThread());

    if (mainScript && m_mainScriptSourceProvider)
        m_mainScriptSourceProvider->tryReplaceScriptBuffer(mainScript);

    for (auto& pair : importedScripts) {
        auto it = m_importedScriptsSourceProviders.find(pair.key);
        if (it == m_importedScriptsSourceProviders.end())
            continue;
        for (auto& sourceProvider : it->value)
            sourceProvider.tryReplaceScriptBuffer(pair.value);
    }
}

} // namespace WebCore
