Port DOMTimer from std::chrono::milliseconds to WTF::Seconds type
[WebKit-https.git] / Source / WebCore / dom / ScriptExecutionContext.h
1 /*
2  * Copyright (C) 2008, 2009, 2010, 2011, 2013, 2014, 2015, 2016 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 #pragma once
29
30 #include "ActiveDOMObject.h"
31 #include "DOMTimer.h"
32 #include "SecurityContext.h"
33 #include "Supplementable.h"
34 #include <heap/HandleTypes.h>
35 #include <runtime/ConsoleTypes.h>
36 #include <wtf/CrossThreadTask.h>
37 #include <wtf/Function.h>
38 #include <wtf/HashSet.h>
39
40 namespace JSC {
41 class Exception;
42 class ExecState;
43 class VM;
44 template<typename> class Strong;
45 }
46
47 namespace Inspector {
48 class ScriptCallStack;
49 }
50
51 namespace WebCore {
52
53 class CachedScript;
54 class DatabaseContext;
55 class EventQueue;
56 class EventTarget;
57 class MessagePort;
58 class PublicURLManager;
59 class ResourceRequest;
60 class SecurityOrigin;
61 class SocketProvider;
62 class URL;
63
64 namespace IDBClient {
65 class IDBConnectionProxy;
66 }
67
68 class ScriptExecutionContext : public SecurityContext {
69 public:
70     ScriptExecutionContext();
71     virtual ~ScriptExecutionContext();
72
73     virtual bool isDocument() const { return false; }
74     virtual bool isWorkerGlobalScope() const { return false; }
75
76     virtual bool isContextThread() const { return true; }
77     virtual bool isJSExecutionForbidden() const = 0;
78
79     virtual const URL& url() const = 0;
80     virtual URL completeURL(const String& url) const = 0;
81
82     virtual String userAgent(const URL&) const = 0;
83
84     virtual void disableEval(const String& errorMessage) = 0;
85
86 #if ENABLE(INDEXED_DATABASE)
87     virtual IDBClient::IDBConnectionProxy* idbConnectionProxy() = 0;
88 #endif
89 #if ENABLE(WEB_SOCKETS)
90     virtual SocketProvider* socketProvider() = 0;
91 #endif
92
93     virtual String resourceRequestIdentifier() const { return String(); };
94
95     bool sanitizeScriptError(String& errorMessage, int& lineNumber, int& columnNumber, String& sourceURL, JSC::Strong<JSC::Unknown>& error, CachedScript* = nullptr);
96     void reportException(const String& errorMessage, int lineNumber, int columnNumber, const String& sourceURL, JSC::Exception*, RefPtr<Inspector::ScriptCallStack>&&, CachedScript* = nullptr);
97
98     void addConsoleMessage(MessageSource, MessageLevel, const String& message, const String& sourceURL, unsigned lineNumber, unsigned columnNumber, JSC::ExecState* = nullptr, unsigned long requestIdentifier = 0);
99     virtual void addConsoleMessage(MessageSource, MessageLevel, const String& message, unsigned long requestIdentifier = 0) = 0;
100
101     virtual SecurityOrigin& topOrigin() const = 0;
102
103     virtual bool shouldBypassMainWorldContentSecurityPolicy() const { return false; }
104
105     PublicURLManager& publicURLManager();
106
107     // Active objects are not garbage collected even if inaccessible, e.g. because their activity may result in callbacks being invoked.
108     WEBCORE_EXPORT bool canSuspendActiveDOMObjectsForDocumentSuspension(Vector<ActiveDOMObject*>* unsuspendableObjects = nullptr);
109
110     // Active objects can be asked to suspend even if canSuspendActiveDOMObjectsForDocumentSuspension() returns 'false' -
111     // step-by-step JS debugging is one example.
112     virtual void suspendActiveDOMObjects(ActiveDOMObject::ReasonForSuspension);
113     virtual void resumeActiveDOMObjects(ActiveDOMObject::ReasonForSuspension);
114     virtual void stopActiveDOMObjects();
115
116     bool activeDOMObjectsAreSuspended() const { return m_activeDOMObjectsAreSuspended; }
117     bool activeDOMObjectsAreStopped() const { return m_activeDOMObjectsAreStopped; }
118
119     // Called from the constructor and destructors of ActiveDOMObject.
120     void didCreateActiveDOMObject(ActiveDOMObject&);
121     void willDestroyActiveDOMObject(ActiveDOMObject&);
122
123     // Called after the construction of an ActiveDOMObject to synchronize suspend state.
124     void suspendActiveDOMObjectIfNeeded(ActiveDOMObject&);
125
126     void didCreateDestructionObserver(ContextDestructionObserver&);
127     void willDestroyDestructionObserver(ContextDestructionObserver&);
128
129     // MessagePort is conceptually a kind of ActiveDOMObject, but it needs to be tracked separately for message dispatch.
130     void processMessagePortMessagesSoon();
131     void dispatchMessagePortEvents();
132     void createdMessagePort(MessagePort&);
133     void destroyedMessagePort(MessagePort&);
134
135     virtual void didLoadResourceSynchronously();
136
137     void ref() { refScriptExecutionContext(); }
138     void deref() { derefScriptExecutionContext(); }
139
140     class Task {
141         WTF_MAKE_FAST_ALLOCATED;
142     public:
143         enum CleanupTaskTag { CleanupTask };
144
145         template<typename T, typename = typename std::enable_if<!std::is_base_of<Task, T>::value && std::is_convertible<T, WTF::Function<void (ScriptExecutionContext&)>>::value>::type>
146         Task(T task)
147             : m_task(WTFMove(task))
148             , m_isCleanupTask(false)
149         {
150         }
151
152         Task(WTF::Function<void ()>&& task)
153             : m_task([task = WTFMove(task)](ScriptExecutionContext&) { task(); })
154             , m_isCleanupTask(false)
155         {
156         }
157
158         template<typename T, typename = typename std::enable_if<std::is_convertible<T, WTF::Function<void (ScriptExecutionContext&)>>::value>::type>
159         Task(CleanupTaskTag, T task)
160             : m_task(WTFMove(task))
161             , m_isCleanupTask(true)
162         {
163         }
164
165         void performTask(ScriptExecutionContext& context) { m_task(context); }
166         bool isCleanupTask() const { return m_isCleanupTask; }
167
168     protected:
169         WTF::Function<void (ScriptExecutionContext&)> m_task;
170         bool m_isCleanupTask;
171     };
172
173     virtual void postTask(Task&&) = 0; // Executes the task on context's thread asynchronously.
174
175     template<typename... Arguments>
176     void postCrossThreadTask(Arguments&&... arguments)
177     {
178         postTask([crossThreadTask = createCrossThreadTask(arguments...)](ScriptExecutionContext&) mutable {
179             crossThreadTask.performTask();
180         });
181     }
182
183     // Gets the next id in a circular sequence from 1 to 2^31-1.
184     int circularSequentialID();
185
186     bool addTimeout(int timeoutId, DOMTimer& timer) { return m_timeouts.add(timeoutId, &timer).isNewEntry; }
187     void removeTimeout(int timeoutId) { m_timeouts.remove(timeoutId); }
188     DOMTimer* findTimeout(int timeoutId) { return m_timeouts.get(timeoutId); }
189
190     WEBCORE_EXPORT JSC::VM& vm();
191
192     void adjustMinimumDOMTimerInterval(Seconds oldMinimumTimerInterval);
193     virtual Seconds minimumDOMTimerInterval() const;
194
195     void didChangeTimerAlignmentInterval();
196     virtual Seconds domTimerAlignmentInterval(bool hasReachedMaxNestingLevel) const;
197
198     virtual EventQueue& eventQueue() const = 0;
199
200     DatabaseContext* databaseContext() { return m_databaseContext.get(); }
201     void setDatabaseContext(DatabaseContext*);
202
203 #if ENABLE(SUBTLE_CRYPTO)
204     virtual bool wrapCryptoKey(const Vector<uint8_t>& key, Vector<uint8_t>& wrappedKey) = 0;
205     virtual bool unwrapCryptoKey(const Vector<uint8_t>& wrappedKey, Vector<uint8_t>& key) = 0;
206 #endif
207
208     int timerNestingLevel() const { return m_timerNestingLevel; }
209     void setTimerNestingLevel(int timerNestingLevel) { m_timerNestingLevel = timerNestingLevel; }
210
211     JSC::ExecState* execState();
212
213 protected:
214     class AddConsoleMessageTask : public Task {
215     public:
216         AddConsoleMessageTask(MessageSource source, MessageLevel level, const String& message)
217             : Task([source, level, message = message.isolatedCopy()](ScriptExecutionContext& context) {
218                 context.addConsoleMessage(source, level, message);
219             })
220         {
221         }
222     };
223
224     ActiveDOMObject::ReasonForSuspension reasonForSuspendingActiveDOMObjects() const { return m_reasonForSuspendingActiveDOMObjects; }
225
226     bool hasPendingActivity() const;
227
228 private:
229     virtual void addMessage(MessageSource, MessageLevel, const String& message, const String& sourceURL, unsigned lineNumber, unsigned columnNumber, RefPtr<Inspector::ScriptCallStack>&&, JSC::ExecState* = nullptr, unsigned long requestIdentifier = 0) = 0;
230     virtual EventTarget* errorEventTarget() = 0;
231     virtual void logExceptionToConsole(const String& errorMessage, const String& sourceURL, int lineNumber, int columnNumber, RefPtr<Inspector::ScriptCallStack>&&) = 0;
232     bool dispatchErrorEvent(const String& errorMessage, int lineNumber, int columnNumber, const String& sourceURL, JSC::Exception*, CachedScript*);
233
234     virtual void refScriptExecutionContext() = 0;
235     virtual void derefScriptExecutionContext() = 0;
236
237     void checkConsistency() const;
238
239     HashSet<MessagePort*> m_messagePorts;
240     HashSet<ContextDestructionObserver*> m_destructionObservers;
241     HashSet<ActiveDOMObject*> m_activeDOMObjects;
242
243     int m_circularSequentialID { 0 };
244     HashMap<int, RefPtr<DOMTimer>> m_timeouts;
245
246     bool m_inDispatchErrorEvent { false };
247     struct PendingException;
248     std::unique_ptr<Vector<std::unique_ptr<PendingException>>> m_pendingExceptions;
249
250     bool m_activeDOMObjectsAreSuspended { false };
251     ActiveDOMObject::ReasonForSuspension m_reasonForSuspendingActiveDOMObjects { static_cast<ActiveDOMObject::ReasonForSuspension>(-1) };
252     bool m_activeDOMObjectsAreStopped { false };
253
254     std::unique_ptr<PublicURLManager> m_publicURLManager;
255
256     RefPtr<DatabaseContext> m_databaseContext;
257
258     bool m_activeDOMObjectAdditionForbidden { false };
259     bool m_willProcessMessagePortMessagesSoon { false };
260     int m_timerNestingLevel { 0 };
261
262 #if !ASSERT_DISABLED
263     bool m_inScriptExecutionContextDestructor { false };
264 #endif
265 #if !ASSERT_DISABLED || ENABLE(SECURITY_ASSERTIONS)
266     bool m_activeDOMObjectRemovalForbidden { false };
267 #endif
268 };
269
270 } // namespace WebCore