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