Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
1 /* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
4 * You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #ifndef mozilla_dom_workers_workers_h__
7 #define mozilla_dom_workers_workers_h__
9 #include "jsapi.h"
10 #include "mozilla/Attributes.h"
11 #include "mozilla/Mutex.h"
12 #include <stdint.h>
13 #include "nsAutoPtr.h"
14 #include "nsCOMPtr.h"
15 #include "nsDebug.h"
16 #include "nsString.h"
18 #define BEGIN_WORKERS_NAMESPACE \
19 namespace mozilla { namespace dom { namespace workers {
20 #define END_WORKERS_NAMESPACE \
21 } /* namespace workers */ } /* namespace dom */ } /* namespace mozilla */
22 #define USING_WORKERS_NAMESPACE \
23 using namespace mozilla::dom::workers;
25 #define WORKERS_SHUTDOWN_TOPIC "web-workers-shutdown"
27 class nsIScriptContext;
28 class nsPIDOMWindow;
30 BEGIN_WORKERS_NAMESPACE
32 class WorkerPrivate;
34 struct PrivatizableBase
35 { };
37 #ifdef DEBUG
38 void
39 AssertIsOnMainThread();
40 #else
41 inline void
42 AssertIsOnMainThread()
43 { }
44 #endif
46 struct JSSettings
47 {
48 enum {
49 // All the GC parameters that we support.
50 JSSettings_JSGC_MAX_BYTES = 0,
51 JSSettings_JSGC_MAX_MALLOC_BYTES,
52 JSSettings_JSGC_HIGH_FREQUENCY_TIME_LIMIT,
53 JSSettings_JSGC_LOW_FREQUENCY_HEAP_GROWTH,
54 JSSettings_JSGC_HIGH_FREQUENCY_HEAP_GROWTH_MIN,
55 JSSettings_JSGC_HIGH_FREQUENCY_HEAP_GROWTH_MAX,
56 JSSettings_JSGC_HIGH_FREQUENCY_LOW_LIMIT,
57 JSSettings_JSGC_HIGH_FREQUENCY_HIGH_LIMIT,
58 JSSettings_JSGC_ALLOCATION_THRESHOLD,
59 JSSettings_JSGC_SLICE_TIME_BUDGET,
60 JSSettings_JSGC_DYNAMIC_HEAP_GROWTH,
61 JSSettings_JSGC_DYNAMIC_MARK_SLICE,
62 // JSGC_MODE not supported
64 // This must be last so that we get an accurate count.
65 kGCSettingsArraySize
66 };
68 struct JSGCSetting
69 {
70 JSGCParamKey key;
71 uint32_t value;
73 JSGCSetting()
74 : key(static_cast<JSGCParamKey>(-1)), value(0)
75 { }
77 bool
78 IsSet() const
79 {
80 return key != static_cast<JSGCParamKey>(-1);
81 }
83 void
84 Unset()
85 {
86 key = static_cast<JSGCParamKey>(-1);
87 value = 0;
88 }
89 };
91 // There are several settings that we know we need so it makes sense to
92 // preallocate here.
93 typedef JSGCSetting JSGCSettingsArray[kGCSettingsArraySize];
95 // Settings that change based on chrome/content context.
96 struct JSContentChromeSettings
97 {
98 JS::ContextOptions contextOptions;
99 JS::CompartmentOptions compartmentOptions;
100 int32_t maxScriptRuntime;
102 JSContentChromeSettings()
103 : contextOptions(), compartmentOptions(), maxScriptRuntime(0)
104 { }
105 };
107 JSContentChromeSettings chrome;
108 JSContentChromeSettings content;
109 JSGCSettingsArray gcSettings;
110 JS::RuntimeOptions runtimeOptions;
112 #ifdef JS_GC_ZEAL
113 uint8_t gcZeal;
114 uint32_t gcZealFrequency;
115 #endif
117 JSSettings()
118 #ifdef JS_GC_ZEAL
119 : gcZeal(0), gcZealFrequency(0)
120 #endif
121 {
122 for (uint32_t index = 0; index < ArrayLength(gcSettings); index++) {
123 new (gcSettings + index) JSGCSetting();
124 }
125 }
127 bool
128 ApplyGCSetting(JSGCParamKey aKey, uint32_t aValue)
129 {
130 JSSettings::JSGCSetting* firstEmptySetting = nullptr;
131 JSSettings::JSGCSetting* foundSetting = nullptr;
133 for (uint32_t index = 0; index < ArrayLength(gcSettings); index++) {
134 JSSettings::JSGCSetting& setting = gcSettings[index];
135 if (setting.key == aKey) {
136 foundSetting = &setting;
137 break;
138 }
139 if (!firstEmptySetting && !setting.IsSet()) {
140 firstEmptySetting = &setting;
141 }
142 }
144 if (aValue) {
145 if (!foundSetting) {
146 foundSetting = firstEmptySetting;
147 if (!foundSetting) {
148 NS_ERROR("Not enough space for this value!");
149 return false;
150 }
151 }
152 foundSetting->key = aKey;
153 foundSetting->value = aValue;
154 return true;
155 }
157 if (foundSetting) {
158 foundSetting->Unset();
159 return true;
160 }
162 return false;
163 }
164 };
166 enum WorkerPreference
167 {
168 WORKERPREF_DUMP = 0, // browser.dom.window.dump.enabled
169 WORKERPREF_COUNT
170 };
172 // All of these are implemented in RuntimeService.cpp
173 bool
174 ResolveWorkerClasses(JSContext* aCx, JS::Handle<JSObject*> aObj, JS::Handle<jsid> aId,
175 JS::MutableHandle<JSObject*> aObjp);
177 void
178 CancelWorkersForWindow(nsPIDOMWindow* aWindow);
180 void
181 SuspendWorkersForWindow(nsPIDOMWindow* aWindow);
183 void
184 ResumeWorkersForWindow(nsPIDOMWindow* aWindow);
186 class WorkerTask
187 {
188 protected:
189 WorkerTask()
190 { }
192 virtual ~WorkerTask()
193 { }
195 public:
196 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WorkerTask)
198 virtual bool
199 RunTask(JSContext* aCx) = 0;
200 };
202 class WorkerCrossThreadDispatcher
203 {
204 friend class WorkerPrivate;
206 // Must be acquired *before* the WorkerPrivate's mutex, when they're both
207 // held.
208 Mutex mMutex;
209 WorkerPrivate* mWorkerPrivate;
211 private:
212 // Only created by WorkerPrivate.
213 WorkerCrossThreadDispatcher(WorkerPrivate* aWorkerPrivate);
215 // Only called by WorkerPrivate.
216 void
217 Forget()
218 {
219 MutexAutoLock lock(mMutex);
220 mWorkerPrivate = nullptr;
221 }
223 public:
224 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WorkerCrossThreadDispatcher)
226 // Generically useful function for running a bit of C++ code on the worker
227 // thread.
228 bool
229 PostTask(WorkerTask* aTask);
230 };
232 WorkerCrossThreadDispatcher*
233 GetWorkerCrossThreadDispatcher(JSContext* aCx, jsval aWorker);
235 // Random unique constant to facilitate JSPrincipal debugging
236 const uint32_t kJSPrincipalsDebugToken = 0x7e2df9d2;
238 namespace exceptions {
240 // Implemented in Exceptions.cpp
241 void
242 ThrowDOMExceptionForNSResult(JSContext* aCx, nsresult aNSResult);
244 } // namespace exceptions
246 // Throws the JSMSG_GETTER_ONLY exception. This shouldn't be used going
247 // forward -- getter-only properties should just use JS_PSG for the setter
248 // (implying no setter at all), which will not throw when set in non-strict
249 // code but will in strict code. Old code should use this only for temporary
250 // compatibility reasons.
251 extern bool
252 GetterOnlyJSNative(JSContext* aCx, unsigned aArgc, JS::Value* aVp);
254 END_WORKERS_NAMESPACE
256 #endif // mozilla_dom_workers_workers_h__