Back out out 3 changesets (bug 1239584) for B2G build failures on a CLOSED TREE.

This commit is contained in:
Kit Cambridge 2016-01-22 11:06:14 -08:00
parent f509c9d773
commit b19af47df1
51 changed files with 375 additions and 644 deletions

View File

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

View File

@ -1,41 +0,0 @@
#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

@ -0,0 +1,40 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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 "nsISupports.idl"
/**
* A push message received by an `nsIPushService`, used as the subject of a
* `push-notification` observer notification.
*/
[scriptable, uuid(56f57607-28b6-44b0-aa56-3d4d3c88be15)]
interface nsIPushObserverNotification : nsISupports
{
/* The URL that receives push messages from an application server. */
attribute string pushEndpoint;
/**
* The notification version sent by the application server. This is a
* monotonically increasing number.
*/
attribute long long version;
/**
* The notification payload. Delivery is not guaranteed; if the browser is
* offline when the application server sends the push message, the payload
* may be discarded.
*/
attribute string data;
/**
* How many times has a push event occured against this pushEndpoint
*/
attribute long long pushCount;
/**
* The last time a push occured against this this pushEndpoint
*/
attribute long long lastPush;
};

View File

@ -81,8 +81,9 @@ interface nsIPushService : nsISupports
* The |endpoint| property of the subscription record is a URL string * The |endpoint| property of the subscription record is a URL string
* that can be used to send push messages to subscribers. * that can be used to send push messages to subscribers.
* *
* Each incoming message fires a `push-message` observer notification, with * Each incoming message fires a `push-notification` observer
* an `nsIPushMessage` as the subject and the |scope| as the data. * notification, with an `nsIPushObserverNotification` as the subject and
* the |scope| as the data.
* *
* If the server drops a subscription, a `push-subscription-change` observer * If the server drops a subscription, a `push-subscription-change` observer
* will be fired, with the subject set to `null` and the data set to |scope|. * will be fired, with the subject set to `null` and the data set to |scope|.

View File

@ -175,7 +175,6 @@
#include "mozilla/dom/PFMRadioChild.h" #include "mozilla/dom/PFMRadioChild.h"
#include "mozilla/dom/PPresentationChild.h" #include "mozilla/dom/PPresentationChild.h"
#include "mozilla/dom/PresentationIPCService.h" #include "mozilla/dom/PresentationIPCService.h"
#include "mozilla/dom/PushNotifier.h"
#include "mozilla/ipc/InputStreamUtils.h" #include "mozilla/ipc/InputStreamUtils.h"
#ifdef MOZ_WEBSPEECH #ifdef MOZ_WEBSPEECH
@ -3218,56 +3217,5 @@ ContentChild::RecvTestGraphicsDeviceReset(const uint32_t& aResetReason)
return true; return true;
} }
bool
ContentChild::RecvPush(const nsCString& aScope,
const IPC::Principal& aPrincipal)
{
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));
return true;
}
bool
ContentChild::RecvPushWithData(const nsCString& aScope,
const IPC::Principal& aPrincipal,
InfallibleTArray<uint8_t>&& aData)
{
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));
return true;
}
bool
ContentChild::RecvPushSubscriptionChange(const nsCString& aScope,
const IPC::Principal& aPrincipal)
{
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));
return true;
}
} // namespace dom } // namespace dom
} // namespace mozilla } // namespace mozilla

View File

@ -526,19 +526,6 @@ public:
virtual bool RecvEndDragSession(const bool& aDoneDrag, virtual bool RecvEndDragSession(const bool& aDoneDrag,
const bool& aUserCancelled) override; 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 #ifdef ANDROID
gfx::IntSize GetScreenSize() { return mScreenSize; } gfx::IntSize GetScreenSize() { return mScreenSize; }
#endif #endif

View File

@ -728,21 +728,6 @@ child:
*/ */
async NotifyGMPsChanged(); 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: parent:
/** /**
* Tell the content process some attributes of itself. This is * Tell the content process some attributes of itself. This is

View File

@ -6,3 +6,6 @@ contract @mozilla.org/push/PushManager;1 {cde1d019-fad8-4044-b141-65fb4fb7a245}
component {daaa8d73-677e-4233-8acd-2c404bd01658} PushComponents.js component {daaa8d73-677e-4233-8acd-2c404bd01658} PushComponents.js
contract @mozilla.org/push/Service;1 {daaa8d73-677e-4233-8acd-2c404bd01658} contract @mozilla.org/push/Service;1 {daaa8d73-677e-4233-8acd-2c404bd01658}
category app-startup PushServiceParent @mozilla.org/push/Service;1 category app-startup PushServiceParent @mozilla.org/push/Service;1
component {e68997fd-8b92-49ee-af12-800830b023e8} PushComponents.js
contract @mozilla.org/push/ObserverNotification;1 {e68997fd-8b92-49ee-af12-800830b023e8}

View File

@ -106,8 +106,10 @@ Object.assign(PushServiceParent.prototype, {
"Push:Registration", "Push:Registration",
"Push:Unregister", "Push:Unregister",
"Push:Clear", "Push:Clear",
"Push:RegisterEventNotificationListener",
"Push:NotificationForOriginShown", "Push:NotificationForOriginShown",
"Push:NotificationForOriginClosed", "Push:NotificationForOriginClosed",
"child-process-shutdown",
], ],
// nsIPushService methods // nsIPushService methods
@ -167,6 +169,14 @@ Object.assign(PushServiceParent.prototype, {
return; return;
} }
let {name, principal, target, data} = message; let {name, principal, target, data} = message;
if (name === "Push:RegisterEventNotificationListener") {
this._service.registerListener(target);
return;
}
if (name === "child-process-shutdown") {
this._service.unregisterListener(target);
return;
}
if (name === "Push:NotificationForOriginShown") { if (name === "Push:NotificationForOriginShown") {
this.notificationForOriginShown(data); this.notificationForOriginShown(data);
return; return;
@ -458,7 +468,21 @@ PushSubscription.prototype = {
}, },
}; };
/**
* `PushObserverNotification` instances are passed to all
* `push-notification` observers.
*/
function PushObserverNotification() {}
PushObserverNotification.prototype = {
classID: Components.ID("{e68997fd-8b92-49ee-af12-800830b023e8}"),
contractID: "@mozilla.org/push/ObserverNotification;1",
QueryInterface: XPCOMUtils.generateQI([Ci.nsIPushObserverNotification]),
};
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([ this.NSGetFactory = XPCOMUtils.generateNSGetFactory([
PushObserverNotification,
// Export the correct implementation depending on whether we're running in // Export the correct implementation depending on whether we're running in
// the parent or content process. // the parent or content process.
isParent ? PushServiceParent : PushServiceContent, isParent ? PushServiceParent : PushServiceContent,

View File

@ -1,315 +0,0 @@
/* 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

View File

@ -1,89 +0,0 @@
/* 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 NotifyPushWorkers(const nsACString& aScope,
nsIPrincipal* aPrincipal,
Maybe<nsTArray<uint8_t>> aData);
nsresult NotifySubscriptionChangeWorkers(const nsACString& aScope,
nsIPrincipal* aPrincipal);
protected:
virtual ~PushNotifier();
private:
nsresult NotifyPush(const nsACString& aScope, nsIPrincipal* aPrincipal,
Maybe<nsTArray<uint8_t>> aData);
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

@ -31,10 +31,6 @@ XPCOMUtils.defineLazyServiceGetter(this, "gContentSecurityManager",
"@mozilla.org/contentsecuritymanager;1", "@mozilla.org/contentsecuritymanager;1",
"nsIContentSecurityManager"); "nsIContentSecurityManager");
XPCOMUtils.defineLazyServiceGetter(this, "gPushNotifier",
"@mozilla.org/push/Notifier;1",
"nsIPushNotifier");
this.EXPORTED_SYMBOLS = ["PushService"]; this.EXPORTED_SYMBOLS = ["PushService"];
XPCOMUtils.defineLazyGetter(this, "console", () => { XPCOMUtils.defineLazyGetter(this, "console", () => {
@ -103,6 +99,8 @@ this.PushService = {
// reduce the quota for a record. Used for testing purposes. // reduce the quota for a record. Used for testing purposes.
_updateQuotaTestCallback: null, _updateQuotaTestCallback: null,
_childListeners: new Set(),
// When serverURI changes (this is used for testing), db is cleaned up and a // When serverURI changes (this is used for testing), db is cleaned up and a
// a new db is started. This events must be sequential. // a new db is started. This events must be sequential.
_stateChangeProcessQueue: null, _stateChangeProcessQueue: null,
@ -594,6 +592,8 @@ this.PushService = {
uninit: function() { uninit: function() {
console.debug("uninit()"); console.debug("uninit()");
this._childListeners.clear();
if (this._state == PUSH_SERVICE_UNINIT) { if (this._state == PUSH_SERVICE_UNINIT) {
return; return;
} }
@ -688,8 +688,38 @@ this.PushService = {
return; return;
} }
// Notify XPCOM observers.
Services.obs.notifyObservers(
null,
"push-subscription-change",
record.scope
);
let data = {
originAttributes: record.originAttributes,
scope: record.scope
};
Services.telemetry.getHistogramById("PUSH_API_NOTIFY_REGISTRATION_LOST").add(); Services.telemetry.getHistogramById("PUSH_API_NOTIFY_REGISTRATION_LOST").add();
gPushNotifier.notifySubscriptionChange(record.scope, record.principal); this._notifyListeners('pushsubscriptionchange', data);
},
_notifyListeners: function(name, data) {
if (this._childListeners.size > 0) {
// Try to send messages to all listeners, but remove any that fail since
// the receiver is likely gone away.
for (let listener of this._childListeners) {
try {
listener.sendAsyncMessage(name, data);
} catch(e) {
this._childListeners.delete(listener);
}
}
} else {
let ppmm = Cc['@mozilla.org/parentprocessmessagemanager;1']
.getService(Ci.nsIMessageListenerManager);
ppmm.broadcastAsyncMessage(name, data);
}
}, },
/** /**
@ -929,6 +959,29 @@ this.PushService = {
} }
console.debug("notifyApp()", aPushRecord.scope); console.debug("notifyApp()", aPushRecord.scope);
// Notify XPCOM observers.
let notification = Cc["@mozilla.org/push/ObserverNotification;1"]
.createInstance(Ci.nsIPushObserverNotification);
notification.pushEndpoint = aPushRecord.pushEndpoint;
notification.version = aPushRecord.version;
let payload = ArrayBuffer.isView(message) ?
new Uint8Array(message.buffer) : message;
if (payload) {
notification.data = "";
for (let i = 0; i < payload.length; i++) {
notification.data += String.fromCharCode(payload[i]);
}
}
notification.lastPush = aPushRecord.lastPush;
notification.pushCount = aPushRecord.pushCount;
Services.obs.notifyObservers(
notification,
"push-notification",
aPushRecord.scope
);
// If permission has been revoked, trash the message. // If permission has been revoked, trash the message.
if (!aPushRecord.hasPermission()) { if (!aPushRecord.hasPermission()) {
@ -936,22 +989,14 @@ this.PushService = {
return false; return false;
} }
let payload = ArrayBuffer.isView(message) ? let data = {
new Uint8Array(message.buffer) : message; payload: payload,
originAttributes: aPushRecord.originAttributes,
if (aPushRecord.quotaApplies()) { scope: aPushRecord.scope
// Don't record telemetry for chrome push messages. };
Services.telemetry.getHistogramById("PUSH_API_NOTIFY").add();
}
if (payload) {
gPushNotifier.notifyPushWithData(aPushRecord.scope,
aPushRecord.principal,
payload.length, payload);
} else {
gPushNotifier.notifyPush(aPushRecord.scope, aPushRecord.principal);
}
Services.telemetry.getHistogramById("PUSH_API_NOTIFY").add();
this._notifyListeners('push', data);
return true; return true;
}, },
@ -1041,7 +1086,14 @@ this.PushService = {
throw reply.error; throw reply.error;
}, },
notificationsCleared() { registerListener(listener) {
console.debug("registerListener: Adding child listener");
this._childListeners.add(listener);
},
unregisterListener(listener) {
console.debug("unregisterListener: Possibly removing child listener");
this._childListeners.delete(listener);
this._visibleNotifications.clear(); this._visibleNotifications.clear();
}, },

View File

@ -0,0 +1,41 @@
/* 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/. */
"use strict";
this.EXPORTED_SYMBOLS = [];
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cu = Components.utils;
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyServiceGetter(this,
"swm",
"@mozilla.org/serviceworkers/manager;1",
"nsIServiceWorkerManager");
var processType = Cc["@mozilla.org/xre/app-info;1"]
.getService(Ci.nsIXULRuntime).processType;
var isParent = processType === Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT;
Services.cpmm.addMessageListener("push", function (aMessage) {
let {originAttributes, scope, payload} = aMessage.data;
if (payload) {
swm.sendPushEvent(originAttributes, scope, payload.length, payload);
} else {
swm.sendPushEvent(originAttributes, scope);
}
});
Services.cpmm.addMessageListener("pushsubscriptionchange", function (aMessage) {
swm.sendPushSubscriptionChangeEvent(aMessage.data.originAttributes,
aMessage.data.scope);
});
if (!isParent) {
Services.cpmm.sendAsyncMessage("Push:RegisterEventNotificationListener", null, null, null);
}

View File

@ -14,6 +14,7 @@ EXTRA_JS_MODULES += [
'PushDB.jsm', 'PushDB.jsm',
'PushRecord.jsm', 'PushRecord.jsm',
'PushService.jsm', 'PushService.jsm',
'PushServiceChildPreload.jsm',
'PushServiceHttp2.jsm', 'PushServiceHttp2.jsm',
'PushServiceWebSocket.jsm', 'PushServiceWebSocket.jsm',
] ]
@ -28,22 +29,16 @@ XPCSHELL_TESTS_MANIFESTS += [
EXPORTS.mozilla.dom += [ EXPORTS.mozilla.dom += [
'PushManager.h', 'PushManager.h',
'PushNotifier.h',
] ]
UNIFIED_SOURCES += [ UNIFIED_SOURCES += [
'PushManager.cpp', 'PushManager.cpp',
'PushNotifier.cpp',
] ]
include('/ipc/chromium/chromium-config.mozbuild')
if CONFIG['GNU_CXX']: if CONFIG['GNU_CXX']:
CXXFLAGS += ['-Wshadow'] CXXFLAGS += ['-Wshadow']
LOCAL_INCLUDES += [ LOCAL_INCLUDES += [
'../base',
'../ipc',
'../workers', '../workers',
] ]

View File

@ -168,6 +168,23 @@ function makeStub(target, stubs) {
}); });
} }
/**
* Disables `push` and `pushsubscriptionchange` service worker events for the
* given scopes. These events cause crashes in xpcshell, so we disable them
* for testing nsIPushNotificationService.
*
* @param {String[]} scopes A list of scope URLs.
*/
function disableServiceWorkerEvents(...scopes) {
for (let scope of scopes) {
Services.perms.add(
Services.io.newURI(scope, null, null),
'desktop-notification',
Ci.nsIPermissionManager.DENY_ACTION
);
}
}
/** /**
* Sets default PushService preferences. All pref names are prefixed with * Sets default PushService preferences. All pref names are prefixed with
* `dom.push.`; any additional preferences will override the defaults. * `dom.push.`; any additional preferences will override the defaults.
@ -204,8 +221,6 @@ function setPrefs(prefs = {}) {
'http2.reset_retry_count_after_ms': 60000, 'http2.reset_retry_count_after_ms': 60000,
maxQuotaPerSubscription: 16, maxQuotaPerSubscription: 16,
quotaUpdateDelay: 3000, quotaUpdateDelay: 3000,
'testing.notifyWorkers': false,
'testing.notifyAllObservers': true,
}, prefs); }, prefs);
for (let pref in defaultPrefs) { for (let pref in defaultPrefs) {
servicePrefs.set(pref, defaultPrefs[pref]); servicePrefs.set(pref, defaultPrefs[pref]);

View File

@ -41,6 +41,9 @@ function run_test() {
requestTimeout: 1000, requestTimeout: 1000,
retryBaseInterval: 150 retryBaseInterval: 150
}); });
disableServiceWorkerEvents(
'https://example.org/1'
);
run_next_test(); run_next_test();
} }

View File

@ -10,6 +10,11 @@ var userAgentID = '5ab1d1df-7a3d-4024-a469-b9e1bb399fad';
function run_test() { function run_test() {
do_get_profile(); do_get_profile();
setPrefs({userAgentID}); setPrefs({userAgentID});
disableServiceWorkerEvents(
'https://example.org/1',
'https://example.org/2',
'https://example.org/3'
);
run_next_test(); run_next_test();
} }
@ -45,9 +50,11 @@ add_task(function* test_notification_ack() {
yield db.put(record); yield db.put(record);
} }
let notifyCount = 0; let notifyPromise = Promise.all([
let notifyPromise = promiseObserverNotification('push-message', () => promiseObserverNotification('push-notification'),
++notifyCount == 3); promiseObserverNotification('push-notification'),
promiseObserverNotification('push-notification')
]);
let acks = 0; let acks = 0;
let ackDone; let ackDone;

View File

@ -218,9 +218,9 @@ add_task(function* test_notification_ack_data() {
]; ];
let sendAndReceive = testData => { let sendAndReceive = testData => {
let messageReceived = promiseObserverNotification('push-message', (subject, data) => { let messageReceived = promiseObserverNotification('push-notification', (subject, data) => {
let notification = subject.QueryInterface(Ci.nsIPushMessage); let notification = subject.QueryInterface(Ci.nsIPushObserverNotification);
equal(notification.text(), testData.receive.data, equal(notification.data, testData.receive.data,
'Check data for notification ' + testData.version); 'Check data for notification ' + testData.version);
equal(data, testData.receive.scope, equal(data, testData.receive.scope,
'Check scope for notification ' + testData.version); 'Check scope for notification ' + testData.version);

View File

@ -12,6 +12,10 @@ function run_test() {
setPrefs({ setPrefs({
userAgentID: userAgentID, userAgentID: userAgentID,
}); });
disableServiceWorkerEvents(
'https://example.com/1',
'https://example.com/2'
);
run_next_test(); run_next_test();
} }
@ -40,7 +44,7 @@ add_task(function* test_notification_duplicate() {
yield db.put(record); yield db.put(record);
} }
let notifyPromise = promiseObserverNotification('push-message'); let notifyPromise = promiseObserverNotification('push-notification');
let acks = 0; let acks = 0;
let ackDone; let ackDone;

View File

@ -12,6 +12,11 @@ function run_test() {
setPrefs({ setPrefs({
userAgentID: userAgentID, userAgentID: userAgentID,
}); });
disableServiceWorkerEvents(
'https://example.com/a',
'https://example.com/b',
'https://example.com/c'
);
run_next_test(); run_next_test();
} }
@ -49,9 +54,16 @@ add_task(function* test_notification_error() {
yield db.put(record); yield db.put(record);
} }
let scopes = []; let notifyPromise = Promise.all([
let notifyPromise = promiseObserverNotification('push-message', (subject, data) => promiseObserverNotification(
scopes.push(data) == 2); 'push-notification',
(subject, data) => data == 'https://example.com/a'
),
promiseObserverNotification(
'push-notification',
(subject, data) => data == 'https://example.com/c'
)
]);
let ackDone; let ackDone;
let ackPromise = new Promise(resolve => ackDone = after(records.length, resolve)); let ackPromise = new Promise(resolve => ackDone = after(records.length, resolve));
@ -87,15 +99,20 @@ add_task(function* test_notification_error() {
} }
}); });
yield waitForPromise( let [a, c] = yield waitForPromise(
notifyPromise, notifyPromise,
DEFAULT_TIMEOUT, DEFAULT_TIMEOUT,
'Timed out waiting for notifications' 'Timed out waiting for notifications'
); );
ok(scopes.includes('https://example.com/a'), let aPush = a.subject.QueryInterface(Ci.nsIPushObserverNotification);
'Missing scope for notification A'); equal(aPush.pushEndpoint, 'https://example.org/update/success-1',
ok(scopes.includes('https://example.com/c'), 'Wrong endpoint for notification A');
'Missing scope for notification C'); equal(aPush.version, 2, 'Wrong version for notification A');
let cPush = c.subject.QueryInterface(Ci.nsIPushObserverNotification);
equal(cPush.pushEndpoint, 'https://example.org/update/success-2',
'Wrong endpoint for notification C');
equal(cPush.version, 4, 'Wrong version for notification C');
yield waitForPromise(ackPromise, DEFAULT_TIMEOUT, yield waitForPromise(ackPromise, DEFAULT_TIMEOUT,
'Timed out waiting for acknowledgements'); 'Timed out waiting for acknowledgements');

View File

@ -35,8 +35,11 @@ function run_test() {
prefs.setIntPref("network.http.speculative-parallel-limit", oldPref); prefs.setIntPref("network.http.speculative-parallel-limit", oldPref);
servicePrefs.set('testing.notifyWorkers', false); disableServiceWorkerEvents(
servicePrefs.set('testing.notifyAllObservers', true); 'https://example.com/page/1',
'https://example.com/page/2',
'https://example.com/page/3'
);
run_next_test(); run_next_test();
} }
@ -121,24 +124,24 @@ add_task(function* test_pushNotifications() {
} }
let notifyPromise = Promise.all([ let notifyPromise = Promise.all([
promiseObserverNotification('push-message', function(subject, data) { promiseObserverNotification('push-notification', function(subject, data) {
var message = subject.QueryInterface(Ci.nsIPushMessage); var notification = subject.QueryInterface(Ci.nsIPushObserverNotification);
if (message && (data == "https://example.com/page/1")){ if (notification && (data == "https://example.com/page/1")){
equal(message.text(), "Some message", "decoded message is incorrect"); equal(subject.data, "Some message", "decoded message is incorrect");
return true; return true;
} }
}), }),
promiseObserverNotification('push-message', function(subject, data) { promiseObserverNotification('push-notification', function(subject, data) {
var message = subject.QueryInterface(Ci.nsIPushMessage); var notification = subject.QueryInterface(Ci.nsIPushObserverNotification);
if (message && (data == "https://example.com/page/2")){ if (notification && (data == "https://example.com/page/2")){
equal(message.text(), "Some message", "decoded message is incorrect"); equal(subject.data, "Some message", "decoded message is incorrect");
return true; return true;
} }
}), }),
promiseObserverNotification('push-message', function(subject, data) { promiseObserverNotification('push-notification', function(subject, data) {
var message = subject.QueryInterface(Ci.nsIPushMessage); var notification = subject.QueryInterface(Ci.nsIPushObserverNotification);
if (message && (data == "https://example.com/page/3")){ if (notification && (data == "https://example.com/page/3")){
equal(message.text(), "Some message", "decoded message is incorrect"); equal(subject.data, "Some message", "decoded message is incorrect");
return true; return true;
} }
}) })

View File

@ -12,6 +12,12 @@ function run_test() {
setPrefs({ setPrefs({
userAgentID: userAgentID, userAgentID: userAgentID,
}); });
disableServiceWorkerEvents(
'https://example.com/page/1',
'https://example.com/page/2',
'https://example.com/page/3',
'https://example.com/page/4'
);
run_next_test(); run_next_test();
} }
@ -51,12 +57,9 @@ add_task(function* test_notification_incomplete() {
yield db.put(record); yield db.put(record);
} }
function observeMessage(subject, topic, data) { Services.obs.addObserver(function observe(subject, topic, data) {
ok(false, 'Should not deliver malformed updates'); ok(false, 'Should not deliver malformed updates');
} }, 'push-notification', false);
do_register_cleanup(() =>
Services.obs.removeObserver(observeMessage, 'push-message'));
Services.obs.addObserver(observeMessage, 'push-message', false);
let notificationDone; let notificationDone;
let notificationPromise = new Promise(resolve => notificationDone = after(2, resolve)); let notificationPromise = new Promise(resolve => notificationDone = after(2, resolve));

View File

@ -12,6 +12,9 @@ function run_test() {
setPrefs({ setPrefs({
userAgentID: userAgentID, userAgentID: userAgentID,
}); });
disableServiceWorkerEvents(
'https://example.net/case'
);
run_next_test(); run_next_test();
} }
@ -28,7 +31,7 @@ add_task(function* test_notification_version_string() {
systemRecord: true, systemRecord: true,
}); });
let notifyPromise = promiseObserverNotification('push-message'); let notifyPromise = promiseObserverNotification('push-notification');
let ackDone; let ackDone;
let ackPromise = new Promise(resolve => ackDone = resolve); let ackPromise = new Promise(resolve => ackDone = resolve);
@ -62,7 +65,11 @@ add_task(function* test_notification_version_string() {
DEFAULT_TIMEOUT, DEFAULT_TIMEOUT,
'Timed out waiting for string notification' 'Timed out waiting for string notification'
); );
equal(notification, null, 'Unexpected data for Simple Push message'); let message = notification.QueryInterface(Ci.nsIPushObserverNotification);
equal(scope, 'https://example.com/page/1', 'Wrong scope');
equal(message.pushEndpoint, 'https://example.org/updates/1',
'Wrong push endpoint');
strictEqual(message.version, 4, 'Wrong version');
yield waitForPromise(ackPromise, DEFAULT_TIMEOUT, yield waitForPromise(ackPromise, DEFAULT_TIMEOUT,
'Timed out waiting for string acknowledgement'); 'Timed out waiting for string acknowledgement');

View File

@ -82,7 +82,7 @@ add_task(function* test_expiration_origin_threshold() {
// different scopes, so each can send 5 notifications before we remove // different scopes, so each can send 5 notifications before we remove
// their subscription. // their subscription.
let updates = 0; let updates = 0;
let notifyPromise = promiseObserverNotification('push-message', (subject, data) => { let notifyPromise = promiseObserverNotification('push-notification', (subject, data) => {
updates++; updates++;
return updates == 6; return updates == 6;
}); });

View File

@ -55,7 +55,7 @@ add_task(function* test_expiration_origin_threshold() {
let numMessages = 10; let numMessages = 10;
let updates = 0; let updates = 0;
let notifyPromise = promiseObserverNotification('push-message', (subject, data) => { let notifyPromise = promiseObserverNotification('push-notification', (subject, data) => {
updates++; updates++;
return updates == numMessages; return updates == numMessages;
}); });

View File

@ -56,6 +56,9 @@ function run_test() {
'http2.retryInterval': 1000, 'http2.retryInterval': 1000,
'http2.maxRetries': 2 'http2.maxRetries': 2
}); });
disableServiceWorkerEvents(
'https://example.com/retry5xxCode'
);
run_next_test(); run_next_test();
} }

View File

@ -10,6 +10,9 @@ const userAgentID = '1760b1f5-c3ba-40e3-9344-adef7c18ab12';
function run_test() { function run_test() {
do_get_profile(); do_get_profile();
setPrefs(); setPrefs();
disableServiceWorkerEvents(
'https://example.net/case'
);
run_next_test(); run_next_test();
} }

View File

@ -23,6 +23,10 @@ function run_test() {
tlsProfile = prefs.getBoolPref("network.http.spdy.enforce-tls-profile"); tlsProfile = prefs.getBoolPref("network.http.spdy.enforce-tls-profile");
disableServiceWorkerEvents(
'https://example.net/page/invalid-response'
);
serverURL = "https://localhost:" + serverPort; serverURL = "https://localhost:" + serverPort;
run_next_test(); run_next_test();

View File

@ -15,6 +15,10 @@ function run_test() {
requestTimeout: 1000, requestTimeout: 1000,
retryBaseInterval: 150 retryBaseInterval: 150
}); });
disableServiceWorkerEvents(
'https://example.com/page/1',
'https://example.com/page/2'
);
run_next_test(); run_next_test();
} }
@ -32,7 +36,7 @@ add_task(function* test_register_flush() {
}; };
yield db.put(record); yield db.put(record);
let notifyPromise = promiseObserverNotification('push-message'); let notifyPromise = promiseObserverNotification('push-notification');
let ackDone; let ackDone;
let ackPromise = new Promise(resolve => ackDone = after(2, resolve)); let ackPromise = new Promise(resolve => ackDone = after(2, resolve));

View File

@ -11,6 +11,9 @@ const channelID = 'cafed00d';
function run_test() { function run_test() {
do_get_profile(); do_get_profile();
setPrefs(); setPrefs();
disableServiceWorkerEvents(
'https://example.com/invalid-channel'
);
run_next_test(); run_next_test();
} }

View File

@ -11,6 +11,9 @@ const channelID = 'c0660af8-b532-4931-81f0-9fd27a12d6ab';
function run_test() { function run_test() {
do_get_profile(); do_get_profile();
setPrefs(); setPrefs();
disableServiceWorkerEvents(
'https://example.net/page/invalid-endpoint'
);
run_next_test(); run_next_test();
} }

View File

@ -14,6 +14,9 @@ function run_test() {
requestTimeout: 1000, requestTimeout: 1000,
retryBaseInterval: 150 retryBaseInterval: 150
}); });
disableServiceWorkerEvents(
'https://example.net/page/invalid-json'
);
run_next_test(); run_next_test();
} }

View File

@ -15,6 +15,9 @@ function run_test() {
requestTimeout: 1000, requestTimeout: 1000,
retryBaseInterval: 150 retryBaseInterval: 150
}); });
disableServiceWorkerEvents(
'https://example.com/incomplete'
);
run_next_test(); run_next_test();
} }

View File

@ -11,6 +11,9 @@ function run_test() {
requestTimeout: 1000, requestTimeout: 1000,
retryBaseInterval: 150 retryBaseInterval: 150
}); });
disableServiceWorkerEvents(
'https://example.com/page/1'
);
run_next_test(); run_next_test();
} }

View File

@ -15,6 +15,9 @@ function run_test() {
requestTimeout: 1000, requestTimeout: 1000,
retryBaseInterval: 150 retryBaseInterval: 150
}); });
disableServiceWorkerEvents(
'https://example.com/storage-error'
);
run_next_test(); run_next_test();
} }

View File

@ -15,6 +15,9 @@ function run_test() {
requestTimeout: 1000, requestTimeout: 1000,
retryBaseInterval: 150 retryBaseInterval: 150
}); });
disableServiceWorkerEvents(
'https://example.org/1'
);
run_next_test(); run_next_test();
} }

View File

@ -37,6 +37,11 @@ function run_test() {
serverURL = "https://localhost:" + serverPort; serverURL = "https://localhost:" + serverPort;
disableServiceWorkerEvents(
'https://example.org/1',
'https://example.org/no_receiptEndpoint'
);
run_next_test(); run_next_test();
} }

View File

@ -14,6 +14,9 @@ function run_test() {
requestTimeout: 1000, requestTimeout: 1000,
retryBaseInterval: 150 retryBaseInterval: 150
}); });
disableServiceWorkerEvents(
'https://example.net/page/timeout'
);
run_next_test(); run_next_test();
} }

View File

@ -16,6 +16,9 @@ function run_test() {
requestTimeout: 1000, requestTimeout: 1000,
retryBaseInterval: 150 retryBaseInterval: 150
}); });
disableServiceWorkerEvents(
'https://example.com/mismatched'
);
run_next_test(); run_next_test();
} }

View File

@ -13,6 +13,9 @@ function run_test() {
requestTimeout: 1000, requestTimeout: 1000,
retryBaseInterval: 150 retryBaseInterval: 150
}); });
disableServiceWorkerEvents(
'https://example.com/mistyped'
);
run_next_test(); run_next_test();
} }

View File

@ -19,6 +19,12 @@ function run_test() {
do_get_profile(); do_get_profile();
prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch); prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
disableServiceWorkerEvents(
'https://example.net/a',
'https://example.net/b',
'https://example.net/c'
);
run_next_test(); run_next_test();
} }

View File

@ -48,8 +48,9 @@ function run_test() {
do_get_profile(); do_get_profile();
servicePrefs.set('testing.notifyWorkers', false); disableServiceWorkerEvents(
servicePrefs.set('testing.notifyAllObservers', true); 'https://example.com/page'
);
run_next_test(); run_next_test();
} }

View File

@ -56,6 +56,9 @@ function run_test() {
'http2.retryInterval': 1000, 'http2.retryInterval': 1000,
'http2.maxRetries': 2 'http2.maxRetries': 2
}); });
disableServiceWorkerEvents(
'https://example.com/page'
);
run_next_test(); run_next_test();
} }

View File

@ -44,6 +44,9 @@ function run_test() {
'http2.retryInterval': 1000, 'http2.retryInterval': 1000,
'http2.maxRetries': 2 'http2.maxRetries': 2
}); });
disableServiceWorkerEvents(
'https://example.com/page'
);
run_next_test(); run_next_test();
} }

View File

@ -34,6 +34,10 @@ function run_test() {
prefs.setIntPref("network.http.speculative-parallel-limit", oldPref); prefs.setIntPref("network.http.speculative-parallel-limit", oldPref);
disableServiceWorkerEvents(
'https://example.com/page/unregister-success'
);
run_next_test(); run_next_test();
} }

View File

@ -32,6 +32,9 @@ function run_test() {
'http2.retryInterval': 1000, 'http2.retryInterval': 1000,
'http2.maxRetries': 2 'http2.maxRetries': 2
}); });
disableServiceWorkerEvents(
'https://example.com/page'
);
run_next_test(); run_next_test();
} }

View File

@ -12,6 +12,11 @@ function run_test() {
setPrefs({ setPrefs({
userAgentID, userAgentID,
}); });
disableServiceWorkerEvents(
'https://example.com/page/1',
'https://example.com/page/2',
'https://example.com/page/3'
);
run_next_test(); run_next_test();
} }

View File

@ -2201,22 +2201,6 @@ ServiceWorkerManager::SendPushEvent(const nsACString& aOriginAttributes,
uint32_t aDataLength, uint32_t aDataLength,
uint8_t* aDataBytes, uint8_t* aDataBytes,
uint8_t optional_argc) 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 #ifdef MOZ_SIMPLEPUSH
return NS_ERROR_NOT_AVAILABLE; return NS_ERROR_NOT_AVAILABLE;
@ -2234,7 +2218,16 @@ ServiceWorkerManager::SendPushEvent(const nsACString& aOriginAttributes,
RefPtr<ServiceWorkerRegistrationInfo> registration = RefPtr<ServiceWorkerRegistrationInfo> registration =
GetRegistration(serviceWorker->GetPrincipal(), aScope); GetRegistration(serviceWorker->GetPrincipal(), aScope);
return serviceWorker->WorkerPrivate()->SendPushEvent(aData, registration); 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);
}
#endif // MOZ_SIMPLEPUSH #endif // MOZ_SIMPLEPUSH
} }

View File

@ -41,7 +41,6 @@ class PrincipalOriginAttributes;
namespace dom { namespace dom {
class ServiceWorkerRegistrationListener; class ServiceWorkerRegistrationListener;
class PushNotifier;
namespace workers { namespace workers {
@ -334,7 +333,6 @@ class ServiceWorkerManager final
friend class ServiceWorkerRegistrationInfo; friend class ServiceWorkerRegistrationInfo;
friend class ServiceWorkerUnregisterJob; friend class ServiceWorkerUnregisterJob;
friend class UpdateTimerCallback; friend class UpdateTimerCallback;
friend class mozilla::dom::PushNotifier;
public: public:
NS_DECL_ISUPPORTS NS_DECL_ISUPPORTS
@ -679,11 +677,6 @@ private:
void void
UpdateTimerFired(nsIPrincipal* aPrincipal, const nsACString& aScope); UpdateTimerFired(nsIPrincipal* aPrincipal, const nsACString& aScope);
nsresult
SendPushEvent(const nsACString& aOriginAttributes,
const nsACString& aScope,
Maybe<nsTArray<uint8_t>> aData);
}; };
} // namespace workers } // namespace workers

View File

@ -88,7 +88,6 @@
#include "mozilla/dom/workers/ServiceWorkerManager.h" #include "mozilla/dom/workers/ServiceWorkerManager.h"
#include "mozilla/dom/workers/WorkerDebuggerManager.h" #include "mozilla/dom/workers/WorkerDebuggerManager.h"
#include "mozilla/dom/Notification.h" #include "mozilla/dom/Notification.h"
#include "mozilla/dom/PushNotifier.h"
#include "mozilla/OSFileConstants.h" #include "mozilla/OSFileConstants.h"
#include "mozilla/Services.h" #include "mozilla/Services.h"
@ -401,11 +400,6 @@ NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsIPresentationService,
NS_CreatePresentationService) NS_CreatePresentationService)
NS_GENERIC_FACTORY_CONSTRUCTOR(PresentationSessionTransport) NS_GENERIC_FACTORY_CONSTRUCTOR(PresentationSessionTransport)
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(NotificationTelemetryService, Init) NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(NotificationTelemetryService, Init)
#ifndef MOZ_SIMPLEPUSH
using mozilla::dom::PushNotifier;
NS_GENERIC_FACTORY_CONSTRUCTOR(PushNotifier)
#endif
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
static bool gInitialized = false; static bool gInitialized = false;
@ -769,13 +763,6 @@ NS_DEFINE_NAMED_CID(DOMREQUEST_SERVICE_CID);
NS_DEFINE_NAMED_CID(QUOTAMANAGER_SERVICE_CID); NS_DEFINE_NAMED_CID(QUOTAMANAGER_SERVICE_CID);
NS_DEFINE_NAMED_CID(SERVICEWORKERMANAGER_CID); NS_DEFINE_NAMED_CID(SERVICEWORKERMANAGER_CID);
NS_DEFINE_NAMED_CID(NOTIFICATIONTELEMETRYSERVICE_CID); NS_DEFINE_NAMED_CID(NOTIFICATIONTELEMETRYSERVICE_CID);
#ifndef MOZ_SIMPLEPUSH
#define PUSHNOTIFIER_CID \
{ 0x2fc2d3e3, 0x020f, 0x404e, { 0xb0, 0x6a, 0x6e, 0xcf, 0x3e, 0xa2, 0x33, 0x4a } }
NS_DEFINE_NAMED_CID(PUSHNOTIFIER_CID);
#endif
NS_DEFINE_NAMED_CID(WORKERDEBUGGERMANAGER_CID); NS_DEFINE_NAMED_CID(WORKERDEBUGGERMANAGER_CID);
#ifdef MOZ_WIDGET_GONK #ifdef MOZ_WIDGET_GONK
NS_DEFINE_NAMED_CID(SYSTEMWORKERMANAGER_CID); NS_DEFINE_NAMED_CID(SYSTEMWORKERMANAGER_CID);
@ -1084,9 +1071,6 @@ static const mozilla::Module::CIDEntry kLayoutCIDs[] = {
{ &kQUOTAMANAGER_SERVICE_CID, false, nullptr, QuotaManagerServiceConstructor }, { &kQUOTAMANAGER_SERVICE_CID, false, nullptr, QuotaManagerServiceConstructor },
{ &kSERVICEWORKERMANAGER_CID, false, nullptr, ServiceWorkerManagerConstructor }, { &kSERVICEWORKERMANAGER_CID, false, nullptr, ServiceWorkerManagerConstructor },
{ &kNOTIFICATIONTELEMETRYSERVICE_CID, false, nullptr, NotificationTelemetryServiceConstructor }, { &kNOTIFICATIONTELEMETRYSERVICE_CID, false, nullptr, NotificationTelemetryServiceConstructor },
#ifndef MOZ_SIMPLEPUSH
{ &kPUSHNOTIFIER_CID, false, nullptr, PushNotifierConstructor },
#endif
{ &kWORKERDEBUGGERMANAGER_CID, true, nullptr, WorkerDebuggerManagerConstructor }, { &kWORKERDEBUGGERMANAGER_CID, true, nullptr, WorkerDebuggerManagerConstructor },
#ifdef MOZ_WIDGET_GONK #ifdef MOZ_WIDGET_GONK
{ &kSYSTEMWORKERMANAGER_CID, true, nullptr, SystemWorkerManagerConstructor }, { &kSYSTEMWORKERMANAGER_CID, true, nullptr, SystemWorkerManagerConstructor },
@ -1255,9 +1239,6 @@ static const mozilla::Module::ContractIDEntry kLayoutContracts[] = {
{ QUOTAMANAGER_SERVICE_CONTRACTID, &kQUOTAMANAGER_SERVICE_CID }, { QUOTAMANAGER_SERVICE_CONTRACTID, &kQUOTAMANAGER_SERVICE_CID },
{ SERVICEWORKERMANAGER_CONTRACTID, &kSERVICEWORKERMANAGER_CID }, { SERVICEWORKERMANAGER_CONTRACTID, &kSERVICEWORKERMANAGER_CID },
{ NOTIFICATIONTELEMETRYSERVICE_CONTRACTID, &kNOTIFICATIONTELEMETRYSERVICE_CID }, { NOTIFICATIONTELEMETRYSERVICE_CONTRACTID, &kNOTIFICATIONTELEMETRYSERVICE_CID },
#ifndef MOZ_SIMPLEPUSH
{ PUSHNOTIFIER_CONTRACTID, &kPUSHNOTIFIER_CID },
#endif
{ WORKERDEBUGGERMANAGER_CONTRACTID, &kWORKERDEBUGGERMANAGER_CID }, { WORKERDEBUGGERMANAGER_CONTRACTID, &kWORKERDEBUGGERMANAGER_CID },
#ifdef MOZ_WIDGET_GONK #ifdef MOZ_WIDGET_GONK
{ SYSTEMWORKERMANAGER_CONTRACTID, &kSYSTEMWORKERMANAGER_CID }, { SYSTEMWORKERMANAGER_CONTRACTID, &kSYSTEMWORKERMANAGER_CID },
@ -1357,9 +1338,6 @@ static const mozilla::Module::CategoryEntry kLayoutCategories[] = {
{ "net-channel-event-sinks", "CSPService", CSPSERVICE_CONTRACTID }, { "net-channel-event-sinks", "CSPService", CSPSERVICE_CONTRACTID },
{ "net-channel-event-sinks", NS_MIXEDCONTENTBLOCKER_CONTRACTID, NS_MIXEDCONTENTBLOCKER_CONTRACTID }, { "net-channel-event-sinks", NS_MIXEDCONTENTBLOCKER_CONTRACTID, NS_MIXEDCONTENTBLOCKER_CONTRACTID },
{ "app-startup", "Script Security Manager", "service," NS_SCRIPTSECURITYMANAGER_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 }, { TOPIC_WEB_APP_CLEAR_DATA, "QuotaManagerService", "service," QUOTAMANAGER_SERVICE_CONTRACTID },
{ OBSERVER_TOPIC_IDLE_DAILY, "QuotaManagerService", QUOTAMANAGER_SERVICE_CONTRACTID }, { OBSERVER_TOPIC_IDLE_DAILY, "QuotaManagerService", QUOTAMANAGER_SERVICE_CONTRACTID },
#ifdef MOZ_WIDGET_GONK #ifdef MOZ_WIDGET_GONK

View File

@ -10,3 +10,6 @@ var { classes: Cc, interfaces: Ci, utils: Cu } = Components;
// and for those that match URLs provided by the parent process will set up // and for those that match URLs provided by the parent process will set up
// a dedicated message port and notify the parent process. // a dedicated message port and notify the parent process.
Cu.import("resource://gre/modules/RemotePageManager.jsm"); Cu.import("resource://gre/modules/RemotePageManager.jsm");
// Hooks to listen for push messages
Cu.import("resource://gre/modules/PushServiceChildPreload.jsm");