diff options
Diffstat (limited to '')
-rw-r--r-- | dom/serviceworkers/ServiceWorkerPrivateImpl.h | 233 |
1 files changed, 233 insertions, 0 deletions
diff --git a/dom/serviceworkers/ServiceWorkerPrivateImpl.h b/dom/serviceworkers/ServiceWorkerPrivateImpl.h new file mode 100644 index 0000000000..9d5ad9c5a7 --- /dev/null +++ b/dom/serviceworkers/ServiceWorkerPrivateImpl.h @@ -0,0 +1,233 @@ +/* -*- 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_serviceworkerprivateimpl_h__ +#define mozilla_dom_serviceworkerprivateimpl_h__ + +#include <functional> + +#include "nsCOMPtr.h" +#include "nsISupportsImpl.h" +#include "nsTArray.h" + +#include "ServiceWorkerPrivate.h" +#include "mozilla/Attributes.h" +#include "mozilla/MozPromise.h" +#include "mozilla/RefPtr.h" +#include "mozilla/UniquePtr.h" +#include "mozilla/dom/RemoteWorkerController.h" +#include "mozilla/dom/RemoteWorkerTypes.h" +#include "mozilla/dom/ServiceWorkerOpArgs.h" + +class nsIInterceptedChannel; + +namespace mozilla { + +template <typename T> +class Maybe; + +namespace dom { + +class ClientInfoAndState; +class LifeCycleEventCallback; +class RemoteWorkerControllerChild; +class ServiceWorkerCloneData; +class ServiceWorkerRegistrationInfo; + +class ServiceWorkerPrivateImpl final : public ServiceWorkerPrivate::Inner, + public RemoteWorkerObserver { + public: + NS_INLINE_DECL_REFCOUNTING(ServiceWorkerPrivateImpl, override); + + explicit ServiceWorkerPrivateImpl(RefPtr<ServiceWorkerPrivate> aOuter); + + nsresult Initialize(); + + RefPtr<GenericPromise> SetSkipWaitingFlag(); + + private: + class RAIIActorPtrHolder; + + ~ServiceWorkerPrivateImpl(); + + /** + * ServiceWorkerPrivate::Inner + */ + nsresult SendMessageEvent( + RefPtr<ServiceWorkerCloneData>&& aData, + const ClientInfoAndState& aClientInfoAndState) override; + + nsresult CheckScriptEvaluation( + RefPtr<LifeCycleEventCallback> aCallback) override; + + nsresult SendLifeCycleEvent( + const nsAString& aEventName, + RefPtr<LifeCycleEventCallback> aCallback) override; + + nsresult SendPushEvent(RefPtr<ServiceWorkerRegistrationInfo> aRegistration, + const nsAString& aMessageId, + const Maybe<nsTArray<uint8_t>>& aData) override; + + nsresult SendPushSubscriptionChangeEvent() override; + + nsresult SendNotificationEvent(const nsAString& aEventName, + const nsAString& aID, const nsAString& aTitle, + const nsAString& aDir, const nsAString& aLang, + const nsAString& aBody, const nsAString& aTag, + const nsAString& aIcon, const nsAString& aData, + const nsAString& aBehavior, + const nsAString& aScope, + uint32_t aDisableOpenClickDelay) override; + + nsresult SendFetchEvent(RefPtr<ServiceWorkerRegistrationInfo> aRegistration, + nsCOMPtr<nsIInterceptedChannel> aChannel, + const nsAString& aClientId, + const nsAString& aResultingClientId) override; + + nsresult SpawnWorkerIfNeeded() override; + + void TerminateWorker() override; + + void UpdateState(ServiceWorkerState aState) override; + + void NoteDeadOuter() override; + + bool WorkerIsDead() const override; + + /** + * RemoteWorkerObserver + */ + void CreationFailed() override; + + void CreationSucceeded() override; + + void ErrorReceived(const ErrorValue& aError) override; + + void Terminated() override; + + // Refreshes only the parts of mRemoteWorkerData that may change over time. + void RefreshRemoteWorkerData( + const RefPtr<ServiceWorkerRegistrationInfo>& aRegistration); + + nsresult SendPushEventInternal( + RefPtr<ServiceWorkerRegistrationInfo>&& aRegistration, + ServiceWorkerPushEventOpArgs&& aArgs); + + nsresult SendFetchEventInternal( + RefPtr<ServiceWorkerRegistrationInfo>&& aRegistration, + ServiceWorkerFetchEventOpArgs&& aArgs, + nsCOMPtr<nsIInterceptedChannel>&& aChannel); + + void Shutdown(); + + RefPtr<GenericNonExclusivePromise> ShutdownInternal( + uint32_t aShutdownStateId); + + nsresult ExecServiceWorkerOp( + ServiceWorkerOpArgs&& aArgs, + std::function<void(ServiceWorkerOpResult&&)>&& aSuccessCallback, + std::function<void()>&& aFailureCallback = [] {}); + + class PendingFunctionalEvent { + public: + PendingFunctionalEvent( + ServiceWorkerPrivateImpl* aOwner, + RefPtr<ServiceWorkerRegistrationInfo>&& aRegistration); + + virtual ~PendingFunctionalEvent(); + + virtual nsresult Send() = 0; + + protected: + ServiceWorkerPrivateImpl* const MOZ_NON_OWNING_REF mOwner; + RefPtr<ServiceWorkerRegistrationInfo> mRegistration; + }; + + class PendingPushEvent final : public PendingFunctionalEvent { + public: + PendingPushEvent(ServiceWorkerPrivateImpl* aOwner, + RefPtr<ServiceWorkerRegistrationInfo>&& aRegistration, + ServiceWorkerPushEventOpArgs&& aArgs); + + nsresult Send() override; + + private: + ServiceWorkerPushEventOpArgs mArgs; + }; + + class PendingFetchEvent final : public PendingFunctionalEvent { + public: + PendingFetchEvent(ServiceWorkerPrivateImpl* aOwner, + RefPtr<ServiceWorkerRegistrationInfo>&& aRegistration, + ServiceWorkerFetchEventOpArgs&& aArgs, + nsCOMPtr<nsIInterceptedChannel>&& aChannel); + + nsresult Send() override; + + ~PendingFetchEvent(); + + private: + ServiceWorkerFetchEventOpArgs mArgs; + nsCOMPtr<nsIInterceptedChannel> mChannel; + }; + + nsTArray<UniquePtr<PendingFunctionalEvent>> mPendingFunctionalEvents; + + /** + * It's possible that there are still in-progress operations when a + * a termination operation is issued. In this case, it's important to keep + * the RemoteWorkerControllerChild actor alive until all pending operations + * have completed before destroying it with Send__delete__(). + * + * RAIIActorPtrHolder holds a singular, owning reference to a + * RemoteWorkerControllerChild actor and is responsible for destroying the + * actor in its (i.e. the holder's) destructor. This implies that all + * in-progress operations must maintain a strong reference to their + * corresponding holders and release the reference once completed/canceled. + * + * Additionally a RAIIActorPtrHolder must be initialized with a non-null actor + * and cannot be moved or copied. Therefore, the identities of two held + * actors can be compared by simply comparing their holders' addresses. + */ + class RAIIActorPtrHolder final { + public: + NS_INLINE_DECL_REFCOUNTING(RAIIActorPtrHolder) + + explicit RAIIActorPtrHolder( + already_AddRefed<RemoteWorkerControllerChild> aActor); + + RAIIActorPtrHolder(const RAIIActorPtrHolder& aOther) = delete; + RAIIActorPtrHolder& operator=(const RAIIActorPtrHolder& aOther) = delete; + + RAIIActorPtrHolder(RAIIActorPtrHolder&& aOther) = delete; + RAIIActorPtrHolder& operator=(RAIIActorPtrHolder&& aOther) = delete; + + RemoteWorkerControllerChild* operator->() const + MOZ_NO_ADDREF_RELEASE_ON_RETURN; + + RemoteWorkerControllerChild* get() const; + + RefPtr<GenericPromise> OnDestructor(); + + private: + ~RAIIActorPtrHolder(); + + MozPromiseHolder<GenericPromise> mDestructorPromiseHolder; + + const RefPtr<RemoteWorkerControllerChild> mActor; + }; + + RefPtr<RAIIActorPtrHolder> mControllerChild; + + RefPtr<ServiceWorkerPrivate> mOuter; + + RemoteWorkerData mRemoteWorkerData; +}; + +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_serviceworkerprivateimpl_h__ |