зеркало из https://github.com/mozilla/gecko-dev.git
Back out out 3 changesets (bug 1239584) for B2G build failures on a CLOSED TREE.
--HG-- extra : commitid : 74RywJW7UVo extra : amend_source : 2088096e01cb7b6fda50c87f05d427cd79147554
This commit is contained in:
Родитель
8f99cd782f
Коммит
f398300afc
|
@ -5,7 +5,7 @@
|
|||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
XPIDL_SOURCES += [
|
||||
'nsIPushNotifier.idl',
|
||||
'nsIPushObserverNotification.idl',
|
||||
'nsIPushService.idl',
|
||||
]
|
||||
|
||||
|
|
|
@ -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);
|
||||
};
|
|
@ -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;
|
||||
};
|
|
@ -81,8 +81,9 @@ interface nsIPushService : nsISupports
|
|||
* The |endpoint| property of the subscription record is a URL string
|
||||
* that can be used to send push messages to subscribers.
|
||||
*
|
||||
* Each incoming message fires a `push-message` observer notification, with
|
||||
* an `nsIPushMessage` as the subject and the |scope| as the data.
|
||||
* Each incoming message fires a `push-notification` observer
|
||||
* notification, with an `nsIPushObserverNotification` as the subject and
|
||||
* the |scope| as the data.
|
||||
*
|
||||
* 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|.
|
||||
|
|
|
@ -175,7 +175,6 @@
|
|||
#include "mozilla/dom/PFMRadioChild.h"
|
||||
#include "mozilla/dom/PPresentationChild.h"
|
||||
#include "mozilla/dom/PresentationIPCService.h"
|
||||
#include "mozilla/dom/PushNotifier.h"
|
||||
#include "mozilla/ipc/InputStreamUtils.h"
|
||||
|
||||
#ifdef MOZ_WEBSPEECH
|
||||
|
@ -3218,56 +3217,5 @@ ContentChild::RecvTestGraphicsDeviceReset(const uint32_t& aResetReason)
|
|||
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 mozilla
|
||||
|
|
|
@ -526,19 +526,6 @@ 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
|
||||
|
|
|
@ -728,21 +728,6 @@ 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
|
||||
|
|
|
@ -6,3 +6,6 @@ contract @mozilla.org/push/PushManager;1 {cde1d019-fad8-4044-b141-65fb4fb7a245}
|
|||
component {daaa8d73-677e-4233-8acd-2c404bd01658} PushComponents.js
|
||||
contract @mozilla.org/push/Service;1 {daaa8d73-677e-4233-8acd-2c404bd01658}
|
||||
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}
|
||||
|
|
|
@ -106,8 +106,10 @@ Object.assign(PushServiceParent.prototype, {
|
|||
"Push:Registration",
|
||||
"Push:Unregister",
|
||||
"Push:Clear",
|
||||
"Push:RegisterEventNotificationListener",
|
||||
"Push:NotificationForOriginShown",
|
||||
"Push:NotificationForOriginClosed",
|
||||
"child-process-shutdown",
|
||||
],
|
||||
|
||||
// nsIPushService methods
|
||||
|
@ -167,6 +169,14 @@ Object.assign(PushServiceParent.prototype, {
|
|||
return;
|
||||
}
|
||||
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") {
|
||||
this.notificationForOriginShown(data);
|
||||
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([
|
||||
PushObserverNotification,
|
||||
|
||||
// Export the correct implementation depending on whether we're running in
|
||||
// the parent or content process.
|
||||
isParent ? PushServiceParent : PushServiceContent,
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -31,10 +31,6 @@ XPCOMUtils.defineLazyServiceGetter(this, "gContentSecurityManager",
|
|||
"@mozilla.org/contentsecuritymanager;1",
|
||||
"nsIContentSecurityManager");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "gPushNotifier",
|
||||
"@mozilla.org/push/Notifier;1",
|
||||
"nsIPushNotifier");
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["PushService"];
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "console", () => {
|
||||
|
@ -103,6 +99,8 @@ this.PushService = {
|
|||
// reduce the quota for a record. Used for testing purposes.
|
||||
_updateQuotaTestCallback: null,
|
||||
|
||||
_childListeners: new Set(),
|
||||
|
||||
// When serverURI changes (this is used for testing), db is cleaned up and a
|
||||
// a new db is started. This events must be sequential.
|
||||
_stateChangeProcessQueue: null,
|
||||
|
@ -594,6 +592,8 @@ this.PushService = {
|
|||
uninit: function() {
|
||||
console.debug("uninit()");
|
||||
|
||||
this._childListeners.clear();
|
||||
|
||||
if (this._state == PUSH_SERVICE_UNINIT) {
|
||||
return;
|
||||
}
|
||||
|
@ -688,8 +688,38 @@ this.PushService = {
|
|||
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();
|
||||
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);
|
||||
// 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 (!aPushRecord.hasPermission()) {
|
||||
|
@ -936,22 +989,14 @@ this.PushService = {
|
|||
return false;
|
||||
}
|
||||
|
||||
let payload = ArrayBuffer.isView(message) ?
|
||||
new Uint8Array(message.buffer) : message;
|
||||
|
||||
if (aPushRecord.quotaApplies()) {
|
||||
// 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);
|
||||
}
|
||||
let data = {
|
||||
payload: payload,
|
||||
originAttributes: aPushRecord.originAttributes,
|
||||
scope: aPushRecord.scope
|
||||
};
|
||||
|
||||
Services.telemetry.getHistogramById("PUSH_API_NOTIFY").add();
|
||||
this._notifyListeners('push', data);
|
||||
return true;
|
||||
},
|
||||
|
||||
|
@ -1041,7 +1086,14 @@ this.PushService = {
|
|||
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();
|
||||
},
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -14,6 +14,7 @@ EXTRA_JS_MODULES += [
|
|||
'PushDB.jsm',
|
||||
'PushRecord.jsm',
|
||||
'PushService.jsm',
|
||||
'PushServiceChildPreload.jsm',
|
||||
'PushServiceHttp2.jsm',
|
||||
'PushServiceWebSocket.jsm',
|
||||
]
|
||||
|
@ -28,22 +29,16 @@ 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',
|
||||
]
|
||||
|
||||
|
|
|
@ -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
|
||||
* `dom.push.`; any additional preferences will override the defaults.
|
||||
|
@ -204,8 +221,6 @@ function setPrefs(prefs = {}) {
|
|||
'http2.reset_retry_count_after_ms': 60000,
|
||||
maxQuotaPerSubscription: 16,
|
||||
quotaUpdateDelay: 3000,
|
||||
'testing.notifyWorkers': false,
|
||||
'testing.notifyAllObservers': true,
|
||||
}, prefs);
|
||||
for (let pref in defaultPrefs) {
|
||||
servicePrefs.set(pref, defaultPrefs[pref]);
|
||||
|
|
|
@ -41,6 +41,9 @@ function run_test() {
|
|||
requestTimeout: 1000,
|
||||
retryBaseInterval: 150
|
||||
});
|
||||
disableServiceWorkerEvents(
|
||||
'https://example.org/1'
|
||||
);
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,11 @@ var userAgentID = '5ab1d1df-7a3d-4024-a469-b9e1bb399fad';
|
|||
function run_test() {
|
||||
do_get_profile();
|
||||
setPrefs({userAgentID});
|
||||
disableServiceWorkerEvents(
|
||||
'https://example.org/1',
|
||||
'https://example.org/2',
|
||||
'https://example.org/3'
|
||||
);
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
|
@ -45,9 +50,11 @@ add_task(function* test_notification_ack() {
|
|||
yield db.put(record);
|
||||
}
|
||||
|
||||
let notifyCount = 0;
|
||||
let notifyPromise = promiseObserverNotification('push-message', () =>
|
||||
++notifyCount == 3);
|
||||
let notifyPromise = Promise.all([
|
||||
promiseObserverNotification('push-notification'),
|
||||
promiseObserverNotification('push-notification'),
|
||||
promiseObserverNotification('push-notification')
|
||||
]);
|
||||
|
||||
let acks = 0;
|
||||
let ackDone;
|
||||
|
|
|
@ -218,9 +218,9 @@ add_task(function* test_notification_ack_data() {
|
|||
];
|
||||
|
||||
let sendAndReceive = testData => {
|
||||
let messageReceived = promiseObserverNotification('push-message', (subject, data) => {
|
||||
let notification = subject.QueryInterface(Ci.nsIPushMessage);
|
||||
equal(notification.text(), testData.receive.data,
|
||||
let messageReceived = promiseObserverNotification('push-notification', (subject, data) => {
|
||||
let notification = subject.QueryInterface(Ci.nsIPushObserverNotification);
|
||||
equal(notification.data, testData.receive.data,
|
||||
'Check data for notification ' + testData.version);
|
||||
equal(data, testData.receive.scope,
|
||||
'Check scope for notification ' + testData.version);
|
||||
|
|
|
@ -12,6 +12,10 @@ function run_test() {
|
|||
setPrefs({
|
||||
userAgentID: userAgentID,
|
||||
});
|
||||
disableServiceWorkerEvents(
|
||||
'https://example.com/1',
|
||||
'https://example.com/2'
|
||||
);
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
|
@ -40,7 +44,7 @@ add_task(function* test_notification_duplicate() {
|
|||
yield db.put(record);
|
||||
}
|
||||
|
||||
let notifyPromise = promiseObserverNotification('push-message');
|
||||
let notifyPromise = promiseObserverNotification('push-notification');
|
||||
|
||||
let acks = 0;
|
||||
let ackDone;
|
||||
|
|
|
@ -12,6 +12,11 @@ function run_test() {
|
|||
setPrefs({
|
||||
userAgentID: userAgentID,
|
||||
});
|
||||
disableServiceWorkerEvents(
|
||||
'https://example.com/a',
|
||||
'https://example.com/b',
|
||||
'https://example.com/c'
|
||||
);
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
|
@ -49,9 +54,16 @@ add_task(function* test_notification_error() {
|
|||
yield db.put(record);
|
||||
}
|
||||
|
||||
let scopes = [];
|
||||
let notifyPromise = promiseObserverNotification('push-message', (subject, data) =>
|
||||
scopes.push(data) == 2);
|
||||
let notifyPromise = Promise.all([
|
||||
promiseObserverNotification(
|
||||
'push-notification',
|
||||
(subject, data) => data == 'https://example.com/a'
|
||||
),
|
||||
promiseObserverNotification(
|
||||
'push-notification',
|
||||
(subject, data) => data == 'https://example.com/c'
|
||||
)
|
||||
]);
|
||||
|
||||
let ackDone;
|
||||
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,
|
||||
DEFAULT_TIMEOUT,
|
||||
'Timed out waiting for notifications'
|
||||
);
|
||||
ok(scopes.includes('https://example.com/a'),
|
||||
'Missing scope for notification A');
|
||||
ok(scopes.includes('https://example.com/c'),
|
||||
'Missing scope for notification C');
|
||||
let aPush = a.subject.QueryInterface(Ci.nsIPushObserverNotification);
|
||||
equal(aPush.pushEndpoint, 'https://example.org/update/success-1',
|
||||
'Wrong endpoint for notification A');
|
||||
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,
|
||||
'Timed out waiting for acknowledgements');
|
||||
|
|
|
@ -35,8 +35,11 @@ function run_test() {
|
|||
|
||||
prefs.setIntPref("network.http.speculative-parallel-limit", oldPref);
|
||||
|
||||
servicePrefs.set('testing.notifyWorkers', false);
|
||||
servicePrefs.set('testing.notifyAllObservers', true);
|
||||
disableServiceWorkerEvents(
|
||||
'https://example.com/page/1',
|
||||
'https://example.com/page/2',
|
||||
'https://example.com/page/3'
|
||||
);
|
||||
|
||||
run_next_test();
|
||||
}
|
||||
|
@ -121,24 +124,24 @@ add_task(function* test_pushNotifications() {
|
|||
}
|
||||
|
||||
let notifyPromise = Promise.all([
|
||||
promiseObserverNotification('push-message', function(subject, data) {
|
||||
var message = subject.QueryInterface(Ci.nsIPushMessage);
|
||||
if (message && (data == "https://example.com/page/1")){
|
||||
equal(message.text(), "Some message", "decoded message is incorrect");
|
||||
promiseObserverNotification('push-notification', function(subject, data) {
|
||||
var notification = subject.QueryInterface(Ci.nsIPushObserverNotification);
|
||||
if (notification && (data == "https://example.com/page/1")){
|
||||
equal(subject.data, "Some message", "decoded message is incorrect");
|
||||
return true;
|
||||
}
|
||||
}),
|
||||
promiseObserverNotification('push-message', function(subject, data) {
|
||||
var message = subject.QueryInterface(Ci.nsIPushMessage);
|
||||
if (message && (data == "https://example.com/page/2")){
|
||||
equal(message.text(), "Some message", "decoded message is incorrect");
|
||||
promiseObserverNotification('push-notification', function(subject, data) {
|
||||
var notification = subject.QueryInterface(Ci.nsIPushObserverNotification);
|
||||
if (notification && (data == "https://example.com/page/2")){
|
||||
equal(subject.data, "Some message", "decoded message is incorrect");
|
||||
return true;
|
||||
}
|
||||
}),
|
||||
promiseObserverNotification('push-message', function(subject, data) {
|
||||
var message = subject.QueryInterface(Ci.nsIPushMessage);
|
||||
if (message && (data == "https://example.com/page/3")){
|
||||
equal(message.text(), "Some message", "decoded message is incorrect");
|
||||
promiseObserverNotification('push-notification', function(subject, data) {
|
||||
var notification = subject.QueryInterface(Ci.nsIPushObserverNotification);
|
||||
if (notification && (data == "https://example.com/page/3")){
|
||||
equal(subject.data, "Some message", "decoded message is incorrect");
|
||||
return true;
|
||||
}
|
||||
})
|
||||
|
|
|
@ -12,6 +12,12 @@ function run_test() {
|
|||
setPrefs({
|
||||
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();
|
||||
}
|
||||
|
||||
|
@ -51,12 +57,9 @@ add_task(function* test_notification_incomplete() {
|
|||
yield db.put(record);
|
||||
}
|
||||
|
||||
function observeMessage(subject, topic, data) {
|
||||
Services.obs.addObserver(function observe(subject, topic, data) {
|
||||
ok(false, 'Should not deliver malformed updates');
|
||||
}
|
||||
do_register_cleanup(() =>
|
||||
Services.obs.removeObserver(observeMessage, 'push-message'));
|
||||
Services.obs.addObserver(observeMessage, 'push-message', false);
|
||||
}, 'push-notification', false);
|
||||
|
||||
let notificationDone;
|
||||
let notificationPromise = new Promise(resolve => notificationDone = after(2, resolve));
|
||||
|
|
|
@ -12,6 +12,9 @@ function run_test() {
|
|||
setPrefs({
|
||||
userAgentID: userAgentID,
|
||||
});
|
||||
disableServiceWorkerEvents(
|
||||
'https://example.net/case'
|
||||
);
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
|
@ -28,7 +31,7 @@ add_task(function* test_notification_version_string() {
|
|||
systemRecord: true,
|
||||
});
|
||||
|
||||
let notifyPromise = promiseObserverNotification('push-message');
|
||||
let notifyPromise = promiseObserverNotification('push-notification');
|
||||
|
||||
let ackDone;
|
||||
let ackPromise = new Promise(resolve => ackDone = resolve);
|
||||
|
@ -62,7 +65,11 @@ add_task(function* test_notification_version_string() {
|
|||
DEFAULT_TIMEOUT,
|
||||
'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,
|
||||
'Timed out waiting for string acknowledgement');
|
||||
|
|
|
@ -82,7 +82,7 @@ add_task(function* test_expiration_origin_threshold() {
|
|||
// different scopes, so each can send 5 notifications before we remove
|
||||
// their subscription.
|
||||
let updates = 0;
|
||||
let notifyPromise = promiseObserverNotification('push-message', (subject, data) => {
|
||||
let notifyPromise = promiseObserverNotification('push-notification', (subject, data) => {
|
||||
updates++;
|
||||
return updates == 6;
|
||||
});
|
||||
|
|
|
@ -55,7 +55,7 @@ add_task(function* test_expiration_origin_threshold() {
|
|||
let numMessages = 10;
|
||||
|
||||
let updates = 0;
|
||||
let notifyPromise = promiseObserverNotification('push-message', (subject, data) => {
|
||||
let notifyPromise = promiseObserverNotification('push-notification', (subject, data) => {
|
||||
updates++;
|
||||
return updates == numMessages;
|
||||
});
|
||||
|
|
|
@ -56,6 +56,9 @@ function run_test() {
|
|||
'http2.retryInterval': 1000,
|
||||
'http2.maxRetries': 2
|
||||
});
|
||||
disableServiceWorkerEvents(
|
||||
'https://example.com/retry5xxCode'
|
||||
);
|
||||
|
||||
run_next_test();
|
||||
}
|
||||
|
|
|
@ -10,6 +10,9 @@ const userAgentID = '1760b1f5-c3ba-40e3-9344-adef7c18ab12';
|
|||
function run_test() {
|
||||
do_get_profile();
|
||||
setPrefs();
|
||||
disableServiceWorkerEvents(
|
||||
'https://example.net/case'
|
||||
);
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
|
|
|
@ -23,6 +23,10 @@ function run_test() {
|
|||
|
||||
tlsProfile = prefs.getBoolPref("network.http.spdy.enforce-tls-profile");
|
||||
|
||||
disableServiceWorkerEvents(
|
||||
'https://example.net/page/invalid-response'
|
||||
);
|
||||
|
||||
serverURL = "https://localhost:" + serverPort;
|
||||
|
||||
run_next_test();
|
||||
|
|
|
@ -15,6 +15,10 @@ function run_test() {
|
|||
requestTimeout: 1000,
|
||||
retryBaseInterval: 150
|
||||
});
|
||||
disableServiceWorkerEvents(
|
||||
'https://example.com/page/1',
|
||||
'https://example.com/page/2'
|
||||
);
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
|
@ -32,7 +36,7 @@ add_task(function* test_register_flush() {
|
|||
};
|
||||
yield db.put(record);
|
||||
|
||||
let notifyPromise = promiseObserverNotification('push-message');
|
||||
let notifyPromise = promiseObserverNotification('push-notification');
|
||||
|
||||
let ackDone;
|
||||
let ackPromise = new Promise(resolve => ackDone = after(2, resolve));
|
||||
|
|
|
@ -11,6 +11,9 @@ const channelID = 'cafed00d';
|
|||
function run_test() {
|
||||
do_get_profile();
|
||||
setPrefs();
|
||||
disableServiceWorkerEvents(
|
||||
'https://example.com/invalid-channel'
|
||||
);
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,9 @@ const channelID = 'c0660af8-b532-4931-81f0-9fd27a12d6ab';
|
|||
function run_test() {
|
||||
do_get_profile();
|
||||
setPrefs();
|
||||
disableServiceWorkerEvents(
|
||||
'https://example.net/page/invalid-endpoint'
|
||||
);
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
|
|
|
@ -14,6 +14,9 @@ function run_test() {
|
|||
requestTimeout: 1000,
|
||||
retryBaseInterval: 150
|
||||
});
|
||||
disableServiceWorkerEvents(
|
||||
'https://example.net/page/invalid-json'
|
||||
);
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,9 @@ function run_test() {
|
|||
requestTimeout: 1000,
|
||||
retryBaseInterval: 150
|
||||
});
|
||||
disableServiceWorkerEvents(
|
||||
'https://example.com/incomplete'
|
||||
);
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,9 @@ function run_test() {
|
|||
requestTimeout: 1000,
|
||||
retryBaseInterval: 150
|
||||
});
|
||||
disableServiceWorkerEvents(
|
||||
'https://example.com/page/1'
|
||||
);
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,9 @@ function run_test() {
|
|||
requestTimeout: 1000,
|
||||
retryBaseInterval: 150
|
||||
});
|
||||
disableServiceWorkerEvents(
|
||||
'https://example.com/storage-error'
|
||||
);
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,9 @@ function run_test() {
|
|||
requestTimeout: 1000,
|
||||
retryBaseInterval: 150
|
||||
});
|
||||
disableServiceWorkerEvents(
|
||||
'https://example.org/1'
|
||||
);
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
|
|
|
@ -37,6 +37,11 @@ function run_test() {
|
|||
|
||||
serverURL = "https://localhost:" + serverPort;
|
||||
|
||||
disableServiceWorkerEvents(
|
||||
'https://example.org/1',
|
||||
'https://example.org/no_receiptEndpoint'
|
||||
);
|
||||
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
|
|
|
@ -14,6 +14,9 @@ function run_test() {
|
|||
requestTimeout: 1000,
|
||||
retryBaseInterval: 150
|
||||
});
|
||||
disableServiceWorkerEvents(
|
||||
'https://example.net/page/timeout'
|
||||
);
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,9 @@ function run_test() {
|
|||
requestTimeout: 1000,
|
||||
retryBaseInterval: 150
|
||||
});
|
||||
disableServiceWorkerEvents(
|
||||
'https://example.com/mismatched'
|
||||
);
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
|
|
|
@ -13,6 +13,9 @@ function run_test() {
|
|||
requestTimeout: 1000,
|
||||
retryBaseInterval: 150
|
||||
});
|
||||
disableServiceWorkerEvents(
|
||||
'https://example.com/mistyped'
|
||||
);
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,12 @@ function run_test() {
|
|||
do_get_profile();
|
||||
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();
|
||||
}
|
||||
|
||||
|
|
|
@ -48,8 +48,9 @@ function run_test() {
|
|||
|
||||
do_get_profile();
|
||||
|
||||
servicePrefs.set('testing.notifyWorkers', false);
|
||||
servicePrefs.set('testing.notifyAllObservers', true);
|
||||
disableServiceWorkerEvents(
|
||||
'https://example.com/page'
|
||||
);
|
||||
|
||||
run_next_test();
|
||||
}
|
||||
|
|
|
@ -56,6 +56,9 @@ function run_test() {
|
|||
'http2.retryInterval': 1000,
|
||||
'http2.maxRetries': 2
|
||||
});
|
||||
disableServiceWorkerEvents(
|
||||
'https://example.com/page'
|
||||
);
|
||||
|
||||
run_next_test();
|
||||
}
|
||||
|
|
|
@ -44,6 +44,9 @@ function run_test() {
|
|||
'http2.retryInterval': 1000,
|
||||
'http2.maxRetries': 2
|
||||
});
|
||||
disableServiceWorkerEvents(
|
||||
'https://example.com/page'
|
||||
);
|
||||
|
||||
run_next_test();
|
||||
}
|
||||
|
|
|
@ -34,6 +34,10 @@ function run_test() {
|
|||
|
||||
prefs.setIntPref("network.http.speculative-parallel-limit", oldPref);
|
||||
|
||||
disableServiceWorkerEvents(
|
||||
'https://example.com/page/unregister-success'
|
||||
);
|
||||
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
|
|
|
@ -32,6 +32,9 @@ function run_test() {
|
|||
'http2.retryInterval': 1000,
|
||||
'http2.maxRetries': 2
|
||||
});
|
||||
disableServiceWorkerEvents(
|
||||
'https://example.com/page'
|
||||
);
|
||||
|
||||
run_next_test();
|
||||
}
|
||||
|
|
|
@ -12,6 +12,11 @@ function run_test() {
|
|||
setPrefs({
|
||||
userAgentID,
|
||||
});
|
||||
disableServiceWorkerEvents(
|
||||
'https://example.com/page/1',
|
||||
'https://example.com/page/2',
|
||||
'https://example.com/page/3'
|
||||
);
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
|
|
|
@ -2201,22 +2201,6 @@ 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;
|
||||
|
@ -2234,7 +2218,16 @@ ServiceWorkerManager::SendPushEvent(const nsACString& aOriginAttributes,
|
|||
RefPtr<ServiceWorkerRegistrationInfo> registration =
|
||||
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
|
||||
}
|
||||
|
||||
|
|
|
@ -41,7 +41,6 @@ class PrincipalOriginAttributes;
|
|||
namespace dom {
|
||||
|
||||
class ServiceWorkerRegistrationListener;
|
||||
class PushNotifier;
|
||||
|
||||
namespace workers {
|
||||
|
||||
|
@ -334,7 +333,6 @@ class ServiceWorkerManager final
|
|||
friend class ServiceWorkerRegistrationInfo;
|
||||
friend class ServiceWorkerUnregisterJob;
|
||||
friend class UpdateTimerCallback;
|
||||
friend class mozilla::dom::PushNotifier;
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
@ -679,11 +677,6 @@ private:
|
|||
|
||||
void
|
||||
UpdateTimerFired(nsIPrincipal* aPrincipal, const nsACString& aScope);
|
||||
|
||||
nsresult
|
||||
SendPushEvent(const nsACString& aOriginAttributes,
|
||||
const nsACString& aScope,
|
||||
Maybe<nsTArray<uint8_t>> aData);
|
||||
};
|
||||
|
||||
} // namespace workers
|
||||
|
|
|
@ -88,7 +88,6 @@
|
|||
#include "mozilla/dom/workers/ServiceWorkerManager.h"
|
||||
#include "mozilla/dom/workers/WorkerDebuggerManager.h"
|
||||
#include "mozilla/dom/Notification.h"
|
||||
#include "mozilla/dom/PushNotifier.h"
|
||||
#include "mozilla/OSFileConstants.h"
|
||||
#include "mozilla/Services.h"
|
||||
|
||||
|
@ -401,11 +400,6 @@ NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsIPresentationService,
|
|||
NS_CreatePresentationService)
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(PresentationSessionTransport)
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(NotificationTelemetryService, Init)
|
||||
|
||||
#ifndef MOZ_SIMPLEPUSH
|
||||
using mozilla::dom::PushNotifier;
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(PushNotifier)
|
||||
#endif
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
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(SERVICEWORKERMANAGER_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);
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
NS_DEFINE_NAMED_CID(SYSTEMWORKERMANAGER_CID);
|
||||
|
@ -1084,9 +1071,6 @@ 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 },
|
||||
|
@ -1255,9 +1239,6 @@ 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 },
|
||||
|
@ -1357,9 +1338,6 @@ 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
|
||||
|
|
|
@ -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
|
||||
// a dedicated message port and notify the parent process.
|
||||
Cu.import("resource://gre/modules/RemotePageManager.jsm");
|
||||
|
||||
// Hooks to listen for push messages
|
||||
Cu.import("resource://gre/modules/PushServiceChildPreload.jsm");
|
||||
|
|
Загрузка…
Ссылка в новой задаче