Source code
Revision control
Copy as Markdown
Other Tools
/* -*- 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
#ifndef mozilla_dom_PushNotifier_h
#define mozilla_dom_PushNotifier_h
#include "mozilla/Maybe.h"
#include "nsCycleCollectionParticipant.h"
#include "nsIPrincipal.h"
#include "nsIPushNotifier.h"
#include "nsString.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<nsIPrincipal> 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<uint8_t>& aData);
  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
  NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(PushData, nsIPushData)
  NS_DECL_NSIPUSHDATA
 private:
  ~PushData();
  nsresult EnsureDecodedText();
  nsTArray<uint8_t> 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<nsIPrincipal> mPrincipal;
  nsCOMPtr<nsIPushData> mData;
};
class PushMessageDispatcher final : public PushDispatcher {
 public:
  PushMessageDispatcher(const nsACString& aScope, nsIPrincipal* aPrincipal,
                        const nsAString& aMessageId,
                        const Maybe<nsTArray<uint8_t>>& aData);
  ~PushMessageDispatcher();
  nsresult NotifyObservers() override;
  nsresult NotifyWorkers() override;
  bool SendToParent(ContentChild* aParentActor) override;
  bool SendToChild(ContentParent* aContentActor) override;
 private:
  const nsString mMessageId;
  const Maybe<nsTArray<uint8_t>> mData;
};
class PushSubscriptionChangeDispatcher final : public PushDispatcher {
 public:
  PushSubscriptionChangeDispatcher(const nsACString& aScope,
                                   nsIPrincipal* aPrincipal,
                                   nsIPushSubscription* aOldSubscription);
  ~PushSubscriptionChangeDispatcher();
  nsresult NotifyObservers() override;
  nsresult NotifyWorkers() override;
  bool SendToParent(ContentChild* aParentActor) override;
  bool SendToChild(ContentParent* aContentActor) override;
 private:
  nsCOMPtr<nsIPushSubscription> mOldSubscription;
};
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