/* -*- 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_PushNotifier_h #define mozilla_dom_PushNotifier_h #include "nsIPushNotifier.h" #include "nsCycleCollectionParticipant.h" #include "nsIPrincipal.h" #include "nsString.h" #include "mozilla/Maybe.h" namespace mozilla::dom { class ContentChild; class ContentParent; /** * `PushDispatcher` is a base class used to forward observer notifications and * service worker events to the correct process. */ class MOZ_STACK_CLASS PushDispatcher { public: // Fires an XPCOM observer notification. This method may be called from both // processes. virtual nsresult NotifyObservers() = 0; // Fires a service worker event. This method is called from the content // process if e10s is enabled, or the parent otherwise. virtual nsresult NotifyWorkers() = 0; // A convenience method that calls `NotifyObservers` and `NotifyWorkers`. nsresult NotifyObserversAndWorkers(); // Sends an IPDL message to fire an observer notification in the parent // process. This method is only called from the content process, and only // if e10s is enabled. virtual bool SendToParent(ContentChild* aParentActor) = 0; // Sends an IPDL message to fire an observer notification and a service worker // event in the content process. This method is only called from the parent, // and only if e10s is enabled. virtual bool SendToChild(ContentParent* aContentActor) = 0; // An optional method, called from the parent if e10s is enabled and there // are no active content processes. The default behavior is a no-op. virtual nsresult HandleNoChildProcesses(); nsIPrincipal* GetPrincipal() { return mPrincipal; } protected: PushDispatcher(const nsACString& aScope, nsIPrincipal* aPrincipal); virtual ~PushDispatcher(); bool ShouldNotifyWorkers(); nsresult DoNotifyObservers(nsISupports* aSubject, const char* aTopic, const nsACString& aScope); const nsCString mScope; nsCOMPtr mPrincipal; }; /** * `PushNotifier` implements the `nsIPushNotifier` interface. This service * broadcasts XPCOM observer notifications for incoming push messages, then * forwards incoming push messages to service workers. * * All scriptable methods on this interface may be called from the parent or * content process. Observer notifications are broadcasted to both processes. */ class PushNotifier final : public nsIPushNotifier { public: PushNotifier(); NS_DECL_CYCLE_COLLECTING_ISUPPORTS NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(PushNotifier, nsIPushNotifier) NS_DECL_NSIPUSHNOTIFIER private: ~PushNotifier(); nsresult Dispatch(PushDispatcher& aDispatcher); }; /** * `PushData` provides methods for retrieving push message data in different * formats. This class is similar to the `PushMessageData` WebIDL interface. */ class PushData final : public nsIPushData { public: explicit PushData(const nsTArray& aData); NS_DECL_CYCLE_COLLECTING_ISUPPORTS NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(PushData, nsIPushData) NS_DECL_NSIPUSHDATA private: ~PushData(); nsresult EnsureDecodedText(); nsTArray mData; nsString mDecodedText; }; /** * `PushMessage` exposes the subscription principal and data for a push * message. Each `push-message` observer receives an instance of this class * as the subject. */ class PushMessage final : public nsIPushMessage { public: PushMessage(nsIPrincipal* aPrincipal, nsIPushData* aData); NS_DECL_CYCLE_COLLECTING_ISUPPORTS NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(PushMessage, nsIPushMessage) NS_DECL_NSIPUSHMESSAGE private: ~PushMessage(); nsCOMPtr mPrincipal; nsCOMPtr mData; }; class PushMessageDispatcher final : public PushDispatcher { public: PushMessageDispatcher(const nsACString& aScope, nsIPrincipal* aPrincipal, const nsAString& aMessageId, const Maybe>& aData); ~PushMessageDispatcher(); nsresult NotifyObservers() override; nsresult NotifyWorkers() override; bool SendToParent(ContentChild* aParentActor) override; bool SendToChild(ContentParent* aContentActor) override; private: const nsString mMessageId; const Maybe> mData; }; class PushSubscriptionChangeDispatcher final : public PushDispatcher { public: PushSubscriptionChangeDispatcher(const nsACString& aScope, nsIPrincipal* aPrincipal); ~PushSubscriptionChangeDispatcher(); nsresult NotifyObservers() override; nsresult NotifyWorkers() override; bool SendToParent(ContentChild* aParentActor) override; bool SendToChild(ContentParent* aContentActor) override; }; class PushSubscriptionModifiedDispatcher : public PushDispatcher { public: PushSubscriptionModifiedDispatcher(const nsACString& aScope, nsIPrincipal* aPrincipal); ~PushSubscriptionModifiedDispatcher(); nsresult NotifyObservers() override; nsresult NotifyWorkers() override; bool SendToParent(ContentChild* aParentActor) override; bool SendToChild(ContentParent* aContentActor) override; }; class PushErrorDispatcher final : public PushDispatcher { public: PushErrorDispatcher(const nsACString& aScope, nsIPrincipal* aPrincipal, const nsAString& aMessage, uint32_t aFlags); ~PushErrorDispatcher(); nsresult NotifyObservers() override; nsresult NotifyWorkers() override; bool SendToParent(ContentChild* aParentActor) override; bool SendToChild(ContentParent* aContentActor) override; private: nsresult HandleNoChildProcesses() override; const nsString mMessage; uint32_t mFlags; }; } // namespace mozilla::dom #endif // mozilla_dom_PushNotifier_h