/* * Copyright (C) 2008 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. * */ #ifndef ScriptExecutionContext_h #define ScriptExecutionContext_h #include "ActiveDOMObject.h" #include "DOMTimer.h" #include "ResourceRequest.h" #include "SecurityContext.h" #include "Supplementable.h" #include #include namespace JSC { class ExecState; class VM; } namespace Inspector { class ScriptCallStack; } namespace WebCore { class CachedScript; class DatabaseContext; class EventQueue; class EventTarget; class MessagePort; class PublicURLManager; class SecurityOrigin; class URL; class ScriptExecutionContext : public SecurityContext, public Supplementable { public: ScriptExecutionContext(); virtual ~ScriptExecutionContext(); virtual bool isDocument() const { return false; } virtual bool isWorkerGlobalScope() const { return false; } virtual bool isContextThread() const { return true; } virtual bool isJSExecutionForbidden() const = 0; virtual const URL& url() const = 0; virtual URL completeURL(const String& url) const = 0; virtual String userAgent(const URL&) const = 0; virtual void disableEval(const String& errorMessage) = 0; bool sanitizeScriptError(String& errorMessage, int& lineNumber, int& columnNumber, String& sourceURL, CachedScript* = nullptr); void reportException(const String& errorMessage, int lineNumber, int columnNumber, const String& sourceURL, RefPtr&&, CachedScript* = nullptr); void addConsoleMessage(MessageSource, MessageLevel, const String& message, const String& sourceURL, unsigned lineNumber, unsigned columnNumber, JSC::ExecState* = 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(); // Active objects are not garbage collected even if inaccessible, e.g. because their activity may result in callbacks being invoked. WEBCORE_EXPORT bool canSuspendActiveDOMObjectsForDocumentSuspension(Vector* unsuspendableObjects = nullptr); // Active objects can be asked to suspend even if canSuspendActiveDOMObjectsForDocumentSuspension() returns 'false' - // step-by-step JS debugging is one example. virtual void suspendActiveDOMObjects(ActiveDOMObject::ReasonForSuspension); virtual void resumeActiveDOMObjects(ActiveDOMObject::ReasonForSuspension); virtual void stopActiveDOMObjects(); bool activeDOMObjectsAreSuspended() const { return m_activeDOMObjectsAreSuspended; } bool activeDOMObjectsAreStopped() const { return m_activeDOMObjectsAreStopped; } // 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 processMessagePortMessagesSoon(); void dispatchMessagePortEvents(); void createdMessagePort(MessagePort&); void destroyedMessagePort(MessagePort&); virtual void didLoadResourceSynchronously(const ResourceRequest&); 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(std::function task) : m_task([task](ScriptExecutionContext&) { task(); }) , m_isCleanupTask(false) { } template>::value>::type> Task(CleanupTaskTag, T task) : m_task(WTFMove(task)) , m_isCleanupTask(true) { } Task(Task&& other) : m_task(WTFMove(other.m_task)) , m_isCleanupTask(other.m_isCleanupTask) { } void performTask(ScriptExecutionContext& context) { m_task(context); } bool isCleanupTask() const { return m_isCleanupTask; } protected: std::function m_task; bool m_isCleanupTask; }; virtual void postTask(Task) = 0; // Executes the task on context's thread asynchronously. // Gets the next id in a circular sequence from 1 to 2^31-1. int circularSequentialID(); bool addTimeout(int timeoutId, PassRefPtr 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); } WEBCORE_EXPORT JSC::VM& vm(); // Interval is in seconds. void adjustMinimumTimerInterval(double oldMinimumTimerInterval); virtual double minimumTimerInterval() const; void didChangeTimerAlignmentInterval(); virtual double timerAlignmentInterval(bool hasReachedMaxNestingLevel) const; virtual EventQueue& eventQueue() const = 0; void setDatabaseContext(DatabaseContext*); #if ENABLE(SUBTLE_CRYPTO) 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; } protected: class AddConsoleMessageTask : public Task { public: AddConsoleMessageTask(MessageSource source, MessageLevel level, const StringCapture& message) : Task([source, level, message](ScriptExecutionContext& context) { context.addConsoleMessage(source, level, message.string()); }) { } }; ActiveDOMObject::ReasonForSuspension reasonForSuspendingActiveDOMObjects() const { return m_reasonForSuspendingActiveDOMObjects; } bool hasPendingActivity() const; private: virtual void addMessage(MessageSource, MessageLevel, const String& message, const String& sourceURL, unsigned lineNumber, unsigned columnNumber, RefPtr&&, JSC::ExecState* = nullptr, unsigned long requestIdentifier = 0) = 0; virtual EventTarget* errorEventTarget() = 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, CachedScript*); virtual void refScriptExecutionContext() = 0; virtual void derefScriptExecutionContext() = 0; void checkConsistency() const; HashSet m_messagePorts; HashSet m_destructionObservers; HashSet m_activeDOMObjects; int m_circularSequentialID; HashMap> m_timeouts; bool m_inDispatchErrorEvent; class PendingException; std::unique_ptr>> m_pendingExceptions; bool m_activeDOMObjectsAreSuspended; ActiveDOMObject::ReasonForSuspension m_reasonForSuspendingActiveDOMObjects; bool m_activeDOMObjectsAreStopped; std::unique_ptr m_publicURLManager; RefPtr m_databaseContext; bool m_activeDOMObjectAdditionForbidden; int m_timerNestingLevel; #if !ASSERT_DISABLED bool m_inScriptExecutionContextDestructor; #endif #if !ASSERT_DISABLED || ENABLE(SECURITY_ASSERTIONS) bool m_activeDOMObjectRemovalForbidden; #endif }; } // namespace WebCore #endif // ScriptExecutionContext_h