/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef mozilla_dom_workerscope_h__ #define mozilla_dom_workerscope_h__ #include "js/TypeDecls.h" #include "mozilla/Assertions.h" #include "mozilla/Attributes.h" #include "mozilla/DOMEventTargetHelper.h" #include "mozilla/Maybe.h" #include "mozilla/NotNull.h" #include "mozilla/RefPtr.h" #include "mozilla/UniquePtr.h" #include "mozilla/TimeStamp.h" #include "mozilla/dom/AnimationFrameProvider.h" #include "mozilla/dom/ImageBitmapBinding.h" #include "mozilla/dom/ImageBitmapSource.h" #include "mozilla/dom/PerformanceWorker.h" #include "mozilla/dom/SafeRefPtr.h" #include "mozilla/dom/WorkerPrivate.h" #include "nsCOMPtr.h" #include "nsCycleCollectionParticipant.h" #include "nsIGlobalObject.h" #include "nsISupports.h" #include "nsWeakReference.h" #ifdef XP_WIN # undef PostMessage #endif class nsAtom; class nsISerialEventTarget; namespace mozilla { class ErrorResult; struct VsyncEvent; namespace extensions { class ExtensionBrowser; } // namespace extensions namespace dom { class AnyCallback; enum class CallerType : uint32_t; class ClientInfo; class ClientSource; class Clients; class Console; class Crypto; class DOMString; class DebuggerNotificationManager; enum class EventCallbackDebuggerNotificationType : uint8_t; class EventHandlerNonNull; class FontFaceSet; class Function; class IDBFactory; class OnErrorEventHandlerNonNull; template class Optional; class Performance; class Promise; class RequestOrUSVString; template class Sequence; class ServiceWorkerDescriptor; class ServiceWorkerRegistration; class ServiceWorkerRegistrationDescriptor; struct StructuredSerializeOptions; class WorkerDocumentListener; class WorkerLocation; class WorkerNavigator; class WorkerPrivate; class VsyncWorkerChild; class WebTaskScheduler; class WebTaskSchedulerWorker; struct RequestInit; namespace cache { class CacheStorage; } // namespace cache class WorkerGlobalScopeBase : public DOMEventTargetHelper, public nsSupportsWeakReference, public nsIGlobalObject { friend class WorkerPrivate; public: NS_DECL_ISUPPORTS_INHERITED NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(WorkerGlobalScopeBase, DOMEventTargetHelper) WorkerGlobalScopeBase(WorkerPrivate* aWorkerPrivate, UniquePtr aClientSource, bool mShouldResistFingerprinting); virtual bool WrapGlobalObject(JSContext* aCx, JS::MutableHandle aReflector) = 0; // EventTarget implementation JSObject* WrapObject(JSContext* aCx, JS::Handle aGivenProto) final { MOZ_CRASH("WrapObject not supported; use WrapGlobalObject."); } // nsIGlobalObject implementation JSObject* GetGlobalJSObject() final; JSObject* GetGlobalJSObjectPreserveColor() const final; bool IsSharedMemoryAllowed() const final; bool ShouldResistFingerprinting() const final; OriginTrials Trials() const final; StorageAccess GetStorageAccess() final; Maybe GetClientInfo() const final; Maybe GetController() const final; mozilla::Result GetStorageKey() final; virtual void Control(const ServiceWorkerDescriptor& aServiceWorker); // DispatcherTrait implementation nsresult Dispatch(TaskCategory aCategory, already_AddRefed&& aRunnable) final; nsISerialEventTarget* EventTargetFor(TaskCategory) const final; AbstractThread* AbstractMainThreadFor(TaskCategory) final { MOZ_CRASH("AbstractMainThreadFor not supported for workers."); } MOZ_CAN_RUN_SCRIPT void ReportError(JSContext* aCx, JS::Handle aError, CallerType aCallerType, ErrorResult& aRv); // atob, btoa, and dump are declared (separately) by both WorkerGlobalScope // and WorkerDebuggerGlobalScope WebIDL interfaces void Atob(const nsAString& aAtob, nsAString& aOut, ErrorResult& aRv) const; void Btoa(const nsAString& aBtoa, nsAString& aOut, ErrorResult& aRv) const; already_AddRefed GetConsole(ErrorResult& aRv); Console* GetConsoleIfExists() const { return mConsole; } uint64_t WindowID() const; // Usually global scope dies earlier than the WorkerPrivate, but if we see // it leak at least we can tell it to not carry away a dead pointer. void NoteWorkerTerminated() { mWorkerPrivate = nullptr; } ClientSource& MutableClientSourceRef() const { return *mClientSource; } // WorkerPrivate wants to be able to forbid script when its state machine // demands it. void WorkerPrivateSaysForbidScript() { StartForbiddingScript(); } void WorkerPrivateSaysAllowScript() { StopForbiddingScript(); } protected: ~WorkerGlobalScopeBase(); CheckedUnsafePtr mWorkerPrivate; void AssertIsOnWorkerThread() const { MOZ_ASSERT(mWorkerThreadUsedOnlyForAssert == PR_GetCurrentThread()); } private: RefPtr mConsole; const UniquePtr mClientSource; nsCOMPtr mSerialEventTarget; bool mShouldResistFingerprinting; #ifdef DEBUG PRThread* mWorkerThreadUsedOnlyForAssert; #endif }; namespace workerinternals { class NamedWorkerGlobalScopeMixin { public: explicit NamedWorkerGlobalScopeMixin(const nsAString& aName) : mName(aName) {} void GetName(DOMString& aName) const; protected: ~NamedWorkerGlobalScopeMixin() = default; private: const nsString mName; }; } // namespace workerinternals class WorkerGlobalScope : public WorkerGlobalScopeBase { public: NS_DECL_ISUPPORTS_INHERITED NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(WorkerGlobalScope, WorkerGlobalScopeBase) using WorkerGlobalScopeBase::WorkerGlobalScopeBase; void NoteTerminating(); void NoteShuttingDown(); // nsIGlobalObject implementation RefPtr GetServiceWorkerRegistration( const ServiceWorkerRegistrationDescriptor& aDescriptor) const final; RefPtr GetOrCreateServiceWorkerRegistration( const ServiceWorkerRegistrationDescriptor& aDescriptor) final; DebuggerNotificationManager* GetOrCreateDebuggerNotificationManager() final; DebuggerNotificationManager* GetExistingDebuggerNotificationManager() final; Maybe GetDebuggerNotificationType() const final; mozilla::dom::StorageManager* GetStorageManager() final; // WorkerGlobalScope WebIDL implementation WorkerGlobalScope* Self() { return this; } already_AddRefed Location(); already_AddRefed Navigator(); already_AddRefed GetExistingNavigator() const; FontFaceSet* Fonts() final; void ImportScripts(JSContext* aCx, const Sequence& aScriptURLs, ErrorResult& aRv); OnErrorEventHandlerNonNull* GetOnerror(); void SetOnerror(OnErrorEventHandlerNonNull* aHandler); IMPL_EVENT_HANDLER(languagechange) IMPL_EVENT_HANDLER(offline) IMPL_EVENT_HANDLER(online) IMPL_EVENT_HANDLER(rejectionhandled) IMPL_EVENT_HANDLER(unhandledrejection) void Dump(const Optional& aString) const; Performance* GetPerformance(); Performance* GetPerformanceIfExists() const { return mPerformance; } static bool IsInAutomation(JSContext* aCx, JSObject*); void GetJSTestingFunctions(JSContext* aCx, JS::MutableHandle aFunctions, ErrorResult& aRv); // GlobalCrypto WebIDL implementation Crypto* GetCrypto(ErrorResult& aError); // WindowOrWorkerGlobalScope WebIDL implementation void GetOrigin(nsAString& aOrigin) const; bool CrossOriginIsolated() const final; MOZ_CAN_RUN_SCRIPT int32_t SetTimeout(JSContext* aCx, Function& aHandler, int32_t aTimeout, const Sequence& aArguments, ErrorResult& aRv); MOZ_CAN_RUN_SCRIPT int32_t SetTimeout(JSContext* aCx, const nsAString& aHandler, int32_t aTimeout, const Sequence&, ErrorResult& aRv); MOZ_CAN_RUN_SCRIPT void ClearTimeout(int32_t aHandle); MOZ_CAN_RUN_SCRIPT int32_t SetInterval(JSContext* aCx, Function& aHandler, int32_t aTimeout, const Sequence& aArguments, ErrorResult& aRv); MOZ_CAN_RUN_SCRIPT int32_t SetInterval(JSContext* aCx, const nsAString& aHandler, int32_t aTimeout, const Sequence&, ErrorResult& aRv); MOZ_CAN_RUN_SCRIPT void ClearInterval(int32_t aHandle); already_AddRefed CreateImageBitmap( const ImageBitmapSource& aImage, const ImageBitmapOptions& aOptions, ErrorResult& aRv); already_AddRefed CreateImageBitmap( const ImageBitmapSource& aImage, int32_t aSx, int32_t aSy, int32_t aSw, int32_t aSh, const ImageBitmapOptions& aOptions, ErrorResult& aRv); void StructuredClone(JSContext* aCx, JS::Handle aValue, const StructuredSerializeOptions& aOptions, JS::MutableHandle aRetval, ErrorResult& aError); already_AddRefed Fetch(const RequestOrUSVString& aInput, const RequestInit& aInit, CallerType aCallerType, ErrorResult& aRv); bool IsSecureContext() const; already_AddRefed GetIndexedDB(JSContext* aCx, ErrorResult& aErrorResult); already_AddRefed GetCaches(ErrorResult& aRv); WebTaskScheduler* Scheduler(); WebTaskScheduler* GetExistingScheduler() const; bool WindowInteractionAllowed() const; void AllowWindowInteraction(); void ConsumeWindowInteraction(); void StorageAccessPermissionGranted(); virtual void OnDocumentVisible(bool aVisible) {} MOZ_CAN_RUN_SCRIPT_BOUNDARY virtual void OnVsync(const VsyncEvent& aVsync) {} protected: ~WorkerGlobalScope(); private: MOZ_CAN_RUN_SCRIPT int32_t SetTimeoutOrInterval(JSContext* aCx, Function& aHandler, int32_t aTimeout, const Sequence& aArguments, bool aIsInterval, ErrorResult& aRv); MOZ_CAN_RUN_SCRIPT int32_t SetTimeoutOrInterval(JSContext* aCx, const nsAString& aHandler, int32_t aTimeout, bool aIsInterval, ErrorResult& aRv); RefPtr mCrypto; RefPtr mLocation; RefPtr mNavigator; RefPtr mFontFaceSet; RefPtr mPerformance; RefPtr mIndexedDB; RefPtr mCacheStorage; RefPtr mDebuggerNotificationManager; RefPtr mWebTaskScheduler; uint32_t mWindowInteractionsAllowed = 0; }; class DedicatedWorkerGlobalScope final : public WorkerGlobalScope, public workerinternals::NamedWorkerGlobalScopeMixin { public: NS_DECL_ISUPPORTS_INHERITED NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED( DedicatedWorkerGlobalScope, WorkerGlobalScope) DedicatedWorkerGlobalScope(WorkerPrivate* aWorkerPrivate, UniquePtr aClientSource, const nsString& aName, bool aShouldResistFingerprinting); bool WrapGlobalObject(JSContext* aCx, JS::MutableHandle aReflector) override; void PostMessage(JSContext* aCx, JS::Handle aMessage, const Sequence& aTransferable, ErrorResult& aRv); void PostMessage(JSContext* aCx, JS::Handle aMessage, const StructuredSerializeOptions& aOptions, ErrorResult& aRv); void Close(); MOZ_CAN_RUN_SCRIPT int32_t RequestAnimationFrame(FrameRequestCallback& aCallback, ErrorResult& aError); MOZ_CAN_RUN_SCRIPT void CancelAnimationFrame(int32_t aHandle, ErrorResult& aError); void OnDocumentVisible(bool aVisible) override; MOZ_CAN_RUN_SCRIPT_BOUNDARY void OnVsync(const VsyncEvent& aVsync) override; IMPL_EVENT_HANDLER(message) IMPL_EVENT_HANDLER(messageerror) private: ~DedicatedWorkerGlobalScope() = default; FrameRequestManager mFrameRequestManager; RefPtr mVsyncChild; RefPtr mDocListener; bool mDocumentVisible = false; }; class SharedWorkerGlobalScope final : public WorkerGlobalScope, public workerinternals::NamedWorkerGlobalScopeMixin { public: SharedWorkerGlobalScope(WorkerPrivate* aWorkerPrivate, UniquePtr aClientSource, const nsString& aName, bool aShouldResistFingerprinting); bool WrapGlobalObject(JSContext* aCx, JS::MutableHandle aReflector) override; void Close(); IMPL_EVENT_HANDLER(connect) private: ~SharedWorkerGlobalScope() = default; }; class ServiceWorkerGlobalScope final : public WorkerGlobalScope { public: NS_DECL_ISUPPORTS_INHERITED NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(ServiceWorkerGlobalScope, WorkerGlobalScope) ServiceWorkerGlobalScope( WorkerPrivate* aWorkerPrivate, UniquePtr aClientSource, const ServiceWorkerRegistrationDescriptor& aRegistrationDescriptor, bool aShouldResistFingerprinting); bool WrapGlobalObject(JSContext* aCx, JS::MutableHandle aReflector) override; already_AddRefed GetClients(); ServiceWorkerRegistration* Registration(); already_AddRefed SkipWaiting(ErrorResult& aRv); SafeRefPtr AcquireExtensionBrowser(); IMPL_EVENT_HANDLER(install) IMPL_EVENT_HANDLER(activate) EventHandlerNonNull* GetOnfetch(); void SetOnfetch(EventHandlerNonNull* aCallback); void EventListenerAdded(nsAtom* aType) override; IMPL_EVENT_HANDLER(message) IMPL_EVENT_HANDLER(messageerror) IMPL_EVENT_HANDLER(notificationclick) IMPL_EVENT_HANDLER(notificationclose) IMPL_EVENT_HANDLER(push) IMPL_EVENT_HANDLER(pushsubscriptionchange) private: ~ServiceWorkerGlobalScope(); void NoteFetchHandlerWasAdded() const; RefPtr mClients; const nsString mScope; RefPtr mRegistration; SafeRefPtr mExtensionBrowser; }; class WorkerDebuggerGlobalScope final : public WorkerGlobalScopeBase { public: using WorkerGlobalScopeBase::WorkerGlobalScopeBase; bool WrapGlobalObject(JSContext* aCx, JS::MutableHandle aReflector) override; void Control(const ServiceWorkerDescriptor& aServiceWorker) override { MOZ_CRASH("Can't control debugger workers."); } void GetGlobal(JSContext* aCx, JS::MutableHandle aGlobal, ErrorResult& aRv); void CreateSandbox(JSContext* aCx, const nsAString& aName, JS::Handle aPrototype, JS::MutableHandle aResult, ErrorResult& aRv); void LoadSubScript(JSContext* aCx, const nsAString& aUrl, const Optional>& aSandbox, ErrorResult& aRv); MOZ_CAN_RUN_SCRIPT void EnterEventLoop(); void LeaveEventLoop(); void PostMessage(const nsAString& aMessage); void SetImmediate(Function& aHandler, ErrorResult& aRv); void ReportError(JSContext* aCx, const nsAString& aMessage); void RetrieveConsoleEvents(JSContext* aCx, nsTArray& aEvents, ErrorResult& aRv); void ClearConsoleEvents(JSContext* aCx, ErrorResult& aRv); void SetConsoleEventHandler(JSContext* aCx, AnyCallback* aHandler, ErrorResult& aRv); void Dump(JSContext* aCx, const Optional& aString) const; IMPL_EVENT_HANDLER(message) IMPL_EVENT_HANDLER(messageerror) private: ~WorkerDebuggerGlobalScope() = default; }; } // namespace dom } // namespace mozilla inline nsISupports* ToSupports(mozilla::dom::WorkerGlobalScope* aScope) { return static_cast(aScope); } #endif /* mozilla_dom_workerscope_h__ */