/* * Copyright (C) 2008-2017 Apple Inc. All Rights Reserved. * Copyright (C) 2012 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. * */ #pragma once #include "ActiveDOMObject.h" #include "DOMTimer.h" #include "RTCDataChannelRemoteHandlerConnection.h" #include "ResourceLoaderOptions.h" #include "ScriptExecutionContextIdentifier.h" #include "SecurityContext.h" #include "ServiceWorkerTypes.h" #include "Settings.h" #include #include #include #include #include #include #include #include namespace JSC { class CallFrame; class Exception; class JSPromise; class VM; enum class ScriptExecutionStatus; } namespace Inspector { class ConsoleMessage; class ScriptCallStack; } namespace WebCore { class EventLoop; class CachedScript; class CSSFontSelector; class CSSValuePool; class DatabaseContext; class EventQueue; class EventLoopTaskGroup; class EventTarget; class FontCache; class FontLoadRequest; class MessagePort; class PublicURLManager; class RejectedPromiseTracker; class ResourceRequest; class SecurityOrigin; class SocketProvider; enum class ReferrerPolicy : uint8_t; enum class TaskSource : uint8_t; #if ENABLE(SERVICE_WORKER) class ServiceWorker; class ServiceWorkerContainer; #endif namespace IDBClient { class IDBConnectionProxy; } class ScriptExecutionContext : public SecurityContext, public CanMakeWeakPtr { public: ScriptExecutionContext(); virtual ~ScriptExecutionContext(); virtual bool isDocument() const { return false; } virtual bool isWorkerGlobalScope() const { return false; } virtual bool isWorkletGlobalScope() const { return false; } virtual bool isContextThread() const { return true; } virtual bool isJSExecutionForbidden() const = 0; virtual EventLoopTaskGroup& eventLoop() = 0; virtual const URL& url() const = 0; enum class ForceUTF8 { No, Yes }; virtual URL completeURL(const String& url, ForceUTF8 = ForceUTF8::No) const = 0; virtual String userAgent(const URL&) const = 0; virtual ReferrerPolicy referrerPolicy() const = 0; virtual const Settings::Values& settingsValues() const = 0; virtual void disableEval(const String& errorMessage) = 0; virtual void disableWebAssembly(const String& errorMessage) = 0; virtual IDBClient::IDBConnectionProxy* idbConnectionProxy() = 0; virtual SocketProvider* socketProvider() = 0; virtual RefPtr createRTCDataChannelRemoteHandlerConnection() { return nullptr; } virtual String resourceRequestIdentifier() const { return String(); }; bool canIncludeErrorDetails(CachedScript*, const String& sourceURL); void reportException(const String& errorMessage, int lineNumber, int columnNumber, const String& sourceURL, JSC::Exception*, RefPtr&&, CachedScript* = nullptr); void reportUnhandledPromiseRejection(JSC::JSGlobalObject&, JSC::JSPromise&, RefPtr&&); virtual void addConsoleMessage(std::unique_ptr&&) = 0; // The following addConsoleMessage functions are deprecated. // Callers should try to create the ConsoleMessage themselves. void addConsoleMessage(MessageSource, MessageLevel, const String& message, const String& sourceURL, unsigned lineNumber, unsigned columnNumber, JSC::JSGlobalObject* = nullptr, unsigned long requestIdentifier = 0); virtual void addConsoleMessage(MessageSource, MessageLevel, const String& message, unsigned long requestIdentifier = 0) = 0; virtual SecurityOrigin& topOrigin() const = 0; virtual bool shouldBypassMainWorldContentSecurityPolicy() const { return false; } PublicURLManager& publicURLManager(); virtual void suspendActiveDOMObjects(ReasonForSuspension); virtual void resumeActiveDOMObjects(ReasonForSuspension); virtual void stopActiveDOMObjects(); bool activeDOMObjectsAreSuspended() const { return m_activeDOMObjectsAreSuspended; } bool activeDOMObjectsAreStopped() const { return m_activeDOMObjectsAreStopped; } JSC::ScriptExecutionStatus jscScriptExecutionStatus() const; // Called from the constructor and destructors of ActiveDOMObject. void didCreateActiveDOMObject(ActiveDOMObject&); void willDestroyActiveDOMObject(ActiveDOMObject&); // Called after the construction of an ActiveDOMObject to synchronize suspend state. void suspendActiveDOMObjectIfNeeded(ActiveDOMObject&); void didCreateDestructionObserver(ContextDestructionObserver&); void willDestroyDestructionObserver(ContextDestructionObserver&); // MessagePort is conceptually a kind of ActiveDOMObject, but it needs to be tracked separately for message dispatch. void processMessageWithMessagePortsSoon(); void dispatchMessagePortEvents(); void createdMessagePort(MessagePort&); void destroyedMessagePort(MessagePort&); virtual void didLoadResourceSynchronously(const URL&); virtual FontCache& fontCache(); virtual CSSFontSelector* cssFontSelector() { return nullptr; } virtual CSSValuePool& cssValuePool(); virtual std::unique_ptr fontLoadRequest(String& url, bool isSVG, bool isInitiatingElementInUserAgentShadowTree, LoadedFromOpaqueSource); virtual void beginLoadingFontSoon(FontLoadRequest&) { } void ref() { refScriptExecutionContext(); } void deref() { derefScriptExecutionContext(); } class Task { WTF_MAKE_FAST_ALLOCATED; public: enum CleanupTaskTag { CleanupTask }; template::value && std::is_convertible>::value>::type> Task(T task) : m_task(WTFMove(task)) , m_isCleanupTask(false) { } Task(WTF::Function&& task) : m_task([task = WTFMove(task)](ScriptExecutionContext&) { task(); }) , m_isCleanupTask(false) { } template>::value>::type> Task(CleanupTaskTag, T task) : m_task(WTFMove(task)) , m_isCleanupTask(true) { } void performTask(ScriptExecutionContext& context) { m_task(context); } bool isCleanupTask() const { return m_isCleanupTask; } protected: WTF::Function m_task; bool m_isCleanupTask; }; virtual void postTask(Task&&) = 0; // Executes the task on context's thread asynchronously. template void postCrossThreadTask(Arguments&&... arguments) { postTask([crossThreadTask = createCrossThreadTask(arguments...)](ScriptExecutionContext&) mutable { crossThreadTask.performTask(); }); } // Gets the next id in a circular sequence from 1 to 2^31-1. int circularSequentialID(); bool addTimeout(int timeoutId, DOMTimer& timer) { return m_timeouts.add(timeoutId, timer).isNewEntry; } void removeTimeout(int timeoutId) { m_timeouts.remove(timeoutId); } DOMTimer* findTimeout(int timeoutId) { return m_timeouts.get(timeoutId); } virtual JSC::VM& vm() = 0; void adjustMinimumDOMTimerInterval(Seconds oldMinimumTimerInterval); virtual Seconds minimumDOMTimerInterval() const; void didChangeTimerAlignmentInterval(); virtual Seconds domTimerAlignmentInterval(bool hasReachedMaxNestingLevel) const; virtual EventTarget* errorEventTarget() = 0; DatabaseContext* databaseContext() { return m_databaseContext.get(); } void setDatabaseContext(DatabaseContext*); #if ENABLE(WEB_CRYPTO) // These two methods are used when CryptoKeys are serialized into IndexedDB. As a side effect, it is also // used for things that utilize the same structure clone algorithm, for example, message passing between // worker and document. virtual bool wrapCryptoKey(const Vector& key, Vector& wrappedKey) = 0; virtual bool unwrapCryptoKey(const Vector& wrappedKey, Vector& key) = 0; #endif int timerNestingLevel() const { return m_timerNestingLevel; } void setTimerNestingLevel(int timerNestingLevel) { m_timerNestingLevel = timerNestingLevel; } RejectedPromiseTracker& ensureRejectedPromiseTracker() { if (m_rejectedPromiseTracker) return *m_rejectedPromiseTracker.get(); return ensureRejectedPromiseTrackerSlow(); } WEBCORE_EXPORT JSC::JSGlobalObject* globalObject(); WEBCORE_EXPORT String domainForCachePartition() const; void setDomainForCachePartition(String&& domain) { m_domainForCachePartition = WTFMove(domain); } bool allowsMediaDevices() const; #if ENABLE(SERVICE_WORKER) ServiceWorker* activeServiceWorker() const; void setActiveServiceWorker(RefPtr&&); void registerServiceWorker(ServiceWorker&); void unregisterServiceWorker(ServiceWorker&); ServiceWorker* serviceWorker(ServiceWorkerIdentifier identifier) { return m_serviceWorkers.get(identifier); } ServiceWorkerContainer* serviceWorkerContainer(); ServiceWorkerContainer* ensureServiceWorkerContainer(); #endif WEBCORE_EXPORT static bool postTaskTo(ScriptExecutionContextIdentifier, Task&&); ScriptExecutionContextIdentifier contextIdentifier() const; protected: class AddConsoleMessageTask : public Task { public: AddConsoleMessageTask(std::unique_ptr&& consoleMessage) : Task([&consoleMessage](ScriptExecutionContext& context) { context.addConsoleMessage(WTFMove(consoleMessage)); }) { } AddConsoleMessageTask(MessageSource source, MessageLevel level, const String& message) : Task([source, level, message = message.isolatedCopy()](ScriptExecutionContext& context) { context.addConsoleMessage(source, level, message); }) { } }; ReasonForSuspension reasonForSuspendingActiveDOMObjects() const { return m_reasonForSuspendingActiveDOMObjects; } bool hasPendingActivity() const; void removeFromContextsMap(); void removeRejectedPromiseTracker(); private: // The following addMessage function is deprecated. // Callers should try to create the ConsoleMessage themselves. virtual void addMessage(MessageSource, MessageLevel, const String& message, const String& sourceURL, unsigned lineNumber, unsigned columnNumber, RefPtr&&, JSC::JSGlobalObject* = nullptr, unsigned long requestIdentifier = 0) = 0; virtual void logExceptionToConsole(const String& errorMessage, const String& sourceURL, int lineNumber, int columnNumber, RefPtr&&) = 0; bool dispatchErrorEvent(const String& errorMessage, int lineNumber, int columnNumber, const String& sourceURL, JSC::Exception*, CachedScript*); virtual void refScriptExecutionContext() = 0; virtual void derefScriptExecutionContext() = 0; enum class ShouldContinue { No, Yes }; void forEachActiveDOMObject(const Function&) const; RejectedPromiseTracker& ensureRejectedPromiseTrackerSlow(); void checkConsistency() const; HashSet m_messagePorts; HashSet m_destructionObservers; HashSet m_activeDOMObjects; HashMap> m_timeouts; struct PendingException; std::unique_ptr>> m_pendingExceptions; std::unique_ptr m_rejectedPromiseTracker; ReasonForSuspension m_reasonForSuspendingActiveDOMObjects { static_cast(-1) }; std::unique_ptr m_publicURLManager; RefPtr m_databaseContext; int m_circularSequentialID { 0 }; int m_timerNestingLevel { 0 }; bool m_activeDOMObjectsAreSuspended { false }; bool m_activeDOMObjectsAreStopped { false }; bool m_inDispatchErrorEvent { false }; mutable bool m_activeDOMObjectAdditionForbidden { false }; bool m_willprocessMessageWithMessagePortsSoon { false }; #if ASSERT_ENABLED bool m_inScriptExecutionContextDestructor { false }; #endif #if ENABLE(SERVICE_WORKER) RefPtr m_activeServiceWorker; HashMap m_serviceWorkers; #endif String m_domainForCachePartition; mutable ScriptExecutionContextIdentifier m_contextIdentifier; }; } // namespace WebCore