1/* 2 * Copyright (C) 2008 Apple Inc. All Rights Reserved. 3 * Copyright (C) 2012 Google Inc. All Rights Reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY 15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR 18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * 26 */ 27 28#ifndef ScriptExecutionContext_h 29#define ScriptExecutionContext_h 30 31#include "ActiveDOMObject.h" 32#include "SecurityContext.h" 33#include "Supplementable.h" 34#include <runtime/ConsoleTypes.h> 35#include <wtf/HashSet.h> 36 37namespace JSC { 38class ExecState; 39class VM; 40} 41 42namespace Inspector { 43class ScriptCallStack; 44} 45 46namespace WebCore { 47 48class CachedScript; 49class DatabaseContext; 50class DOMTimer; 51class EventQueue; 52class EventTarget; 53class MessagePort; 54class PublicURLManager; 55class URL; 56 57class ScriptExecutionContext : public SecurityContext, public Supplementable<ScriptExecutionContext> { 58public: 59 ScriptExecutionContext(); 60 virtual ~ScriptExecutionContext(); 61 62 virtual bool isDocument() const { return false; } 63 virtual bool isWorkerGlobalScope() const { return false; } 64 65 virtual bool isContextThread() const { return true; } 66 virtual bool isJSExecutionForbidden() const = 0; 67 68 virtual const URL& url() const = 0; 69 virtual URL completeURL(const String& url) const = 0; 70 71 virtual String userAgent(const URL&) const = 0; 72 73 virtual void disableEval(const String& errorMessage) = 0; 74 75 bool sanitizeScriptError(String& errorMessage, int& lineNumber, int& columnNumber, String& sourceURL, CachedScript* = nullptr); 76 void reportException(const String& errorMessage, int lineNumber, int columnNumber, const String& sourceURL, PassRefPtr<Inspector::ScriptCallStack>, CachedScript* = nullptr); 77 78 void addConsoleMessage(MessageSource, MessageLevel, const String& message, const String& sourceURL, unsigned lineNumber, unsigned columnNumber, JSC::ExecState* = nullptr, unsigned long requestIdentifier = 0); 79 virtual void addConsoleMessage(MessageSource, MessageLevel, const String& message, unsigned long requestIdentifier = 0) = 0; 80 81 virtual SecurityOrigin* topOrigin() const = 0; 82 83 PublicURLManager& publicURLManager(); 84 85 // Active objects are not garbage collected even if inaccessible, e.g. because their activity may result in callbacks being invoked. 86 bool canSuspendActiveDOMObjects(); 87 // Active objects can be asked to suspend even if canSuspendActiveDOMObjects() returns 'false' - 88 // step-by-step JS debugging is one example. 89 virtual void suspendActiveDOMObjects(ActiveDOMObject::ReasonForSuspension); 90 virtual void resumeActiveDOMObjects(ActiveDOMObject::ReasonForSuspension); 91 virtual void stopActiveDOMObjects(); 92 93 bool activeDOMObjectsAreSuspended() const { return m_activeDOMObjectsAreSuspended; } 94 bool activeDOMObjectsAreStopped() const { return m_activeDOMObjectsAreStopped; } 95 96 // Called from the constructor and destructors of ActiveDOMObject. 97 void didCreateActiveDOMObject(ActiveDOMObject&); 98 void willDestroyActiveDOMObject(ActiveDOMObject&); 99 100 // Called after the construction of an ActiveDOMObject to synchronize suspend state. 101 void suspendActiveDOMObjectIfNeeded(ActiveDOMObject&); 102 103 void didCreateDestructionObserver(ContextDestructionObserver&); 104 void willDestroyDestructionObserver(ContextDestructionObserver&); 105 106 // MessagePort is conceptually a kind of ActiveDOMObject, but it needs to be tracked separately for message dispatch. 107 void processMessagePortMessagesSoon(); 108 void dispatchMessagePortEvents(); 109 void createdMessagePort(MessagePort&); 110 void destroyedMessagePort(MessagePort&); 111 112 void ref() { refScriptExecutionContext(); } 113 void deref() { derefScriptExecutionContext(); } 114 115 class Task { 116 WTF_MAKE_FAST_ALLOCATED; 117 public: 118 enum CleanupTaskTag { CleanupTask }; 119 120 template<typename T, typename = typename std::enable_if<!std::is_base_of<Task, T>::value && std::is_convertible<T, std::function<void (ScriptExecutionContext&)>>::value>::type> 121 Task(T task) 122 : m_task(WTF::move(task)) 123 , m_isCleanupTask(false) 124 { 125 } 126 127 template<typename T, typename = typename std::enable_if<std::is_convertible<T, std::function<void (ScriptExecutionContext&)>>::value>::type> 128 Task(CleanupTaskTag, T task) 129 : m_task(WTF::move(task)) 130 , m_isCleanupTask(true) 131 { 132 } 133 134 Task(Task&& other) 135 : m_task(WTF::move(other.m_task)) 136 , m_isCleanupTask(other.m_isCleanupTask) 137 { 138 } 139 140 void performTask(ScriptExecutionContext& context) { m_task(context); } 141 bool isCleanupTask() const { return m_isCleanupTask; } 142 143 protected: 144 std::function<void (ScriptExecutionContext&)> m_task; 145 bool m_isCleanupTask; 146 }; 147 148 virtual void postTask(Task) = 0; // Executes the task on context's thread asynchronously. 149 150 // Gets the next id in a circular sequence from 1 to 2^31-1. 151 int circularSequentialID(); 152 153 bool addTimeout(int timeoutId, DOMTimer* timer) { return m_timeouts.add(timeoutId, timer).isNewEntry; } 154 void removeTimeout(int timeoutId) { m_timeouts.remove(timeoutId); } 155 DOMTimer* findTimeout(int timeoutId) { return m_timeouts.get(timeoutId); } 156 157 JSC::VM& vm(); 158 159 // Interval is in seconds. 160 void adjustMinimumTimerInterval(double oldMinimumTimerInterval); 161 virtual double minimumTimerInterval() const; 162 163 void didChangeTimerAlignmentInterval(); 164 virtual double timerAlignmentInterval() const; 165 166 virtual EventQueue& eventQueue() const = 0; 167 168#if ENABLE(SQL_DATABASE) 169 void setDatabaseContext(DatabaseContext*); 170#endif 171 172#if ENABLE(SUBTLE_CRYPTO) 173 virtual bool wrapCryptoKey(const Vector<uint8_t>& key, Vector<uint8_t>& wrappedKey) = 0; 174 virtual bool unwrapCryptoKey(const Vector<uint8_t>& wrappedKey, Vector<uint8_t>& key) = 0; 175#endif 176 177protected: 178 class AddConsoleMessageTask : public Task { 179 public: 180 AddConsoleMessageTask(MessageSource source, MessageLevel level, const String& message) 181 : Task([=] (ScriptExecutionContext& context) { 182 context.addConsoleMessage(source, level, message); 183 }) 184 { 185 } 186 }; 187 188 ActiveDOMObject::ReasonForSuspension reasonForSuspendingActiveDOMObjects() const { return m_reasonForSuspendingActiveDOMObjects; } 189 190 bool hasPendingActivity() const; 191 192private: 193 virtual void addMessage(MessageSource, MessageLevel, const String& message, const String& sourceURL, unsigned lineNumber, unsigned columnNumber, PassRefPtr<Inspector::ScriptCallStack>, JSC::ExecState* = nullptr, unsigned long requestIdentifier = 0) = 0; 194 virtual EventTarget* errorEventTarget() = 0; 195 virtual void logExceptionToConsole(const String& errorMessage, const String& sourceURL, int lineNumber, int columnNumber, PassRefPtr<Inspector::ScriptCallStack>) = 0; 196 bool dispatchErrorEvent(const String& errorMessage, int lineNumber, int columnNumber, const String& sourceURL, CachedScript*); 197 198 virtual void refScriptExecutionContext() = 0; 199 virtual void derefScriptExecutionContext() = 0; 200 201 void checkConsistency() const; 202 203 HashSet<MessagePort*> m_messagePorts; 204 HashSet<ContextDestructionObserver*> m_destructionObservers; 205 HashSet<ActiveDOMObject*> m_activeDOMObjects; 206 207 int m_circularSequentialID; 208 HashMap<int, DOMTimer*> m_timeouts; 209 210 bool m_inDispatchErrorEvent; 211 class PendingException; 212 std::unique_ptr<Vector<std::unique_ptr<PendingException>>> m_pendingExceptions; 213 214 bool m_activeDOMObjectsAreSuspended; 215 ActiveDOMObject::ReasonForSuspension m_reasonForSuspendingActiveDOMObjects; 216 bool m_activeDOMObjectsAreStopped; 217 218 std::unique_ptr<PublicURLManager> m_publicURLManager; 219 220#if ENABLE(SQL_DATABASE) 221 RefPtr<DatabaseContext> m_databaseContext; 222#endif 223 224 bool m_activeDOMObjectAdditionForbidden; 225 226#if !ASSERT_DISABLED 227 bool m_inScriptExecutionContextDestructor; 228 bool m_activeDOMObjectRemovalForbidden; 229#endif 230}; 231 232#define SCRIPT_EXECUTION_CONTEXT_TYPE_CASTS(ToValueTypeName) \ 233 TYPE_CASTS_BASE(ToValueTypeName, ScriptExecutionContext, context, context->is##ToValueTypeName(), context.is##ToValueTypeName()) 234 235} // namespace WebCore 236 237#endif // ScriptExecutionContext_h 238