Bug 1239584, Part 1 - Add nsIPushNotifier and nsIPushMessage interfaces. r=dragana

This commit is contained in:
Kit Cambridge 2016-01-13 22:19:51 -07:00
parent 28a636727c
commit 1a7e1adb65
11 changed files with 588 additions and 10 deletions

View File

@ -5,6 +5,7 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
XPIDL_SOURCES += [
'nsIPushNotifier.idl',
'nsIPushObserverNotification.idl',
'nsIPushService.idl',
]

View File

@ -0,0 +1,41 @@
#include "nsISupports.idl"
interface nsIPrincipal;
/**
* Fires service worker events for push messages sent to content subscriptions,
* and XPCOM observer notifications for system subscriptions. This service
* can only be used from the parent process.
*/
[scriptable, uuid(b00dfdeb-14e5-425b-adc7-b531442e3216)]
interface nsIPushNotifier : nsISupports
{
void notifyPush(in ACString scope, in nsIPrincipal principal);
void notifyPushWithData(in ACString scope, in nsIPrincipal principal,
[optional] in uint32_t dataLen,
[array, size_is(dataLen)] in uint8_t data);
void notifySubscriptionChange(in ACString scope, in nsIPrincipal principal);
};
/**
* A push message sent to a system subscription, used as the subject of a
* `push-message` observer notification. System subscriptions are created by
* the system principal, and do not use worker events.
*
* This interface resembles the `PushMessageData` WebIDL interface.
*/
[scriptable, uuid(136dc8fd-8c56-4176-9170-eaa86b6ba99e)]
interface nsIPushMessage : nsISupports
{
/** Extracts the data as a UTF-8 text string. */
DOMString text();
/** Extracts the data as a JSON value. */
[implicit_jscontext] jsval json();
/** Extracts the raw binary data. */
void binary([optional] out uint32_t dataLen,
[array, retval, size_is(dataLen)] out uint8_t data);
};

View File

@ -163,6 +163,10 @@
#include "mozilla/dom/GamepadService.h"
#endif
#ifndef MOZ_SIMPLEPUSH
#include "mozilla/dom/PushNotifier.h"
#endif
#include "mozilla/dom/File.h"
#include "mozilla/dom/cellbroadcast/CellBroadcastIPCService.h"
#include "mozilla/dom/icc/IccChild.h"
@ -3217,5 +3221,62 @@ ContentChild::RecvTestGraphicsDeviceReset(const uint32_t& aResetReason)
return true;
}
bool
ContentChild::RecvPush(const nsCString& aScope,
const IPC::Principal& aPrincipal)
{
#ifndef MOZ_SIMPLEPUSH
nsCOMPtr<nsIPushNotifier> pushNotifierIface =
do_GetService("@mozilla.org/push/Notifier;1");
if (NS_WARN_IF(!pushNotifierIface)) {
return true;
}
PushNotifier* pushNotifier =
static_cast<PushNotifier*>(pushNotifierIface.get());
nsresult rv = pushNotifier->NotifyPushWorkers(aScope, aPrincipal, Nothing());
Unused << NS_WARN_IF(NS_FAILED(rv));
#endif
return true;
}
bool
ContentChild::RecvPushWithData(const nsCString& aScope,
const IPC::Principal& aPrincipal,
InfallibleTArray<uint8_t>&& aData)
{
#ifndef MOZ_SIMPLEPUSH
nsCOMPtr<nsIPushNotifier> pushNotifierIface =
do_GetService("@mozilla.org/push/Notifier;1");
if (NS_WARN_IF(!pushNotifierIface)) {
return true;
}
PushNotifier* pushNotifier =
static_cast<PushNotifier*>(pushNotifierIface.get());
nsresult rv = pushNotifier->NotifyPushWorkers(aScope, aPrincipal,
Some(aData));
Unused << NS_WARN_IF(NS_FAILED(rv));
#endif
return true;
}
bool
ContentChild::RecvPushSubscriptionChange(const nsCString& aScope,
const IPC::Principal& aPrincipal)
{
#ifndef MOZ_SIMPLEPUSH
nsCOMPtr<nsIPushNotifier> pushNotifierIface =
do_GetService("@mozilla.org/push/Notifier;1");
if (NS_WARN_IF(!pushNotifierIface)) {
return true;
}
PushNotifier* pushNotifier =
static_cast<PushNotifier*>(pushNotifierIface.get());
nsresult rv = pushNotifier->NotifySubscriptionChangeWorkers(aScope,
aPrincipal);
Unused << NS_WARN_IF(NS_FAILED(rv));
#endif
return true;
}
} // namespace dom
} // namespace mozilla

View File

@ -526,6 +526,19 @@ public:
virtual bool RecvEndDragSession(const bool& aDoneDrag,
const bool& aUserCancelled) override;
virtual bool
RecvPush(const nsCString& aScope,
const IPC::Principal& aPrincipal) override;
virtual bool
RecvPushWithData(const nsCString& aScope,
const IPC::Principal& aPrincipal,
InfallibleTArray<uint8_t>&& aData) override;
virtual bool
RecvPushSubscriptionChange(const nsCString& aScope,
const IPC::Principal& aPrincipal) override;
#ifdef ANDROID
gfx::IntSize GetScreenSize() { return mScreenSize; }
#endif

View File

@ -728,6 +728,21 @@ child:
*/
async NotifyGMPsChanged();
/**
* Send a `push` event without data to a service worker in the child.
*/
Push(nsCString scope, Principal principal);
/**
* Send a `push` event with data to a service worker in the child.
*/
PushWithData(nsCString scope, Principal principal, uint8_t[] data);
/**
* Send a `pushsubscriptionchange` event to a service worker in the child.
*/
PushSubscriptionChange(nsCString scope, Principal principal);
parent:
/**
* Tell the content process some attributes of itself. This is

315
dom/push/PushNotifier.cpp Normal file
View File

@ -0,0 +1,315 @@
/* 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/. */
#include "PushNotifier.h"
#include "nsContentUtils.h"
#include "nsCOMPtr.h"
#include "nsXPCOM.h"
#include "nsIXULRuntime.h"
#include "ServiceWorkerManager.h"
#include "mozilla/Services.h"
#include "mozilla/unused.h"
#include "mozilla/dom/ContentParent.h"
#include "mozilla/dom/FetchUtil.h"
namespace mozilla {
namespace dom {
using workers::ServiceWorkerManager;
PushNotifier::PushNotifier()
{}
PushNotifier::~PushNotifier()
{}
NS_IMPL_CYCLE_COLLECTION_0(PushNotifier)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PushNotifier)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIPushNotifier)
NS_INTERFACE_MAP_ENTRY(nsIPushNotifier)
NS_INTERFACE_MAP_END
NS_IMPL_CYCLE_COLLECTING_ADDREF(PushNotifier)
NS_IMPL_CYCLE_COLLECTING_RELEASE(PushNotifier)
NS_IMETHODIMP
PushNotifier::NotifyPushWithData(const nsACString& aScope,
nsIPrincipal* aPrincipal,
uint32_t aDataLen, uint8_t* aData)
{
nsTArray<uint8_t> data;
if (!data.SetCapacity(aDataLen, fallible)) {
return NS_ERROR_OUT_OF_MEMORY;
}
if (!data.InsertElementsAt(0, aData, aDataLen, fallible)) {
return NS_ERROR_OUT_OF_MEMORY;
}
return NotifyPush(aScope, aPrincipal, Some(data));
}
NS_IMETHODIMP
PushNotifier::NotifyPush(const nsACString& aScope, nsIPrincipal* aPrincipal)
{
return NotifyPush(aScope, aPrincipal, Nothing());
}
NS_IMETHODIMP
PushNotifier::NotifySubscriptionChange(const nsACString& aScope,
nsIPrincipal* aPrincipal)
{
if (XRE_IsContentProcess()) {
return NS_ERROR_NOT_IMPLEMENTED;
}
nsresult rv;
if (ShouldNotifyObservers(aPrincipal)) {
rv = NotifySubscriptionChangeObservers(aScope);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
}
if (ShouldNotifyWorkers(aPrincipal)) {
rv = NotifySubscriptionChangeWorkers(aScope, aPrincipal);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
}
return NS_OK;
}
nsresult
PushNotifier::NotifyPush(const nsACString& aScope, nsIPrincipal* aPrincipal,
Maybe<nsTArray<uint8_t>> aData)
{
if (XRE_IsContentProcess()) {
return NS_ERROR_NOT_IMPLEMENTED;
}
nsresult rv;
if (ShouldNotifyObservers(aPrincipal)) {
rv = NotifyPushObservers(aScope, aData);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
}
if (ShouldNotifyWorkers(aPrincipal)) {
rv = NotifyPushWorkers(aScope, aPrincipal, aData);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
}
return NS_OK;
}
nsresult
PushNotifier::NotifyPushWorkers(const nsACString& aScope,
nsIPrincipal* aPrincipal,
Maybe<nsTArray<uint8_t>> aData)
{
if (!aPrincipal) {
return NS_ERROR_INVALID_ARG;
}
if (XRE_IsContentProcess() || !BrowserTabsRemoteAutostart()) {
// Notify the worker from the current process. Either we're running in
// the content process and received a message from the parent, or e10s
// is disabled.
RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
if (!swm) {
return NS_ERROR_FAILURE;
}
nsAutoCString originSuffix;
nsresult rv = aPrincipal->GetOriginSuffix(originSuffix);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
return swm->SendPushEvent(originSuffix, aScope, aData);
}
// Otherwise, we're in the parent and e10s is enabled. Broadcast the event
// to all content processes.
bool ok = false;
nsTArray<ContentParent*> contentActors;
ContentParent::GetAll(contentActors);
for (uint32_t i = 0; i < contentActors.Length(); ++i) {
if (aData) {
ok &= contentActors[i]->SendPushWithData(PromiseFlatCString(aScope),
IPC::Principal(aPrincipal), aData.ref());
} else {
ok &= contentActors[i]->SendPush(PromiseFlatCString(aScope),
IPC::Principal(aPrincipal));
}
}
return ok ? NS_OK : NS_ERROR_FAILURE;
}
nsresult
PushNotifier::NotifySubscriptionChangeWorkers(const nsACString& aScope,
nsIPrincipal* aPrincipal)
{
if (!aPrincipal) {
return NS_ERROR_INVALID_ARG;
}
if (XRE_IsContentProcess() || !BrowserTabsRemoteAutostart()) {
// Content process or e10s disabled.
RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
if (!swm) {
return NS_ERROR_FAILURE;
}
nsAutoCString originSuffix;
nsresult rv = aPrincipal->GetOriginSuffix(originSuffix);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
return swm->SendPushSubscriptionChangeEvent(originSuffix, aScope);
}
// Parent process, e10s enabled.
bool ok = false;
nsTArray<ContentParent*> contentActors;
ContentParent::GetAll(contentActors);
for (uint32_t i = 0; i < contentActors.Length(); ++i) {
ok &= contentActors[i]->SendPushSubscriptionChange(
PromiseFlatCString(aScope), IPC::Principal(aPrincipal));
}
return ok ? NS_OK : NS_ERROR_FAILURE;
}
nsresult
PushNotifier::NotifyPushObservers(const nsACString& aScope,
Maybe<nsTArray<uint8_t>> aData)
{
nsCOMPtr<nsIObserverService> obsService =
mozilla::services::GetObserverService();
if (!obsService) {
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIPushMessage> message = nullptr;
if (aData) {
message = new PushMessage(aData.ref());
}
return obsService->NotifyObservers(message, "push-message",
NS_ConvertUTF8toUTF16(aScope).get());
}
nsresult
PushNotifier::NotifySubscriptionChangeObservers(const nsACString& aScope)
{
nsCOMPtr<nsIObserverService> obsService =
mozilla::services::GetObserverService();
if (!obsService) {
return NS_ERROR_FAILURE;
}
return obsService->NotifyObservers(nullptr, "push-subscription-change",
NS_ConvertUTF8toUTF16(aScope).get());
}
bool
PushNotifier::ShouldNotifyObservers(nsIPrincipal* aPrincipal)
{
// Notify XPCOM observers for system subscriptions, or all subscriptions
// if the `testing.notifyAllObservers` pref is set.
return nsContentUtils::IsSystemPrincipal(aPrincipal) ||
Preferences::GetBool("dom.push.testing.notifyAllObservers");
}
bool
PushNotifier::ShouldNotifyWorkers(nsIPrincipal* aPrincipal)
{
// System subscriptions use XPCOM observer notifications instead of service
// worker events. The `testing.notifyWorkers` pref disables worker events for
// non-system subscriptions.
return !nsContentUtils::IsSystemPrincipal(aPrincipal) &&
Preferences::GetBool("dom.push.testing.notifyWorkers", true);
}
PushMessage::PushMessage(const nsTArray<uint8_t>& aData)
: mData(aData)
{}
PushMessage::~PushMessage()
{}
NS_IMPL_CYCLE_COLLECTION_0(PushMessage)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PushMessage)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIPushMessage)
NS_INTERFACE_MAP_ENTRY(nsIPushMessage)
NS_INTERFACE_MAP_END
NS_IMPL_CYCLE_COLLECTING_ADDREF(PushMessage)
NS_IMPL_CYCLE_COLLECTING_RELEASE(PushMessage)
nsresult
PushMessage::EnsureDecodedText()
{
if (mData.IsEmpty() || !mDecodedText.IsEmpty()) {
return NS_OK;
}
nsresult rv = FetchUtil::ConsumeText(
mData.Length(),
reinterpret_cast<uint8_t*>(mData.Elements()),
mDecodedText
);
if (NS_WARN_IF(NS_FAILED(rv))) {
mDecodedText.Truncate();
return rv;
}
return NS_OK;
}
NS_IMETHODIMP
PushMessage::Text(nsAString& aText)
{
nsresult rv = EnsureDecodedText();
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
aText = mDecodedText;
return NS_OK;
}
NS_IMETHODIMP
PushMessage::Json(JSContext* aCx,
JS::MutableHandle<JS::Value> aResult)
{
nsresult rv = EnsureDecodedText();
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
ErrorResult error;
FetchUtil::ConsumeJson(aCx, aResult, mDecodedText, error);
if (error.Failed()) {
return error.StealNSResult();
}
return NS_OK;
}
NS_IMETHODIMP
PushMessage::Binary(uint32_t* aDataLen, uint8_t** aData)
{
if (!aDataLen || !aData) {
return NS_ERROR_INVALID_ARG;
}
*aData = nullptr;
if (mData.IsEmpty()) {
*aDataLen = 0;
return NS_OK;
}
uint32_t length = mData.Length();
uint8_t* data = static_cast<uint8_t*>(NS_Alloc(length * sizeof(uint8_t)));
if (!data) {
return NS_ERROR_OUT_OF_MEMORY;
}
memcpy(data, mData.Elements(), length * sizeof(uint8_t));
*aDataLen = length;
*aData = data;
return NS_OK;
}
} // namespace dom
} // namespace mozilla

89
dom/push/PushNotifier.h Normal file
View File

@ -0,0 +1,89 @@
/* 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 "nsTArray.h"
#include "mozilla/Maybe.h"
#define PUSHNOTIFIER_CONTRACTID \
"@mozilla.org/push/Notifier;1"
namespace mozilla {
namespace dom {
/**
* `PushNotifier` implements the `nsIPushNotifier` interface. This service
* forwards incoming push messages to service workers running in the content
* process, and emits XPCOM observer notifications for system subscriptions.
*
* The XPCOM service can only be used from the main process. Callers running
* in the content process should use
* `ServiceWorkerManager::SendPush{SubscriptionChange}Event` directly.
*/
class PushNotifier final : public nsIPushNotifier
{
public:
PushNotifier();
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(PushNotifier, nsIPushNotifier)
NS_DECL_NSIPUSHNOTIFIER
nsresult NotifyPush(const nsACString& aScope, nsIPrincipal* aPrincipal,
Maybe<nsTArray<uint8_t>> aData);
nsresult NotifyPushWorkers(const nsACString& aScope,
nsIPrincipal* aPrincipal,
Maybe<nsTArray<uint8_t>> aData);
nsresult NotifySubscriptionChangeWorkers(const nsACString& aScope,
nsIPrincipal* aPrincipal);
protected:
virtual ~PushNotifier();
private:
nsresult NotifyPushObservers(const nsACString& aScope,
Maybe<nsTArray<uint8_t>> aData);
nsresult NotifySubscriptionChangeObservers(const nsACString& aScope);
bool ShouldNotifyObservers(nsIPrincipal* aPrincipal);
bool ShouldNotifyWorkers(nsIPrincipal* aPrincipal);
};
/**
* `PushMessage` implements the `nsIPushMessage` interface, similar to
* the `PushMessageData` WebIDL interface. Instances of this class are
* passed as the subject of `push-message` observer notifications for
* system subscriptions.
*/
class PushMessage final : public nsIPushMessage
{
public:
explicit PushMessage(const nsTArray<uint8_t>& aData);
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(PushMessage,
nsIPushMessage)
NS_DECL_NSIPUSHMESSAGE
protected:
virtual ~PushMessage();
private:
nsresult EnsureDecodedText();
nsTArray<uint8_t> mData;
nsString mDecodedText;
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_PushNotifier_h

View File

@ -29,16 +29,22 @@ XPCSHELL_TESTS_MANIFESTS += [
EXPORTS.mozilla.dom += [
'PushManager.h',
'PushNotifier.h',
]
UNIFIED_SOURCES += [
'PushManager.cpp',
'PushNotifier.cpp',
]
include('/ipc/chromium/chromium-config.mozbuild')
if CONFIG['GNU_CXX']:
CXXFLAGS += ['-Wshadow']
LOCAL_INCLUDES += [
'../base',
'../ipc',
'../workers',
]

View File

@ -2201,6 +2201,22 @@ ServiceWorkerManager::SendPushEvent(const nsACString& aOriginAttributes,
uint32_t aDataLength,
uint8_t* aDataBytes,
uint8_t optional_argc)
{
if (optional_argc == 2) {
nsTArray<uint8_t> data;
if (!data.InsertElementsAt(0, aDataBytes, aDataLength, fallible)) {
return NS_ERROR_OUT_OF_MEMORY;
}
return SendPushEvent(aOriginAttributes, aScope, Some(data));
}
MOZ_ASSERT(optional_argc == 0);
return SendPushEvent(aOriginAttributes, aScope, Nothing());
}
nsresult
ServiceWorkerManager::SendPushEvent(const nsACString& aOriginAttributes,
const nsACString& aScope,
Maybe<nsTArray<uint8_t>> aData)
{
#ifdef MOZ_SIMPLEPUSH
return NS_ERROR_NOT_AVAILABLE;
@ -2218,16 +2234,7 @@ ServiceWorkerManager::SendPushEvent(const nsACString& aOriginAttributes,
RefPtr<ServiceWorkerRegistrationInfo> registration =
GetRegistration(serviceWorker->GetPrincipal(), aScope);
if (optional_argc == 2) {
nsTArray<uint8_t> data;
if (!data.InsertElementsAt(0, aDataBytes, aDataLength, fallible)) {
return NS_ERROR_OUT_OF_MEMORY;
}
return serviceWorker->WorkerPrivate()->SendPushEvent(Some(data), registration);
} else {
MOZ_ASSERT(optional_argc == 0);
return serviceWorker->WorkerPrivate()->SendPushEvent(Nothing(), registration);
}
return serviceWorker->WorkerPrivate()->SendPushEvent(aData, registration);
#endif // MOZ_SIMPLEPUSH
}

View File

@ -494,6 +494,11 @@ public:
void
MaybeCheckNavigationUpdate(nsIDocument* aDoc);
nsresult
SendPushEvent(const nsACString& aOriginAttributes,
const nsACString& aScope,
Maybe<nsTArray<uint8_t>> aData);
private:
ServiceWorkerManager();
~ServiceWorkerManager();

View File

@ -126,6 +126,13 @@ using mozilla::dom::gonk::AudioManager;
using mozilla::system::nsVolumeService;
#endif
#ifndef MOZ_SIMPLEPUSH
#include "mozilla/dom/PushNotifier.h"
using mozilla::dom::PushNotifier;
#define PUSHNOTIFIER_CID \
{ 0x2fc2d3e3, 0x020f, 0x404e, { 0xb0, 0x6a, 0x6e, 0xcf, 0x3e, 0xa2, 0x33, 0x4a } }
#endif
#include "AudioChannelAgent.h"
using mozilla::dom::AudioChannelAgent;
@ -400,6 +407,10 @@ NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsIPresentationService,
NS_CreatePresentationService)
NS_GENERIC_FACTORY_CONSTRUCTOR(PresentationSessionTransport)
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(NotificationTelemetryService, Init)
#ifndef MOZ_SIMPLEPUSH
NS_GENERIC_FACTORY_CONSTRUCTOR(PushNotifier)
#endif
//-----------------------------------------------------------------------------
static bool gInitialized = false;
@ -763,6 +774,11 @@ NS_DEFINE_NAMED_CID(DOMREQUEST_SERVICE_CID);
NS_DEFINE_NAMED_CID(QUOTAMANAGER_SERVICE_CID);
NS_DEFINE_NAMED_CID(SERVICEWORKERMANAGER_CID);
NS_DEFINE_NAMED_CID(NOTIFICATIONTELEMETRYSERVICE_CID);
#ifndef MOZ_SIMPLEPUSH
NS_DEFINE_NAMED_CID(PUSHNOTIFIER_CID);
#endif
NS_DEFINE_NAMED_CID(WORKERDEBUGGERMANAGER_CID);
#ifdef MOZ_WIDGET_GONK
NS_DEFINE_NAMED_CID(SYSTEMWORKERMANAGER_CID);
@ -1071,6 +1087,9 @@ static const mozilla::Module::CIDEntry kLayoutCIDs[] = {
{ &kQUOTAMANAGER_SERVICE_CID, false, nullptr, QuotaManagerServiceConstructor },
{ &kSERVICEWORKERMANAGER_CID, false, nullptr, ServiceWorkerManagerConstructor },
{ &kNOTIFICATIONTELEMETRYSERVICE_CID, false, nullptr, NotificationTelemetryServiceConstructor },
#ifndef MOZ_SIMPLEPUSH
{ &kPUSHNOTIFIER_CID, false, nullptr, PushNotifierConstructor },
#endif
{ &kWORKERDEBUGGERMANAGER_CID, true, nullptr, WorkerDebuggerManagerConstructor },
#ifdef MOZ_WIDGET_GONK
{ &kSYSTEMWORKERMANAGER_CID, true, nullptr, SystemWorkerManagerConstructor },
@ -1239,6 +1258,9 @@ static const mozilla::Module::ContractIDEntry kLayoutContracts[] = {
{ QUOTAMANAGER_SERVICE_CONTRACTID, &kQUOTAMANAGER_SERVICE_CID },
{ SERVICEWORKERMANAGER_CONTRACTID, &kSERVICEWORKERMANAGER_CID },
{ NOTIFICATIONTELEMETRYSERVICE_CONTRACTID, &kNOTIFICATIONTELEMETRYSERVICE_CID },
#ifndef MOZ_SIMPLEPUSH
{ PUSHNOTIFIER_CONTRACTID, &kPUSHNOTIFIER_CID },
#endif
{ WORKERDEBUGGERMANAGER_CONTRACTID, &kWORKERDEBUGGERMANAGER_CID },
#ifdef MOZ_WIDGET_GONK
{ SYSTEMWORKERMANAGER_CONTRACTID, &kSYSTEMWORKERMANAGER_CID },
@ -1338,6 +1360,9 @@ static const mozilla::Module::CategoryEntry kLayoutCategories[] = {
{ "net-channel-event-sinks", "CSPService", CSPSERVICE_CONTRACTID },
{ "net-channel-event-sinks", NS_MIXEDCONTENTBLOCKER_CONTRACTID, NS_MIXEDCONTENTBLOCKER_CONTRACTID },
{ "app-startup", "Script Security Manager", "service," NS_SCRIPTSECURITYMANAGER_CONTRACTID },
#ifndef MOZ_SIMPLEPUSH
{ "app-startup", "Push Notifier", "service," PUSHNOTIFIER_CONTRACTID },
#endif
{ TOPIC_WEB_APP_CLEAR_DATA, "QuotaManagerService", "service," QUOTAMANAGER_SERVICE_CONTRACTID },
{ OBSERVER_TOPIC_IDLE_DAILY, "QuotaManagerService", QUOTAMANAGER_SERVICE_CONTRACTID },
#ifdef MOZ_WIDGET_GONK