/* -*- 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 "mozilla/Assertions.h" #include "mozilla/Attributes.h" #include "mozilla/DOMEventTargetHelper.h" #include "mozilla/ErrorResult.h" #include "mozilla/Maybe.h" #include "mozilla/NotNull.h" #include "mozilla/RefPtr.h" #include "mozilla/UniquePtr.h" #include "mozilla/dom/ClientSource.h" #include "mozilla/dom/Console.h" #include "mozilla/dom/DOMString.h" #include "mozilla/dom/EventCallbackDebuggerNotification.h" #include "mozilla/dom/ImageBitmapSource.h" #include "mozilla/dom/RequestBinding.h" #include "mozilla/dom/RequestBinding.h" #include "nsCOMPtr.h" #include "nsContentUtils.h" #include "nsCycleCollectionParticipant.h" #include "nsIGlobalObject.h" #include "nsISupportsImpl.h" #include "nsWeakReference.h" #ifdef XP_WIN # undef PostMessage #endif class nsAtom; class nsISerialEventTarget; namespace mozilla { namespace dom { class AnyCallback; enum class CallerType : uint32_t; class ClientInfo; class Clients; class Console; class Crypto; class DOMString; class DebuggerNotificationManager; class Function; class IDBFactory; class OnErrorEventHandlerNonNull; template class Optional; struct PostMessageOptions; class Promise; template class Sequence; class ServiceWorkerDescriptor; class ServiceWorkerRegistrationDescriptor; class WorkerLocation; class WorkerNavigator; class WorkerPrivate; namespace cache { class CacheStorage; } // namespace cache class WorkerGlobalScopeBase : public DOMEventTargetHelper, public nsIGlobalObject { friend class WorkerPrivate; public: NS_DECL_ISUPPORTS_INHERITED NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(WorkerGlobalScopeBase, DOMEventTargetHelper) WorkerGlobalScopeBase(NotNull aWorkerPrivate, UniquePtr aClientSource); 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; Maybe GetClientInfo() const final { return Some(mClientSource->Info()); } Maybe GetController() const final { return mClientSource->GetController(); } 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."); } // 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; void NoteTerminating() { StartDying(); } 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() = default; const NotNull mWorkerPrivate; private: RefPtr mConsole; const UniquePtr mClientSource; nsCOMPtr mSerialEventTarget; }; namespace workerinternals { class NamedWorkerGlobalScopeMixin { public: explicit NamedWorkerGlobalScopeMixin(const nsAString& aName) : mName(aName) {} void GetName(DOMString& aName) const { aName.AsAString() = mName; } protected: ~NamedWorkerGlobalScopeMixin() = default; private: const nsString mName; }; } // namespace workerinternals class WorkerGlobalScope : public WorkerGlobalScopeBase, public nsSupportsWeakReference { public: NS_DECL_ISUPPORTS_INHERITED NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(WorkerGlobalScope, WorkerGlobalScopeBase) using WorkerGlobalScopeBase::WorkerGlobalScopeBase; // 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 { return Some(EventCallbackDebuggerNotificationType::Global); } // WorkerGlobalScope WebIDL implementation WorkerGlobalScope* Self() { return this; } already_AddRefed Location(); already_AddRefed Navigator(); already_AddRefed GetExistingNavigator() const; 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, ErrorResult& aRv); already_AddRefed CreateImageBitmap(const ImageBitmapSource& aImage, int32_t aSx, int32_t aSy, int32_t aSw, int32_t aSh, ErrorResult& aRv); already_AddRefed Fetch(const RequestOrUSVString& aInput, const RequestInit& aInit, CallerType aCallerType, ErrorResult& aRv); bool IsSecureContext() const; already_AddRefed GetIndexedDB(ErrorResult& aErrorResult); already_AddRefed GetCaches(ErrorResult& aRv); bool WindowInteractionAllowed() const; void AllowWindowInteraction(); void ConsumeWindowInteraction(); void StorageAccessPermissionGranted(); protected: ~WorkerGlobalScope() = default; 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 mPerformance; RefPtr mIndexedDB; RefPtr mCacheStorage; RefPtr mDebuggerNotificationManager; uint32_t mWindowInteractionsAllowed = 0; }; class DedicatedWorkerGlobalScope final : public WorkerGlobalScope, public workerinternals::NamedWorkerGlobalScopeMixin { public: DedicatedWorkerGlobalScope(NotNull aWorkerPrivate, UniquePtr aClientSource, const nsString& aName); 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 PostMessageOptions& aOptions, ErrorResult& aRv); void Close(); IMPL_EVENT_HANDLER(message) IMPL_EVENT_HANDLER(messageerror) private: ~DedicatedWorkerGlobalScope() = default; }; class SharedWorkerGlobalScope final : public WorkerGlobalScope, public workerinternals::NamedWorkerGlobalScopeMixin { public: SharedWorkerGlobalScope(NotNull aWorkerPrivate, UniquePtr aClientSource, const nsString& aName); 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( NotNull aWorkerPrivate, UniquePtr aClientSource, const ServiceWorkerRegistrationDescriptor& aRegistrationDescriptor); bool WrapGlobalObject(JSContext* aCx, JS::MutableHandle aReflector) override; already_AddRefed GetClients(); ServiceWorkerRegistration* Registration(); already_AddRefed SkipWaiting(ErrorResult& aRv); 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() = default; void NoteFetchHandlerWasAdded() const; RefPtr mClients; const nsString mScope; RefPtr mRegistration; }; 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 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__ */