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
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7 #ifndef mozilla_dom_workerscope_h__
8 #define mozilla_dom_workerscope_h__
9
10 #include "mozilla/Assertions.h"
11 #include "mozilla/Attributes.h"
12 #include "mozilla/DOMEventTargetHelper.h"
13 #include "mozilla/ErrorResult.h"
14 #include "mozilla/Maybe.h"
15 #include "mozilla/NotNull.h"
16 #include "mozilla/RefPtr.h"
17 #include "mozilla/UniquePtr.h"
18 #include "mozilla/dom/ClientSource.h"
19 #include "mozilla/dom/Console.h"
20 #include "mozilla/dom/DOMString.h"
21 #include "mozilla/dom/EventCallbackDebuggerNotification.h"
22 #include "mozilla/dom/ImageBitmapSource.h"
23 #include "mozilla/dom/RequestBinding.h"
24 #include "mozilla/dom/RequestBinding.h"
25 #include "nsCOMPtr.h"
26 #include "nsContentUtils.h"
27 #include "nsCycleCollectionParticipant.h"
28 #include "nsIGlobalObject.h"
29 #include "nsISupportsImpl.h"
30 #include "nsWeakReference.h"
31
32 #ifdef XP_WIN
33 # undef PostMessage
34 #endif
35
36 class nsAtom;
37 class nsISerialEventTarget;
38
39 namespace mozilla {
40 namespace dom {
41
42 class AnyCallback;
43 enum class CallerType : uint32_t;
44 class ClientInfo;
45 class Clients;
46 class Console;
47 class Crypto;
48 class DOMString;
49 class DebuggerNotificationManager;
50 class Function;
51 class IDBFactory;
52 class OnErrorEventHandlerNonNull;
53 template <typename T>
54 class Optional;
55 struct PostMessageOptions;
56 class Promise;
57 template <typename T>
58 class Sequence;
59 class ServiceWorkerDescriptor;
60 class ServiceWorkerRegistrationDescriptor;
61 class WorkerLocation;
62 class WorkerNavigator;
63 class WorkerPrivate;
64
65 namespace cache {
66
67 class CacheStorage;
68
69 } // namespace cache
70
71 class WorkerGlobalScopeBase : public DOMEventTargetHelper,
72 public nsIGlobalObject {
73 friend class WorkerPrivate;
74
75 public:
76 NS_DECL_ISUPPORTS_INHERITED
77 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(WorkerGlobalScopeBase,
78 DOMEventTargetHelper)
79
80 WorkerGlobalScopeBase(NotNull<WorkerPrivate*> aWorkerPrivate,
81 UniquePtr<ClientSource> aClientSource);
82
83 virtual bool WrapGlobalObject(JSContext* aCx,
84 JS::MutableHandle<JSObject*> aReflector) = 0;
85
86 // EventTarget implementation
WrapObject(JSContext * aCx,JS::Handle<JSObject * > aGivenProto)87 JSObject* WrapObject(JSContext* aCx,
88 JS::Handle<JSObject*> aGivenProto) final {
89 MOZ_CRASH("WrapObject not supported; use WrapGlobalObject.");
90 }
91
92 // nsIGlobalObject implementation
93 JSObject* GetGlobalJSObject() final;
94
95 JSObject* GetGlobalJSObjectPreserveColor() const final;
96
97 bool IsSharedMemoryAllowed() const final;
98
GetClientInfo()99 Maybe<ClientInfo> GetClientInfo() const final {
100 return Some(mClientSource->Info());
101 }
102
GetController()103 Maybe<ServiceWorkerDescriptor> GetController() const final {
104 return mClientSource->GetController();
105 }
106
107 virtual void Control(const ServiceWorkerDescriptor& aServiceWorker);
108
109 // DispatcherTrait implementation
110 nsresult Dispatch(TaskCategory aCategory,
111 already_AddRefed<nsIRunnable>&& aRunnable) final;
112
EventTargetFor(TaskCategory)113 nsISerialEventTarget* EventTargetFor(TaskCategory) const final;
114
115 AbstractThread* AbstractMainThreadFor(TaskCategory) final {
116 MOZ_CRASH("AbstractMainThreadFor not supported for workers.");
117 }
118
119 // atob, btoa, and dump are declared (separately) by both WorkerGlobalScope
120 // and WorkerDebuggerGlobalScope WebIDL interfaces
121 void Atob(const nsAString& aAtob, nsAString& aOut, ErrorResult& aRv) const;
122
123 void Btoa(const nsAString& aBtoa, nsAString& aOut, ErrorResult& aRv) const;
124
125 already_AddRefed<Console> GetConsole(ErrorResult& aRv);
126
GetConsoleIfExists()127 Console* GetConsoleIfExists() const { return mConsole; }
128
129 uint64_t WindowID() const;
130
NoteTerminating()131 void NoteTerminating() { StartDying(); }
132
MutableClientSourceRef()133 ClientSource& MutableClientSourceRef() const { return *mClientSource; }
134
135 // WorkerPrivate wants to be able to forbid script when its state machine
136 // demands it.
WorkerPrivateSaysForbidScript()137 void WorkerPrivateSaysForbidScript() { StartForbiddingScript(); }
WorkerPrivateSaysAllowScript()138 void WorkerPrivateSaysAllowScript() { StopForbiddingScript(); }
139
140 protected:
141 ~WorkerGlobalScopeBase() = default;
142
143 const NotNull<WorkerPrivate*> mWorkerPrivate;
144
145 private:
146 RefPtr<Console> mConsole;
147 const UniquePtr<ClientSource> mClientSource;
148 nsCOMPtr<nsISerialEventTarget> mSerialEventTarget;
149 };
150
151 namespace workerinternals {
152
153 class NamedWorkerGlobalScopeMixin {
154 public:
NamedWorkerGlobalScopeMixin(const nsAString & aName)155 explicit NamedWorkerGlobalScopeMixin(const nsAString& aName) : mName(aName) {}
156
GetName(DOMString & aName)157 void GetName(DOMString& aName) const { aName.AsAString() = mName; }
158
159 protected:
160 ~NamedWorkerGlobalScopeMixin() = default;
161
162 private:
163 const nsString mName;
164 };
165
166 } // namespace workerinternals
167
168 class WorkerGlobalScope : public WorkerGlobalScopeBase,
169 public nsSupportsWeakReference {
170 public:
171 NS_DECL_ISUPPORTS_INHERITED
172 NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(WorkerGlobalScope,
173 WorkerGlobalScopeBase)
174
175 using WorkerGlobalScopeBase::WorkerGlobalScopeBase;
176
177 // nsIGlobalObject implementation
178 RefPtr<ServiceWorkerRegistration> GetServiceWorkerRegistration(
179 const ServiceWorkerRegistrationDescriptor& aDescriptor) const final;
180
181 RefPtr<ServiceWorkerRegistration> GetOrCreateServiceWorkerRegistration(
182 const ServiceWorkerRegistrationDescriptor& aDescriptor) final;
183
184 DebuggerNotificationManager* GetOrCreateDebuggerNotificationManager() final;
185
186 DebuggerNotificationManager* GetExistingDebuggerNotificationManager() final;
187
GetDebuggerNotificationType()188 Maybe<EventCallbackDebuggerNotificationType> GetDebuggerNotificationType()
189 const final {
190 return Some(EventCallbackDebuggerNotificationType::Global);
191 }
192
193 // WorkerGlobalScope WebIDL implementation
Self()194 WorkerGlobalScope* Self() { return this; }
195
196 already_AddRefed<WorkerLocation> Location();
197
198 already_AddRefed<WorkerNavigator> Navigator();
199
200 already_AddRefed<WorkerNavigator> GetExistingNavigator() const;
201
202 void ImportScripts(JSContext* aCx, const Sequence<nsString>& aScriptURLs,
203 ErrorResult& aRv);
204
205 OnErrorEventHandlerNonNull* GetOnerror();
206
207 void SetOnerror(OnErrorEventHandlerNonNull* aHandler);
208
209 IMPL_EVENT_HANDLER(languagechange)
210 IMPL_EVENT_HANDLER(offline)
211 IMPL_EVENT_HANDLER(online)
212 IMPL_EVENT_HANDLER(rejectionhandled)
213 IMPL_EVENT_HANDLER(unhandledrejection)
214
215 void Dump(const Optional<nsAString>& aString) const;
216
217 Performance* GetPerformance();
218
GetPerformanceIfExists()219 Performance* GetPerformanceIfExists() const { return mPerformance; }
220
221 static bool IsInAutomation(JSContext* aCx, JSObject*);
222
223 void GetJSTestingFunctions(JSContext* aCx,
224 JS::MutableHandle<JSObject*> aFunctions,
225 ErrorResult& aRv);
226
227 // GlobalCrypto WebIDL implementation
228 Crypto* GetCrypto(ErrorResult& aError);
229
230 // WindowOrWorkerGlobalScope WebIDL implementation
231 void GetOrigin(nsAString& aOrigin) const;
232
233 bool CrossOriginIsolated() const final;
234
235 MOZ_CAN_RUN_SCRIPT
236 int32_t SetTimeout(JSContext* aCx, Function& aHandler, int32_t aTimeout,
237 const Sequence<JS::Value>& aArguments, ErrorResult& aRv);
238
239 MOZ_CAN_RUN_SCRIPT
240 int32_t SetTimeout(JSContext* aCx, const nsAString& aHandler,
241 int32_t aTimeout, const Sequence<JS::Value>&,
242 ErrorResult& aRv);
243
244 MOZ_CAN_RUN_SCRIPT
245 void ClearTimeout(int32_t aHandle);
246
247 MOZ_CAN_RUN_SCRIPT
248 int32_t SetInterval(JSContext* aCx, Function& aHandler, int32_t aTimeout,
249 const Sequence<JS::Value>& aArguments, ErrorResult& aRv);
250 MOZ_CAN_RUN_SCRIPT
251 int32_t SetInterval(JSContext* aCx, const nsAString& aHandler,
252 int32_t aTimeout, const Sequence<JS::Value>&,
253 ErrorResult& aRv);
254
255 MOZ_CAN_RUN_SCRIPT
256 void ClearInterval(int32_t aHandle);
257
258 already_AddRefed<Promise> CreateImageBitmap(const ImageBitmapSource& aImage,
259 ErrorResult& aRv);
260
261 already_AddRefed<Promise> CreateImageBitmap(const ImageBitmapSource& aImage,
262 int32_t aSx, int32_t aSy,
263 int32_t aSw, int32_t aSh,
264 ErrorResult& aRv);
265
266 already_AddRefed<Promise> Fetch(const RequestOrUSVString& aInput,
267 const RequestInit& aInit,
268 CallerType aCallerType, ErrorResult& aRv);
269
270 bool IsSecureContext() const;
271
272 already_AddRefed<IDBFactory> GetIndexedDB(ErrorResult& aErrorResult);
273
274 already_AddRefed<cache::CacheStorage> GetCaches(ErrorResult& aRv);
275
276 bool WindowInteractionAllowed() const;
277
278 void AllowWindowInteraction();
279
280 void ConsumeWindowInteraction();
281
282 void FirstPartyStorageAccessGranted();
283
284 protected:
285 ~WorkerGlobalScope() = default;
286
287 private:
288 MOZ_CAN_RUN_SCRIPT
289 int32_t SetTimeoutOrInterval(JSContext* aCx, Function& aHandler,
290 int32_t aTimeout,
291 const Sequence<JS::Value>& aArguments,
292 bool aIsInterval, ErrorResult& aRv);
293
294 MOZ_CAN_RUN_SCRIPT
295 int32_t SetTimeoutOrInterval(JSContext* aCx, const nsAString& aHandler,
296 int32_t aTimeout, bool aIsInterval,
297 ErrorResult& aRv);
298
299 RefPtr<Crypto> mCrypto;
300 RefPtr<WorkerLocation> mLocation;
301 RefPtr<WorkerNavigator> mNavigator;
302 RefPtr<Performance> mPerformance;
303 RefPtr<IDBFactory> mIndexedDB;
304 RefPtr<cache::CacheStorage> mCacheStorage;
305 RefPtr<DebuggerNotificationManager> mDebuggerNotificationManager;
306 uint32_t mWindowInteractionsAllowed = 0;
307 };
308
309 class DedicatedWorkerGlobalScope final
310 : public WorkerGlobalScope,
311 public workerinternals::NamedWorkerGlobalScopeMixin {
312 public:
313 DedicatedWorkerGlobalScope(NotNull<WorkerPrivate*> aWorkerPrivate,
314 UniquePtr<ClientSource> aClientSource,
315 const nsString& aName);
316
317 bool WrapGlobalObject(JSContext* aCx,
318 JS::MutableHandle<JSObject*> aReflector) override;
319
320 void PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
321 const Sequence<JSObject*>& aTransferable, ErrorResult& aRv);
322
323 void PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
324 const PostMessageOptions& aOptions, ErrorResult& aRv);
325
326 void Close();
327
328 IMPL_EVENT_HANDLER(message)
329 IMPL_EVENT_HANDLER(messageerror)
330
331 private:
332 ~DedicatedWorkerGlobalScope() = default;
333 };
334
335 class SharedWorkerGlobalScope final
336 : public WorkerGlobalScope,
337 public workerinternals::NamedWorkerGlobalScopeMixin {
338 public:
339 SharedWorkerGlobalScope(NotNull<WorkerPrivate*> aWorkerPrivate,
340 UniquePtr<ClientSource> aClientSource,
341 const nsString& aName);
342
343 bool WrapGlobalObject(JSContext* aCx,
344 JS::MutableHandle<JSObject*> aReflector) override;
345
346 void Close();
347
348 IMPL_EVENT_HANDLER(connect)
349
350 private:
351 ~SharedWorkerGlobalScope() = default;
352 };
353
354 class ServiceWorkerGlobalScope final : public WorkerGlobalScope {
355 public:
356 NS_DECL_ISUPPORTS_INHERITED
357 NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(ServiceWorkerGlobalScope,
358 WorkerGlobalScope)
359
360 ServiceWorkerGlobalScope(
361 NotNull<WorkerPrivate*> aWorkerPrivate,
362 UniquePtr<ClientSource> aClientSource,
363 const ServiceWorkerRegistrationDescriptor& aRegistrationDescriptor);
364
365 bool WrapGlobalObject(JSContext* aCx,
366 JS::MutableHandle<JSObject*> aReflector) override;
367
368 already_AddRefed<Clients> GetClients();
369
370 ServiceWorkerRegistration* Registration();
371
372 already_AddRefed<Promise> SkipWaiting(ErrorResult& aRv);
373
374 IMPL_EVENT_HANDLER(install)
375 IMPL_EVENT_HANDLER(activate)
376
377 EventHandlerNonNull* GetOnfetch();
378
379 void SetOnfetch(EventHandlerNonNull* aCallback);
380
381 void EventListenerAdded(nsAtom* aType) override;
382
383 IMPL_EVENT_HANDLER(message)
384 IMPL_EVENT_HANDLER(messageerror)
385
386 IMPL_EVENT_HANDLER(notificationclick)
387 IMPL_EVENT_HANDLER(notificationclose)
388
389 IMPL_EVENT_HANDLER(push)
390 IMPL_EVENT_HANDLER(pushsubscriptionchange)
391
392 private:
393 ~ServiceWorkerGlobalScope() = default;
394
395 void NoteFetchHandlerWasAdded() const;
396
397 RefPtr<Clients> mClients;
398 const nsString mScope;
399 RefPtr<ServiceWorkerRegistration> mRegistration;
400 };
401
402 class WorkerDebuggerGlobalScope final : public WorkerGlobalScopeBase {
403 public:
404 using WorkerGlobalScopeBase::WorkerGlobalScopeBase;
405
406 bool WrapGlobalObject(JSContext* aCx,
407 JS::MutableHandle<JSObject*> aReflector) override;
408
Control(const ServiceWorkerDescriptor & aServiceWorker)409 void Control(const ServiceWorkerDescriptor& aServiceWorker) override {
410 MOZ_CRASH("Can't control debugger workers.");
411 }
412
413 void GetGlobal(JSContext* aCx, JS::MutableHandle<JSObject*> aGlobal,
414 ErrorResult& aRv);
415
416 void CreateSandbox(JSContext* aCx, const nsAString& aName,
417 JS::Handle<JSObject*> aPrototype,
418 JS::MutableHandle<JSObject*> aResult, ErrorResult& aRv);
419
420 void LoadSubScript(JSContext* aCx, const nsAString& aUrl,
421 const Optional<JS::Handle<JSObject*>>& aSandbox,
422 ErrorResult& aRv);
423
424 MOZ_CAN_RUN_SCRIPT void EnterEventLoop();
425
426 void LeaveEventLoop();
427
428 void PostMessage(const nsAString& aMessage);
429
430 void SetImmediate(Function& aHandler, ErrorResult& aRv);
431
432 void ReportError(JSContext* aCx, const nsAString& aMessage);
433
434 void RetrieveConsoleEvents(JSContext* aCx, nsTArray<JS::Value>& aEvents,
435 ErrorResult& aRv);
436
437 void SetConsoleEventHandler(JSContext* aCx, AnyCallback* aHandler,
438 ErrorResult& aRv);
439
440 void Dump(JSContext* aCx, const Optional<nsAString>& aString) const;
441
442 IMPL_EVENT_HANDLER(message)
443 IMPL_EVENT_HANDLER(messageerror)
444
445 private:
446 ~WorkerDebuggerGlobalScope() = default;
447 };
448
449 } // namespace dom
450 } // namespace mozilla
451
ToSupports(mozilla::dom::WorkerGlobalScope * aScope)452 inline nsISupports* ToSupports(mozilla::dom::WorkerGlobalScope* aScope) {
453 return static_cast<mozilla::dom::EventTarget*>(aScope);
454 }
455
456 #endif /* mozilla_dom_workerscope_h__ */
457