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
* 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<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);
~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