Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 : /* This Source Code Form is subject to the terms of the Mozilla Public
4 : * License, v. 2.0. If a copy of the MPL was not distributed with this file,
5 : * You can obtain one at http://mozilla.org/MPL/2.0/. */
6 :
7 : #ifndef mozilla_dom_workers_workers_h__
8 : #define mozilla_dom_workers_workers_h__
9 :
10 : #include "jsapi.h"
11 : #include "mozilla/Attributes.h"
12 : #include "mozilla/Mutex.h"
13 : #include <stdint.h>
14 : #include "nsAutoPtr.h"
15 : #include "nsCOMPtr.h"
16 : #include "nsDebug.h"
17 : #include "nsString.h"
18 : #include "nsTArray.h"
19 :
20 : #include "nsILoadContext.h"
21 : #include "nsIWeakReferenceUtils.h"
22 : #include "nsIInterfaceRequestor.h"
23 : #include "mozilla/dom/ChannelInfo.h"
24 : #include "mozilla/net/ReferrerPolicy.h"
25 :
26 : #define BEGIN_WORKERS_NAMESPACE \
27 : namespace mozilla { namespace dom { namespace workers {
28 : #define END_WORKERS_NAMESPACE \
29 : } /* namespace workers */ } /* namespace dom */ } /* namespace mozilla */
30 : #define USING_WORKERS_NAMESPACE \
31 : using namespace mozilla::dom::workers;
32 :
33 : #define WORKERS_SHUTDOWN_TOPIC "web-workers-shutdown"
34 :
35 : class nsIContentSecurityPolicy;
36 : class nsIScriptContext;
37 : class nsIGlobalObject;
38 : class nsPIDOMWindowInner;
39 : class nsIPrincipal;
40 : class nsILoadGroup;
41 : class nsITabChild;
42 : class nsIChannel;
43 : class nsIRunnable;
44 : class nsIURI;
45 :
46 : namespace mozilla {
47 : namespace ipc {
48 : class PrincipalInfo;
49 : } // namespace ipc
50 :
51 : namespace dom {
52 : // If you change this, the corresponding list in nsIWorkerDebugger.idl needs to
53 : // be updated too.
54 : enum WorkerType
55 : {
56 : WorkerTypeDedicated,
57 : WorkerTypeShared,
58 : WorkerTypeService
59 : };
60 :
61 : } // namespace dom
62 : } // namespace mozilla
63 :
64 : BEGIN_WORKERS_NAMESPACE
65 :
66 : class WorkerPrivate;
67 :
68 : struct PrivatizableBase
69 : { };
70 :
71 : #ifdef DEBUG
72 : void
73 : AssertIsOnMainThread();
74 : #else
75 : inline void
76 : AssertIsOnMainThread()
77 : { }
78 : #endif
79 :
80 : struct JSSettings
81 : {
82 : enum {
83 : // All the GC parameters that we support.
84 : JSSettings_JSGC_MAX_BYTES = 0,
85 : JSSettings_JSGC_MAX_MALLOC_BYTES,
86 : JSSettings_JSGC_HIGH_FREQUENCY_TIME_LIMIT,
87 : JSSettings_JSGC_LOW_FREQUENCY_HEAP_GROWTH,
88 : JSSettings_JSGC_HIGH_FREQUENCY_HEAP_GROWTH_MIN,
89 : JSSettings_JSGC_HIGH_FREQUENCY_HEAP_GROWTH_MAX,
90 : JSSettings_JSGC_HIGH_FREQUENCY_LOW_LIMIT,
91 : JSSettings_JSGC_HIGH_FREQUENCY_HIGH_LIMIT,
92 : JSSettings_JSGC_ALLOCATION_THRESHOLD,
93 : JSSettings_JSGC_SLICE_TIME_BUDGET,
94 : JSSettings_JSGC_DYNAMIC_HEAP_GROWTH,
95 : JSSettings_JSGC_DYNAMIC_MARK_SLICE,
96 : JSSettings_JSGC_REFRESH_FRAME_SLICES,
97 : // JSGC_MODE not supported
98 :
99 : // This must be last so that we get an accurate count.
100 : kGCSettingsArraySize
101 : };
102 :
103 : struct JSGCSetting
104 : {
105 : JSGCParamKey key;
106 : uint32_t value;
107 :
108 130 : JSGCSetting()
109 130 : : key(static_cast<JSGCParamKey>(-1)), value(0)
110 130 : { }
111 :
112 : bool
113 103 : IsSet() const
114 : {
115 103 : return key != static_cast<JSGCParamKey>(-1);
116 : }
117 :
118 : void
119 0 : Unset()
120 : {
121 0 : key = static_cast<JSGCParamKey>(-1);
122 0 : value = 0;
123 0 : }
124 : };
125 :
126 : // There are several settings that we know we need so it makes sense to
127 : // preallocate here.
128 : typedef JSGCSetting JSGCSettingsArray[kGCSettingsArraySize];
129 :
130 : // Settings that change based on chrome/content context.
131 : struct JSContentChromeSettings
132 : {
133 : JS::CompartmentOptions compartmentOptions;
134 : int32_t maxScriptRuntime;
135 :
136 10 : JSContentChromeSettings()
137 10 : : compartmentOptions(), maxScriptRuntime(0)
138 10 : { }
139 : };
140 :
141 : JSContentChromeSettings chrome;
142 : JSContentChromeSettings content;
143 : JSGCSettingsArray gcSettings;
144 : JS::ContextOptions contextOptions;
145 :
146 : #ifdef JS_GC_ZEAL
147 : uint8_t gcZeal;
148 : uint32_t gcZealFrequency;
149 : #endif
150 :
151 5 : JSSettings()
152 : #ifdef JS_GC_ZEAL
153 5 : : gcZeal(0), gcZealFrequency(0)
154 : #endif
155 : {
156 70 : for (uint32_t index = 0; index < ArrayLength(gcSettings); index++) {
157 65 : new (gcSettings + index) JSGCSetting();
158 : }
159 5 : }
160 :
161 : bool
162 15 : ApplyGCSetting(JSGCParamKey aKey, uint32_t aValue)
163 : {
164 15 : JSSettings::JSGCSetting* firstEmptySetting = nullptr;
165 15 : JSSettings::JSGCSetting* foundSetting = nullptr;
166 :
167 185 : for (uint32_t index = 0; index < ArrayLength(gcSettings); index++) {
168 172 : JSSettings::JSGCSetting& setting = gcSettings[index];
169 172 : if (setting.key == aKey) {
170 2 : foundSetting = &setting;
171 2 : break;
172 : }
173 170 : if (!firstEmptySetting && !setting.IsSet()) {
174 13 : firstEmptySetting = &setting;
175 : }
176 : }
177 :
178 15 : if (aValue) {
179 13 : if (!foundSetting) {
180 11 : foundSetting = firstEmptySetting;
181 11 : if (!foundSetting) {
182 0 : NS_ERROR("Not enough space for this value!");
183 0 : return false;
184 : }
185 : }
186 13 : foundSetting->key = aKey;
187 13 : foundSetting->value = aValue;
188 13 : return true;
189 : }
190 :
191 2 : if (foundSetting) {
192 0 : foundSetting->Unset();
193 0 : return true;
194 : }
195 :
196 2 : return false;
197 : }
198 : };
199 :
200 : enum WorkerPreference
201 : {
202 : #define WORKER_SIMPLE_PREF(name, getter, NAME) WORKERPREF_ ## NAME,
203 : #define WORKER_PREF(name, callback)
204 : #include "mozilla/dom/WorkerPrefs.h"
205 : #undef WORKER_SIMPLE_PREF
206 : #undef WORKER_PREF
207 : WORKERPREF_COUNT
208 : };
209 :
210 : // Implemented in WorkerPrivate.cpp
211 :
212 : struct WorkerLoadInfo
213 : {
214 : // All of these should be released in WorkerPrivateParent::ForgetMainThreadObjects.
215 : nsCOMPtr<nsIURI> mBaseURI;
216 : nsCOMPtr<nsIURI> mResolvedScriptURI;
217 : nsCOMPtr<nsIPrincipal> mPrincipal;
218 : nsCOMPtr<nsIScriptContext> mScriptContext;
219 : nsCOMPtr<nsPIDOMWindowInner> mWindow;
220 : nsCOMPtr<nsIContentSecurityPolicy> mCSP;
221 : nsCOMPtr<nsIChannel> mChannel;
222 : nsCOMPtr<nsILoadGroup> mLoadGroup;
223 :
224 : // mLoadFailedAsyncRunnable will execute on main thread if script loading
225 : // fails during script loading. If script loading is never started due to
226 : // a synchronous error, then the runnable is never executed. The runnable
227 : // is guaranteed to be released on the main thread.
228 : nsCOMPtr<nsIRunnable> mLoadFailedAsyncRunnable;
229 :
230 : class InterfaceRequestor final : public nsIInterfaceRequestor
231 : {
232 : NS_DECL_ISUPPORTS
233 :
234 : public:
235 : InterfaceRequestor(nsIPrincipal* aPrincipal, nsILoadGroup* aLoadGroup);
236 : void MaybeAddTabChild(nsILoadGroup* aLoadGroup);
237 : NS_IMETHOD GetInterface(const nsIID& aIID, void** aSink) override;
238 :
239 : private:
240 0 : ~InterfaceRequestor() { }
241 :
242 : already_AddRefed<nsITabChild> GetAnyLiveTabChild();
243 :
244 : nsCOMPtr<nsILoadContext> mLoadContext;
245 : nsCOMPtr<nsIInterfaceRequestor> mOuterRequestor;
246 :
247 : // Array of weak references to nsITabChild. We do not want to keep TabChild
248 : // actors alive for long after their ActorDestroy() methods are called.
249 : nsTArray<nsWeakPtr> mTabChildList;
250 : };
251 :
252 : // Only set if we have a custom overriden load group
253 : RefPtr<InterfaceRequestor> mInterfaceRequestor;
254 :
255 : nsAutoPtr<mozilla::ipc::PrincipalInfo> mPrincipalInfo;
256 : nsCString mDomain;
257 : nsString mOrigin; // Derived from mPrincipal; can be used on worker thread.
258 :
259 : nsString mServiceWorkerCacheName;
260 :
261 : ChannelInfo mChannelInfo;
262 : nsLoadFlags mLoadFlags;
263 :
264 : uint64_t mWindowID;
265 : uint64_t mServiceWorkerID;
266 :
267 : net::ReferrerPolicy mReferrerPolicy;
268 : bool mFromWindow;
269 : bool mEvalAllowed;
270 : bool mReportCSPViolations;
271 : bool mXHRParamsAllowed;
272 : bool mPrincipalIsSystem;
273 : bool mStorageAllowed;
274 : bool mServiceWorkersTestingInWindow;
275 : OriginAttributes mOriginAttributes;
276 :
277 : WorkerLoadInfo();
278 : ~WorkerLoadInfo();
279 :
280 : void StealFrom(WorkerLoadInfo& aOther);
281 :
282 : nsresult
283 : SetPrincipalOnMainThread(nsIPrincipal* aPrincipal, nsILoadGroup* aLoadGroup);
284 :
285 : nsresult
286 : GetPrincipalAndLoadGroupFromChannel(nsIChannel* aChannel,
287 : nsIPrincipal** aPrincipalOut,
288 : nsILoadGroup** aLoadGroupOut);
289 :
290 : nsresult
291 : SetPrincipalFromChannel(nsIChannel* aChannel);
292 :
293 : #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
294 : bool
295 : FinalChannelPrincipalIsValid(nsIChannel* aChannel);
296 :
297 : bool
298 : PrincipalIsValid() const;
299 :
300 : bool
301 : PrincipalURIMatchesScriptURL();
302 : #endif
303 :
304 : bool
305 : ProxyReleaseMainThreadObjects(WorkerPrivate* aWorkerPrivate);
306 :
307 : bool
308 : ProxyReleaseMainThreadObjects(WorkerPrivate* aWorkerPrivate,
309 : nsCOMPtr<nsILoadGroup>& aLoadGroupToCancel);
310 : };
311 :
312 : // All of these are implemented in RuntimeService.cpp
313 :
314 : void
315 : CancelWorkersForWindow(nsPIDOMWindowInner* aWindow);
316 :
317 : void
318 : FreezeWorkersForWindow(nsPIDOMWindowInner* aWindow);
319 :
320 : void
321 : ThawWorkersForWindow(nsPIDOMWindowInner* aWindow);
322 :
323 : void
324 : SuspendWorkersForWindow(nsPIDOMWindowInner* aWindow);
325 :
326 : void
327 : ResumeWorkersForWindow(nsPIDOMWindowInner* aWindow);
328 :
329 : // A class that can be used with WorkerCrossThreadDispatcher to run a
330 : // bit of C++ code on the worker thread.
331 : class WorkerTask
332 : {
333 : protected:
334 : WorkerTask()
335 : { }
336 :
337 : virtual ~WorkerTask()
338 : { }
339 :
340 : public:
341 0 : NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WorkerTask)
342 :
343 : // The return value here has the same semantics as the return value
344 : // of WorkerRunnable::WorkerRun.
345 : virtual bool
346 : RunTask(JSContext* aCx) = 0;
347 : };
348 :
349 : class WorkerCrossThreadDispatcher
350 : {
351 : friend class WorkerPrivate;
352 :
353 : // Must be acquired *before* the WorkerPrivate's mutex, when they're both
354 : // held.
355 : Mutex mMutex;
356 : WorkerPrivate* mWorkerPrivate;
357 :
358 : private:
359 : // Only created by WorkerPrivate.
360 : explicit WorkerCrossThreadDispatcher(WorkerPrivate* aWorkerPrivate);
361 :
362 : // Only called by WorkerPrivate.
363 : void
364 0 : Forget()
365 : {
366 0 : MutexAutoLock lock(mMutex);
367 0 : mWorkerPrivate = nullptr;
368 0 : }
369 :
370 0 : ~WorkerCrossThreadDispatcher() {}
371 :
372 : public:
373 0 : NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WorkerCrossThreadDispatcher)
374 :
375 : // Generically useful function for running a bit of C++ code on the worker
376 : // thread.
377 : bool
378 : PostTask(WorkerTask* aTask);
379 : };
380 :
381 : WorkerCrossThreadDispatcher*
382 : GetWorkerCrossThreadDispatcher(JSContext* aCx, const JS::Value& aWorker);
383 :
384 : // Random unique constant to facilitate JSPrincipal debugging
385 : const uint32_t kJSPrincipalsDebugToken = 0x7e2df9d2;
386 :
387 : bool
388 : IsWorkerGlobal(JSObject* global);
389 :
390 : bool
391 : IsDebuggerGlobal(JSObject* global);
392 :
393 : bool
394 : IsDebuggerSandbox(JSObject* object);
395 :
396 : END_WORKERS_NAMESPACE
397 :
398 : #endif // mozilla_dom_workers_workers_h__
|