зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1541888 - Enable ESLinting in dom/push/ r=glasserc,lina
Enable ESLinting in dom/push/ Differential Revision: https://phabricator.services.mozilla.com/D26321 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
bc581a4d5e
Коммит
1cdc04dfda
|
@ -183,7 +183,6 @@ dom/payments/**
|
|||
dom/performance/**
|
||||
dom/permission/**
|
||||
dom/promise/**
|
||||
dom/push/**
|
||||
dom/quota/**
|
||||
dom/security/test/cors/**
|
||||
dom/security/test/csp/**
|
||||
|
|
|
@ -35,13 +35,13 @@ Push.prototype = {
|
|||
|
||||
contractID: "@mozilla.org/push/PushManager;1",
|
||||
|
||||
classID : PUSH_CID,
|
||||
classID: PUSH_CID,
|
||||
|
||||
QueryInterface : ChromeUtils.generateQI([Ci.nsIDOMGlobalPropertyInitializer,
|
||||
Ci.nsISupportsWeakReference,
|
||||
Ci.nsIObserver]),
|
||||
QueryInterface: ChromeUtils.generateQI([Ci.nsIDOMGlobalPropertyInitializer,
|
||||
Ci.nsISupportsWeakReference,
|
||||
Ci.nsIObserver]),
|
||||
|
||||
init: function(win) {
|
||||
init(win) {
|
||||
console.debug("init()");
|
||||
|
||||
this._window = win;
|
||||
|
@ -53,11 +53,11 @@ Push.prototype = {
|
|||
this._topLevelPrincipal = win.top.document.nodePrincipal;
|
||||
},
|
||||
|
||||
__init: function(scope) {
|
||||
__init(scope) {
|
||||
this._scope = scope;
|
||||
},
|
||||
|
||||
askPermission: function () {
|
||||
askPermission() {
|
||||
console.debug("askPermission()");
|
||||
|
||||
let isHandlingUserInput = this._window.windowUtils.isHandlingUserInput;
|
||||
|
@ -78,7 +78,7 @@ Push.prototype = {
|
|||
});
|
||||
},
|
||||
|
||||
subscribe: function(options) {
|
||||
subscribe(options) {
|
||||
console.debug("subscribe()", this._scope);
|
||||
|
||||
return this.askPermission().then(() =>
|
||||
|
@ -102,7 +102,7 @@ Push.prototype = {
|
|||
);
|
||||
},
|
||||
|
||||
_normalizeAppServerKey: function(appServerKey) {
|
||||
_normalizeAppServerKey(appServerKey) {
|
||||
let key;
|
||||
if (typeof appServerKey == "string") {
|
||||
try {
|
||||
|
@ -124,7 +124,7 @@ Push.prototype = {
|
|||
return new this._window.Uint8Array(key);
|
||||
},
|
||||
|
||||
getSubscription: function() {
|
||||
getSubscription() {
|
||||
console.debug("getSubscription()", this._scope);
|
||||
|
||||
return this.createPromise((resolve, reject) => {
|
||||
|
@ -133,7 +133,7 @@ Push.prototype = {
|
|||
});
|
||||
},
|
||||
|
||||
permissionState: function() {
|
||||
permissionState() {
|
||||
console.debug("permissionState()", this._scope);
|
||||
|
||||
return this.createPromise((resolve, reject) => {
|
||||
|
@ -141,7 +141,7 @@ Push.prototype = {
|
|||
|
||||
try {
|
||||
permission = this._testPermission();
|
||||
} catch(e) {
|
||||
} catch (e) {
|
||||
reject();
|
||||
return;
|
||||
}
|
||||
|
@ -156,7 +156,7 @@ Push.prototype = {
|
|||
});
|
||||
},
|
||||
|
||||
_testPermission: function() {
|
||||
_testPermission() {
|
||||
let permission = Services.perms.testExactPermissionFromPrincipal(
|
||||
this._principal, "desktop-notification");
|
||||
if (permission == Ci.nsIPermissionManager.ALLOW_ACTION) {
|
||||
|
@ -170,7 +170,7 @@ Push.prototype = {
|
|||
return permission;
|
||||
},
|
||||
|
||||
_requestPermission: function(isHandlingUserInput, allowCallback, cancelCallback) {
|
||||
_requestPermission(isHandlingUserInput, allowCallback, cancelCallback) {
|
||||
// Create an array with a single nsIContentPermissionType element.
|
||||
let type = {
|
||||
type: "desktop-notification",
|
||||
|
@ -208,7 +208,7 @@ function PushSubscriptionCallback(pushManager, resolve, reject) {
|
|||
PushSubscriptionCallback.prototype = {
|
||||
QueryInterface: ChromeUtils.generateQI([Ci.nsIPushSubscriptionCallback]),
|
||||
|
||||
onPushSubscription: function(ok, subscription) {
|
||||
onPushSubscription(ok, subscription) {
|
||||
let {pushManager} = this;
|
||||
if (!Components.isSuccessCode(ok)) {
|
||||
this._rejectWithError(ok);
|
||||
|
@ -225,8 +225,8 @@ PushSubscriptionCallback.prototype = {
|
|||
let options = {
|
||||
endpoint: subscription.endpoint,
|
||||
scope: pushManager._scope,
|
||||
p256dhKey: p256dhKey,
|
||||
authSecret: authSecret,
|
||||
p256dhKey,
|
||||
authSecret,
|
||||
};
|
||||
let appServerKey = this._getKey(subscription, "appServer");
|
||||
if (appServerKey) {
|
||||
|
@ -237,7 +237,7 @@ PushSubscriptionCallback.prototype = {
|
|||
this.resolve(sub);
|
||||
},
|
||||
|
||||
_getKey: function(subscription, name) {
|
||||
_getKey(subscription, name) {
|
||||
let outKeyLen = {};
|
||||
let rawKey = Cu.cloneInto(subscription.getKey(name, outKeyLen),
|
||||
this.pushManager._window);
|
||||
|
@ -251,7 +251,7 @@ PushSubscriptionCallback.prototype = {
|
|||
return key;
|
||||
},
|
||||
|
||||
_rejectWithError: function(result) {
|
||||
_rejectWithError(result) {
|
||||
let error;
|
||||
switch (result) {
|
||||
case Cr.NS_ERROR_DOM_PUSH_INVALID_KEY_ERR:
|
||||
|
@ -278,4 +278,4 @@ PushSubscriptionCallback.prototype = {
|
|||
},
|
||||
};
|
||||
|
||||
var EXPORTED_SYMBOLS = ["Push"];
|
||||
const EXPORTED_SYMBOLS = ["Push"];
|
||||
|
|
|
@ -9,7 +9,7 @@ const {OS} = ChromeUtils.import("resource://gre/modules/osfile.jsm");
|
|||
const {XPCOMUtils} = ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
ChromeUtils.defineModuleGetter(this, "JSONFile", "resource://gre/modules/JSONFile.jsm");
|
||||
|
||||
var EXPORTED_SYMBOLS = ["pushBroadcastService"];
|
||||
const EXPORTED_SYMBOLS = ["pushBroadcastService"];
|
||||
|
||||
// We are supposed to ignore any updates with this version.
|
||||
const DUMMY_VERSION_STRING = "____NOP____";
|
||||
|
@ -26,7 +26,7 @@ ChromeUtils.defineModuleGetter(this, "PushService", "resource://gre/modules/Push
|
|||
class InvalidSourceInfo extends Error {
|
||||
constructor(message) {
|
||||
super(message);
|
||||
this.name = 'InvalidSourceInfo';
|
||||
this.name = "InvalidSourceInfo";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -177,7 +177,7 @@ var BroadcastService = class {
|
|||
|
||||
if (!module[symbolName]) {
|
||||
console.error("receivedBroadcastMessage: couldn't invoke", broadcastId,
|
||||
"because module", moduleName, "missing attribute", symbolName);
|
||||
"because module", moduleURI, "missing attribute", symbolName);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -214,7 +214,7 @@ var BroadcastService = class {
|
|||
_saveImmediately() {
|
||||
return this.jsonFile._save();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function initializeBroadcastService() {
|
||||
// Fallback path for xpcshell tests.
|
||||
|
@ -224,6 +224,6 @@ function initializeBroadcastService() {
|
|||
path = OS.Path.join(OS.Constants.Path.profileDir, path);
|
||||
}
|
||||
return new BroadcastService(PushService, path);
|
||||
};
|
||||
}
|
||||
|
||||
var pushBroadcastService = initializeBroadcastService();
|
||||
|
|
|
@ -89,7 +89,6 @@ PushServiceBase.prototype = {
|
|||
if (topic === "android-push-service") {
|
||||
// Load PushService immediately.
|
||||
this._handleReady();
|
||||
return;
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -147,7 +146,7 @@ Object.assign(PushServiceParent.prototype, {
|
|||
|
||||
subscribeWithKey(scope, principal, keyLen, key, callback) {
|
||||
this._handleRequest("Push:Register", principal, {
|
||||
scope: scope,
|
||||
scope,
|
||||
appServerKey: key,
|
||||
}).then(result => {
|
||||
this._deliverSubscription(callback, result);
|
||||
|
@ -158,7 +157,7 @@ Object.assign(PushServiceParent.prototype, {
|
|||
|
||||
unsubscribe(scope, principal, callback) {
|
||||
this._handleRequest("Push:Unregister", principal, {
|
||||
scope: scope,
|
||||
scope,
|
||||
}).then(result => {
|
||||
callback.onUnsubscribe(Cr.NS_OK, result);
|
||||
}, error => {
|
||||
|
@ -168,7 +167,7 @@ Object.assign(PushServiceParent.prototype, {
|
|||
|
||||
getSubscription(scope, principal, callback) {
|
||||
return this._handleRequest("Push:Registration", principal, {
|
||||
scope: scope,
|
||||
scope,
|
||||
}).then(result => {
|
||||
this._deliverSubscription(callback, result);
|
||||
}, error => {
|
||||
|
@ -178,7 +177,7 @@ Object.assign(PushServiceParent.prototype, {
|
|||
|
||||
clearForDomain(domain, callback) {
|
||||
return this._handleRequest("Push:Clear", null, {
|
||||
domain: domain,
|
||||
domain,
|
||||
}).then(result => {
|
||||
callback.onClear(Cr.NS_OK);
|
||||
}, error => {
|
||||
|
@ -219,10 +218,10 @@ Object.assign(PushServiceParent.prototype, {
|
|||
this.reportDeliveryError(data.messageId, data.reason);
|
||||
return;
|
||||
}
|
||||
return this._handleRequest(name, principal, data).then(result => {
|
||||
this._handleRequest(name, principal, data).then(result => {
|
||||
target.sendAsyncMessage(this._getResponseName(name, "OK"), {
|
||||
requestID: data.requestID,
|
||||
result: result
|
||||
result,
|
||||
});
|
||||
}, error => {
|
||||
target.sendAsyncMessage(this._getResponseName(name, "KO"), {
|
||||
|
@ -353,35 +352,35 @@ Object.assign(PushServiceContent.prototype, {
|
|||
},
|
||||
|
||||
subscribeWithKey(scope, principal, keyLen, key, callback) {
|
||||
let requestId = this._addRequest(callback);
|
||||
let requestID = this._addRequest(callback);
|
||||
this._mm.sendAsyncMessage("Push:Register", {
|
||||
scope: scope,
|
||||
scope,
|
||||
appServerKey: key,
|
||||
requestID: requestId,
|
||||
requestID,
|
||||
}, null, principal);
|
||||
},
|
||||
|
||||
unsubscribe(scope, principal, callback) {
|
||||
let requestId = this._addRequest(callback);
|
||||
let requestID = this._addRequest(callback);
|
||||
this._mm.sendAsyncMessage("Push:Unregister", {
|
||||
scope: scope,
|
||||
requestID: requestId,
|
||||
scope,
|
||||
requestID,
|
||||
}, null, principal);
|
||||
},
|
||||
|
||||
getSubscription(scope, principal, callback) {
|
||||
let requestId = this._addRequest(callback);
|
||||
let requestID = this._addRequest(callback);
|
||||
this._mm.sendAsyncMessage("Push:Registration", {
|
||||
scope: scope,
|
||||
requestID: requestId,
|
||||
scope,
|
||||
requestID,
|
||||
}, null, principal);
|
||||
},
|
||||
|
||||
clearForDomain(domain, callback) {
|
||||
let requestId = this._addRequest(callback);
|
||||
let requestID = this._addRequest(callback);
|
||||
this._mm.sendAsyncMessage("Push:Clear", {
|
||||
domain: domain,
|
||||
requestID: requestId,
|
||||
domain,
|
||||
requestID,
|
||||
});
|
||||
},
|
||||
|
||||
|
@ -399,8 +398,8 @@ Object.assign(PushServiceContent.prototype, {
|
|||
|
||||
reportDeliveryError(messageId, reason) {
|
||||
this._mm.sendAsyncMessage("Push:ReportError", {
|
||||
messageId: messageId,
|
||||
reason: reason,
|
||||
messageId,
|
||||
reason,
|
||||
});
|
||||
},
|
||||
|
||||
|
@ -560,4 +559,4 @@ PushSubscription.prototype = {
|
|||
// the parent or content process.
|
||||
let Service = isParent ? PushServiceParent : PushServiceContent;
|
||||
|
||||
var EXPORTED_SYMBOLS = ["Service"];
|
||||
const EXPORTED_SYMBOLS = ["Service"];
|
||||
|
|
|
@ -1,47 +1,48 @@
|
|||
/* jshint moz: true, esnext: true */
|
||||
/* 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';
|
||||
"use strict";
|
||||
|
||||
const {Services} = ChromeUtils.import('resource://gre/modules/Services.jsm');
|
||||
const {XPCOMUtils} = ChromeUtils.import('resource://gre/modules/XPCOMUtils.jsm');
|
||||
const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
const {XPCOMUtils} = ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, 'gDOMBundle', () =>
|
||||
Services.strings.createBundle('chrome://global/locale/dom/dom.properties'));
|
||||
XPCOMUtils.defineLazyGetter(this, "gDOMBundle", () =>
|
||||
Services.strings.createBundle("chrome://global/locale/dom/dom.properties"));
|
||||
|
||||
XPCOMUtils.defineLazyGlobalGetters(this, ['crypto']);
|
||||
XPCOMUtils.defineLazyGlobalGetters(this, ["crypto"]);
|
||||
|
||||
var EXPORTED_SYMBOLS = ['PushCrypto', 'concatArray'];
|
||||
const EXPORTED_SYMBOLS = ["PushCrypto", "concatArray"];
|
||||
|
||||
var UTF8 = new TextEncoder('utf-8');
|
||||
const UTF8 = new TextEncoder("utf-8");
|
||||
|
||||
var ECDH_KEY = { name: 'ECDH', namedCurve: 'P-256' };
|
||||
var ECDSA_KEY = { name: 'ECDSA', namedCurve: 'P-256' };
|
||||
const ECDH_KEY = { name: "ECDH", namedCurve: "P-256" };
|
||||
const ECDSA_KEY = { name: "ECDSA", namedCurve: "P-256" };
|
||||
const HMAC_SHA256 = { name: "HMAC", hash: "SHA-256" };
|
||||
const NONCE_INFO = UTF8.encode("Content-Encoding: nonce");
|
||||
|
||||
// A default keyid with a name that won't conflict with a real keyid.
|
||||
var DEFAULT_KEYID = '';
|
||||
const DEFAULT_KEYID = "";
|
||||
|
||||
/** Localized error property names. */
|
||||
|
||||
// `Encryption` header missing or malformed.
|
||||
const BAD_ENCRYPTION_HEADER = 'PushMessageBadEncryptionHeader';
|
||||
const BAD_ENCRYPTION_HEADER = "PushMessageBadEncryptionHeader";
|
||||
// `Crypto-Key` or legacy `Encryption-Key` header missing.
|
||||
const BAD_CRYPTO_KEY_HEADER = 'PushMessageBadCryptoKeyHeader';
|
||||
const BAD_ENCRYPTION_KEY_HEADER = 'PushMessageBadEncryptionKeyHeader';
|
||||
const BAD_CRYPTO_KEY_HEADER = "PushMessageBadCryptoKeyHeader";
|
||||
const BAD_ENCRYPTION_KEY_HEADER = "PushMessageBadEncryptionKeyHeader";
|
||||
// `Content-Encoding` header missing or contains unsupported encoding.
|
||||
const BAD_ENCODING_HEADER = 'PushMessageBadEncodingHeader';
|
||||
const BAD_ENCODING_HEADER = "PushMessageBadEncodingHeader";
|
||||
// `dh` parameter of `Crypto-Key` header missing or not base64url-encoded.
|
||||
const BAD_DH_PARAM = 'PushMessageBadSenderKey';
|
||||
const BAD_DH_PARAM = "PushMessageBadSenderKey";
|
||||
// `salt` parameter of `Encryption` header missing or not base64url-encoded.
|
||||
const BAD_SALT_PARAM = 'PushMessageBadSalt';
|
||||
const BAD_SALT_PARAM = "PushMessageBadSalt";
|
||||
// `rs` parameter of `Encryption` header not a number or less than pad size.
|
||||
const BAD_RS_PARAM = 'PushMessageBadRecordSize';
|
||||
const BAD_RS_PARAM = "PushMessageBadRecordSize";
|
||||
// Invalid or insufficient padding for encrypted chunk.
|
||||
const BAD_PADDING = 'PushMessageBadPaddingError';
|
||||
const BAD_PADDING = "PushMessageBadPaddingError";
|
||||
// Generic crypto error.
|
||||
const BAD_CRYPTO = 'PushMessageBadCryptoError';
|
||||
const BAD_CRYPTO = "PushMessageBadCryptoError";
|
||||
|
||||
class CryptoError extends Error {
|
||||
/**
|
||||
|
@ -80,9 +81,9 @@ function getEncryptionKeyParams(encryptKeyField) {
|
|||
if (!encryptKeyField) {
|
||||
return null;
|
||||
}
|
||||
var params = encryptKeyField.split(',');
|
||||
var params = encryptKeyField.split(",");
|
||||
return params.reduce((m, p) => {
|
||||
var pmap = p.split(';').reduce(parseHeaderFieldParams, {});
|
||||
var pmap = p.split(";").reduce(parseHeaderFieldParams, {});
|
||||
if (pmap.keyid && pmap.dh) {
|
||||
m[pmap.keyid] = pmap.dh;
|
||||
}
|
||||
|
@ -95,34 +96,34 @@ function getEncryptionKeyParams(encryptKeyField) {
|
|||
|
||||
function getEncryptionParams(encryptField) {
|
||||
if (!encryptField) {
|
||||
throw new CryptoError('Missing encryption header',
|
||||
throw new CryptoError("Missing encryption header",
|
||||
BAD_ENCRYPTION_HEADER);
|
||||
}
|
||||
var p = encryptField.split(',', 1)[0];
|
||||
var p = encryptField.split(",", 1)[0];
|
||||
if (!p) {
|
||||
throw new CryptoError('Encryption header missing params',
|
||||
throw new CryptoError("Encryption header missing params",
|
||||
BAD_ENCRYPTION_HEADER);
|
||||
}
|
||||
return p.split(';').reduce(parseHeaderFieldParams, {});
|
||||
return p.split(";").reduce(parseHeaderFieldParams, {});
|
||||
}
|
||||
|
||||
// Extracts the sender public key, salt, and record size from the payload for the
|
||||
// aes128gcm scheme.
|
||||
function getCryptoParamsFromPayload(payload) {
|
||||
if (payload.byteLength < 21) {
|
||||
throw new CryptoError('Truncated header', BAD_CRYPTO);
|
||||
throw new CryptoError("Truncated header", BAD_CRYPTO);
|
||||
}
|
||||
let rs = (payload[16] << 24) | (payload[17] << 16) | (payload[18] << 8) | payload[19];
|
||||
let keyIdLen = payload[20];
|
||||
if (keyIdLen != 65) {
|
||||
throw new CryptoError('Invalid sender public key', BAD_DH_PARAM);
|
||||
throw new CryptoError("Invalid sender public key", BAD_DH_PARAM);
|
||||
}
|
||||
if (payload.byteLength <= 21 + keyIdLen) {
|
||||
throw new CryptoError('Truncated payload', BAD_CRYPTO);
|
||||
throw new CryptoError("Truncated payload", BAD_CRYPTO);
|
||||
}
|
||||
return {
|
||||
salt: payload.slice(0, 16),
|
||||
rs: rs,
|
||||
rs,
|
||||
senderKey: payload.slice(21, 21 + keyIdLen),
|
||||
ciphertext: payload.slice(21 + keyIdLen),
|
||||
};
|
||||
|
@ -143,7 +144,7 @@ function getCryptoParamsFromHeaders(headers) {
|
|||
// https://tools.ietf.org/html/draft-ietf-httpbis-encryption-encoding-01
|
||||
keymap = getEncryptionKeyParams(headers.crypto_key);
|
||||
if (!keymap) {
|
||||
throw new CryptoError('Missing Crypto-Key header',
|
||||
throw new CryptoError("Missing Crypto-Key header",
|
||||
BAD_CRYPTO_KEY_HEADER);
|
||||
}
|
||||
} else if (headers.encoding == AESGCM128_ENCODING) {
|
||||
|
@ -151,7 +152,7 @@ function getCryptoParamsFromHeaders(headers) {
|
|||
// https://tools.ietf.org/html/draft-thomson-http-encryption-02
|
||||
keymap = getEncryptionKeyParams(headers.encryption_key);
|
||||
if (!keymap) {
|
||||
throw new CryptoError('Missing Encryption-Key header',
|
||||
throw new CryptoError("Missing Encryption-Key header",
|
||||
BAD_ENCRYPTION_KEY_HEADER);
|
||||
}
|
||||
}
|
||||
|
@ -160,21 +161,21 @@ function getCryptoParamsFromHeaders(headers) {
|
|||
var dh = keymap[enc.keyid || DEFAULT_KEYID];
|
||||
var senderKey = base64URLDecode(dh);
|
||||
if (!senderKey) {
|
||||
throw new CryptoError('Invalid dh parameter', BAD_DH_PARAM);
|
||||
throw new CryptoError("Invalid dh parameter", BAD_DH_PARAM);
|
||||
}
|
||||
|
||||
var salt = base64URLDecode(enc.salt);
|
||||
if (!salt) {
|
||||
throw new CryptoError('Invalid salt parameter', BAD_SALT_PARAM);
|
||||
throw new CryptoError("Invalid salt parameter", BAD_SALT_PARAM);
|
||||
}
|
||||
var rs = enc.rs ? parseInt(enc.rs, 10) : 4096;
|
||||
if (isNaN(rs)) {
|
||||
throw new CryptoError('rs parameter must be a number', BAD_RS_PARAM);
|
||||
throw new CryptoError("rs parameter must be a number", BAD_RS_PARAM);
|
||||
}
|
||||
return {
|
||||
salt: salt,
|
||||
rs: rs,
|
||||
senderKey: senderKey,
|
||||
salt,
|
||||
rs,
|
||||
senderKey,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -186,19 +187,19 @@ function base64URLDecode(string) {
|
|||
try {
|
||||
return ChromeUtils.base64URLDecode(string, {
|
||||
// draft-ietf-httpbis-encryption-encoding-01 prohibits padding.
|
||||
padding: 'reject',
|
||||
padding: "reject",
|
||||
});
|
||||
} catch (ex) {}
|
||||
return null;
|
||||
}
|
||||
|
||||
var parseHeaderFieldParams = (m, v) => {
|
||||
var i = v.indexOf('=');
|
||||
var i = v.indexOf("=");
|
||||
if (i >= 0) {
|
||||
// A quoted string with internal quotes is invalid for all the possible
|
||||
// values of this header field.
|
||||
m[v.substring(0, i).trim()] = v.substring(i + 1).trim()
|
||||
.replace(/^"(.*)"$/, '$1');
|
||||
.replace(/^"(.*)"$/, "$1");
|
||||
}
|
||||
return m;
|
||||
};
|
||||
|
@ -208,7 +209,7 @@ function chunkArray(array, size) {
|
|||
array = array.buffer || array;
|
||||
var index = 0;
|
||||
var result = [];
|
||||
while(index + size <= array.byteLength) {
|
||||
while (index + size <= array.byteLength) {
|
||||
result.push(new Uint8Array(array, start + index, size));
|
||||
index += size;
|
||||
}
|
||||
|
@ -218,7 +219,7 @@ function chunkArray(array, size) {
|
|||
return result;
|
||||
}
|
||||
|
||||
var concatArray = function(arrays) {
|
||||
function concatArray(arrays) {
|
||||
var size = arrays.reduce((total, a) => total + a.byteLength, 0);
|
||||
var index = 0;
|
||||
return arrays.reduce((result, a) => {
|
||||
|
@ -226,17 +227,15 @@ var concatArray = function(arrays) {
|
|||
index += a.byteLength;
|
||||
return result;
|
||||
}, new Uint8Array(size));
|
||||
};
|
||||
|
||||
var HMAC_SHA256 = { name: 'HMAC', hash: 'SHA-256' };
|
||||
}
|
||||
|
||||
function hmac(key) {
|
||||
this.keyPromise = crypto.subtle.importKey('raw', key, HMAC_SHA256,
|
||||
false, ['sign']);
|
||||
this.keyPromise = crypto.subtle.importKey("raw", key, HMAC_SHA256,
|
||||
false, ["sign"]);
|
||||
}
|
||||
|
||||
hmac.prototype.hash = function(input) {
|
||||
return this.keyPromise.then(k => crypto.subtle.sign('HMAC', k, input));
|
||||
return this.keyPromise.then(k => crypto.subtle.sign("HMAC", k, input));
|
||||
};
|
||||
|
||||
function hkdf(salt, ikm) {
|
||||
|
@ -250,7 +249,7 @@ hkdf.prototype.extract = function(info, len) {
|
|||
.then(prkh => prkh.hash(input))
|
||||
.then(h => {
|
||||
if (h.byteLength < len) {
|
||||
throw new CryptoError('HKDF length is too long', BAD_CRYPTO);
|
||||
throw new CryptoError("HKDF length is too long", BAD_CRYPTO);
|
||||
}
|
||||
return h.slice(0, len);
|
||||
});
|
||||
|
@ -259,7 +258,7 @@ hkdf.prototype.extract = function(info, len) {
|
|||
/* generate a 96-bit nonce for use in GCM, 48-bits of which are populated */
|
||||
function generateNonce(base, index) {
|
||||
if (index >= Math.pow(2, 48)) {
|
||||
throw new CryptoError('Nonce index is too large', BAD_CRYPTO);
|
||||
throw new CryptoError("Nonce index is too large", BAD_CRYPTO);
|
||||
}
|
||||
var nonce = base.slice(0, 12);
|
||||
nonce = new Uint8Array(nonce);
|
||||
|
@ -273,8 +272,6 @@ function encodeLength(buffer) {
|
|||
return new Uint8Array([0, buffer.byteLength]);
|
||||
}
|
||||
|
||||
var NONCE_INFO = UTF8.encode('Content-Encoding: nonce');
|
||||
|
||||
class Decoder {
|
||||
/**
|
||||
* Creates a decoder for decrypting an incoming push message.
|
||||
|
@ -312,8 +309,8 @@ class Decoder {
|
|||
try {
|
||||
let ikm = await this.computeSharedSecret();
|
||||
let [gcmBits, nonce] = await this.deriveKeyAndNonce(ikm);
|
||||
let key = await crypto.subtle.importKey('raw', gcmBits, 'AES-GCM', false,
|
||||
['decrypt']);
|
||||
let key = await crypto.subtle.importKey("raw", gcmBits, "AES-GCM", false,
|
||||
["decrypt"]);
|
||||
|
||||
let r = await Promise.all(chunkArray(this.ciphertext, this.chunkSize)
|
||||
.map((slice, index, chunks) => this.decodeChunk(slice, index, nonce,
|
||||
|
@ -327,7 +324,7 @@ class Decoder {
|
|||
// Web Crypto returns an unhelpful "operation failed for an
|
||||
// operation-specific reason" error if decryption fails. We don't have
|
||||
// context about what went wrong, so we throw a generic error instead.
|
||||
throw new CryptoError('Bad encryption', BAD_CRYPTO);
|
||||
throw new CryptoError("Bad encryption", BAD_CRYPTO);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -339,12 +336,12 @@ class Decoder {
|
|||
*/
|
||||
async computeSharedSecret() {
|
||||
let [appServerKey, subscriptionPrivateKey] = await Promise.all([
|
||||
crypto.subtle.importKey('raw', this.senderKey, ECDH_KEY,
|
||||
false, ['deriveBits']),
|
||||
crypto.subtle.importKey('jwk', this.privateKey, ECDH_KEY,
|
||||
false, ['deriveBits'])
|
||||
crypto.subtle.importKey("raw", this.senderKey, ECDH_KEY,
|
||||
false, ["deriveBits"]),
|
||||
crypto.subtle.importKey("jwk", this.privateKey, ECDH_KEY,
|
||||
false, ["deriveBits"]),
|
||||
]);
|
||||
return crypto.subtle.deriveBits({ name: 'ECDH', public: appServerKey },
|
||||
return crypto.subtle.deriveBits({ name: "ECDH", public: appServerKey },
|
||||
subscriptionPrivateKey, 256);
|
||||
}
|
||||
|
||||
|
@ -355,7 +352,7 @@ class Decoder {
|
|||
* @returns {Array} A `[gcmBits, nonce]` tuple.
|
||||
*/
|
||||
async deriveKeyAndNonce(ikm) {
|
||||
throw new Error('Missing `deriveKeyAndNonce` implementation');
|
||||
throw new Error("Missing `deriveKeyAndNonce` implementation");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -371,8 +368,8 @@ class Decoder {
|
|||
*/
|
||||
async decodeChunk(slice, index, nonce, key, last) {
|
||||
let params = {
|
||||
name: 'AES-GCM',
|
||||
iv: generateNonce(nonce, index)
|
||||
name: "AES-GCM",
|
||||
iv: generateNonce(nonce, index),
|
||||
};
|
||||
let decoded = await crypto.subtle.decrypt(params, key, slice);
|
||||
return this.unpadChunk(new Uint8Array(decoded), last);
|
||||
|
@ -386,12 +383,12 @@ class Decoder {
|
|||
* @returns {Uint8Array} The block with padding removed.
|
||||
*/
|
||||
unpadChunk(chunk, last) {
|
||||
throw new Error('Missing `unpadChunk` implementation');
|
||||
throw new Error("Missing `unpadChunk` implementation");
|
||||
}
|
||||
|
||||
/** The record chunking size. */
|
||||
get chunkSize() {
|
||||
throw new Error('Missing `chunkSize` implementation');
|
||||
throw new Error("Missing `chunkSize` implementation");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -401,7 +398,7 @@ class OldSchemeDecoder extends Decoder {
|
|||
// boundary.
|
||||
if (this.ciphertext.byteLength > 0 &&
|
||||
this.ciphertext.byteLength % this.chunkSize === 0) {
|
||||
throw new CryptoError('Encrypted data truncated', BAD_CRYPTO);
|
||||
throw new CryptoError("Encrypted data truncated", BAD_CRYPTO);
|
||||
}
|
||||
return super.decode();
|
||||
}
|
||||
|
@ -412,19 +409,19 @@ class OldSchemeDecoder extends Decoder {
|
|||
*/
|
||||
unpadChunk(decoded) {
|
||||
if (decoded.length < this.padSize) {
|
||||
throw new CryptoError('Decoded array is too short!', BAD_PADDING);
|
||||
throw new CryptoError("Decoded array is too short!", BAD_PADDING);
|
||||
}
|
||||
var pad = decoded[0]
|
||||
var pad = decoded[0];
|
||||
if (this.padSize == 2) {
|
||||
pad = (pad << 8) | decoded[1];
|
||||
}
|
||||
if (pad > decoded.length - this.padSize) {
|
||||
throw new CryptoError('Padding is wrong!', BAD_PADDING);
|
||||
throw new CryptoError("Padding is wrong!", BAD_PADDING);
|
||||
}
|
||||
// All padded bytes must be zero except the first one.
|
||||
for (var i = this.padSize; i < this.padSize + pad; i++) {
|
||||
if (decoded[i] !== 0) {
|
||||
throw new CryptoError('Padding is wrong!', BAD_PADDING);
|
||||
throw new CryptoError("Padding is wrong!", BAD_PADDING);
|
||||
}
|
||||
}
|
||||
return decoded.slice(pad + this.padSize);
|
||||
|
@ -439,16 +436,16 @@ class OldSchemeDecoder extends Decoder {
|
|||
}
|
||||
|
||||
get padSize() {
|
||||
throw new Error('Missing `padSize` implementation');
|
||||
throw new Error("Missing `padSize` implementation");
|
||||
}
|
||||
}
|
||||
|
||||
/** New encryption scheme (draft-ietf-httpbis-encryption-encoding-06). */
|
||||
|
||||
var AES128GCM_ENCODING = 'aes128gcm';
|
||||
var AES128GCM_KEY_INFO = UTF8.encode('Content-Encoding: aes128gcm\0');
|
||||
var AES128GCM_AUTH_INFO = UTF8.encode('WebPush: info\0');
|
||||
var AES128GCM_NONCE_INFO = UTF8.encode('Content-Encoding: nonce\0');
|
||||
const AES128GCM_ENCODING = "aes128gcm";
|
||||
const AES128GCM_KEY_INFO = UTF8.encode("Content-Encoding: aes128gcm\0");
|
||||
const AES128GCM_AUTH_INFO = UTF8.encode("WebPush: info\0");
|
||||
const AES128GCM_NONCE_INFO = UTF8.encode("Content-Encoding: nonce\0");
|
||||
|
||||
class aes128gcmDecoder extends Decoder {
|
||||
/**
|
||||
|
@ -461,13 +458,13 @@ class aes128gcmDecoder extends Decoder {
|
|||
let authInfo = concatArray([
|
||||
AES128GCM_AUTH_INFO,
|
||||
this.publicKey,
|
||||
this.senderKey
|
||||
this.senderKey,
|
||||
]);
|
||||
let prk = await authKdf.extract(authInfo, 32);
|
||||
let prkKdf = new hkdf(this.salt, prk);
|
||||
return Promise.all([
|
||||
prkKdf.extract(AES128GCM_KEY_INFO, 16),
|
||||
prkKdf.extract(AES128GCM_NONCE_INFO, 12)
|
||||
prkKdf.extract(AES128GCM_NONCE_INFO, 12),
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -479,11 +476,11 @@ class aes128gcmDecoder extends Decoder {
|
|||
}
|
||||
let recordPad = last ? 2 : 1;
|
||||
if (decoded[length] != recordPad) {
|
||||
throw new CryptoError('Padding is wrong!', BAD_PADDING);
|
||||
throw new CryptoError("Padding is wrong!", BAD_PADDING);
|
||||
}
|
||||
return decoded.slice(0, length);
|
||||
}
|
||||
throw new CryptoError('Zero plaintext', BAD_PADDING);
|
||||
throw new CryptoError("Zero plaintext", BAD_PADDING);
|
||||
}
|
||||
|
||||
/** aes128gcm accounts for the authentication tag in the record size. */
|
||||
|
@ -494,10 +491,10 @@ class aes128gcmDecoder extends Decoder {
|
|||
|
||||
/** Older encryption scheme (draft-ietf-httpbis-encryption-encoding-01). */
|
||||
|
||||
var AESGCM_ENCODING = 'aesgcm';
|
||||
var AESGCM_KEY_INFO = UTF8.encode('Content-Encoding: aesgcm\0');
|
||||
var AESGCM_AUTH_INFO = UTF8.encode('Content-Encoding: auth\0'); // note nul-terminus
|
||||
var AESGCM_P256DH_INFO = UTF8.encode('P-256\0');
|
||||
const AESGCM_ENCODING = "aesgcm";
|
||||
const AESGCM_KEY_INFO = UTF8.encode("Content-Encoding: aesgcm\0");
|
||||
const AESGCM_AUTH_INFO = UTF8.encode("Content-Encoding: auth\0"); // note nul-terminus
|
||||
const AESGCM_P256DH_INFO = UTF8.encode("P-256\0");
|
||||
|
||||
class aesgcmDecoder extends OldSchemeDecoder {
|
||||
/**
|
||||
|
@ -516,16 +513,16 @@ class aesgcmDecoder extends OldSchemeDecoder {
|
|||
let keyInfo = concatArray([
|
||||
AESGCM_KEY_INFO, AESGCM_P256DH_INFO,
|
||||
encodeLength(this.publicKey), this.publicKey,
|
||||
encodeLength(this.senderKey), this.senderKey
|
||||
encodeLength(this.senderKey), this.senderKey,
|
||||
]);
|
||||
let nonceInfo = concatArray([
|
||||
NONCE_INFO, new Uint8Array([0]), AESGCM_P256DH_INFO,
|
||||
encodeLength(this.publicKey), this.publicKey,
|
||||
encodeLength(this.senderKey), this.senderKey
|
||||
encodeLength(this.senderKey), this.senderKey,
|
||||
]);
|
||||
return Promise.all([
|
||||
prkKdf.extract(keyInfo, 16),
|
||||
prkKdf.extract(nonceInfo, 12)
|
||||
prkKdf.extract(nonceInfo, 12),
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -536,8 +533,8 @@ class aesgcmDecoder extends OldSchemeDecoder {
|
|||
|
||||
/** Oldest encryption scheme (draft-thomson-http-encryption-02). */
|
||||
|
||||
var AESGCM128_ENCODING = 'aesgcm128';
|
||||
var AESGCM128_KEY_INFO = UTF8.encode('Content-Encoding: aesgcm128');
|
||||
const AESGCM128_ENCODING = "aesgcm128";
|
||||
const AESGCM128_KEY_INFO = UTF8.encode("Content-Encoding: aesgcm128");
|
||||
|
||||
class aesgcm128Decoder extends OldSchemeDecoder {
|
||||
constructor(privateKey, publicKey, cryptoParams, ciphertext) {
|
||||
|
@ -553,7 +550,7 @@ class aesgcm128Decoder extends OldSchemeDecoder {
|
|||
let prkKdf = new hkdf(this.salt, ikm);
|
||||
return Promise.all([
|
||||
prkKdf.extract(AESGCM128_KEY_INFO, 16),
|
||||
prkKdf.extract(NONCE_INFO, 12)
|
||||
prkKdf.extract(NONCE_INFO, 12),
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -569,17 +566,17 @@ var PushCrypto = {
|
|||
},
|
||||
|
||||
validateAppServerKey(key) {
|
||||
return crypto.subtle.importKey('raw', key, ECDSA_KEY,
|
||||
true, ['verify'])
|
||||
return crypto.subtle.importKey("raw", key, ECDSA_KEY,
|
||||
true, ["verify"])
|
||||
.then(_ => key);
|
||||
},
|
||||
|
||||
generateKeys() {
|
||||
return crypto.subtle.generateKey(ECDH_KEY, true, ['deriveBits'])
|
||||
return crypto.subtle.generateKey(ECDH_KEY, true, ["deriveBits"])
|
||||
.then(cryptoKey =>
|
||||
Promise.all([
|
||||
crypto.subtle.exportKey('raw', cryptoKey.publicKey),
|
||||
crypto.subtle.exportKey('jwk', cryptoKey.privateKey)
|
||||
crypto.subtle.exportKey("raw", cryptoKey.publicKey),
|
||||
crypto.subtle.exportKey("jwk", cryptoKey.privateKey),
|
||||
]));
|
||||
},
|
||||
|
||||
|
@ -604,7 +601,7 @@ var PushCrypto = {
|
|||
|
||||
let encoding = headers.encoding;
|
||||
if (!headers.encoding) {
|
||||
throw new CryptoError('Missing Content-Encoding header',
|
||||
throw new CryptoError("Missing Content-Encoding header",
|
||||
BAD_ENCODING_HEADER);
|
||||
}
|
||||
|
||||
|
@ -630,7 +627,7 @@ var PushCrypto = {
|
|||
}
|
||||
|
||||
if (!decoder) {
|
||||
throw new CryptoError('Unsupported Content-Encoding: ' + encoding,
|
||||
throw new CryptoError("Unsupported Content-Encoding: " + encoding,
|
||||
BAD_ENCODING_HEADER);
|
||||
}
|
||||
|
||||
|
@ -650,7 +647,7 @@ var PushCrypto = {
|
|||
* @param {options} Object Encryption options, used for tests.
|
||||
* @returns {ciphertext, encoding} The encrypted payload and encoding.
|
||||
*/
|
||||
async encrypt(plaintext, receiverPublicKey, receiverAuthSecret, options={}) {
|
||||
async encrypt(plaintext, receiverPublicKey, receiverAuthSecret, options = {}) {
|
||||
const encoding = options.encoding || AES128GCM_ENCODING;
|
||||
// We only support one encoding type.
|
||||
if (encoding != AES128GCM_ENCODING) {
|
||||
|
@ -674,7 +671,7 @@ var PushCrypto = {
|
|||
|
||||
// A class for aes128gcm encryption - the only kind we support.
|
||||
class aes128gcmEncoder {
|
||||
constructor(plaintext ,receiverPublicKey, receiverAuthSecret, senderKeyPair, salt, rs) {
|
||||
constructor(plaintext, receiverPublicKey, receiverAuthSecret, senderKeyPair, salt, rs) {
|
||||
this.receiverPublicKey = receiverPublicKey;
|
||||
this.receiverAuthSecret = receiverAuthSecret;
|
||||
this.senderKeyPair = senderKeyPair;
|
||||
|
@ -689,7 +686,7 @@ class aes128gcmEncoder {
|
|||
|
||||
const rawSenderPublicKey = await crypto.subtle.exportKey("raw", this.senderKeyPair.publicKey);
|
||||
const [gcmBits, nonce] = await this.deriveKeyAndNonce(sharedSecret,
|
||||
rawSenderPublicKey)
|
||||
rawSenderPublicKey);
|
||||
|
||||
const contentEncryptionKey = await crypto.subtle.importKey("raw", gcmBits,
|
||||
"AES-GCM", false,
|
||||
|
@ -712,17 +709,17 @@ class aes128gcmEncoder {
|
|||
// Send an authentication tag for empty messages.
|
||||
chunks = [await crypto.subtle.encrypt({
|
||||
name: "AES-GCM",
|
||||
iv: generateNonce(nonce, 0)
|
||||
iv: generateNonce(nonce, 0),
|
||||
}, key, new Uint8Array([2]))];
|
||||
} else {
|
||||
// Use specified recordsize, though we burn 1 for padding and 16 byte
|
||||
// overhead.
|
||||
let inChunks = chunkArray(this.plaintext, this.rs - 1 - 16);
|
||||
chunks = await Promise.all(inChunks.map(async function (slice, index) {
|
||||
chunks = await Promise.all(inChunks.map(async function(slice, index) {
|
||||
let isLast = index == inChunks.length - 1;
|
||||
let padding = new Uint8Array([isLast ? 2 : 1]);
|
||||
let input = concatArray([slice, padding]);
|
||||
return await crypto.subtle.encrypt({
|
||||
return crypto.subtle.encrypt({
|
||||
name: "AES-GCM",
|
||||
iv: generateNonce(nonce, index),
|
||||
}, key, input);
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
/* jshint moz: true, esnext: true */
|
||||
/* 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/. */
|
||||
|
@ -7,9 +6,8 @@
|
|||
|
||||
const {IndexedDBHelper} = ChromeUtils.import("resource://gre/modules/IndexedDBHelper.jsm");
|
||||
const {XPCOMUtils} = ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
XPCOMUtils.defineLazyGlobalGetters(this, ["indexedDB"]);
|
||||
|
||||
var EXPORTED_SYMBOLS = ["PushDB"];
|
||||
const EXPORTED_SYMBOLS = ["PushDB"];
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "console", () => {
|
||||
let {ConsoleAPI} = ChromeUtils.import("resource://gre/modules/Console.jsm");
|
||||
|
@ -33,24 +31,24 @@ function PushDB(dbName, dbVersion, dbStoreName, keyPath, model) {
|
|||
this.PushDB.prototype = {
|
||||
__proto__: IndexedDBHelper.prototype,
|
||||
|
||||
toPushRecord: function(record) {
|
||||
toPushRecord(record) {
|
||||
if (!record) {
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
return new this._model(record);
|
||||
},
|
||||
|
||||
isValidRecord: function(record) {
|
||||
isValidRecord(record) {
|
||||
return record && typeof record.scope == "string" &&
|
||||
typeof record.originAttributes == "string" &&
|
||||
record.quota >= 0 &&
|
||||
typeof record[this._keyPath] == "string";
|
||||
},
|
||||
|
||||
upgradeSchema: function(aTransaction, aDb, aOldVersion, aNewVersion) {
|
||||
upgradeSchema(aTransaction, aDb, aOldVersion, aNewVersion) {
|
||||
if (aOldVersion <= 3) {
|
||||
//XXXnsm We haven't shipped Push during this upgrade, so I'm just going to throw old
|
||||
//registrations away without even informing the app.
|
||||
// XXXnsm We haven't shipped Push during this upgrade, so I'm just going to throw old
|
||||
// registrations away without even informing the app.
|
||||
if (aDb.objectStoreNames.contains(this._dbStoreName)) {
|
||||
aDb.deleteObjectStore(this._dbStoreName);
|
||||
}
|
||||
|
@ -83,7 +81,7 @@ this.PushDB.prototype = {
|
|||
* The record to be added.
|
||||
*/
|
||||
|
||||
put: function(aRecord) {
|
||||
put(aRecord) {
|
||||
console.debug("put()", aRecord);
|
||||
if (!this.isValidRecord(aRecord)) {
|
||||
return Promise.reject(new TypeError(
|
||||
|
@ -116,7 +114,7 @@ this.PushDB.prototype = {
|
|||
* @param aKeyID
|
||||
* The ID of record to be deleted.
|
||||
*/
|
||||
delete: function(aKeyID) {
|
||||
delete(aKeyID) {
|
||||
console.debug("delete()");
|
||||
|
||||
return new Promise((resolve, reject) =>
|
||||
|
@ -138,7 +136,7 @@ this.PushDB.prototype = {
|
|||
|
||||
// testFn(record) is called with a database record and should return true if
|
||||
// that record should be deleted.
|
||||
clearIf: function(testFn) {
|
||||
clearIf(testFn) {
|
||||
console.debug("clearIf()");
|
||||
return new Promise((resolve, reject) =>
|
||||
this.newTxn(
|
||||
|
@ -156,11 +154,11 @@ this.PushDB.prototype = {
|
|||
deleteRequest.onerror = e => {
|
||||
console.error("clearIf: Error removing record",
|
||||
record.keyID, e);
|
||||
}
|
||||
};
|
||||
}
|
||||
cursor.continue();
|
||||
}
|
||||
}
|
||||
};
|
||||
},
|
||||
resolve,
|
||||
reject
|
||||
|
@ -168,7 +166,7 @@ this.PushDB.prototype = {
|
|||
);
|
||||
},
|
||||
|
||||
getByPushEndpoint: function(aPushEndpoint) {
|
||||
getByPushEndpoint(aPushEndpoint) {
|
||||
console.debug("getByPushEndpoint()");
|
||||
|
||||
return new Promise((resolve, reject) =>
|
||||
|
@ -191,7 +189,7 @@ this.PushDB.prototype = {
|
|||
);
|
||||
},
|
||||
|
||||
getByKeyID: function(aKeyID) {
|
||||
getByKeyID(aKeyID) {
|
||||
console.debug("getByKeyID()");
|
||||
|
||||
return new Promise((resolve, reject) =>
|
||||
|
@ -224,7 +222,7 @@ this.PushDB.prototype = {
|
|||
* `cursor` is an `IDBCursor`.
|
||||
* @returns {Promise} Resolves once all records have been processed.
|
||||
*/
|
||||
forEachOrigin: function(origin, originAttributes, callback) {
|
||||
forEachOrigin(origin, originAttributes, callback) {
|
||||
console.debug("forEachOrigin()");
|
||||
|
||||
return new Promise((resolve, reject) =>
|
||||
|
@ -255,7 +253,7 @@ this.PushDB.prototype = {
|
|||
},
|
||||
|
||||
// Perform a unique match against { scope, originAttributes }
|
||||
getByIdentifiers: function(aPageRecord) {
|
||||
getByIdentifiers(aPageRecord) {
|
||||
console.debug("getByIdentifiers()", aPageRecord);
|
||||
if (!aPageRecord.scope || aPageRecord.originAttributes == undefined) {
|
||||
console.error("getByIdentifiers: Scope and originAttributes are required",
|
||||
|
@ -282,7 +280,7 @@ this.PushDB.prototype = {
|
|||
);
|
||||
},
|
||||
|
||||
_getAllByKey: function(aKeyName, aKeyValue) {
|
||||
_getAllByKey(aKeyName, aKeyValue) {
|
||||
return new Promise((resolve, reject) =>
|
||||
this.newTxn(
|
||||
"readonly",
|
||||
|
@ -307,14 +305,14 @@ this.PushDB.prototype = {
|
|||
},
|
||||
|
||||
// aOriginAttributes must be a string!
|
||||
getAllByOriginAttributes: function(aOriginAttributes) {
|
||||
getAllByOriginAttributes(aOriginAttributes) {
|
||||
if (typeof aOriginAttributes !== "string") {
|
||||
return Promise.reject("Expected string!");
|
||||
}
|
||||
return this._getAllByKey("originAttributes", aOriginAttributes);
|
||||
},
|
||||
|
||||
getAllKeyIDs: function() {
|
||||
getAllKeyIDs() {
|
||||
console.debug("getAllKeyIDs()");
|
||||
|
||||
return new Promise((resolve, reject) =>
|
||||
|
@ -334,7 +332,7 @@ this.PushDB.prototype = {
|
|||
);
|
||||
},
|
||||
|
||||
_getAllByPushQuota: function(range) {
|
||||
_getAllByPushQuota(range) {
|
||||
console.debug("getAllByPushQuota()");
|
||||
|
||||
return new Promise((resolve, reject) =>
|
||||
|
@ -359,12 +357,12 @@ this.PushDB.prototype = {
|
|||
);
|
||||
},
|
||||
|
||||
getAllUnexpired: function() {
|
||||
getAllUnexpired() {
|
||||
console.debug("getAllUnexpired()");
|
||||
return this._getAllByPushQuota(IDBKeyRange.lowerBound(1));
|
||||
},
|
||||
|
||||
getAllExpired: function() {
|
||||
getAllExpired() {
|
||||
console.debug("getAllExpired()");
|
||||
return this._getAllByPushQuota(IDBKeyRange.only(0));
|
||||
},
|
||||
|
@ -379,7 +377,7 @@ this.PushDB.prototype = {
|
|||
* Rejects if the record does not exist, or the function returns an invalid
|
||||
* record.
|
||||
*/
|
||||
update: function(aKeyID, aUpdateFunc) {
|
||||
update(aKeyID, aUpdateFunc) {
|
||||
return new Promise((resolve, reject) =>
|
||||
this.newTxn(
|
||||
"readwrite",
|
||||
|
@ -420,7 +418,7 @@ this.PushDB.prototype = {
|
|||
);
|
||||
},
|
||||
|
||||
drop: function() {
|
||||
drop() {
|
||||
console.debug("drop()");
|
||||
|
||||
return new Promise((resolve, reject) =>
|
||||
|
|
|
@ -16,7 +16,7 @@ ChromeUtils.defineModuleGetter(this, "PrivateBrowsingUtils",
|
|||
"resource://gre/modules/PrivateBrowsingUtils.jsm");
|
||||
|
||||
|
||||
var EXPORTED_SYMBOLS = ["PushRecord"];
|
||||
const EXPORTED_SYMBOLS = ["PushRecord"];
|
||||
|
||||
const prefs = Services.prefs.getBranch("dom.push.");
|
||||
|
||||
|
@ -147,7 +147,7 @@ PushRecord.prototype = {
|
|||
Ci.nsINavHistoryService.TRANSITION_TYPED,
|
||||
Ci.nsINavHistoryService.TRANSITION_BOOKMARK,
|
||||
Ci.nsINavHistoryService.TRANSITION_REDIRECT_PERMANENT,
|
||||
Ci.nsINavHistoryService.TRANSITION_REDIRECT_TEMPORARY
|
||||
Ci.nsINavHistoryService.TRANSITION_REDIRECT_TEMPORARY,
|
||||
].join(",");
|
||||
|
||||
let db = await PlacesUtils.promiseDBConnection();
|
||||
|
@ -282,7 +282,6 @@ Object.defineProperties(PushRecord.prototype, {
|
|||
let uri = Services.io.newURI(this.scope);
|
||||
// Allow tests to omit origin attributes.
|
||||
let originSuffix = this.originAttributes || "";
|
||||
let originAttributes =
|
||||
principal = Services.scriptSecurityManager.createCodebasePrincipal(uri,
|
||||
ChromeUtils.createOriginAttributesFromOrigin(originSuffix));
|
||||
principals.set(this, principal);
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
/* jshint moz: true, esnext: true */
|
||||
/* 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/. */
|
||||
|
@ -11,23 +10,16 @@ const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
|||
const {clearTimeout, setTimeout} = ChromeUtils.import("resource://gre/modules/Timer.jsm");
|
||||
const {XPCOMUtils} = ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
var {
|
||||
PushCrypto,
|
||||
CryptoError,
|
||||
} = ChromeUtils.import("resource://gre/modules/PushCrypto.jsm", null);
|
||||
const {PushDB} = ChromeUtils.import("resource://gre/modules/PushDB.jsm");
|
||||
|
||||
var PushServiceWebSocket, PushServiceHttp2;
|
||||
|
||||
const CONNECTION_PROTOCOLS = (function() {
|
||||
if ('android' != AppConstants.MOZ_WIDGET_TOOLKIT) {
|
||||
if ("android" != AppConstants.MOZ_WIDGET_TOOLKIT) {
|
||||
({PushServiceWebSocket} = ChromeUtils.import("resource://gre/modules/PushServiceWebSocket.jsm"));
|
||||
({PushServiceHttp2} = ChromeUtils.import("resource://gre/modules/PushServiceHttp2.jsm"));
|
||||
return [PushServiceWebSocket, PushServiceHttp2];
|
||||
} else {
|
||||
const {PushServiceAndroidGCM} = ChromeUtils.import("resource://gre/modules/PushServiceAndroidGCM.jsm");
|
||||
return [PushServiceAndroidGCM];
|
||||
}
|
||||
const {PushServiceAndroidGCM} = ChromeUtils.import("resource://gre/modules/PushServiceAndroidGCM.jsm");
|
||||
return [PushServiceAndroidGCM];
|
||||
})();
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "gPushNotifier",
|
||||
|
@ -37,8 +29,9 @@ XPCOMUtils.defineLazyServiceGetter(this, "eTLDService",
|
|||
"@mozilla.org/network/effective-tld-service;1",
|
||||
"nsIEffectiveTLDService");
|
||||
ChromeUtils.defineModuleGetter(this, "pushBroadcastService", "resource://gre/modules/PushBroadcastService.jsm");
|
||||
ChromeUtils.defineModuleGetter(this, "PushCrypto", "resource://gre/modules/PushCrypto.jsm");
|
||||
|
||||
var EXPORTED_SYMBOLS = ["PushService"];
|
||||
const EXPORTED_SYMBOLS = ["PushService"];
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "console", () => {
|
||||
let {ConsoleAPI} = ChromeUtils.import("resource://gre/modules/Console.jsm");
|
||||
|
@ -52,7 +45,7 @@ const prefs = new Preferences("dom.push.");
|
|||
|
||||
const PUSH_SERVICE_UNINIT = 0;
|
||||
const PUSH_SERVICE_INIT = 1; // No serverURI
|
||||
const PUSH_SERVICE_ACTIVATING = 2;//activating db
|
||||
const PUSH_SERVICE_ACTIVATING = 2; // activating db
|
||||
const PUSH_SERVICE_CONNECTION_DISABLE = 3;
|
||||
const PUSH_SERVICE_ACTIVE_OFFLINE = 4;
|
||||
const PUSH_SERVICE_RUNNING = 5;
|
||||
|
@ -112,7 +105,7 @@ var PushService = {
|
|||
// 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,
|
||||
_stateChangeProcessEnqueue: function(op) {
|
||||
_stateChangeProcessEnqueue(op) {
|
||||
if (!this._stateChangeProcessQueue) {
|
||||
this._stateChangeProcessQueue = Promise.resolve();
|
||||
}
|
||||
|
@ -137,24 +130,26 @@ var PushService = {
|
|||
_pendingRegisterRequest: {},
|
||||
_notifyActivated: null,
|
||||
_activated: null,
|
||||
_checkActivated: function() {
|
||||
_checkActivated() {
|
||||
if (this._state < PUSH_SERVICE_ACTIVATING) {
|
||||
return Promise.reject(new Error("Push service not active"));
|
||||
} else if (this._state > PUSH_SERVICE_ACTIVATING) {
|
||||
return Promise.resolve();
|
||||
} else {
|
||||
return (this._activated) ? this._activated :
|
||||
this._activated = new Promise((res, rej) =>
|
||||
this._notifyActivated = {resolve: res,
|
||||
reject: rej});
|
||||
}
|
||||
if (this._state > PUSH_SERVICE_ACTIVATING) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
if (!this._activated) {
|
||||
this._activated = new Promise((resolve, reject) => {
|
||||
this._notifyActivated = {resolve, reject};
|
||||
});
|
||||
}
|
||||
return this._activated;
|
||||
},
|
||||
|
||||
_makePendingKey: function(aPageRecord) {
|
||||
_makePendingKey(aPageRecord) {
|
||||
return aPageRecord.scope + "|" + aPageRecord.originAttributes;
|
||||
},
|
||||
|
||||
_lookupOrPutPendingRequest: function(aPageRecord) {
|
||||
_lookupOrPutPendingRequest(aPageRecord) {
|
||||
let key = this._makePendingKey(aPageRecord);
|
||||
if (this._pendingRegisterRequest[key]) {
|
||||
return this._pendingRegisterRequest[key];
|
||||
|
@ -163,14 +158,14 @@ var PushService = {
|
|||
return this._pendingRegisterRequest[key] = this._registerWithServer(aPageRecord);
|
||||
},
|
||||
|
||||
_deletePendingRequest: function(aPageRecord) {
|
||||
_deletePendingRequest(aPageRecord) {
|
||||
let key = this._makePendingKey(aPageRecord);
|
||||
if (this._pendingRegisterRequest[key]) {
|
||||
delete this._pendingRegisterRequest[key];
|
||||
}
|
||||
},
|
||||
|
||||
_setState: function(aNewState) {
|
||||
_setState(aNewState) {
|
||||
console.debug("setState()", "new state", aNewState, "old state", this._state);
|
||||
|
||||
if (this._state == aNewState) {
|
||||
|
@ -232,7 +227,7 @@ var PushService = {
|
|||
this._service.connect(broadcastListeners);
|
||||
},
|
||||
|
||||
_changeStateConnectionEnabledEvent: function(enabled) {
|
||||
_changeStateConnectionEnabledEvent(enabled) {
|
||||
console.debug("changeStateConnectionEnabledEvent()", enabled);
|
||||
|
||||
if (this._state < PUSH_SERVICE_CONNECTION_DISABLE &&
|
||||
|
@ -289,7 +284,6 @@ var PushService = {
|
|||
this._changeServerURL(prefs.get("serverURL"),
|
||||
CHANGING_SERVICE_EVENT)
|
||||
);
|
||||
|
||||
} else if (aData == "dom.push.connection.enabled") {
|
||||
this._stateChangeProcessEnqueue(_ =>
|
||||
this._changeStateConnectionEnabledEvent(prefs.get("connection.enabled"))
|
||||
|
@ -307,7 +301,7 @@ var PushService = {
|
|||
this._onPermissionChange(aSubject, aData).catch(error => {
|
||||
console.error("onPermissionChange: Error updating registrations:",
|
||||
error);
|
||||
})
|
||||
});
|
||||
break;
|
||||
|
||||
case "clear-origin-attributes-data":
|
||||
|
@ -318,7 +312,7 @@ var PushService = {
|
|||
}
|
||||
},
|
||||
|
||||
_clearOriginData: function(data) {
|
||||
_clearOriginData(data) {
|
||||
console.log("clearOriginData()");
|
||||
|
||||
if (!data) {
|
||||
|
@ -353,7 +347,7 @@ var PushService = {
|
|||
});
|
||||
},
|
||||
|
||||
_findService: function(serverURL) {
|
||||
_findService(serverURL) {
|
||||
console.debug("findService()");
|
||||
|
||||
let uri;
|
||||
|
@ -381,10 +375,10 @@ var PushService = {
|
|||
return [service, uri];
|
||||
},
|
||||
|
||||
_changeServerURL: function(serverURI, event, options = {}) {
|
||||
_changeServerURL(serverURI, event, options = {}) {
|
||||
console.debug("changeServerURL()");
|
||||
|
||||
switch(event) {
|
||||
switch (event) {
|
||||
case UNINIT_EVENT:
|
||||
return this._stopService(event);
|
||||
|
||||
|
@ -408,30 +402,22 @@ var PushService = {
|
|||
return this._startService(service, uri, options)
|
||||
.then(_ => this._changeStateConnectionEnabledEvent(prefs.get("connection.enabled"))
|
||||
);
|
||||
|
||||
} else {
|
||||
this._setState(PUSH_SERVICE_ACTIVATING);
|
||||
// If we already had running service - stop service, start the new
|
||||
// one and check connection.enabled and offline state(offline state
|
||||
// check is called in changeStateConnectionEnabledEvent function)
|
||||
return this._stopService(CHANGING_SERVICE_EVENT)
|
||||
.then(_ =>
|
||||
this._startService(service, uri, options)
|
||||
)
|
||||
.then(_ => this._changeStateConnectionEnabledEvent(prefs.get("connection.enabled"))
|
||||
);
|
||||
|
||||
}
|
||||
} else {
|
||||
if (this._state == PUSH_SERVICE_INIT) {
|
||||
return Promise.resolve();
|
||||
|
||||
} else {
|
||||
// The new serverUri is empty or misconfigured - stop service.
|
||||
this._setState(PUSH_SERVICE_INIT);
|
||||
return this._stopService(STOPPING_SERVICE_EVENT);
|
||||
}
|
||||
this._setState(PUSH_SERVICE_ACTIVATING);
|
||||
// If we already had running service - stop service, start the new
|
||||
// one and check connection.enabled and offline state(offline state
|
||||
// check is called in changeStateConnectionEnabledEvent function)
|
||||
return this._stopService(CHANGING_SERVICE_EVENT)
|
||||
.then(_ => this._startService(service, uri, options))
|
||||
.then(_ => this._changeStateConnectionEnabledEvent(prefs.get("connection.enabled")));
|
||||
}
|
||||
if (this._state == PUSH_SERVICE_INIT) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
// The new serverUri is empty or misconfigured - stop service.
|
||||
this._setState(PUSH_SERVICE_INIT);
|
||||
return this._stopService(STOPPING_SERVICE_EVENT);
|
||||
|
||||
default:
|
||||
console.error("Unexpected event in _changeServerURL", event);
|
||||
return Promise.reject(new Error(`Unexpected event ${event}`));
|
||||
|
@ -470,7 +456,6 @@ var PushService = {
|
|||
|
||||
await this._stateChangeProcessEnqueue(_ =>
|
||||
this._changeServerURL(options.serverURI, STARTING_SERVICE_EVENT, options));
|
||||
|
||||
} else {
|
||||
// This is only used for testing. Different tests require connecting to
|
||||
// slightly different URLs.
|
||||
|
@ -479,7 +464,7 @@ var PushService = {
|
|||
}
|
||||
},
|
||||
|
||||
_startObservers: function() {
|
||||
_startObservers() {
|
||||
console.debug("startObservers()");
|
||||
|
||||
if (this._state != PUSH_SERVICE_ACTIVATING) {
|
||||
|
@ -534,7 +519,7 @@ var PushService = {
|
|||
* uninit() - stop listening for quit-application and serverURL changes.
|
||||
* state is change to PUSH_SERVICE_UNINIT
|
||||
*/
|
||||
_stopService: function(event) {
|
||||
_stopService(event) {
|
||||
console.debug("stopService()");
|
||||
|
||||
if (this._state < PUSH_SERVICE_ACTIVATING) {
|
||||
|
@ -570,7 +555,7 @@ var PushService = {
|
|||
});
|
||||
},
|
||||
|
||||
_stopObservers: function() {
|
||||
_stopObservers() {
|
||||
console.debug("stopObservers()");
|
||||
|
||||
if (this._state < PUSH_SERVICE_ACTIVATING) {
|
||||
|
@ -616,7 +601,7 @@ var PushService = {
|
|||
* expired because the user revoked the notification permission are evicted
|
||||
* once the permission is reinstated.
|
||||
*/
|
||||
dropUnexpiredRegistrations: function() {
|
||||
dropUnexpiredRegistrations() {
|
||||
return this._db.clearIf(record => {
|
||||
if (record.isExpired()) {
|
||||
return false;
|
||||
|
@ -626,7 +611,7 @@ var PushService = {
|
|||
});
|
||||
},
|
||||
|
||||
_notifySubscriptionChangeObservers: function(record) {
|
||||
_notifySubscriptionChangeObservers(record) {
|
||||
if (!record) {
|
||||
return;
|
||||
}
|
||||
|
@ -640,7 +625,7 @@ var PushService = {
|
|||
* @param {String} keyID The registration ID to remove.
|
||||
* @returns {Promise} Resolves once the worker has been notified.
|
||||
*/
|
||||
dropRegistrationAndNotifyApp: function(aKeyID) {
|
||||
dropRegistrationAndNotifyApp(aKeyID) {
|
||||
return this._db.delete(aKeyID)
|
||||
.then(record => this._notifySubscriptionChangeObservers(record));
|
||||
},
|
||||
|
@ -653,7 +638,7 @@ var PushService = {
|
|||
* @param {PushRecord} aNewRecord The new record.
|
||||
* @returns {Promise} Resolves once the worker has been notified.
|
||||
*/
|
||||
updateRegistrationAndNotifyApp: function(aOldKey, aNewRecord) {
|
||||
updateRegistrationAndNotifyApp(aOldKey, aNewRecord) {
|
||||
return this.updateRecordAndNotifyApp(aOldKey, _ => aNewRecord);
|
||||
},
|
||||
/**
|
||||
|
@ -664,7 +649,7 @@ var PushService = {
|
|||
* @returns {Promise} Resolves with the updated record once the worker
|
||||
* has been notified.
|
||||
*/
|
||||
updateRecordAndNotifyApp: function(aKeyID, aUpdateFunc) {
|
||||
updateRecordAndNotifyApp(aKeyID, aUpdateFunc) {
|
||||
return this._db.update(aKeyID, aUpdateFunc)
|
||||
.then(record => {
|
||||
this._notifySubscriptionChangeObservers(record);
|
||||
|
@ -672,7 +657,7 @@ var PushService = {
|
|||
});
|
||||
},
|
||||
|
||||
ensureCrypto: function(record) {
|
||||
ensureCrypto(record) {
|
||||
if (record.hasAuthenticationSecret() &&
|
||||
record.p256dhPublicKey &&
|
||||
record.p256dhPrivateKey) {
|
||||
|
@ -730,8 +715,7 @@ var PushService = {
|
|||
if (record.quotaApplies()) {
|
||||
// Update quota after the delay, at which point
|
||||
// we check for visible notifications.
|
||||
let timeoutID = setTimeout(_ =>
|
||||
{
|
||||
let timeoutID = setTimeout(_ => {
|
||||
this._updateQuota(keyID);
|
||||
if (!this._updateQuotaTimeouts.delete(timeoutID)) {
|
||||
console.debug("receivedPushMessage: quota update timeout missing?");
|
||||
|
@ -753,7 +737,7 @@ var PushService = {
|
|||
pushBroadcastService.receivedBroadcastMessage(message.broadcasts)
|
||||
.catch(e => {
|
||||
console.error(e);
|
||||
});;
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -827,7 +811,7 @@ var PushService = {
|
|||
});
|
||||
},
|
||||
|
||||
_updateQuota: function(keyID) {
|
||||
_updateQuota(keyID) {
|
||||
console.debug("updateQuota()");
|
||||
|
||||
this._db.update(keyID, record => {
|
||||
|
@ -894,7 +878,6 @@ var PushService = {
|
|||
console.debug("reportDeliveryError()", messageID, reason);
|
||||
if (this._state == PUSH_SERVICE_RUNNING &&
|
||||
this._service.isConnected()) {
|
||||
|
||||
// Only report errors if we're initialized and connected.
|
||||
this._service.reportDeliveryError(messageID, reason);
|
||||
}
|
||||
|
@ -935,11 +918,11 @@ var PushService = {
|
|||
return Ci.nsIPushErrorReporter.ACK_DELIVERED;
|
||||
},
|
||||
|
||||
getByKeyID: function(aKeyID) {
|
||||
getByKeyID(aKeyID) {
|
||||
return this._db.getByKeyID(aKeyID);
|
||||
},
|
||||
|
||||
getAllUnexpired: function() {
|
||||
getAllUnexpired() {
|
||||
return this._db.getAllUnexpired();
|
||||
},
|
||||
|
||||
|
@ -968,7 +951,7 @@ var PushService = {
|
|||
* Called on message from the child process. aPageRecord is an object sent by
|
||||
* the push manager, identifying the sending page and other fields.
|
||||
*/
|
||||
_registerWithServer: function(aPageRecord) {
|
||||
_registerWithServer(aPageRecord) {
|
||||
console.debug("registerWithServer()", aPageRecord);
|
||||
|
||||
return this._sendRequest("register", aPageRecord)
|
||||
|
@ -993,7 +976,7 @@ var PushService = {
|
|||
* Exceptions thrown in _onRegisterSuccess are caught by the promise obtained
|
||||
* from _service.request, causing the promise to be rejected instead.
|
||||
*/
|
||||
_onRegisterSuccess: function(aRecord) {
|
||||
_onRegisterSuccess(aRecord) {
|
||||
console.debug("_onRegisterSuccess()");
|
||||
|
||||
return this._db.put(aRecord)
|
||||
|
@ -1009,7 +992,7 @@ var PushService = {
|
|||
* Exceptions thrown in _onRegisterError are caught by the promise obtained
|
||||
* from _service.request, causing the promise to be rejected instead.
|
||||
*/
|
||||
_onRegisterError: function(reply) {
|
||||
_onRegisterError(reply) {
|
||||
console.debug("_onRegisterError()");
|
||||
|
||||
if (!reply.error) {
|
||||
|
@ -1030,7 +1013,7 @@ var PushService = {
|
|||
);
|
||||
},
|
||||
|
||||
register: function(aPageRecord) {
|
||||
register(aPageRecord) {
|
||||
console.debug("register()", aPageRecord);
|
||||
|
||||
let keyPromise;
|
||||
|
@ -1114,29 +1097,29 @@ var PushService = {
|
|||
* client acknowledge. On a server, data is cheap, reliable notification is
|
||||
* not.
|
||||
*/
|
||||
unregister: function(aPageRecord) {
|
||||
unregister(aPageRecord) {
|
||||
console.debug("unregister()", aPageRecord);
|
||||
|
||||
return this._getByPageRecord(aPageRecord)
|
||||
.then(record => {
|
||||
if (record === undefined) {
|
||||
if (record === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let reason = Ci.nsIPushErrorReporter.UNSUBSCRIBE_MANUAL;
|
||||
return Promise.all([
|
||||
this._sendUnregister(record, reason),
|
||||
this._db.delete(record.keyID).then(record => {
|
||||
if (record) {
|
||||
gPushNotifier.notifySubscriptionModified(record.scope,
|
||||
record.principal);
|
||||
this._db.delete(record.keyID).then(rec => {
|
||||
if (rec) {
|
||||
gPushNotifier.notifySubscriptionModified(rec.scope,
|
||||
rec.principal);
|
||||
}
|
||||
}),
|
||||
]).then(([success]) => success);
|
||||
});
|
||||
},
|
||||
|
||||
clear: function(info) {
|
||||
clear(info) {
|
||||
return this._checkActivated()
|
||||
.then(_ => {
|
||||
return this._dropRegistrationsIf(record =>
|
||||
|
@ -1151,7 +1134,7 @@ var PushService = {
|
|||
});
|
||||
},
|
||||
|
||||
registration: function(aPageRecord) {
|
||||
registration(aPageRecord) {
|
||||
console.debug("registration()");
|
||||
|
||||
return this._getByPageRecord(aPageRecord)
|
||||
|
@ -1171,7 +1154,7 @@ var PushService = {
|
|||
});
|
||||
},
|
||||
|
||||
_dropExpiredRegistrations: function() {
|
||||
_dropExpiredRegistrations() {
|
||||
console.debug("dropExpiredRegistrations()");
|
||||
|
||||
return this._db.getAllExpired().then(records => {
|
||||
|
@ -1180,7 +1163,7 @@ var PushService = {
|
|||
if (isChanged) {
|
||||
// If the user revisited the site, drop the expired push
|
||||
// registration and notify the associated service worker.
|
||||
return this.dropRegistrationAndNotifyApp(record.keyID);
|
||||
this.dropRegistrationAndNotifyApp(record.keyID);
|
||||
}
|
||||
}).catch(error => {
|
||||
console.error("dropExpiredRegistrations: Error dropping registration",
|
||||
|
@ -1190,7 +1173,7 @@ var PushService = {
|
|||
});
|
||||
},
|
||||
|
||||
_onPermissionChange: function(subject, data) {
|
||||
_onPermissionChange(subject, data) {
|
||||
console.debug("onPermissionChange()");
|
||||
|
||||
if (data == "cleared") {
|
||||
|
@ -1219,7 +1202,7 @@ var PushService = {
|
|||
});
|
||||
},
|
||||
|
||||
_updatePermission: function(permission, type) {
|
||||
_updatePermission(permission, type) {
|
||||
console.debug("updatePermission()");
|
||||
|
||||
let isAllow = permission.capability ==
|
||||
|
@ -1246,7 +1229,7 @@ var PushService = {
|
|||
return Promise.resolve();
|
||||
},
|
||||
|
||||
_forEachPrincipal: function(principal, callback) {
|
||||
_forEachPrincipal(principal, callback) {
|
||||
return this._db.forEachOrigin(
|
||||
principal.URI.prePath,
|
||||
ChromeUtils.originAttributesToSuffix(principal.originAttributes),
|
||||
|
@ -1264,7 +1247,7 @@ var PushService = {
|
|||
* @param {PushRecord} record The record to expire.
|
||||
* @param {IDBCursor} cursor The IndexedDB cursor.
|
||||
*/
|
||||
_permissionDenied: function(record, cursor) {
|
||||
_permissionDenied(record, cursor) {
|
||||
console.debug("permissionDenied()");
|
||||
|
||||
if (!record.quotaApplies() || record.isExpired()) {
|
||||
|
|
|
@ -1,21 +1,24 @@
|
|||
/* jshint moz: true, esnext: true */
|
||||
/* 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";
|
||||
|
||||
const {PushDB} = ChromeUtils.import("resource://gre/modules/PushDB.jsm");
|
||||
const {PushRecord} = ChromeUtils.import("resource://gre/modules/PushRecord.jsm");
|
||||
const {PushCrypto} = ChromeUtils.import("resource://gre/modules/PushCrypto.jsm");
|
||||
const {EventDispatcher} = ChromeUtils.import("resource://gre/modules/Messaging.jsm"); /*global: EventDispatcher */
|
||||
const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm"); /*global: Services */
|
||||
const {Preferences} = ChromeUtils.import("resource://gre/modules/Preferences.jsm"); /*global: Preferences */
|
||||
const {XPCOMUtils} = ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm"); /*global: XPCOMUtils */
|
||||
const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
const {XPCOMUtils} = ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
const Log = ChromeUtils.import("resource://gre/modules/AndroidLog.jsm", {}).AndroidLog.bind("Push");
|
||||
ChromeUtils.defineModuleGetter(this, "PushDB", "resource://gre/modules/PushDB.jsm");
|
||||
ChromeUtils.defineModuleGetter(this, "PushRecord", "resource://gre/modules/PushRecord.jsm");
|
||||
ChromeUtils.defineModuleGetter(this, "PushCrypto", "resource://gre/modules/PushCrypto.jsm");
|
||||
ChromeUtils.defineModuleGetter(this, "EventDispatcher", "resource://gre/modules/Messaging.jsm");
|
||||
ChromeUtils.defineModuleGetter(this, "Preferences", "resource://gre/modules/Preferences.jsm");
|
||||
|
||||
var EXPORTED_SYMBOLS = ["PushServiceAndroidGCM"];
|
||||
XPCOMUtils.defineLazyGetter(this, "Log", () => {
|
||||
return ChromeUtils.import("resource://gre/modules/AndroidLog.jsm", {})
|
||||
.AndroidLog.bind("Push");
|
||||
});
|
||||
|
||||
const EXPORTED_SYMBOLS = ["PushServiceAndroidGCM"];
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "console", () => {
|
||||
let {ConsoleAPI} = ChromeUtils.import("resource://gre/modules/Console.jsm");
|
||||
|
@ -42,7 +45,7 @@ var PushServiceAndroidGCM = {
|
|||
_mainPushService: null,
|
||||
_serverURI: null,
|
||||
|
||||
newPushDB: function() {
|
||||
newPushDB() {
|
||||
return new PushDB(kPUSHANDROIDGCMDB_DB_NAME,
|
||||
kPUSHANDROIDGCMDB_DB_VERSION,
|
||||
kPUSHANDROIDGCMDB_STORE_NAME,
|
||||
|
@ -50,7 +53,7 @@ var PushServiceAndroidGCM = {
|
|||
PushRecordAndroidGCM);
|
||||
},
|
||||
|
||||
validServerURI: function(serverURI) {
|
||||
validServerURI(serverURI) {
|
||||
if (!serverURI) {
|
||||
return false;
|
||||
}
|
||||
|
@ -66,7 +69,7 @@ var PushServiceAndroidGCM = {
|
|||
return false;
|
||||
},
|
||||
|
||||
observe: function(subject, topic, data) {
|
||||
observe(subject, topic, data) {
|
||||
switch (topic) {
|
||||
case "nsPref:changed":
|
||||
if (data == "dom.push.debug") {
|
||||
|
@ -121,7 +124,7 @@ var PushServiceAndroidGCM = {
|
|||
encryption: data.enc,
|
||||
encoding: data.con,
|
||||
};
|
||||
} else if (data.con == 'aes128gcm') {
|
||||
} else if (data.con == "aes128gcm") {
|
||||
headers = {
|
||||
encoding: data.con,
|
||||
};
|
||||
|
@ -136,15 +139,15 @@ var PushServiceAndroidGCM = {
|
|||
return { headers, message };
|
||||
},
|
||||
|
||||
_configure: function(serverURL, debug) {
|
||||
_configure(serverURL, debug) {
|
||||
return EventDispatcher.instance.sendRequestForResult({
|
||||
type: "PushServiceAndroidGCM:Configure",
|
||||
endpoint: serverURL.spec,
|
||||
debug: debug,
|
||||
debug,
|
||||
});
|
||||
},
|
||||
|
||||
init: function(options, mainPushService, serverURL) {
|
||||
init(options, mainPushService, serverURL) {
|
||||
console.debug("init()");
|
||||
this._mainPushService = mainPushService;
|
||||
this._serverURI = serverURL;
|
||||
|
@ -154,15 +157,15 @@ var PushServiceAndroidGCM = {
|
|||
|
||||
return this._configure(serverURL, !!prefs.get("debug")).then(() => {
|
||||
EventDispatcher.instance.sendRequestForResult({
|
||||
type: "PushServiceAndroidGCM:Initialized"
|
||||
type: "PushServiceAndroidGCM:Initialized",
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
uninit: function() {
|
||||
uninit() {
|
||||
console.debug("uninit()");
|
||||
EventDispatcher.instance.sendRequestForResult({
|
||||
type: "PushServiceAndroidGCM:Uninitialized"
|
||||
type: "PushServiceAndroidGCM:Uninitialized",
|
||||
});
|
||||
|
||||
this._mainPushService = null;
|
||||
|
@ -170,11 +173,11 @@ var PushServiceAndroidGCM = {
|
|||
prefs.ignore("debug", this);
|
||||
},
|
||||
|
||||
onAlarmFired: function() {
|
||||
onAlarmFired() {
|
||||
// No action required.
|
||||
},
|
||||
|
||||
connect: function(records, broadcastListeners) {
|
||||
connect(records, broadcastListeners) {
|
||||
console.debug("connect:", records);
|
||||
// It's possible for the registration or subscriptions backing the
|
||||
// PushService to not be registered with the underlying AndroidPushService.
|
||||
|
@ -201,19 +204,19 @@ var PushServiceAndroidGCM = {
|
|||
});
|
||||
},
|
||||
|
||||
sendSubscribeBroadcast: async function(serviceId, version) {
|
||||
async sendSubscribeBroadcast(serviceId, version) {
|
||||
// Not implemented yet
|
||||
},
|
||||
|
||||
isConnected: function() {
|
||||
isConnected() {
|
||||
return this._mainPushService != null;
|
||||
},
|
||||
|
||||
disconnect: function() {
|
||||
disconnect() {
|
||||
console.debug("disconnect");
|
||||
},
|
||||
|
||||
register: function(record) {
|
||||
register(record) {
|
||||
console.debug("register:", record);
|
||||
let ctime = Date.now();
|
||||
let appServerKey = record.appServerKey ?
|
||||
|
@ -223,8 +226,8 @@ var PushServiceAndroidGCM = {
|
|||
}) : null;
|
||||
let message = {
|
||||
type: "PushServiceAndroidGCM:SubscribeChannel",
|
||||
appServerKey: appServerKey,
|
||||
}
|
||||
appServerKey,
|
||||
};
|
||||
if (record.scope == FXA_PUSH_SCOPE) {
|
||||
message.service = "fxa";
|
||||
}
|
||||
|
@ -242,7 +245,7 @@ var PushServiceAndroidGCM = {
|
|||
// Common to all PushRecord implementations.
|
||||
scope: record.scope,
|
||||
originAttributes: record.originAttributes,
|
||||
ctime: ctime,
|
||||
ctime,
|
||||
systemRecord: record.systemRecord,
|
||||
// Cryptography!
|
||||
p256dhPublicKey: exportedKeys[0],
|
||||
|
@ -254,7 +257,7 @@ var PushServiceAndroidGCM = {
|
|||
});
|
||||
},
|
||||
|
||||
unregister: function(record) {
|
||||
unregister(record) {
|
||||
console.debug("unregister: ", record);
|
||||
return EventDispatcher.instance.sendRequestForResult({
|
||||
type: "PushServiceAndroidGCM:UnsubscribeChannel",
|
||||
|
@ -262,7 +265,7 @@ var PushServiceAndroidGCM = {
|
|||
});
|
||||
},
|
||||
|
||||
reportDeliveryError: function(messageID, reason) {
|
||||
reportDeliveryError(messageID, reason) {
|
||||
console.warn("reportDeliveryError: Ignoring message delivery error",
|
||||
messageID, reason);
|
||||
},
|
||||
|
|
|
@ -52,16 +52,16 @@ PushSubscriptionListener.prototype = {
|
|||
QueryInterface: ChromeUtils.generateQI(["nsIHttpPushListener",
|
||||
"nsIStreamListener"]),
|
||||
|
||||
getInterface: function(aIID) {
|
||||
getInterface(aIID) {
|
||||
return this.QueryInterface(aIID);
|
||||
},
|
||||
|
||||
onStartRequest: function(aRequest) {
|
||||
onStartRequest(aRequest) {
|
||||
console.debug("PushSubscriptionListener: onStartRequest()");
|
||||
// We do not do anything here.
|
||||
},
|
||||
|
||||
onDataAvailable: function(aRequest, aStream, aOffset, aCount) {
|
||||
onDataAvailable(aRequest, aStream, aOffset, aCount) {
|
||||
console.debug("PushSubscriptionListener: onDataAvailable()");
|
||||
// Nobody should send data, but just to be sure, otherwise necko will
|
||||
// complain.
|
||||
|
@ -73,10 +73,10 @@ PushSubscriptionListener.prototype = {
|
|||
.createInstance(Ci.nsIScriptableInputStream);
|
||||
|
||||
inputStream.init(aStream);
|
||||
var data = inputStream.read(aCount);
|
||||
inputStream.read(aCount);
|
||||
},
|
||||
|
||||
onStopRequest: function(aRequest, aStatusCode) {
|
||||
onStopRequest(aRequest, aStatusCode) {
|
||||
console.debug("PushSubscriptionListener: onStopRequest()");
|
||||
if (!this._pushService) {
|
||||
return;
|
||||
|
@ -87,15 +87,15 @@ PushSubscriptionListener.prototype = {
|
|||
this.uri);
|
||||
},
|
||||
|
||||
onPush: function(associatedChannel, pushChannel) {
|
||||
onPush(associatedChannel, pushChannel) {
|
||||
console.debug("PushSubscriptionListener: onPush()");
|
||||
var pushChannelListener = new PushChannelListener(this);
|
||||
pushChannel.asyncOpen(pushChannelListener);
|
||||
},
|
||||
|
||||
disconnect: function() {
|
||||
disconnect() {
|
||||
this._pushService = null;
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -111,11 +111,11 @@ var PushChannelListener = function(pushSubscriptionListener) {
|
|||
|
||||
PushChannelListener.prototype = {
|
||||
|
||||
onStartRequest: function(aRequest) {
|
||||
onStartRequest(aRequest) {
|
||||
this._ackUri = aRequest.URI.spec;
|
||||
},
|
||||
|
||||
onDataAvailable: function(aRequest, aStream, aOffset, aCount) {
|
||||
onDataAvailable(aRequest, aStream, aOffset, aCount) {
|
||||
console.debug("PushChannelListener: onDataAvailable()");
|
||||
|
||||
if (aCount === 0) {
|
||||
|
@ -131,7 +131,7 @@ PushChannelListener.prototype = {
|
|||
this._message.push(chunk);
|
||||
},
|
||||
|
||||
onStopRequest: function(aRequest, aStatusCode) {
|
||||
onStopRequest(aRequest, aStatusCode) {
|
||||
console.debug("PushChannelListener: onStopRequest()", "status code",
|
||||
aStatusCode);
|
||||
if (Components.isSuccessCode(aStatusCode) &&
|
||||
|
@ -150,13 +150,13 @@ PushChannelListener.prototype = {
|
|||
headers,
|
||||
msg);
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
function getHeaderField(aRequest, name) {
|
||||
try {
|
||||
return aRequest.getRequestHeader(name);
|
||||
} catch(e) {
|
||||
} catch (e) {
|
||||
// getRequestHeader can throw.
|
||||
return null;
|
||||
}
|
||||
|
@ -169,9 +169,9 @@ var PushServiceDelete = function(resolve, reject) {
|
|||
|
||||
PushServiceDelete.prototype = {
|
||||
|
||||
onStartRequest: function(aRequest) {},
|
||||
onStartRequest(aRequest) {},
|
||||
|
||||
onDataAvailable: function(aRequest, aStream, aOffset, aCount) {
|
||||
onDataAvailable(aRequest, aStream, aOffset, aCount) {
|
||||
// Nobody should send data, but just to be sure, otherwise necko will
|
||||
// complain.
|
||||
if (aCount === 0) {
|
||||
|
@ -182,17 +182,16 @@ PushServiceDelete.prototype = {
|
|||
.createInstance(Ci.nsIScriptableInputStream);
|
||||
|
||||
inputStream.init(aStream);
|
||||
var data = inputStream.read(aCount);
|
||||
inputStream.read(aCount);
|
||||
},
|
||||
|
||||
onStopRequest: function(aRequest, aStatusCode) {
|
||||
|
||||
onStopRequest(aRequest, aStatusCode) {
|
||||
if (Components.isSuccessCode(aStatusCode)) {
|
||||
this._resolve();
|
||||
} else {
|
||||
this._reject(new Error("Error removing subscription: " + aStatusCode));
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
var SubscriptionListener = function(aSubInfo, aResolve, aReject,
|
||||
|
@ -201,7 +200,6 @@ var SubscriptionListener = function(aSubInfo, aResolve, aReject,
|
|||
this._subInfo = aSubInfo;
|
||||
this._resolve = aResolve;
|
||||
this._reject = aReject;
|
||||
this._data = '';
|
||||
this._serverURI = aServerURI;
|
||||
this._service = aPushServiceHttp2;
|
||||
this._ctime = Date.now();
|
||||
|
@ -210,25 +208,11 @@ var SubscriptionListener = function(aSubInfo, aResolve, aReject,
|
|||
|
||||
SubscriptionListener.prototype = {
|
||||
|
||||
onStartRequest: function(aRequest) {},
|
||||
onStartRequest(aRequest) {},
|
||||
|
||||
onDataAvailable: function(aRequest, aStream, aOffset, aCount) {
|
||||
console.debug("SubscriptionListener: onDataAvailable()");
|
||||
onDataAvailable(aRequest, aStream, aOffset, aCount) {},
|
||||
|
||||
// We do not expect any data, but necko will complain if we do not consume
|
||||
// it.
|
||||
if (aCount === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
let inputStream = Cc["@mozilla.org/scriptableinputstream;1"]
|
||||
.createInstance(Ci.nsIScriptableInputStream);
|
||||
|
||||
inputStream.init(aStream);
|
||||
this._data.concat(inputStream.read(aCount));
|
||||
},
|
||||
|
||||
onStopRequest: function(aRequest, aStatus) {
|
||||
onStopRequest(aRequest, aStatus) {
|
||||
console.debug("SubscriptionListener: onStopRequest()");
|
||||
|
||||
// Check if pushService is still active.
|
||||
|
@ -248,12 +232,11 @@ SubscriptionListener.prototype = {
|
|||
if (this._subInfo.retries < prefs.getIntPref("http2.maxRetries")) {
|
||||
this._subInfo.retries++;
|
||||
var retryAfter = retryAfterParser(aRequest);
|
||||
this._retryTimeoutID = setTimeout(_ =>
|
||||
{
|
||||
this._retryTimeoutID = setTimeout(_ => {
|
||||
this._reject(
|
||||
{
|
||||
retry: true,
|
||||
subInfo: this._subInfo
|
||||
subInfo: this._subInfo,
|
||||
});
|
||||
this._service.removeListenerPendingRetry(this);
|
||||
this._retryTimeoutID = null;
|
||||
|
@ -299,7 +282,7 @@ SubscriptionListener.prototype = {
|
|||
return;
|
||||
}
|
||||
try {
|
||||
let uriTry = Services.io.newURI(subscriptionUri);
|
||||
Services.io.newURI(subscriptionUri);
|
||||
} catch (e) {
|
||||
console.error("onStopRequest: Invalid subscription URI",
|
||||
subscriptionUri);
|
||||
|
@ -309,7 +292,7 @@ SubscriptionListener.prototype = {
|
|||
}
|
||||
|
||||
let reply = new PushRecordHttp2({
|
||||
subscriptionUri: subscriptionUri,
|
||||
subscriptionUri,
|
||||
pushEndpoint: linkParserResult.pushEndpoint,
|
||||
pushReceiptEndpoint: linkParserResult.pushReceiptEndpoint,
|
||||
scope: this._subInfo.record.scope,
|
||||
|
@ -322,7 +305,7 @@ SubscriptionListener.prototype = {
|
|||
this._resolve(reply);
|
||||
},
|
||||
|
||||
abortRetry: function() {
|
||||
abortRetry() {
|
||||
if (this._retryTimeoutID != null) {
|
||||
clearTimeout(this._retryTimeoutID);
|
||||
this._retryTimeoutID = null;
|
||||
|
@ -333,41 +316,39 @@ SubscriptionListener.prototype = {
|
|||
};
|
||||
|
||||
function retryAfterParser(aRequest) {
|
||||
var retryAfter = 0;
|
||||
let retryAfter = 0;
|
||||
try {
|
||||
var retryField = aRequest.getResponseHeader("retry-after");
|
||||
let retryField = aRequest.getResponseHeader("retry-after");
|
||||
if (isNaN(retryField)) {
|
||||
retryAfter = Date.parse(retryField) - (new Date().getTime());
|
||||
} else {
|
||||
retryAfter = parseInt(retryField, 10) * 1000;
|
||||
}
|
||||
retryAfter = (retryAfter > 0) ? retryAfter : 0;
|
||||
} catch(e) {}
|
||||
} catch (e) {}
|
||||
|
||||
return retryAfter;
|
||||
}
|
||||
|
||||
function linkParser(linkHeader, serverURI) {
|
||||
|
||||
var linkList = linkHeader.split(',');
|
||||
let linkList = linkHeader.split(",");
|
||||
if ((linkList.length < 1)) {
|
||||
throw new Error("Invalid Link header");
|
||||
}
|
||||
|
||||
var pushEndpoint;
|
||||
var pushReceiptEndpoint;
|
||||
let pushEndpoint;
|
||||
let pushReceiptEndpoint;
|
||||
|
||||
linkList.forEach(link => {
|
||||
var linkElems = link.split(';');
|
||||
let linkElems = link.split(";");
|
||||
|
||||
if (linkElems.length == 2) {
|
||||
if (linkElems[1].trim() === 'rel="urn:ietf:params:push"') {
|
||||
pushEndpoint = linkElems[0].substring(linkElems[0].indexOf('<') + 1,
|
||||
linkElems[0].indexOf('>'));
|
||||
|
||||
pushEndpoint = linkElems[0].substring(linkElems[0].indexOf("<") + 1,
|
||||
linkElems[0].indexOf(">"));
|
||||
} else if (linkElems[1].trim() === 'rel="urn:ietf:params:push:receipt"') {
|
||||
pushReceiptEndpoint = linkElems[0].substring(linkElems[0].indexOf('<') + 1,
|
||||
linkElems[0].indexOf('>'));
|
||||
pushReceiptEndpoint = linkElems[0].substring(linkElems[0].indexOf("<") + 1,
|
||||
linkElems[0].indexOf(">"));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -379,8 +360,8 @@ function linkParser(linkHeader, serverURI) {
|
|||
throw new Error("Missing push endpoint");
|
||||
}
|
||||
|
||||
var pushURI = Services.io.newURI(pushEndpoint, null, serverURI);
|
||||
var pushReceiptURI;
|
||||
const pushURI = Services.io.newURI(pushEndpoint, null, serverURI);
|
||||
let pushReceiptURI;
|
||||
if (pushReceiptEndpoint) {
|
||||
pushReceiptURI = Services.io.newURI(pushReceiptEndpoint, null,
|
||||
serverURI);
|
||||
|
@ -406,7 +387,7 @@ var PushServiceHttp2 = {
|
|||
// Set of SubscriptionListeners that are pending a subscription retry attempt.
|
||||
_listenersPendingRetry: new Set(),
|
||||
|
||||
newPushDB: function() {
|
||||
newPushDB() {
|
||||
return new PushDB(kPUSHHTTP2DB_DB_NAME,
|
||||
kPUSHHTTP2DB_DB_VERSION,
|
||||
kPUSHHTTP2DB_STORE_NAME,
|
||||
|
@ -414,11 +395,11 @@ var PushServiceHttp2 = {
|
|||
PushRecordHttp2);
|
||||
},
|
||||
|
||||
hasmainPushService: function() {
|
||||
hasmainPushService() {
|
||||
return this._mainPushService !== null;
|
||||
},
|
||||
|
||||
validServerURI: function(serverURI) {
|
||||
validServerURI(serverURI) {
|
||||
if (serverURI.scheme == "http") {
|
||||
return !!prefs.getBoolPref("testing.allowInsecureServerURL", false);
|
||||
}
|
||||
|
@ -430,19 +411,19 @@ var PushServiceHttp2 = {
|
|||
this.startConnections(subscriptions);
|
||||
},
|
||||
|
||||
sendSubscribeBroadcast: async function(serviceId, version) {
|
||||
async sendSubscribeBroadcast(serviceId, version) {
|
||||
// Not implemented yet
|
||||
},
|
||||
|
||||
isConnected: function() {
|
||||
isConnected() {
|
||||
return this._mainPushService != null;
|
||||
},
|
||||
|
||||
disconnect: function() {
|
||||
disconnect() {
|
||||
this._shutdownConnections(false);
|
||||
},
|
||||
|
||||
_makeChannel: function(aUri) {
|
||||
_makeChannel(aUri) {
|
||||
var chan = NetUtil.newChannel({uri: aUri, loadUsingSystemPrincipal: true})
|
||||
.QueryInterface(Ci.nsIHttpChannel);
|
||||
|
||||
|
@ -455,33 +436,33 @@ var PushServiceHttp2 = {
|
|||
/**
|
||||
* Subscribe new resource.
|
||||
*/
|
||||
register: function(aRecord) {
|
||||
register(aRecord) {
|
||||
console.debug("subscribeResource()");
|
||||
|
||||
return this._subscribeResourceInternal({
|
||||
record: aRecord,
|
||||
retries: 0
|
||||
retries: 0,
|
||||
})
|
||||
.then(result =>
|
||||
PushCrypto.generateKeys()
|
||||
.then(([publicKey, privateKey]) => {
|
||||
result.p256dhPublicKey = publicKey;
|
||||
result.p256dhPrivateKey = privateKey;
|
||||
result.authenticationSecret = PushCrypto.generateAuthenticationSecret();
|
||||
this._conns[result.subscriptionUri] = {
|
||||
channel: null,
|
||||
listener: null,
|
||||
countUnableToConnect: 0,
|
||||
lastStartListening: 0,
|
||||
retryTimerID: 0,
|
||||
};
|
||||
this._listenForMsgs(result.subscriptionUri);
|
||||
return result;
|
||||
})
|
||||
result.p256dhPublicKey = publicKey;
|
||||
result.p256dhPrivateKey = privateKey;
|
||||
result.authenticationSecret = PushCrypto.generateAuthenticationSecret();
|
||||
this._conns[result.subscriptionUri] = {
|
||||
channel: null,
|
||||
listener: null,
|
||||
countUnableToConnect: 0,
|
||||
lastStartListening: 0,
|
||||
retryTimerID: 0,
|
||||
};
|
||||
this._listenForMsgs(result.subscriptionUri);
|
||||
return result;
|
||||
})
|
||||
);
|
||||
},
|
||||
|
||||
_subscribeResourceInternal: function(aSubInfo) {
|
||||
_subscribeResourceInternal(aSubInfo) {
|
||||
console.debug("subscribeResourceInternal()");
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
|
@ -498,15 +479,13 @@ var PushServiceHttp2 = {
|
|||
.catch(err => {
|
||||
if ("retry" in err) {
|
||||
return this._subscribeResourceInternal(err.subInfo);
|
||||
} else {
|
||||
throw err;
|
||||
}
|
||||
})
|
||||
throw err;
|
||||
});
|
||||
},
|
||||
|
||||
_deleteResource: function(aUri) {
|
||||
|
||||
return new Promise((resolve,reject) => {
|
||||
_deleteResource(aUri) {
|
||||
return new Promise((resolve, reject) => {
|
||||
var chan = this._makeChannel(aUri);
|
||||
chan.requestMethod = "DELETE";
|
||||
chan.asyncOpen(new PushServiceDelete(resolve, reject));
|
||||
|
@ -517,7 +496,7 @@ var PushServiceHttp2 = {
|
|||
* Unsubscribe the resource with a subscription uri aSubscriptionUri.
|
||||
* We can't do anything about it if it fails, so we don't listen for response.
|
||||
*/
|
||||
_unsubscribeResource: function(aSubscriptionUri) {
|
||||
_unsubscribeResource(aSubscriptionUri) {
|
||||
console.debug("unsubscribeResource()");
|
||||
|
||||
return this._deleteResource(aSubscriptionUri);
|
||||
|
@ -526,7 +505,7 @@ var PushServiceHttp2 = {
|
|||
/**
|
||||
* Start listening for messages.
|
||||
*/
|
||||
_listenForMsgs: function(aSubscriptionUri) {
|
||||
_listenForMsgs(aSubscriptionUri) {
|
||||
console.debug("listenForMsgs()", aSubscriptionUri);
|
||||
if (!this._conns[aSubscriptionUri]) {
|
||||
console.warn("listenForMsgs: We do not have this subscription",
|
||||
|
@ -556,15 +535,14 @@ var PushServiceHttp2 = {
|
|||
this._conns[aSubscriptionUri].lastStartListening = Date.now();
|
||||
this._conns[aSubscriptionUri].channel = conn.channel;
|
||||
this._conns[aSubscriptionUri].listener = conn.listener;
|
||||
|
||||
},
|
||||
|
||||
_ackMsgRecv: function(aAckUri) {
|
||||
_ackMsgRecv(aAckUri) {
|
||||
console.debug("ackMsgRecv()", aAckUri);
|
||||
return this._deleteResource(aAckUri);
|
||||
},
|
||||
|
||||
init: function(aOptions, aMainPushService, aServerURL) {
|
||||
init(aOptions, aMainPushService, aServerURL) {
|
||||
console.debug("init()");
|
||||
this._mainPushService = aMainPushService;
|
||||
this._serverURI = aServerURL;
|
||||
|
@ -572,7 +550,7 @@ var PushServiceHttp2 = {
|
|||
return Promise.resolve();
|
||||
},
|
||||
|
||||
_retryAfterBackoff: function(aSubscriptionUri, retryAfter) {
|
||||
_retryAfterBackoff(aSubscriptionUri, retryAfter) {
|
||||
console.debug("retryAfterBackoff()");
|
||||
|
||||
var resetRetryCount = prefs.getIntPref("http2.reset_retry_count_after_ms");
|
||||
|
@ -610,7 +588,7 @@ var PushServiceHttp2 = {
|
|||
},
|
||||
|
||||
// Close connections.
|
||||
_shutdownConnections: function(deleteInfo) {
|
||||
_shutdownConnections(deleteInfo) {
|
||||
console.debug("shutdownConnections()");
|
||||
|
||||
for (let subscriptionUri in this._conns) {
|
||||
|
@ -639,7 +617,7 @@ var PushServiceHttp2 = {
|
|||
},
|
||||
|
||||
// Start listening if subscriptions present.
|
||||
startConnections: function(aSubscriptions) {
|
||||
startConnections(aSubscriptions) {
|
||||
console.debug("startConnections()", aSubscriptions.length);
|
||||
|
||||
for (let i = 0; i < aSubscriptions.length; i++) {
|
||||
|
@ -653,7 +631,7 @@ var PushServiceHttp2 = {
|
|||
}
|
||||
},
|
||||
|
||||
_startSingleConnection: function(record) {
|
||||
_startSingleConnection(record) {
|
||||
console.debug("_startSingleConnection()");
|
||||
if (typeof this._conns[record.subscriptionUri] != "object") {
|
||||
this._conns[record.subscriptionUri] = {channel: null,
|
||||
|
@ -667,7 +645,7 @@ var PushServiceHttp2 = {
|
|||
},
|
||||
|
||||
// Close connection and notify apps that subscription are gone.
|
||||
_shutdownSubscription: function(aSubscriptionUri) {
|
||||
_shutdownSubscription(aSubscriptionUri) {
|
||||
console.debug("shutdownSubscriptions()");
|
||||
|
||||
if (typeof this._conns[aSubscriptionUri] == "object") {
|
||||
|
@ -684,24 +662,24 @@ var PushServiceHttp2 = {
|
|||
}
|
||||
},
|
||||
|
||||
uninit: function() {
|
||||
uninit() {
|
||||
console.debug("uninit()");
|
||||
this._abortPendingSubscriptionRetries();
|
||||
this._shutdownConnections(true);
|
||||
this._mainPushService = null;
|
||||
},
|
||||
|
||||
_abortPendingSubscriptionRetries: function() {
|
||||
_abortPendingSubscriptionRetries() {
|
||||
this._listenersPendingRetry.forEach((listener) => listener.abortRetry());
|
||||
this._listenersPendingRetry.clear();
|
||||
},
|
||||
|
||||
unregister: function(aRecord) {
|
||||
unregister(aRecord) {
|
||||
this._shutdownSubscription(aRecord.subscriptionUri);
|
||||
return this._unsubscribeResource(aRecord.subscriptionUri);
|
||||
},
|
||||
|
||||
reportDeliveryError: function(messageID, reason) {
|
||||
reportDeliveryError(messageID, reason) {
|
||||
console.warn("reportDeliveryError: Ignoring message delivery error",
|
||||
messageID, reason);
|
||||
},
|
||||
|
@ -712,7 +690,7 @@ var PushServiceHttp2 = {
|
|||
* - on error delete record and send pushsubscriptionchange
|
||||
* TODO: maybe pushsubscriptionerror will be included.
|
||||
*/
|
||||
_resubscribe: function(aSubscriptionUri) {
|
||||
_resubscribe(aSubscriptionUri) {
|
||||
this._mainPushService.getByKeyID(aSubscriptionUri)
|
||||
.then(record => this.register(record)
|
||||
.then(recordNew => {
|
||||
|
@ -731,8 +709,7 @@ var PushServiceHttp2 = {
|
|||
);
|
||||
},
|
||||
|
||||
connOnStop: function(aRequest, aSuccess,
|
||||
aSubscriptionUri) {
|
||||
connOnStop(aRequest, aSuccess, aSubscriptionUri) {
|
||||
console.debug("connOnStop() succeeded", aSuccess);
|
||||
|
||||
var conn = this._conns[aSubscriptionUri];
|
||||
|
@ -748,11 +725,9 @@ var PushServiceHttp2 = {
|
|||
|
||||
if (!aSuccess) {
|
||||
this._retryAfterBackoff(aSubscriptionUri, -1);
|
||||
|
||||
} else if (Math.floor(aRequest.responseStatus / 100) == 5) {
|
||||
var retryAfter = retryAfterParser(aRequest);
|
||||
this._retryAfterBackoff(aSubscriptionUri, retryAfter);
|
||||
|
||||
} else if (Math.floor(aRequest.responseStatus / 100) == 4) {
|
||||
this._shutdownSubscription(aSubscriptionUri);
|
||||
this._resubscribe(aSubscriptionUri);
|
||||
|
@ -763,17 +738,17 @@ var PushServiceHttp2 = {
|
|||
}
|
||||
},
|
||||
|
||||
addListenerPendingRetry: function(aListener) {
|
||||
addListenerPendingRetry(aListener) {
|
||||
this._listenersPendingRetry.add(aListener);
|
||||
},
|
||||
|
||||
removeListenerPendingRetry: function(aListener) {
|
||||
removeListenerPendingRetry(aListener) {
|
||||
if (!this._listenersPendingRetry.remove(aListener)) {
|
||||
console.debug("removeListenerPendingRetry: listener not in list?");
|
||||
}
|
||||
},
|
||||
|
||||
_pushChannelOnStop: function(aUri, aAckUri, aHeaders, aMessage) {
|
||||
_pushChannelOnStop(aUri, aAckUri, aHeaders, aMessage) {
|
||||
console.debug("pushChannelOnStop()");
|
||||
|
||||
this._mainPushService.receivedPushMessage(
|
||||
|
|
|
@ -43,7 +43,7 @@ const kDELIVERY_REASON_TO_CODE = {
|
|||
|
||||
const prefs = new Preferences("dom.push.");
|
||||
|
||||
var EXPORTED_SYMBOLS = ["PushServiceWebSocket"];
|
||||
const EXPORTED_SYMBOLS = ["PushServiceWebSocket"];
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "console", () => {
|
||||
let {ConsoleAPI} = ChromeUtils.import("resource://gre/modules/Console.jsm");
|
||||
|
@ -66,41 +66,41 @@ var PushWebSocketListener = function(pushService) {
|
|||
};
|
||||
|
||||
PushWebSocketListener.prototype = {
|
||||
onStart: function(context) {
|
||||
onStart(context) {
|
||||
if (!this._pushService) {
|
||||
return;
|
||||
}
|
||||
this._pushService._wsOnStart(context);
|
||||
},
|
||||
|
||||
onStop: function(context, statusCode) {
|
||||
onStop(context, statusCode) {
|
||||
if (!this._pushService) {
|
||||
return;
|
||||
}
|
||||
this._pushService._wsOnStop(context, statusCode);
|
||||
},
|
||||
|
||||
onAcknowledge: function(context, size) {
|
||||
onAcknowledge(context, size) {
|
||||
// EMPTY
|
||||
},
|
||||
|
||||
onBinaryMessageAvailable: function(context, message) {
|
||||
onBinaryMessageAvailable(context, message) {
|
||||
// EMPTY
|
||||
},
|
||||
|
||||
onMessageAvailable: function(context, message) {
|
||||
onMessageAvailable(context, message) {
|
||||
if (!this._pushService) {
|
||||
return;
|
||||
}
|
||||
this._pushService._wsOnMessageAvailable(context, message);
|
||||
},
|
||||
|
||||
onServerClose: function(context, aStatusCode, aReason) {
|
||||
onServerClose(context, aStatusCode, aReason) {
|
||||
if (!this._pushService) {
|
||||
return;
|
||||
}
|
||||
this._pushService._wsOnServerClose(context, aStatusCode, aReason);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
// websocket states
|
||||
|
@ -118,7 +118,7 @@ var PushServiceWebSocket = {
|
|||
_mainPushService: null,
|
||||
_serverURI: null,
|
||||
|
||||
newPushDB: function() {
|
||||
newPushDB() {
|
||||
return new PushDB(kPUSHWSDB_DB_NAME,
|
||||
kPUSHWSDB_DB_VERSION,
|
||||
kPUSHWSDB_STORE_NAME,
|
||||
|
@ -126,11 +126,11 @@ var PushServiceWebSocket = {
|
|||
PushRecordWebSocket);
|
||||
},
|
||||
|
||||
disconnect: function() {
|
||||
disconnect() {
|
||||
this._shutdownWS();
|
||||
},
|
||||
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
observe(aSubject, aTopic, aData) {
|
||||
if (aTopic == "nsPref:changed" && aData == "dom.push.userAgentID") {
|
||||
this._onUAIDChanged();
|
||||
} else if (aTopic == "timer-callback") {
|
||||
|
@ -167,7 +167,6 @@ var PushServiceWebSocket = {
|
|||
|
||||
if (timer == this._requestTimeoutTimer) {
|
||||
this._timeOutRequests();
|
||||
return;
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -208,10 +207,8 @@ var PushServiceWebSocket = {
|
|||
|
||||
if (this._lastPingTime > 0 &&
|
||||
now - this._lastPingTime > this._requestTimeout) {
|
||||
|
||||
console.debug("timeOutRequests: Did not receive pong in time");
|
||||
requestTimedOut = true;
|
||||
|
||||
} else {
|
||||
for (let [key, request] of this._pendingRequests) {
|
||||
let duration = now - request.ctime;
|
||||
|
@ -233,7 +230,7 @@ var PushServiceWebSocket = {
|
|||
}
|
||||
},
|
||||
|
||||
validServerURI: function(serverURI) {
|
||||
validServerURI(serverURI) {
|
||||
if (serverURI.scheme == "ws") {
|
||||
return !!prefs.get("testing.allowInsecureServerURL");
|
||||
}
|
||||
|
@ -296,7 +293,7 @@ var PushServiceWebSocket = {
|
|||
* Sends a message to the Push Server through an open websocket.
|
||||
* typeof(msg) shall be an object
|
||||
*/
|
||||
_wsSendMessage: function(msg) {
|
||||
_wsSendMessage(msg) {
|
||||
if (!this._ws) {
|
||||
console.warn("wsSendMessage: No WebSocket initialized.",
|
||||
"Cannot send a message");
|
||||
|
@ -307,7 +304,7 @@ var PushServiceWebSocket = {
|
|||
this._ws.sendMsg(msg);
|
||||
},
|
||||
|
||||
init: function(options, mainPushService, serverURI) {
|
||||
init(options, mainPushService, serverURI) {
|
||||
console.debug("init()");
|
||||
|
||||
this._mainPushService = mainPushService;
|
||||
|
@ -327,13 +324,13 @@ var PushServiceWebSocket = {
|
|||
return Promise.resolve();
|
||||
},
|
||||
|
||||
_reconnect: function () {
|
||||
_reconnect() {
|
||||
console.debug("reconnect()");
|
||||
this._shutdownWS(false);
|
||||
this._startBackoffTimer();
|
||||
},
|
||||
|
||||
_shutdownWS: function(shouldCancelPending = true) {
|
||||
_shutdownWS(shouldCancelPending = true) {
|
||||
console.debug("shutdownWS()");
|
||||
|
||||
if (this._currentState == STATE_READY) {
|
||||
|
@ -367,7 +364,7 @@ var PushServiceWebSocket = {
|
|||
}
|
||||
},
|
||||
|
||||
uninit: function() {
|
||||
uninit() {
|
||||
// All pending requests (ideally none) are dropped at this point. We
|
||||
// shouldn't have any applications performing registration/unregistration
|
||||
// or receiving notifications.
|
||||
|
@ -449,7 +446,7 @@ var PushServiceWebSocket = {
|
|||
Ci.nsITimer.TYPE_ONE_SHOT);
|
||||
},
|
||||
|
||||
_makeWebSocket: function(uri) {
|
||||
_makeWebSocket(uri) {
|
||||
if (!prefs.get("connection.enabled")) {
|
||||
console.warn("makeWebSocket: connection.enabled is not set to true.",
|
||||
"Aborting.");
|
||||
|
@ -473,7 +470,7 @@ var PushServiceWebSocket = {
|
|||
return socket;
|
||||
},
|
||||
|
||||
_beginWSSetup: function() {
|
||||
_beginWSSetup() {
|
||||
console.debug("beginWSSetup()");
|
||||
if (this._currentState != STATE_SHUT_DOWN) {
|
||||
console.error("_beginWSSetup: Not in shutdown state! Current state",
|
||||
|
@ -505,27 +502,27 @@ var PushServiceWebSocket = {
|
|||
// sleep before connection the is opened.
|
||||
this._ws.asyncOpen(uri, uri.spec, 0, this._wsListener, null);
|
||||
this._currentState = STATE_WAITING_FOR_WS_START;
|
||||
} catch(e) {
|
||||
} catch (e) {
|
||||
console.error("beginWSSetup: Error opening websocket.",
|
||||
"asyncOpen failed", e);
|
||||
this._reconnect();
|
||||
}
|
||||
},
|
||||
|
||||
connect: function(broadcastListeners) {
|
||||
connect(broadcastListeners) {
|
||||
console.debug("connect()", broadcastListeners);
|
||||
this._broadcastListeners = broadcastListeners;
|
||||
this._beginWSSetup();
|
||||
},
|
||||
|
||||
isConnected: function() {
|
||||
isConnected() {
|
||||
return !!this._ws;
|
||||
},
|
||||
|
||||
/**
|
||||
* Protocol handler invoked by server message.
|
||||
*/
|
||||
_handleHelloReply: function(reply) {
|
||||
_handleHelloReply(reply) {
|
||||
console.debug("handleHelloReply()");
|
||||
if (this._currentState != STATE_WAITING_FOR_HELLO) {
|
||||
console.error("handleHelloReply: Unexpected state", this._currentState,
|
||||
|
@ -611,7 +608,7 @@ var PushServiceWebSocket = {
|
|||
/**
|
||||
* Protocol handler invoked by server message.
|
||||
*/
|
||||
_handleRegisterReply: function(reply) {
|
||||
_handleRegisterReply(reply) {
|
||||
console.debug("handleRegisterReply()");
|
||||
|
||||
let tmp = this._takeRequestForReply(reply);
|
||||
|
@ -622,8 +619,7 @@ var PushServiceWebSocket = {
|
|||
if (reply.status == 200) {
|
||||
try {
|
||||
Services.io.newURI(reply.pushEndpoint);
|
||||
}
|
||||
catch (e) {
|
||||
} catch (e) {
|
||||
tmp.reject(new Error("Invalid push endpoint: " + reply.pushEndpoint));
|
||||
return;
|
||||
}
|
||||
|
@ -658,7 +654,7 @@ var PushServiceWebSocket = {
|
|||
request.resolve(success);
|
||||
},
|
||||
|
||||
_handleDataUpdate: function(update) {
|
||||
_handleDataUpdate(update) {
|
||||
let promise;
|
||||
if (typeof update.channelID != "string") {
|
||||
console.warn("handleDataUpdate: Discarding update without channel ID",
|
||||
|
@ -714,14 +710,14 @@ var PushServiceWebSocket = {
|
|||
/**
|
||||
* Protocol handler invoked by server message.
|
||||
*/
|
||||
_handleNotificationReply: function(reply) {
|
||||
_handleNotificationReply(reply) {
|
||||
console.debug("handleNotificationReply()");
|
||||
if (this._dataEnabled) {
|
||||
this._handleDataUpdate(reply);
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeof reply.updates !== 'object') {
|
||||
if (typeof reply.updates !== "object") {
|
||||
console.warn("handleNotificationReply: Missing updates", reply.updates);
|
||||
return;
|
||||
}
|
||||
|
@ -755,7 +751,7 @@ var PushServiceWebSocket = {
|
|||
}
|
||||
},
|
||||
|
||||
_handleBroadcastReply: function(reply) {
|
||||
_handleBroadcastReply(reply) {
|
||||
this._mainPushService.receivedBroadcastMessage(reply);
|
||||
},
|
||||
|
||||
|
@ -763,11 +759,11 @@ var PushServiceWebSocket = {
|
|||
console.debug("reportDeliveryError()");
|
||||
let code = kDELIVERY_REASON_TO_CODE[reason];
|
||||
if (!code) {
|
||||
throw new Error('Invalid delivery error reason');
|
||||
throw new Error("Invalid delivery error reason");
|
||||
}
|
||||
let data = {messageType: 'nack',
|
||||
let data = {messageType: "nack",
|
||||
version: messageID,
|
||||
code: code};
|
||||
code};
|
||||
this._queueRequest(data);
|
||||
},
|
||||
|
||||
|
@ -775,16 +771,16 @@ var PushServiceWebSocket = {
|
|||
console.debug("sendAck()");
|
||||
let code = kACK_STATUS_TO_CODE[status];
|
||||
if (!code) {
|
||||
throw new Error('Invalid ack status');
|
||||
throw new Error("Invalid ack status");
|
||||
}
|
||||
let data = {messageType: 'ack',
|
||||
updates: [{channelID: channelID,
|
||||
version: version,
|
||||
code: code}]};
|
||||
let data = {messageType: "ack",
|
||||
updates: [{channelID,
|
||||
version,
|
||||
code}]};
|
||||
this._queueRequest(data);
|
||||
},
|
||||
|
||||
_generateID: function() {
|
||||
_generateID() {
|
||||
let uuidGenerator = Cc["@mozilla.org/uuid-generator;1"]
|
||||
.getService(Ci.nsIUUIDGenerator);
|
||||
// generateUUID() gives a UUID surrounded by {...}, slice them off.
|
||||
|
@ -824,11 +820,11 @@ var PushServiceWebSocket = {
|
|||
return Promise.resolve().then(_ => {
|
||||
let code = kUNREGISTER_REASON_TO_CODE[reason];
|
||||
if (!code) {
|
||||
throw new Error('Invalid unregister reason');
|
||||
throw new Error("Invalid unregister reason");
|
||||
}
|
||||
let data = {channelID: record.channelID,
|
||||
messageType: "unregister",
|
||||
code: code};
|
||||
code};
|
||||
|
||||
return this._sendRequestForReply(record, data);
|
||||
});
|
||||
|
@ -837,7 +833,7 @@ var PushServiceWebSocket = {
|
|||
_queueStart: Promise.resolve(),
|
||||
_notifyRequestQueue: null,
|
||||
_queue: null,
|
||||
_enqueue: function(op) {
|
||||
_enqueue(op) {
|
||||
console.debug("enqueue()");
|
||||
if (!this._queue) {
|
||||
this._queue = this._queueStart;
|
||||
|
@ -923,7 +919,7 @@ var PushServiceWebSocket = {
|
|||
}
|
||||
},
|
||||
|
||||
_receivedUpdate: function(aChannelID, aLatestVersion) {
|
||||
_receivedUpdate(aChannelID, aLatestVersion) {
|
||||
console.debug("receivedUpdate: Updating", aChannelID, "->", aLatestVersion);
|
||||
|
||||
this._mainPushService.receivedPushMessage(aChannelID, "", null, null, record => {
|
||||
|
@ -946,7 +942,7 @@ var PushServiceWebSocket = {
|
|||
},
|
||||
|
||||
// begin Push protocol handshake
|
||||
_wsOnStart: function(context) {
|
||||
_wsOnStart(context) {
|
||||
console.debug("wsOnStart()");
|
||||
|
||||
if (this._currentState != STATE_WAITING_FOR_WS_START) {
|
||||
|
@ -976,7 +972,7 @@ var PushServiceWebSocket = {
|
|||
* If we do not explicitly call ws.close() then statusCode is always
|
||||
* NS_BASE_STREAM_CLOSED, even on a successful close.
|
||||
*/
|
||||
_wsOnStop: function(context, statusCode) {
|
||||
_wsOnStop(context, statusCode) {
|
||||
console.debug("wsOnStop()");
|
||||
|
||||
if (statusCode != Cr.NS_OK && !this._skipReconnect) {
|
||||
|
@ -988,7 +984,7 @@ var PushServiceWebSocket = {
|
|||
this._shutdownWS();
|
||||
},
|
||||
|
||||
_wsOnMessageAvailable: function(context, message) {
|
||||
_wsOnMessageAvailable(context, message) {
|
||||
console.debug("wsOnMessageAvailable()", message);
|
||||
|
||||
// Clearing the last ping time indicates we're no longer waiting for a pong.
|
||||
|
@ -997,7 +993,7 @@ var PushServiceWebSocket = {
|
|||
let reply;
|
||||
try {
|
||||
reply = JSON.parse(message);
|
||||
} catch(e) {
|
||||
} catch (e) {
|
||||
console.warn("wsOnMessageAvailable: Invalid JSON", message, e);
|
||||
return;
|
||||
}
|
||||
|
@ -1007,7 +1003,7 @@ var PushServiceWebSocket = {
|
|||
this._retryFailCount = 0;
|
||||
|
||||
let doNotHandle = false;
|
||||
if ((message === '{}') ||
|
||||
if ((message === "{}") ||
|
||||
(reply.messageType === undefined) ||
|
||||
(reply.messageType === "ping") ||
|
||||
(typeof reply.messageType != "string")) {
|
||||
|
@ -1060,7 +1056,7 @@ var PushServiceWebSocket = {
|
|||
* next network state change event, or until we need to send a new register
|
||||
* request.
|
||||
*/
|
||||
_wsOnServerClose: function(context, aStatusCode, aReason) {
|
||||
_wsOnServerClose(context, aStatusCode, aReason) {
|
||||
console.debug("wsOnServerClose()", aStatusCode, aReason);
|
||||
|
||||
if (aStatusCode == kBACKOFF_WS_STATUS_CODE) {
|
||||
|
@ -1093,8 +1089,8 @@ var PushServiceWebSocket = {
|
|||
let key = this._makePendingRequestKey(data);
|
||||
if (!this._pendingRequests.has(key)) {
|
||||
let request = {
|
||||
data: data,
|
||||
record: record,
|
||||
data,
|
||||
record,
|
||||
ctime: Date.now(),
|
||||
};
|
||||
request.promise = new Promise((resolve, reject) => {
|
||||
|
@ -1130,7 +1126,7 @@ var PushServiceWebSocket = {
|
|||
let data = {
|
||||
messageType: "broadcast_subscribe",
|
||||
broadcasts: {
|
||||
[serviceId]: version
|
||||
[serviceId]: version,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
var state = "from_scope";
|
||||
var resolvePromiseCallback;
|
||||
|
||||
onfetch = function(event) {
|
||||
self.onfetch = function(event) {
|
||||
if (event.request.url.includes("lifetime_frame.html")) {
|
||||
event.respondWith(new Response("iframe_lifetime"));
|
||||
return;
|
||||
|
@ -9,12 +9,12 @@ onfetch = function(event) {
|
|||
|
||||
var currentState = state;
|
||||
event.waitUntil(
|
||||
clients.matchAll()
|
||||
.then(clients => {
|
||||
clients.forEach(client => {
|
||||
client.postMessage({type: "fetch", state: currentState});
|
||||
});
|
||||
})
|
||||
self.clients.matchAll()
|
||||
.then(clients => {
|
||||
clients.forEach(client => {
|
||||
client.postMessage({type: "fetch", state: currentState});
|
||||
});
|
||||
})
|
||||
);
|
||||
|
||||
if (event.request.url.includes("update")) {
|
||||
|
@ -33,7 +33,7 @@ onfetch = function(event) {
|
|||
state = "release";
|
||||
resolvePromise();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function resolvePromise() {
|
||||
if (resolvePromiseCallback === undefined || resolvePromiseCallback == null) {
|
||||
|
@ -44,23 +44,23 @@ function resolvePromise() {
|
|||
resolvePromiseCallback = null;
|
||||
}
|
||||
|
||||
onmessage = function(event) {
|
||||
self.onmessage = function(event) {
|
||||
var lastState = state;
|
||||
state = event.data;
|
||||
if (state === 'wait') {
|
||||
if (state === "wait") {
|
||||
event.waitUntil(new Promise(function(res, rej) {
|
||||
if (resolvePromiseCallback) {
|
||||
dump("ERROR: service worker was already waiting on a promise.\n");
|
||||
}
|
||||
resolvePromiseCallback = res;
|
||||
}));
|
||||
} else if (state === 'release') {
|
||||
} else if (state === "release") {
|
||||
resolvePromise();
|
||||
}
|
||||
event.source.postMessage({type: "message", state: lastState});
|
||||
}
|
||||
};
|
||||
|
||||
onpush = function(event) {
|
||||
self.onpush = function(event) {
|
||||
var pushResolve;
|
||||
event.waitUntil(new Promise(function(resolve) {
|
||||
pushResolve = resolve;
|
||||
|
@ -68,12 +68,12 @@ onpush = function(event) {
|
|||
|
||||
// FIXME(catalinb): push message carry no data. So we assume the only
|
||||
// push message we get is "wait"
|
||||
clients.matchAll().then(function(client) {
|
||||
self.clients.matchAll().then(function(client) {
|
||||
if (client.length == 0) {
|
||||
dump("ERROR: no clients to send the response to.\n");
|
||||
}
|
||||
|
||||
client[0].postMessage({type: "push", state: state});
|
||||
client[0].postMessage({type: "push", state});
|
||||
|
||||
state = "wait";
|
||||
if (resolvePromiseCallback) {
|
||||
|
@ -82,4 +82,4 @@ onpush = function(event) {
|
|||
resolvePromiseCallback = pushResolve;
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
/* eslint-env mozilla/frame-script */
|
||||
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
|
@ -61,7 +63,7 @@ var pushService = Cc["@mozilla.org/push/Service;1"].
|
|||
var mockSocket;
|
||||
var serverMsgs = [];
|
||||
|
||||
addMessageListener("socket-setup", function () {
|
||||
addMessageListener("socket-setup", function() {
|
||||
pushService.replaceServiceBackend({
|
||||
serverURI: "wss://push.example.org/",
|
||||
makeWebSocket(uri) {
|
||||
|
@ -71,11 +73,11 @@ addMessageListener("socket-setup", function () {
|
|||
mockSocket.serverSendMsg(msg);
|
||||
}
|
||||
return mockSocket;
|
||||
}
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
addMessageListener("socket-teardown", function (msg) {
|
||||
addMessageListener("socket-teardown", function(msg) {
|
||||
pushService.restoreServiceBackend().then(_ => {
|
||||
serverMsgs.length = 0;
|
||||
if (mockSocket) {
|
||||
|
@ -85,10 +87,10 @@ addMessageListener("socket-teardown", function (msg) {
|
|||
sendAsyncMessage("socket-server-teardown");
|
||||
}).catch(error => {
|
||||
Cu.reportError(`Error restoring service backend: ${error}`);
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
addMessageListener("socket-server-msg", function (msg) {
|
||||
addMessageListener("socket-server-msg", function(msg) {
|
||||
if (mockSocket) {
|
||||
mockSocket.serverSendMsg(msg);
|
||||
} else {
|
||||
|
@ -105,9 +107,9 @@ var MockService = {
|
|||
let id = this.requestID++;
|
||||
this.resolvers.set(id, { resolve, reject });
|
||||
sendAsyncMessage("service-request", {
|
||||
name: name,
|
||||
id: id,
|
||||
params: params,
|
||||
name,
|
||||
id,
|
||||
params,
|
||||
});
|
||||
});
|
||||
},
|
||||
|
@ -142,8 +144,8 @@ var MockService = {
|
|||
|
||||
reportDeliveryError(messageId, reason) {
|
||||
sendAsyncMessage("service-delivery-error", {
|
||||
messageId: messageId,
|
||||
reason: reason,
|
||||
messageId,
|
||||
reason,
|
||||
});
|
||||
},
|
||||
|
||||
|
@ -174,6 +176,6 @@ addMessageListener("service-restore", function() {
|
|||
});
|
||||
});
|
||||
|
||||
addMessageListener("service-response", function (response) {
|
||||
addMessageListener("service-response", function(response) {
|
||||
MockService.handleResponse(response);
|
||||
});
|
||||
|
|
|
@ -25,6 +25,10 @@ http://creativecommons.org/licenses/publicdomain/
|
|||
</pre>
|
||||
|
||||
<script class="testbody" type="text/javascript">
|
||||
/* import-globals-from ./test_utils.js */
|
||||
|
||||
/* globals webPushEncrypt */
|
||||
|
||||
var userAgentID = "ac44402c-85fc-41e4-a0d0-483316d15351";
|
||||
var channelID = null;
|
||||
|
||||
|
@ -36,7 +40,7 @@ http://creativecommons.org/licenses/publicdomain/
|
|||
uaid: userAgentID,
|
||||
channelID,
|
||||
status: 200,
|
||||
pushEndpoint: "https://example.com/endpoint/1"
|
||||
pushEndpoint: "https://example.com/endpoint/1",
|
||||
}));
|
||||
};
|
||||
|
||||
|
@ -45,7 +49,7 @@ http://creativecommons.org/licenses/publicdomain/
|
|||
await setupPrefsAndMockSocket(mockSocket);
|
||||
await setPushPermission(true);
|
||||
|
||||
var url = "worker.js" + "?" + (Math.random());
|
||||
var url = "worker.js?" + (Math.random());
|
||||
registration = await navigator.serviceWorker.register(url, {scope: "."});
|
||||
await waitForActive(registration);
|
||||
});
|
||||
|
@ -92,28 +96,28 @@ http://creativecommons.org/licenses/publicdomain/
|
|||
});
|
||||
|
||||
var version = 0;
|
||||
function sendEncryptedMsg(pushSubscription, message) {
|
||||
return webPushEncrypt(pushSubscription, message)
|
||||
function sendEncryptedMsg(pushSub, message) {
|
||||
return webPushEncrypt(pushSub, message)
|
||||
.then((encryptedData) => {
|
||||
mockSocket.serverSendMsg(JSON.stringify({
|
||||
messageType: 'notification',
|
||||
messageType: "notification",
|
||||
version: version++,
|
||||
channelID: channelID,
|
||||
channelID,
|
||||
data: encryptedData.data,
|
||||
headers: {
|
||||
encryption: encryptedData.encryption,
|
||||
encryption_key: encryptedData.encryption_key,
|
||||
encoding: encryptedData.encoding
|
||||
}
|
||||
encoding: encryptedData.encoding,
|
||||
},
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
function waitForMessage(pushSubscription, message) {
|
||||
function waitForMessage(pushSub, message) {
|
||||
return Promise.all([
|
||||
controlledFrame.waitOnWorkerMessage("finished"),
|
||||
sendEncryptedMsg(pushSubscription, message),
|
||||
]).then(([message]) => message);
|
||||
sendEncryptedMsg(pushSub, message),
|
||||
]).then(([msg]) => msg);
|
||||
}
|
||||
|
||||
add_task(async function sendPushMessageFromPage() {
|
||||
|
@ -169,11 +173,11 @@ http://creativecommons.org/licenses/publicdomain/
|
|||
mockSocket.serverSendMsg(JSON.stringify({
|
||||
messageType: "notification",
|
||||
version: "vDummy",
|
||||
channelID: channelID
|
||||
channelID,
|
||||
}));
|
||||
|
||||
var message = await finishedPromise;
|
||||
ok(!message.data, "Should exclude data for blank messages");
|
||||
var msg = await finishedPromise;
|
||||
ok(!msg.data, "Should exclude data for blank messages");
|
||||
});
|
||||
|
||||
add_task(async function unsubscribe() {
|
||||
|
|
|
@ -24,6 +24,7 @@ http://creativecommons.org/licenses/publicdomain/
|
|||
</pre>
|
||||
|
||||
<script class="testbody" type="text/javascript">
|
||||
/* import-globals-from ./test_utils.js */
|
||||
|
||||
var pushNotifier = SpecialPowers.Cc["@mozilla.org/push/Notifier;1"]
|
||||
.getService(SpecialPowers.Ci.nsIPushNotifier);
|
||||
|
@ -35,7 +36,7 @@ http://creativecommons.org/licenses/publicdomain/
|
|||
await setupPrefsAndReplaceService({
|
||||
reportDeliveryError(messageId, reason) {
|
||||
ok(reporters.has(messageId),
|
||||
'Unexpected error reported for message ' + messageId);
|
||||
"Unexpected error reported for message " + messageId);
|
||||
var resolve = reporters.get(messageId);
|
||||
reporters.delete(messageId);
|
||||
resolve(reason);
|
||||
|
@ -43,7 +44,7 @@ http://creativecommons.org/licenses/publicdomain/
|
|||
});
|
||||
await setPushPermission(true);
|
||||
|
||||
var url = "error_worker.js" + "?" + (Math.random());
|
||||
var url = "error_worker.js?" + (Math.random());
|
||||
registration = await navigator.serviceWorker.register(url, {scope: "."});
|
||||
await waitForActive(registration);
|
||||
});
|
||||
|
@ -78,15 +79,15 @@ http://creativecommons.org/licenses/publicdomain/
|
|||
|
||||
add_task(async function reportDecryptionError() {
|
||||
var message = await new Promise(resolve => {
|
||||
SpecialPowers.registerConsoleListener(message => {
|
||||
if (!message.isScriptError && !message.isConsoleEvent) {
|
||||
SpecialPowers.registerConsoleListener(msg => {
|
||||
if (!msg.isScriptError && !msg.isConsoleEvent) {
|
||||
return;
|
||||
}
|
||||
const scope = "http://mochi.test:8888/tests/dom/push/test/";
|
||||
if (message.innerWindowID === "ServiceWorker" &&
|
||||
message.windowID === scope) {
|
||||
if (msg.innerWindowID === "ServiceWorker" &&
|
||||
msg.windowID === scope) {
|
||||
SpecialPowers.postConsoleSentinel();
|
||||
resolve(message);
|
||||
resolve(msg);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -24,15 +24,18 @@ http://creativecommons.org/licenses/publicdomain/
|
|||
</pre>
|
||||
|
||||
<script class="testbody" type="text/javascript">
|
||||
/* import-globals-from ./test_utils.js */
|
||||
|
||||
function debug(str) {
|
||||
// console.log(str + "\n");
|
||||
}
|
||||
|
||||
var registration;
|
||||
|
||||
add_task(async function start() {
|
||||
await setupPrefsAndMockSocket(new MockWebSocket());
|
||||
|
||||
var url = "worker.js" + "?" + Math.random();
|
||||
var url = "worker.js?" + Math.random();
|
||||
registration = await navigator.serviceWorker.register(url, {scope: "."});
|
||||
await waitForActive(registration);
|
||||
});
|
||||
|
|
|
@ -23,15 +23,18 @@ http://creativecommons.org/licenses/publicdomain/
|
|||
</pre>
|
||||
|
||||
<script class="testbody" type="text/javascript">
|
||||
/* import-globals-from ./test_utils.js */
|
||||
|
||||
function debug(str) {
|
||||
// console.log(str + "\n");
|
||||
}
|
||||
|
||||
var registration;
|
||||
|
||||
function start() {
|
||||
return navigator.serviceWorker.register("worker.js" + "?" + (Math.random()), {scope: "."})
|
||||
return navigator.serviceWorker.register("worker.js?" + (Math.random()), {scope: "."})
|
||||
.then((swr) => {
|
||||
registration = swr
|
||||
registration = swr;
|
||||
return waitForActive(registration);
|
||||
});
|
||||
}
|
||||
|
@ -49,7 +52,7 @@ http://creativecommons.org/licenses/publicdomain/
|
|||
swr.pushManager.subscribe().then(
|
||||
function(pushSubscription) {
|
||||
ok(true, "successful registered for push notification");
|
||||
res({swr: swr, pushSubscription: pushSubscription});
|
||||
res({swr, pushSubscription});
|
||||
}, function(error) {
|
||||
ok(false, "could not register for push notification");
|
||||
res(null);
|
||||
|
|
|
@ -23,6 +23,7 @@ http://creativecommons.org/licenses/publicdomain/
|
|||
</pre>
|
||||
|
||||
<script class="testbody" type="text/javascript">
|
||||
/* import-globals-from ./test_utils.js */
|
||||
|
||||
var scopeA = "./a/";
|
||||
var scopeB = "./b/";
|
||||
|
@ -32,7 +33,7 @@ http://creativecommons.org/licenses/publicdomain/
|
|||
}
|
||||
|
||||
function registerServiceWorker(scope) {
|
||||
return navigator.serviceWorker.register("worker.js" + "?" + (Math.random()), {scope: scope})
|
||||
return navigator.serviceWorker.register("worker.js?" + (Math.random()), {scope})
|
||||
.then(swr => waitForActive(swr));
|
||||
}
|
||||
|
||||
|
@ -41,7 +42,7 @@ http://creativecommons.org/licenses/publicdomain/
|
|||
.then(result => {
|
||||
ok(result, "Unregister should return true.");
|
||||
}, err => {
|
||||
ok(false,"Unregistering the SW failed with " + err + "\n");
|
||||
ok(false, "Unregistering the SW failed with " + err + "\n");
|
||||
throw err;
|
||||
});
|
||||
}
|
||||
|
@ -61,7 +62,7 @@ http://creativecommons.org/licenses/publicdomain/
|
|||
function setupMultipleSubscriptions(swr1, swr2) {
|
||||
return Promise.all([
|
||||
subscribe(swr1),
|
||||
subscribe(swr2)
|
||||
subscribe(swr2),
|
||||
]).then(a => {
|
||||
ok(a[0].endpoint != a[1].endpoint, "setupMultipleSubscriptions - Got different endpoints.");
|
||||
return a;
|
||||
|
|
|
@ -25,13 +25,16 @@ http://creativecommons.org/licenses/publicdomain/
|
|||
</pre>
|
||||
|
||||
<script class="testbody" type="text/javascript">
|
||||
/* import-globals-from ./test_utils.js */
|
||||
|
||||
/* globals setupMockPushSocket,teardownMockPushSocket */
|
||||
|
||||
function debug(str) {
|
||||
// console.log(str + "\n");
|
||||
}
|
||||
|
||||
function registerServiceWorker() {
|
||||
return navigator.serviceWorker.register("worker.js" + "?" + (Math.random()), {scope: "."});
|
||||
return navigator.serviceWorker.register("worker.js?" + (Math.random()), {scope: "."});
|
||||
}
|
||||
|
||||
function unregister(swr) {
|
||||
|
@ -63,7 +66,7 @@ http://creativecommons.org/licenses/publicdomain/
|
|||
var pushSubscription;
|
||||
return Promise.all([
|
||||
subscribe(swr),
|
||||
subscribe(swr)
|
||||
subscribe(swr),
|
||||
]).then(a => {
|
||||
ok(a[0].endpoint == a[1].endpoint, "setupMultipleSubscriptions - Got the same endpoint back.");
|
||||
pushSubscription = a[0];
|
||||
|
|
|
@ -24,6 +24,7 @@ http://creativecommons.org/licenses/publicdomain/
|
|||
</pre>
|
||||
|
||||
<script class="testbody" type="text/javascript">
|
||||
/* import-globals-from ./test_utils.js */
|
||||
|
||||
function debug(str) {
|
||||
// console.log(str + "\n");
|
||||
|
@ -34,7 +35,7 @@ http://creativecommons.org/licenses/publicdomain/
|
|||
await setupPrefsAndMockSocket(new MockWebSocket());
|
||||
await setPushPermission(false);
|
||||
|
||||
var url = "worker.js" + "?" + Math.random();
|
||||
var url = "worker.js?" + Math.random();
|
||||
registration = await navigator.serviceWorker.register(url, {scope: "."});
|
||||
await waitForActive(registration);
|
||||
});
|
||||
|
|
|
@ -24,6 +24,7 @@ http://creativecommons.org/licenses/publicdomain/
|
|||
</pre>
|
||||
|
||||
<script class="testbody" type="text/javascript">
|
||||
/* import-globals-from ./test_utils.js */
|
||||
|
||||
function debug(str) {
|
||||
// console.log(str + "\n");
|
||||
|
@ -40,7 +41,7 @@ http://creativecommons.org/licenses/publicdomain/
|
|||
uaid: "c69e2014-9e15-438d-b253-d79cc2df60a8",
|
||||
channelID,
|
||||
status: 200,
|
||||
pushEndpoint: "https://example.com/endpoint/1"
|
||||
pushEndpoint: "https://example.com/endpoint/1",
|
||||
}));
|
||||
};
|
||||
|
||||
|
@ -49,7 +50,7 @@ http://creativecommons.org/licenses/publicdomain/
|
|||
await setupPrefsAndMockSocket(mockSocket);
|
||||
await setPushPermission(true);
|
||||
|
||||
var url = "worker.js" + "?" + (Math.random());
|
||||
var url = "worker.js?" + (Math.random());
|
||||
registration = await navigator.serviceWorker.register(url, {scope: "."});
|
||||
await waitForActive(registration);
|
||||
});
|
||||
|
@ -88,7 +89,7 @@ http://creativecommons.org/licenses/publicdomain/
|
|||
mockSocket.serverSendMsg(JSON.stringify({
|
||||
messageType: "notification",
|
||||
version: "vDummy",
|
||||
channelID: channelID
|
||||
channelID,
|
||||
}));
|
||||
|
||||
await finishedPromise;
|
||||
|
|
|
@ -24,6 +24,7 @@ http://creativecommons.org/licenses/publicdomain/
|
|||
</pre>
|
||||
|
||||
<script class="testbody" type="text/javascript">
|
||||
/* import-globals-from ./test_utils.js */
|
||||
|
||||
var isTestingMismatchedKey = false;
|
||||
var subscriptions = 0;
|
||||
|
@ -45,10 +46,12 @@ http://creativecommons.org/licenses/publicdomain/
|
|||
ok(pageRecord.appServerKey.length > 0,
|
||||
"App server key should not be empty");
|
||||
if (pageRecord.appServerKey.length != 65) {
|
||||
// eslint-disable-next-line no-throw-literal
|
||||
throw { result:
|
||||
SpecialPowers.Cr.NS_ERROR_DOM_PUSH_INVALID_KEY_ERR };
|
||||
}
|
||||
if (isTestingMismatchedKey) {
|
||||
SpecialPowers.Cr.NS_ERROR_DOM_PUSH_INVALID_KEY_ERR };
|
||||
}
|
||||
if (isTestingMismatchedKey) {
|
||||
// eslint-disable-next-line no-throw-literal
|
||||
throw { result:
|
||||
SpecialPowers.Cr.NS_ERROR_DOM_PUSH_MISMATCHED_KEY_ERR };
|
||||
}
|
||||
|
@ -68,7 +71,7 @@ http://creativecommons.org/licenses/publicdomain/
|
|||
await setPushPermission(true);
|
||||
testKey = await generateKey();
|
||||
|
||||
var url = "worker.js" + "?" + (Math.random());
|
||||
var url = "worker.js?" + (Math.random());
|
||||
registration = await navigator.serviceWorker.register(url, {scope: "."});
|
||||
await waitForActive(registration);
|
||||
});
|
||||
|
@ -171,7 +174,7 @@ http://creativecommons.org/licenses/publicdomain/
|
|||
var key = await generateKey();
|
||||
var data = await sendRequestToWorker({
|
||||
type: "subscribeWithKey",
|
||||
key: key,
|
||||
key,
|
||||
});
|
||||
is(data.endpoint, "https://example.com/push/2",
|
||||
"Wrong endpoint for subscription with key created in worker");
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
</pre>
|
||||
|
||||
<script class="testbody" type="text/javascript">
|
||||
/* import-globals-from ./test_utils.js */
|
||||
|
||||
function start() {
|
||||
return navigator.serviceWorker.register("lifetime_worker.js", {scope: "./"})
|
||||
|
@ -82,7 +83,7 @@
|
|||
uaid: "fa8f2e4b-5ddc-4408-b1e3-5f25a02abff0",
|
||||
channelID,
|
||||
status: 200,
|
||||
pushEndpoint: endpoint
|
||||
pushEndpoint: endpoint,
|
||||
}));
|
||||
};
|
||||
|
||||
|
@ -91,7 +92,7 @@
|
|||
mockSocket.serverSendMsg(JSON.stringify({
|
||||
messageType: "notification",
|
||||
version: "vDummy",
|
||||
channelID
|
||||
channelID,
|
||||
}));
|
||||
}
|
||||
|
||||
|
@ -105,7 +106,7 @@
|
|||
|
||||
function createIframe(ctx) {
|
||||
var p = new Promise(function(res, rej) {
|
||||
var iframe = document.createElement('iframe');
|
||||
var iframe = document.createElement("iframe");
|
||||
// This file doesn't exist, the service worker will give us an empty
|
||||
// document.
|
||||
iframe.src = "http://mochi.test:8888/tests/dom/push/test/lifetime_frame.html";
|
||||
|
@ -113,7 +114,7 @@
|
|||
iframe.onload = function() {
|
||||
ctx.iframe = iframe;
|
||||
res(ctx);
|
||||
}
|
||||
};
|
||||
document.body.appendChild(iframe);
|
||||
});
|
||||
return p;
|
||||
|
@ -130,9 +131,9 @@
|
|||
}
|
||||
|
||||
function waitAndCheckMessage(contentWindow, expected) {
|
||||
function checkMessage(expected, resolve, event) {
|
||||
ok(event.data.type == expected.type, "Received correct message type: " + expected.type);
|
||||
ok(event.data.state == expected.state, "Service worker is in the correct state: " + expected.state);
|
||||
function checkMessage({ type, state }, resolve, event) {
|
||||
ok(event.data.type == type, "Received correct message type: " + type);
|
||||
ok(event.data.state == state, "Service worker is in the correct state: " + state);
|
||||
this.navigator.serviceWorker.onmessage = null;
|
||||
resolve();
|
||||
}
|
||||
|
@ -174,7 +175,7 @@
|
|||
return function(ctx) {
|
||||
return eventFunction(ctx, expected_state, new_state)
|
||||
.then(() => ctx);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
let shutdownTopic =
|
||||
|
@ -190,21 +191,21 @@
|
|||
|
||||
ctx.observer_promise = new Promise(function(res, rej) {
|
||||
ctx.observer = {
|
||||
observe: function(subject, topic, data) {
|
||||
observe(subject, topic, data) {
|
||||
ok((topic == shutdownTopic) && expectingEvent, "Service worker was terminated.");
|
||||
this.remove(ctx);
|
||||
},
|
||||
remove: function(ctx) {
|
||||
remove(context) {
|
||||
SpecialPowers.removeObserver(this, shutdownTopic);
|
||||
ctx.observer = null;
|
||||
res(ctx);
|
||||
}
|
||||
}
|
||||
context.observer = null;
|
||||
res(context);
|
||||
},
|
||||
};
|
||||
SpecialPowers.addObserver(ctx.observer, shutdownTopic);
|
||||
});
|
||||
|
||||
return ctx;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function waitOnShutdownObserver(ctx) {
|
||||
|
@ -225,22 +226,22 @@
|
|||
function run() {
|
||||
test.steps(ctx).catch(function(e) {
|
||||
ok(false, "Some test failed with error: " + e);
|
||||
}).then((ctx) => res(ctx));
|
||||
}).then(res);
|
||||
}
|
||||
|
||||
SpecialPowers.pushPrefEnv({"set" : test.prefs}, run);
|
||||
SpecialPowers.pushPrefEnv({"set": test.prefs}, run);
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
var test1 = {
|
||||
prefs: [
|
||||
["dom.serviceWorkers.idle_timeout", 0],
|
||||
["dom.serviceWorkers.idle_extended_timeout", 2999999]
|
||||
["dom.serviceWorkers.idle_extended_timeout", 2999999],
|
||||
],
|
||||
// Test that service workers are terminated after the grace period expires
|
||||
// when there are no pending waitUntil or respondWith promises.
|
||||
steps: function(ctx) {
|
||||
steps(ctx) {
|
||||
// Test with fetch events and respondWith promises
|
||||
return createIframe(ctx)
|
||||
.then(setShutdownObserver(true))
|
||||
|
@ -271,16 +272,16 @@
|
|||
.then(setShutdownObserver(true))
|
||||
.then(checkStateAndUpdate(messageEventIframe, "update", "release"))
|
||||
.then(waitOnShutdownObserver)
|
||||
.then(closeIframe)
|
||||
}
|
||||
}
|
||||
.then(closeIframe);
|
||||
},
|
||||
};
|
||||
|
||||
var test2 = {
|
||||
prefs: [
|
||||
["dom.serviceWorkers.idle_timeout", 0],
|
||||
["dom.serviceWorkers.idle_extended_timeout", 2999999]
|
||||
["dom.serviceWorkers.idle_extended_timeout", 2999999],
|
||||
],
|
||||
steps: function(ctx) {
|
||||
steps(ctx) {
|
||||
// Older versions used to terminate workers when the last controlled
|
||||
// window was closed. This should no longer happen, though. Verify
|
||||
// the new behavior.
|
||||
|
@ -308,30 +309,30 @@
|
|||
.then(closeIframe)
|
||||
.then(setShutdownObserver(true))
|
||||
.then(checkStateAndUpdate(messageEvent, "wait", "release"))
|
||||
.then(waitOnShutdownObserver)
|
||||
}
|
||||
.then(waitOnShutdownObserver);
|
||||
},
|
||||
};
|
||||
|
||||
var test3 = {
|
||||
prefs: [
|
||||
["dom.serviceWorkers.idle_timeout", 2999999],
|
||||
["dom.serviceWorkers.idle_extended_timeout", 0]
|
||||
["dom.serviceWorkers.idle_extended_timeout", 0],
|
||||
],
|
||||
steps: function(ctx) {
|
||||
steps(ctx) {
|
||||
// set the grace period to 0 and dispatch a message which will reset
|
||||
// the internal sw timer to the new value.
|
||||
var test3_1 = {
|
||||
prefs: [
|
||||
["dom.serviceWorkers.idle_timeout", 0],
|
||||
["dom.serviceWorkers.idle_extended_timeout", 0]
|
||||
["dom.serviceWorkers.idle_extended_timeout", 0],
|
||||
],
|
||||
steps: function(ctx) {
|
||||
return new Promise(function(res, rej) {
|
||||
ctx.iframe.contentWindow.fetch("update");
|
||||
res(ctx);
|
||||
});
|
||||
}
|
||||
}
|
||||
steps(context) {
|
||||
return new Promise(function(res, rej) {
|
||||
context.iframe.contentWindow.fetch("update");
|
||||
res(context);
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
// Test that service worker is closed when the extended timeout expired
|
||||
return createIframe(ctx)
|
||||
|
@ -342,9 +343,9 @@
|
|||
.then(setShutdownObserver(true))
|
||||
.then(subTest(test3_1)) // This should cause the internal timer to expire.
|
||||
.then(waitOnShutdownObserver)
|
||||
.then(closeIframe)
|
||||
}
|
||||
}
|
||||
.then(closeIframe);
|
||||
},
|
||||
};
|
||||
|
||||
function runTest() {
|
||||
start()
|
||||
|
@ -356,12 +357,12 @@
|
|||
.then(unregisterPushNotification)
|
||||
.then(unregister)
|
||||
.catch(function(e) {
|
||||
ok(false, "Some test failed with error " + e)
|
||||
ok(false, "Some test failed with error " + e);
|
||||
}).then(SimpleTest.finish);
|
||||
}
|
||||
|
||||
setupPrefsAndMockSocket(mockSocket).then(_ => runTest());
|
||||
SpecialPowers.addPermission('desktop-notification', true, document);
|
||||
SpecialPowers.addPermission("desktop-notification", true, document);
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
</script>
|
||||
</body>
|
||||
|
|
|
@ -24,13 +24,14 @@ http://creativecommons.org/licenses/publicdomain/
|
|||
</pre>
|
||||
|
||||
<script class="testbody" type="text/javascript">
|
||||
/* import-globals-from ./test_utils.js */
|
||||
|
||||
var registration;
|
||||
add_task(async function start() {
|
||||
await setupPrefsAndMockSocket(new MockWebSocket());
|
||||
await setPushPermission(true);
|
||||
|
||||
var url = "worker.js" + "?" + (Math.random());
|
||||
var url = "worker.js?" + (Math.random());
|
||||
registration = await navigator.serviceWorker.register(url, {scope: "."});
|
||||
await waitForActive(registration);
|
||||
});
|
||||
|
@ -48,7 +49,7 @@ http://creativecommons.org/licenses/publicdomain/
|
|||
var permissionState = await registration.pushManager.permissionState();
|
||||
is(permissionState, "denied", "Should deny push permission");
|
||||
|
||||
var subscription = await registration.pushManager.getSubscription();
|
||||
subscription = await registration.pushManager.getSubscription();
|
||||
is(subscription, null, "Should not return subscription when permission is revoked");
|
||||
|
||||
var changePromise = controlledFrame.waitOnWorkerMessage("changed");
|
||||
|
|
|
@ -23,13 +23,15 @@ http://creativecommons.org/licenses/publicdomain/
|
|||
</pre>
|
||||
|
||||
<script class="testbody" type="text/javascript">
|
||||
/* eslint-env mozilla/frame-script */
|
||||
/* import-globals-from ./test_utils.js */
|
||||
|
||||
function debug(str) {
|
||||
// console.log(str + "\n");
|
||||
}
|
||||
|
||||
function registerServiceWorker() {
|
||||
return navigator.serviceWorker.register("worker.js" + "?" + (Math.random()), {scope: "."})
|
||||
return navigator.serviceWorker.register("worker.js?" + (Math.random()), {scope: "."})
|
||||
.then(swr => waitForActive(swr));
|
||||
}
|
||||
|
||||
|
@ -59,7 +61,7 @@ http://creativecommons.org/licenses/publicdomain/
|
|||
swr.pushManager.subscribe()
|
||||
.then(sub => {
|
||||
ok(false, "successful registered for push notification");
|
||||
throw "Should fail";
|
||||
throw new Error("Should fail");
|
||||
}, err => {
|
||||
ok(true, "could not register for push notification");
|
||||
res(swr);
|
||||
|
@ -90,10 +92,11 @@ http://creativecommons.org/licenses/publicdomain/
|
|||
|
||||
// Load chrome script to change offline status in the
|
||||
// parent process.
|
||||
var chromeScript = SpecialPowers.loadChromeScript(_ => {
|
||||
var ioService = Cc["@mozilla.org/network/io-service;1"]
|
||||
.getService(Ci.nsIIOService);
|
||||
var offlineChromeScript = SpecialPowers.loadChromeScript(_ => {
|
||||
addMessageListener("change-status", function(offline) {
|
||||
// eslint-disable-next-line mozilla/use-services
|
||||
const ioService = Cc["@mozilla.org/network/io-service;1"]
|
||||
.getService(Ci.nsIIOService);
|
||||
ioService.offline = offline;
|
||||
});
|
||||
});
|
||||
|
@ -104,24 +107,26 @@ http://creativecommons.org/licenses/publicdomain/
|
|||
offlineObserver.prototype = {
|
||||
_res: null,
|
||||
|
||||
observe: function(subject, topic, data) {
|
||||
debug("observe: " + subject + " " + topic + " " + data);
|
||||
if (topic === "network:offline-status-changed") {
|
||||
var obsService = SpecialPowers.Cc["@mozilla.org/observer-service;1"]
|
||||
.getService(SpecialPowers.Ci.nsIObserverService);
|
||||
obsService.removeObserver(this, topic);
|
||||
this._res(null);
|
||||
}
|
||||
observe(subject, topic, data) {
|
||||
debug("observe: " + subject + " " + topic + " " + data);
|
||||
if (topic === "network:offline-status-changed") {
|
||||
// eslint-disable-next-line mozilla/use-services
|
||||
const obsService = SpecialPowers.Cc["@mozilla.org/observer-service;1"]
|
||||
.getService(SpecialPowers.Ci.nsIObserverService);
|
||||
obsService.removeObserver(this, topic);
|
||||
this._res(null);
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
function changeOfflineState(offline) {
|
||||
return new Promise(function(res, rej) {
|
||||
var obsService = SpecialPowers.Cc["@mozilla.org/observer-service;1"]
|
||||
.getService(SpecialPowers.Ci.nsIObserverService);
|
||||
// eslint-disable-next-line mozilla/use-services
|
||||
const obsService = SpecialPowers.Cc["@mozilla.org/observer-service;1"]
|
||||
.getService(SpecialPowers.Ci.nsIObserverService);
|
||||
obsService.addObserver(SpecialPowers.wrapCallbackObject(new offlineObserver(res)),
|
||||
"network:offline-status-changed");
|
||||
chromeScript.sendAsyncMessage("change-status", offline);
|
||||
"network:offline-status-changed");
|
||||
offlineChromeScript.sendAsyncMessage("change-status", offline);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -132,7 +137,7 @@ http://creativecommons.org/licenses/publicdomain/
|
|||
|
||||
function unsubscribe(sub) {
|
||||
return sub.unsubscribe()
|
||||
.then(_ => {ok(true, "Unsubscribed!");});
|
||||
.then(_ => { ok(true, "Unsubscribed!"); });
|
||||
}
|
||||
|
||||
// go offline then go online
|
||||
|
@ -146,14 +151,14 @@ http://creativecommons.org/licenses/publicdomain/
|
|||
.then(_ => changeOfflineState(false))
|
||||
.then(_ => subscribe(swr))
|
||||
.then(sub => getEndpoint(swr, sub)
|
||||
.then(sub => unsubscribe(sub))
|
||||
.then(s => unsubscribe(s))
|
||||
)
|
||||
.then(_ => getEndpointExpectNull(swr))
|
||||
.then(_ => unregister(swr))
|
||||
)
|
||||
.catch(err => {
|
||||
ok(false, "Some test failed with error " + err);
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
// disable - enable push connection.
|
||||
|
@ -167,14 +172,14 @@ http://creativecommons.org/licenses/publicdomain/
|
|||
.then(_ => changePushServerConnectionEnabled(true))
|
||||
.then(_ => subscribe(swr))
|
||||
.then(sub => getEndpoint(swr, sub)
|
||||
.then(sub => unsubscribe(sub))
|
||||
.then(s => unsubscribe(s))
|
||||
)
|
||||
.then(_ => getEndpointExpectNull(swr))
|
||||
.then(_ => unregister(swr))
|
||||
)
|
||||
.catch(err => {
|
||||
ok(false, "Some test failed with error " + err);
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
// go offline - disable - enable - go online
|
||||
|
@ -194,14 +199,14 @@ http://creativecommons.org/licenses/publicdomain/
|
|||
.then(_ => changeOfflineState(false))
|
||||
.then(_ => subscribe(swr))
|
||||
.then(sub => getEndpoint(swr, sub)
|
||||
.then(sub => unsubscribe(sub))
|
||||
.then(s => unsubscribe(s))
|
||||
)
|
||||
.then(_ => getEndpointExpectNull(swr))
|
||||
.then(_ => unregister(swr))
|
||||
)
|
||||
.catch(err => {
|
||||
ok(false, "Some test failed with error " + err);
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
// disable - offline - online - enable.
|
||||
|
@ -221,14 +226,14 @@ http://creativecommons.org/licenses/publicdomain/
|
|||
.then(_ => changePushServerConnectionEnabled(true))
|
||||
.then(_ => subscribe(swr))
|
||||
.then(sub => getEndpoint(swr, sub)
|
||||
.then(sub => unsubscribe(sub))
|
||||
.then(s => unsubscribe(s))
|
||||
)
|
||||
.then(_ => getEndpointExpectNull(swr))
|
||||
.then(_ => unregister(swr))
|
||||
)
|
||||
.catch(err => {
|
||||
ok(false, "Some test failed with error " + err);
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
// go offline - disable - go online - enable
|
||||
|
@ -248,14 +253,14 @@ http://creativecommons.org/licenses/publicdomain/
|
|||
.then(_ => changePushServerConnectionEnabled(true))
|
||||
.then(_ => subscribe(swr))
|
||||
.then(sub => getEndpoint(swr, sub)
|
||||
.then(sub => unsubscribe(sub))
|
||||
.then(s => unsubscribe(s))
|
||||
)
|
||||
.then(_ => getEndpointExpectNull(swr))
|
||||
.then(_ => unregister(swr))
|
||||
)
|
||||
.catch(err => {
|
||||
ok(false, "Some test failed with error " + err);
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
// disable - go offline - enable - go online.
|
||||
|
@ -275,14 +280,14 @@ http://creativecommons.org/licenses/publicdomain/
|
|||
.then(_ => changeOfflineState(false))
|
||||
.then(_ => subscribe(swr))
|
||||
.then(sub => getEndpoint(swr, sub)
|
||||
.then(sub => unsubscribe(sub))
|
||||
.then(s => unsubscribe(s))
|
||||
)
|
||||
.then(_ => getEndpointExpectNull(swr))
|
||||
.then(_ => unregister(swr))
|
||||
)
|
||||
.catch(err => {
|
||||
ok(false, "Some test failed with error " + err);
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
function runTest() {
|
||||
|
|
|
@ -24,9 +24,10 @@ http://creativecommons.org/licenses/publicdomain/
|
|||
</pre>
|
||||
|
||||
<script class="testbody" type="text/javascript">
|
||||
/* import-globals-from ./test_utils.js */
|
||||
|
||||
function generateURL() {
|
||||
return "worker.js" + "?" + (Math.random());
|
||||
return "worker.js?" + (Math.random());
|
||||
}
|
||||
|
||||
var registration;
|
||||
|
@ -65,7 +66,7 @@ http://creativecommons.org/licenses/publicdomain/
|
|||
registration = await navigator.serviceWorker.register(
|
||||
generateURL(), {scope: "."});
|
||||
await waitForActive(registration);
|
||||
var pushSubscription = await registration.pushManager.getSubscription();
|
||||
pushSubscription = await registration.pushManager.getSubscription();
|
||||
ok(!pushSubscription,
|
||||
"Unregistering a service worker should drop its subscription");
|
||||
});
|
||||
|
|
|
@ -1,168 +1,158 @@
|
|||
(function (g) {
|
||||
"use strict";
|
||||
"use strict";
|
||||
|
||||
let url = SimpleTest.getTestFileURL("mockpushserviceparent.js");
|
||||
let chromeScript = SpecialPowers.loadChromeScript(url);
|
||||
const url = SimpleTest.getTestFileURL("mockpushserviceparent.js");
|
||||
const chromeScript = SpecialPowers.loadChromeScript(url);
|
||||
|
||||
/**
|
||||
* Replaces `PushService.jsm` with a mock implementation that handles requests
|
||||
* from the DOM API. This allows tests to simulate local errors and error
|
||||
* reporting, bypassing the `PushService.jsm` machinery.
|
||||
*/
|
||||
async function replacePushService(mockService) {
|
||||
chromeScript.addMessageListener("service-delivery-error", function(msg) {
|
||||
mockService.reportDeliveryError(msg.messageId, msg.reason);
|
||||
});
|
||||
chromeScript.addMessageListener("service-request", function(msg) {
|
||||
let promise;
|
||||
try {
|
||||
let handler = mockService[msg.name];
|
||||
promise = Promise.resolve(handler(msg.params));
|
||||
} catch (error) {
|
||||
promise = Promise.reject(error);
|
||||
}
|
||||
promise.then(result => {
|
||||
chromeScript.sendAsyncMessage("service-response", {
|
||||
id: msg.id,
|
||||
result: result,
|
||||
});
|
||||
}, error => {
|
||||
chromeScript.sendAsyncMessage("service-response", {
|
||||
id: msg.id,
|
||||
error: error,
|
||||
});
|
||||
});
|
||||
});
|
||||
await new Promise(resolve => {
|
||||
chromeScript.addMessageListener("service-replaced", function onReplaced() {
|
||||
chromeScript.removeMessageListener("service-replaced", onReplaced);
|
||||
resolve();
|
||||
});
|
||||
chromeScript.sendAsyncMessage("service-replace");
|
||||
});
|
||||
}
|
||||
|
||||
async function restorePushService() {
|
||||
await new Promise(resolve => {
|
||||
chromeScript.addMessageListener("service-restored", function onRestored() {
|
||||
chromeScript.removeMessageListener("service-restored", onRestored);
|
||||
resolve();
|
||||
});
|
||||
chromeScript.sendAsyncMessage("service-restore");
|
||||
});
|
||||
}
|
||||
|
||||
let userAgentID = "8e1c93a9-139b-419c-b200-e715bb1e8ce8";
|
||||
|
||||
let currentMockSocket = null;
|
||||
|
||||
/**
|
||||
* Sets up a mock connection for the WebSocket backend. This only replaces
|
||||
* the transport layer; `PushService.jsm` still handles DOM API requests,
|
||||
* observes permission changes, writes to IndexedDB, and notifies service
|
||||
* workers of incoming push messages.
|
||||
*/
|
||||
function setupMockPushSocket(mockWebSocket) {
|
||||
currentMockSocket = mockWebSocket;
|
||||
currentMockSocket._isActive = true;
|
||||
chromeScript.sendSyncMessage("socket-setup");
|
||||
chromeScript.addMessageListener("socket-client-msg", function(msg) {
|
||||
mockWebSocket.handleMessage(msg);
|
||||
});
|
||||
}
|
||||
|
||||
function teardownMockPushSocket() {
|
||||
if (currentMockSocket) {
|
||||
return new Promise(resolve => {
|
||||
currentMockSocket._isActive = false;
|
||||
chromeScript.addMessageListener("socket-server-teardown", resolve);
|
||||
chromeScript.sendSyncMessage("socket-teardown");
|
||||
});
|
||||
/**
|
||||
* Replaces `PushService.jsm` with a mock implementation that handles requests
|
||||
* from the DOM API. This allows tests to simulate local errors and error
|
||||
* reporting, bypassing the `PushService.jsm` machinery.
|
||||
*/
|
||||
async function replacePushService(mockService) {
|
||||
chromeScript.addMessageListener("service-delivery-error", function(msg) {
|
||||
mockService.reportDeliveryError(msg.messageId, msg.reason);
|
||||
});
|
||||
chromeScript.addMessageListener("service-request", function(msg) {
|
||||
let promise;
|
||||
try {
|
||||
let handler = mockService[msg.name];
|
||||
promise = Promise.resolve(handler(msg.params));
|
||||
} catch (error) {
|
||||
promise = Promise.reject(error);
|
||||
}
|
||||
return Promise.resolve();
|
||||
promise.then(result => {
|
||||
chromeScript.sendAsyncMessage("service-response", {
|
||||
id: msg.id,
|
||||
result,
|
||||
});
|
||||
}, error => {
|
||||
chromeScript.sendAsyncMessage("service-response", {
|
||||
id: msg.id,
|
||||
error,
|
||||
});
|
||||
});
|
||||
});
|
||||
await new Promise(resolve => {
|
||||
chromeScript.addMessageListener("service-replaced", function onReplaced() {
|
||||
chromeScript.removeMessageListener("service-replaced", onReplaced);
|
||||
resolve();
|
||||
});
|
||||
chromeScript.sendAsyncMessage("service-replace");
|
||||
});
|
||||
}
|
||||
|
||||
async function restorePushService() {
|
||||
await new Promise(resolve => {
|
||||
chromeScript.addMessageListener("service-restored", function onRestored() {
|
||||
chromeScript.removeMessageListener("service-restored", onRestored);
|
||||
resolve();
|
||||
});
|
||||
chromeScript.sendAsyncMessage("service-restore");
|
||||
});
|
||||
}
|
||||
|
||||
let currentMockSocket = null;
|
||||
|
||||
/**
|
||||
* Sets up a mock connection for the WebSocket backend. This only replaces
|
||||
* the transport layer; `PushService.jsm` still handles DOM API requests,
|
||||
* observes permission changes, writes to IndexedDB, and notifies service
|
||||
* workers of incoming push messages.
|
||||
*/
|
||||
function setupMockPushSocket(mockWebSocket) {
|
||||
currentMockSocket = mockWebSocket;
|
||||
currentMockSocket._isActive = true;
|
||||
chromeScript.sendSyncMessage("socket-setup");
|
||||
chromeScript.addMessageListener("socket-client-msg", function(msg) {
|
||||
mockWebSocket.handleMessage(msg);
|
||||
});
|
||||
}
|
||||
|
||||
function teardownMockPushSocket() {
|
||||
if (currentMockSocket) {
|
||||
return new Promise(resolve => {
|
||||
currentMockSocket._isActive = false;
|
||||
chromeScript.addMessageListener("socket-server-teardown", resolve);
|
||||
chromeScript.sendSyncMessage("socket-teardown");
|
||||
});
|
||||
}
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
/**
|
||||
* Minimal implementation of web sockets for use in testing. Forwards
|
||||
* messages to a mock web socket in the parent process that is used
|
||||
* by the push service.
|
||||
*/
|
||||
function MockWebSocket() {}
|
||||
|
||||
let registerCount = 0;
|
||||
|
||||
/**
|
||||
* Minimal implementation of web sockets for use in testing. Forwards
|
||||
* messages to a mock web socket in the parent process that is used
|
||||
* by the push service.
|
||||
*/
|
||||
class MockWebSocket {
|
||||
// Default implementation to make the push server work minimally.
|
||||
// Override methods to implement custom functionality.
|
||||
MockWebSocket.prototype = {
|
||||
constructor() {
|
||||
this.userAgentID = "8e1c93a9-139b-419c-b200-e715bb1e8ce8";
|
||||
this.registerCount = 0;
|
||||
// We only allow one active mock web socket to talk to the parent.
|
||||
// This flag is used to keep track of which mock web socket is active.
|
||||
_isActive: false,
|
||||
this._isActive = false;
|
||||
}
|
||||
|
||||
onHello(request) {
|
||||
this.serverSendMsg(JSON.stringify({
|
||||
messageType: "hello",
|
||||
uaid: userAgentID,
|
||||
status: 200,
|
||||
use_webpush: true,
|
||||
}));
|
||||
},
|
||||
onHello(request) {
|
||||
this.serverSendMsg(JSON.stringify({
|
||||
messageType: "hello",
|
||||
uaid: this.userAgentID,
|
||||
status: 200,
|
||||
use_webpush: true,
|
||||
}));
|
||||
}
|
||||
|
||||
onRegister(request) {
|
||||
this.serverSendMsg(JSON.stringify({
|
||||
messageType: "register",
|
||||
uaid: userAgentID,
|
||||
channelID: request.channelID,
|
||||
status: 200,
|
||||
pushEndpoint: "https://example.com/endpoint/" + registerCount++
|
||||
}));
|
||||
},
|
||||
onRegister(request) {
|
||||
this.serverSendMsg(JSON.stringify({
|
||||
messageType: "register",
|
||||
uaid: this.userAgentID,
|
||||
channelID: request.channelID,
|
||||
status: 200,
|
||||
pushEndpoint: "https://example.com/endpoint/" + this.registerCount++,
|
||||
}));
|
||||
}
|
||||
|
||||
onUnregister(request) {
|
||||
this.serverSendMsg(JSON.stringify({
|
||||
messageType: "unregister",
|
||||
channelID: request.channelID,
|
||||
status: 200,
|
||||
}));
|
||||
},
|
||||
onUnregister(request) {
|
||||
this.serverSendMsg(JSON.stringify({
|
||||
messageType: "unregister",
|
||||
channelID: request.channelID,
|
||||
status: 200,
|
||||
}));
|
||||
}
|
||||
|
||||
onAck(request) {
|
||||
// Do nothing.
|
||||
},
|
||||
onAck(request) {
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
handleMessage(msg) {
|
||||
let request = JSON.parse(msg);
|
||||
let messageType = request.messageType;
|
||||
switch (messageType) {
|
||||
case "hello":
|
||||
this.onHello(request);
|
||||
break;
|
||||
case "register":
|
||||
this.onRegister(request);
|
||||
break;
|
||||
case "unregister":
|
||||
this.onUnregister(request);
|
||||
break;
|
||||
case "ack":
|
||||
this.onAck(request);
|
||||
break;
|
||||
default:
|
||||
throw new Error("Unexpected message: " + messageType);
|
||||
}
|
||||
},
|
||||
handleMessage(msg) {
|
||||
let request = JSON.parse(msg);
|
||||
let messageType = request.messageType;
|
||||
switch (messageType) {
|
||||
case "hello":
|
||||
this.onHello(request);
|
||||
break;
|
||||
case "register":
|
||||
this.onRegister(request);
|
||||
break;
|
||||
case "unregister":
|
||||
this.onUnregister(request);
|
||||
break;
|
||||
case "ack":
|
||||
this.onAck(request);
|
||||
break;
|
||||
default:
|
||||
throw new Error("Unexpected message: " + messageType);
|
||||
}
|
||||
}
|
||||
|
||||
serverSendMsg(msg) {
|
||||
if (this._isActive) {
|
||||
chromeScript.sendAsyncMessage("socket-server-msg", msg);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
g.MockWebSocket = MockWebSocket;
|
||||
g.setupMockPushSocket = setupMockPushSocket;
|
||||
g.teardownMockPushSocket = teardownMockPushSocket;
|
||||
g.replacePushService = replacePushService;
|
||||
g.restorePushService = restorePushService;
|
||||
}(this));
|
||||
serverSendMsg(msg) {
|
||||
if (this._isActive) {
|
||||
chromeScript.sendAsyncMessage("socket-server-msg", msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Remove permissions and prefs when the test finishes.
|
||||
SimpleTest.registerCleanupFunction(async function() {
|
||||
|
@ -187,7 +177,7 @@ function setupPrefs() {
|
|||
["dom.push.maxRecentMessageIDsPerSubscription", 0],
|
||||
["dom.serviceWorkers.exemptFromPerDomainMax", true],
|
||||
["dom.serviceWorkers.enabled", true],
|
||||
["dom.serviceWorkers.testing.enabled", true]
|
||||
["dom.serviceWorkers.testing.enabled", true],
|
||||
]});
|
||||
}
|
||||
|
||||
|
@ -241,13 +231,13 @@ function sendRequestToWorker(request) {
|
|||
function waitForActive(swr) {
|
||||
let sw = swr.installing || swr.waiting || swr.active;
|
||||
return new Promise(resolve => {
|
||||
if (sw.state === 'activated') {
|
||||
if (sw.state === "activated") {
|
||||
resolve(swr);
|
||||
return;
|
||||
}
|
||||
sw.addEventListener('statechange', function onStateChange(evt) {
|
||||
if (sw.state === 'activated') {
|
||||
sw.removeEventListener('statechange', onStateChange);
|
||||
sw.addEventListener("statechange", function onStateChange(evt) {
|
||||
if (sw.state === "activated") {
|
||||
sw.removeEventListener("statechange", onStateChange);
|
||||
resolve(swr);
|
||||
}
|
||||
});
|
||||
|
@ -255,7 +245,7 @@ function waitForActive(swr) {
|
|||
}
|
||||
|
||||
function base64UrlDecode(s) {
|
||||
s = s.replace(/-/g, '+').replace(/_/g, '/');
|
||||
s = s.replace(/-/g, "+").replace(/_/g, "/");
|
||||
|
||||
// Replace padding if it was stripped by the sender.
|
||||
// See http://tools.ietf.org/html/rfc4648#section-4
|
||||
|
@ -263,13 +253,13 @@ function base64UrlDecode(s) {
|
|||
case 0:
|
||||
break; // No pad chars in this case
|
||||
case 2:
|
||||
s += '==';
|
||||
s += "==";
|
||||
break; // Two pad chars
|
||||
case 3:
|
||||
s += '=';
|
||||
s += "=";
|
||||
break; // One pad char
|
||||
default:
|
||||
throw new Error('Illegal base64url string!');
|
||||
throw new Error("Illegal base64url string!");
|
||||
}
|
||||
|
||||
// With correct padding restored, apply the standard base64 decoder
|
||||
|
|
|
@ -12,23 +12,23 @@
|
|||
* use PushCrypto directly is easier said than done.)
|
||||
*/
|
||||
|
||||
(function (g) {
|
||||
'use strict';
|
||||
(function(g) {
|
||||
"use strict";
|
||||
|
||||
var P256DH = {
|
||||
name: 'ECDH',
|
||||
namedCurve: 'P-256'
|
||||
name: "ECDH",
|
||||
namedCurve: "P-256",
|
||||
};
|
||||
var webCrypto = g.crypto.subtle;
|
||||
var ENCRYPT_INFO = new TextEncoder('utf-8').encode("Content-Encoding: aesgcm128");
|
||||
var NONCE_INFO = new TextEncoder('utf-8').encode("Content-Encoding: nonce");
|
||||
var ENCRYPT_INFO = new TextEncoder("utf-8").encode("Content-Encoding: aesgcm128");
|
||||
var NONCE_INFO = new TextEncoder("utf-8").encode("Content-Encoding: nonce");
|
||||
|
||||
function chunkArray(array, size) {
|
||||
var start = array.byteOffset || 0;
|
||||
array = array.buffer || array;
|
||||
var index = 0;
|
||||
var result = [];
|
||||
while(index + size <= array.byteLength) {
|
||||
while (index + size <= array.byteLength) {
|
||||
result.push(new Uint8Array(array, start + index, size));
|
||||
index += size;
|
||||
}
|
||||
|
@ -42,21 +42,21 @@
|
|||
* Note: these are not efficient, merely expedient.
|
||||
*/
|
||||
var base64url = {
|
||||
_strmap: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_',
|
||||
encode: function(data) {
|
||||
_strmap: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_",
|
||||
encode(data) {
|
||||
data = new Uint8Array(data);
|
||||
var len = Math.ceil(data.length * 4 / 3);
|
||||
return chunkArray(data, 3).map(chunk => [
|
||||
chunk[0] >>> 2,
|
||||
((chunk[0] & 0x3) << 4) | (chunk[1] >>> 4),
|
||||
((chunk[1] & 0xf) << 2) | (chunk[2] >>> 6),
|
||||
chunk[2] & 0x3f
|
||||
].map(v => base64url._strmap[v]).join('')).join('').slice(0, len);
|
||||
chunk[2] & 0x3f,
|
||||
].map(v => base64url._strmap[v]).join("")).join("").slice(0, len);
|
||||
},
|
||||
_lookup: function(s, i) {
|
||||
_lookup(s, i) {
|
||||
return base64url._strmap.indexOf(s.charAt(i));
|
||||
},
|
||||
decode: function(str) {
|
||||
decode(str) {
|
||||
var v = new Uint8Array(Math.floor(str.length * 3 / 4));
|
||||
var vi = 0;
|
||||
for (var si = 0; si < str.length;) {
|
||||
|
@ -69,15 +69,15 @@
|
|||
v[vi++] = y << 6 | z;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
g.base64url = base64url;
|
||||
|
||||
/* Coerces data into a Uint8Array */
|
||||
function ensureView(data) {
|
||||
if (typeof data === 'string') {
|
||||
return new TextEncoder('utf-8').encode(data);
|
||||
if (typeof data === "string") {
|
||||
return new TextEncoder("utf-8").encode(data);
|
||||
}
|
||||
if (data instanceof ArrayBuffer) {
|
||||
return new Uint8Array(data);
|
||||
|
@ -85,7 +85,7 @@
|
|||
if (ArrayBuffer.isView(data)) {
|
||||
return new Uint8Array(data.buffer);
|
||||
}
|
||||
throw new Error('webpush() needs a string or BufferSource');
|
||||
throw new Error("webpush() needs a string or BufferSource");
|
||||
}
|
||||
|
||||
function bsConcat(arrays) {
|
||||
|
@ -99,11 +99,11 @@
|
|||
}
|
||||
|
||||
function hmac(key) {
|
||||
this.keyPromise = webCrypto.importKey('raw', key, { name: 'HMAC', hash: 'SHA-256' },
|
||||
false, ['sign']);
|
||||
this.keyPromise = webCrypto.importKey("raw", key, { name: "HMAC", hash: "SHA-256" },
|
||||
false, ["sign"]);
|
||||
}
|
||||
hmac.prototype.hash = function(input) {
|
||||
return this.keyPromise.then(k => webCrypto.sign('HMAC', k, input));
|
||||
return this.keyPromise.then(k => webCrypto.sign("HMAC", k, input));
|
||||
};
|
||||
|
||||
function hkdf(salt, ikm) {
|
||||
|
@ -117,7 +117,7 @@
|
|||
.then(prkh => prkh.hash(input))
|
||||
.then(h => {
|
||||
if (h.byteLength < len) {
|
||||
throw new Error('Length is too long');
|
||||
throw new Error("Length is too long");
|
||||
}
|
||||
return h.slice(0, len);
|
||||
});
|
||||
|
@ -133,7 +133,7 @@
|
|||
}
|
||||
|
||||
function encrypt(localKey, remoteShare, salt, data) {
|
||||
return webCrypto.importKey('raw', remoteShare, P256DH, false, ['deriveBits'])
|
||||
return webCrypto.importKey("raw", remoteShare, P256DH, false, ["deriveBits"])
|
||||
.then(remoteKey =>
|
||||
webCrypto.deriveBits({ name: P256DH.name, public: remoteKey },
|
||||
localKey, 256))
|
||||
|
@ -142,24 +142,24 @@
|
|||
return Promise.all([
|
||||
kdf.generate(ENCRYPT_INFO, 16)
|
||||
.then(gcmBits =>
|
||||
webCrypto.importKey('raw', gcmBits, 'AES-GCM', false, ['encrypt'])),
|
||||
kdf.generate(NONCE_INFO, 12)
|
||||
webCrypto.importKey("raw", gcmBits, "AES-GCM", false, ["encrypt"])),
|
||||
kdf.generate(NONCE_INFO, 12),
|
||||
]);
|
||||
})
|
||||
.then(([key, nonce]) => {
|
||||
if (data.byteLength === 0) {
|
||||
// Send an authentication tag for empty messages.
|
||||
return webCrypto.encrypt({
|
||||
name: 'AES-GCM',
|
||||
iv: generateNonce(nonce, 0)
|
||||
name: "AES-GCM",
|
||||
iv: generateNonce(nonce, 0),
|
||||
}, key, new Uint8Array([0])).then(value => [value]);
|
||||
}
|
||||
// 4096 is the default size, though we burn 1 for padding
|
||||
return Promise.all(chunkArray(data, 4095).map((slice, index) => {
|
||||
var padded = bsConcat([new Uint8Array([0]), slice]);
|
||||
return webCrypto.encrypt({
|
||||
name: 'AES-GCM',
|
||||
iv: generateNonce(nonce, index)
|
||||
name: "AES-GCM",
|
||||
iv: generateNonce(nonce, index),
|
||||
}, key, padded);
|
||||
}));
|
||||
}).then(bsConcat);
|
||||
|
@ -169,19 +169,19 @@
|
|||
data = ensureView(data);
|
||||
|
||||
var salt = g.crypto.getRandomValues(new Uint8Array(16));
|
||||
return webCrypto.generateKey(P256DH, false, ['deriveBits'])
|
||||
return webCrypto.generateKey(P256DH, false, ["deriveBits"])
|
||||
.then(localKey => {
|
||||
return Promise.all([
|
||||
encrypt(localKey.privateKey, subscription.getKey("p256dh"), salt, data),
|
||||
// 1337 p-256 specific haxx to get the raw value out of the spki value
|
||||
webCrypto.exportKey('raw', localKey.publicKey),
|
||||
webCrypto.exportKey("raw", localKey.publicKey),
|
||||
]);
|
||||
}).then(([payload, pubkey]) => {
|
||||
return {
|
||||
data: base64url.encode(payload),
|
||||
encryption: 'keyid=p256dh;salt=' + base64url.encode(salt),
|
||||
encryption_key: 'keyid=p256dh;dh=' + base64url.encode(pubkey),
|
||||
encoding: 'aesgcm128'
|
||||
encryption: "keyid=p256dh;salt=" + base64url.encode(salt),
|
||||
encryption_key: "keyid=p256dh;dh=" + base64url.encode(pubkey),
|
||||
encoding: "aesgcm128",
|
||||
};
|
||||
});
|
||||
}
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
// and `test_data.html`, and verifies that `PushManager` can be used from
|
||||
// the worker.
|
||||
|
||||
/* globals PushEvent */
|
||||
|
||||
this.onpush = handlePush;
|
||||
this.onmessage = handleMessage;
|
||||
this.onpushsubscriptionchange = handlePushSubscriptionChange;
|
||||
|
@ -51,7 +53,7 @@ function reply(event, promise) {
|
|||
|
||||
function handlePush(event) {
|
||||
if (event instanceof PushEvent) {
|
||||
if (!('data' in event)) {
|
||||
if (!("data" in event)) {
|
||||
broadcast(event, {type: "finished", okay: "yes"});
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -24,6 +24,6 @@ PushServiceHandler.prototype = {
|
|||
observe(subject, topic, data) {
|
||||
this.observed.push({ subject, topic, data });
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([PushServiceHandler]);
|
||||
|
|
|
@ -12,5 +12,5 @@ var broadcastHandler = {
|
|||
this.notifications.push(Array.from(arguments));
|
||||
};
|
||||
});
|
||||
}
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,32 +1,30 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
'use strict';
|
||||
"use strict";
|
||||
|
||||
var {XPCOMUtils} = ChromeUtils.import('resource://gre/modules/XPCOMUtils.jsm');
|
||||
var {Services} = ChromeUtils.import('resource://gre/modules/Services.jsm');
|
||||
var {clearInterval, clearTimeout, setInterval, setIntervalWithTarget, setTimeout, setTimeoutWithTarget} = ChromeUtils.import('resource://gre/modules/Timer.jsm');
|
||||
var {Preferences} = ChromeUtils.import('resource://gre/modules/Preferences.jsm');
|
||||
var {PlacesUtils} = ChromeUtils.import('resource://gre/modules/PlacesUtils.jsm');
|
||||
var {ObjectUtils} = ChromeUtils.import('resource://gre/modules/ObjectUtils.jsm');
|
||||
var {XPCOMUtils} = ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
var {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
var {clearInterval, clearTimeout, setInterval, setIntervalWithTarget, setTimeout, setTimeoutWithTarget} = ChromeUtils.import("resource://gre/modules/Timer.jsm");
|
||||
var {Preferences} = ChromeUtils.import("resource://gre/modules/Preferences.jsm");
|
||||
var {PlacesUtils} = ChromeUtils.import("resource://gre/modules/PlacesUtils.jsm");
|
||||
var {ObjectUtils} = ChromeUtils.import("resource://gre/modules/ObjectUtils.jsm");
|
||||
|
||||
ChromeUtils.defineModuleGetter(this, 'PlacesTestUtils',
|
||||
'resource://testing-common/PlacesTestUtils.jsm');
|
||||
ChromeUtils.defineModuleGetter(this, 'pushBroadcastService',
|
||||
'resource://gre/modules/PushBroadcastService.jsm', {});
|
||||
XPCOMUtils.defineLazyServiceGetter(this, 'PushServiceComponent',
|
||||
'@mozilla.org/push/Service;1', 'nsIPushService');
|
||||
ChromeUtils.defineModuleGetter(this, "PlacesTestUtils",
|
||||
"resource://testing-common/PlacesTestUtils.jsm");
|
||||
ChromeUtils.defineModuleGetter(this, "pushBroadcastService",
|
||||
"resource://gre/modules/PushBroadcastService.jsm", {});
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "PushServiceComponent",
|
||||
"@mozilla.org/push/Service;1", "nsIPushService");
|
||||
|
||||
const serviceExports = ChromeUtils.import("resource://gre/modules/PushService.jsm", null);
|
||||
const servicePrefs = new Preferences('dom.push.');
|
||||
const servicePrefs = new Preferences("dom.push.");
|
||||
|
||||
const WEBSOCKET_CLOSE_GOING_AWAY = 1001;
|
||||
|
||||
const MS_IN_ONE_DAY = 24 * 60 * 60 * 1000;
|
||||
|
||||
var isParent = Cc['@mozilla.org/xre/runtime;1']
|
||||
.getService(Ci.nsIXULRuntime).processType ==
|
||||
Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT;
|
||||
var isParent = Services.appinfo.processType == Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT;
|
||||
|
||||
// Stop and clean up after the PushService.
|
||||
Services.obs.addObserver(function observe(subject, topic, data) {
|
||||
|
@ -46,7 +44,7 @@ Services.obs.addObserver(function observe(subject, topic, data) {
|
|||
Cu.reportError(e);
|
||||
}
|
||||
}
|
||||
}, 'profile-change-net-teardown');
|
||||
}, "profile-change-net-teardown");
|
||||
|
||||
/**
|
||||
* Gates a function so that it is called only after the wrapper is called a
|
||||
|
@ -59,7 +57,7 @@ Services.obs.addObserver(function observe(subject, topic, data) {
|
|||
function after(times, func) {
|
||||
return function afterFunc() {
|
||||
if (--times <= 0) {
|
||||
return func.apply(this, arguments);
|
||||
func.apply(this, arguments);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -85,12 +83,12 @@ function waterfall(...callbacks) {
|
|||
*/
|
||||
function promiseObserverNotification(topic, matchFunc) {
|
||||
return new Promise((resolve, reject) => {
|
||||
Services.obs.addObserver(function observe(subject, topic, data) {
|
||||
let matches = typeof matchFunc != 'function' || matchFunc(subject, data);
|
||||
Services.obs.addObserver(function observe(subject, aTopic, data) {
|
||||
let matches = typeof matchFunc != "function" || matchFunc(subject, data);
|
||||
if (!matches) {
|
||||
return;
|
||||
}
|
||||
Services.obs.removeObserver(observe, topic);
|
||||
Services.obs.removeObserver(observe, aTopic);
|
||||
resolve({subject, data});
|
||||
}, topic);
|
||||
});
|
||||
|
@ -108,22 +106,22 @@ function promiseObserverNotification(topic, matchFunc) {
|
|||
*/
|
||||
function makeStub(target, stubs) {
|
||||
return new Proxy(target, {
|
||||
get(target, property) {
|
||||
if (!stubs || typeof stubs != 'object' || !(property in stubs)) {
|
||||
return target[property];
|
||||
get(aTarget, property) {
|
||||
if (!stubs || typeof stubs != "object" || !(property in stubs)) {
|
||||
return aTarget[property];
|
||||
}
|
||||
let stub = stubs[property];
|
||||
if (typeof stub != 'function') {
|
||||
if (typeof stub != "function") {
|
||||
return stub;
|
||||
}
|
||||
let original = target[property];
|
||||
if (typeof original != 'function') {
|
||||
let original = aTarget[property];
|
||||
if (typeof original != "function") {
|
||||
return stub.call(this, original);
|
||||
}
|
||||
return function callStub(...params) {
|
||||
return stub.call(this, original, ...params);
|
||||
};
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -135,22 +133,22 @@ function makeStub(target, stubs) {
|
|||
*/
|
||||
function setPrefs(prefs = {}) {
|
||||
let defaultPrefs = Object.assign({
|
||||
loglevel: 'all',
|
||||
serverURL: 'wss://push.example.org',
|
||||
'connection.enabled': true,
|
||||
userAgentID: '',
|
||||
loglevel: "all",
|
||||
serverURL: "wss://push.example.org",
|
||||
"connection.enabled": true,
|
||||
userAgentID: "",
|
||||
enabled: true,
|
||||
// Defaults taken from /modules/libpref/init/all.js.
|
||||
requestTimeout: 10000,
|
||||
retryBaseInterval: 5000,
|
||||
pingInterval: 30 * 60 * 1000,
|
||||
// Misc. defaults.
|
||||
'http2.maxRetries': 2,
|
||||
'http2.retryInterval': 500,
|
||||
'http2.reset_retry_count_after_ms': 60000,
|
||||
"http2.maxRetries": 2,
|
||||
"http2.retryInterval": 500,
|
||||
"http2.reset_retry_count_after_ms": 60000,
|
||||
maxQuotaPerSubscription: 16,
|
||||
quotaUpdateDelay: 3000,
|
||||
'testing.notifyWorkers': false,
|
||||
"testing.notifyWorkers": false,
|
||||
}, prefs);
|
||||
for (let pref in defaultPrefs) {
|
||||
servicePrefs.set(pref, defaultPrefs[pref]);
|
||||
|
@ -158,7 +156,10 @@ function setPrefs(prefs = {}) {
|
|||
}
|
||||
|
||||
function compareAscending(a, b) {
|
||||
return a > b ? 1 : a < b ? -1 : 0;
|
||||
if (a > b) {
|
||||
return 1;
|
||||
}
|
||||
return a < b ? -1 : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -215,60 +216,60 @@ MockWebSocket.prototype = {
|
|||
|
||||
_handleMessage(msg) {
|
||||
let messageType, request;
|
||||
if (msg == '{}') {
|
||||
if (msg == "{}") {
|
||||
request = {};
|
||||
messageType = 'ping';
|
||||
messageType = "ping";
|
||||
} else {
|
||||
request = JSON.parse(msg);
|
||||
messageType = request.messageType;
|
||||
}
|
||||
switch (messageType) {
|
||||
case 'hello':
|
||||
if (typeof this._onHello != 'function') {
|
||||
throw new Error('Unexpected handshake request');
|
||||
case "hello":
|
||||
if (typeof this._onHello != "function") {
|
||||
throw new Error("Unexpected handshake request");
|
||||
}
|
||||
this._onHello(request);
|
||||
break;
|
||||
|
||||
case 'register':
|
||||
if (typeof this._onRegister != 'function') {
|
||||
throw new Error('Unexpected register request');
|
||||
case "register":
|
||||
if (typeof this._onRegister != "function") {
|
||||
throw new Error("Unexpected register request");
|
||||
}
|
||||
this._onRegister(request);
|
||||
break;
|
||||
|
||||
case 'unregister':
|
||||
if (typeof this._onUnregister != 'function') {
|
||||
throw new Error('Unexpected unregister request');
|
||||
case "unregister":
|
||||
if (typeof this._onUnregister != "function") {
|
||||
throw new Error("Unexpected unregister request");
|
||||
}
|
||||
this._onUnregister(request);
|
||||
break;
|
||||
|
||||
case 'ack':
|
||||
if (typeof this._onACK != 'function') {
|
||||
throw new Error('Unexpected acknowledgement');
|
||||
case "ack":
|
||||
if (typeof this._onACK != "function") {
|
||||
throw new Error("Unexpected acknowledgement");
|
||||
}
|
||||
this._onACK(request);
|
||||
break;
|
||||
|
||||
case 'ping':
|
||||
if (typeof this._onPing == 'function') {
|
||||
case "ping":
|
||||
if (typeof this._onPing == "function") {
|
||||
this._onPing(request);
|
||||
} else {
|
||||
// Echo ping packets.
|
||||
this.serverSendMsg('{}');
|
||||
this.serverSendMsg("{}");
|
||||
}
|
||||
break;
|
||||
|
||||
case 'broadcast_subscribe':
|
||||
if (typeof this._onBroadcastSubscribe != 'function') {
|
||||
throw new Error('Unexpected broadcast_subscribe');
|
||||
case "broadcast_subscribe":
|
||||
if (typeof this._onBroadcastSubscribe != "function") {
|
||||
throw new Error("Unexpected broadcast_subscribe");
|
||||
}
|
||||
this._onBroadcastSubscribe(request);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new Error('Unexpected message: ' + messageType);
|
||||
throw new Error("Unexpected message: " + messageType);
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -288,8 +289,8 @@ MockWebSocket.prototype = {
|
|||
* @param {String} msg The message to send to the client.
|
||||
*/
|
||||
serverSendMsg(msg) {
|
||||
if (typeof msg != 'string') {
|
||||
throw new Error('Invalid response message');
|
||||
if (typeof msg != "string") {
|
||||
throw new Error("Invalid response message");
|
||||
}
|
||||
waterfall(
|
||||
() => this._listener.onMessageAvailable(this._context, msg),
|
||||
|
@ -304,7 +305,7 @@ MockWebSocket.prototype = {
|
|||
* @param {Number} [statusCode] The WebSocket connection close code.
|
||||
* @param {String} [reason] The connection close reason.
|
||||
*/
|
||||
serverClose(statusCode, reason = '') {
|
||||
serverClose(statusCode, reason = "") {
|
||||
if (!isFinite(statusCode)) {
|
||||
statusCode = WEBSOCKET_CLOSE_GOING_AWAY;
|
||||
}
|
||||
|
@ -324,36 +325,36 @@ var setUpServiceInParent = async function(service, db) {
|
|||
return;
|
||||
}
|
||||
|
||||
let userAgentID = 'ce704e41-cb77-4206-b07b-5bf47114791b';
|
||||
let userAgentID = "ce704e41-cb77-4206-b07b-5bf47114791b";
|
||||
setPrefs({
|
||||
userAgentID: userAgentID,
|
||||
userAgentID,
|
||||
});
|
||||
|
||||
await db.put({
|
||||
channelID: '6e2814e1-5f84-489e-b542-855cc1311f09',
|
||||
pushEndpoint: 'https://example.org/push/get',
|
||||
scope: 'https://example.com/get/ok',
|
||||
originAttributes: '',
|
||||
channelID: "6e2814e1-5f84-489e-b542-855cc1311f09",
|
||||
pushEndpoint: "https://example.org/push/get",
|
||||
scope: "https://example.com/get/ok",
|
||||
originAttributes: "",
|
||||
version: 1,
|
||||
pushCount: 10,
|
||||
lastPush: 1438360548322,
|
||||
quota: 16,
|
||||
});
|
||||
await db.put({
|
||||
channelID: '3a414737-2fd0-44c0-af05-7efc172475fc',
|
||||
pushEndpoint: 'https://example.org/push/unsub',
|
||||
scope: 'https://example.com/unsub/ok',
|
||||
originAttributes: '',
|
||||
channelID: "3a414737-2fd0-44c0-af05-7efc172475fc",
|
||||
pushEndpoint: "https://example.org/push/unsub",
|
||||
scope: "https://example.com/unsub/ok",
|
||||
originAttributes: "",
|
||||
version: 2,
|
||||
pushCount: 10,
|
||||
lastPush: 1438360848322,
|
||||
quota: 4,
|
||||
});
|
||||
await db.put({
|
||||
channelID: 'ca3054e8-b59b-4ea0-9c23-4a3c518f3161',
|
||||
pushEndpoint: 'https://example.org/push/stale',
|
||||
scope: 'https://example.com/unsub/fail',
|
||||
originAttributes: '',
|
||||
channelID: "ca3054e8-b59b-4ea0-9c23-4a3c518f3161",
|
||||
pushEndpoint: "https://example.org/push/stale",
|
||||
scope: "https://example.com/unsub/fail",
|
||||
originAttributes: "",
|
||||
version: 3,
|
||||
pushCount: 10,
|
||||
lastPush: 1438362348322,
|
||||
|
@ -361,23 +362,23 @@ var setUpServiceInParent = async function(service, db) {
|
|||
});
|
||||
|
||||
service.init({
|
||||
serverURI: 'wss://push.example.org/',
|
||||
serverURI: "wss://push.example.org/",
|
||||
db: makeStub(db, {
|
||||
put(prev, record) {
|
||||
if (record.scope == 'https://example.com/sub/fail') {
|
||||
return Promise.reject('synergies not aligned');
|
||||
if (record.scope == "https://example.com/sub/fail") {
|
||||
return Promise.reject("synergies not aligned");
|
||||
}
|
||||
return prev.call(this, record);
|
||||
},
|
||||
delete: function(prev, channelID) {
|
||||
if (channelID == 'ca3054e8-b59b-4ea0-9c23-4a3c518f3161') {
|
||||
return Promise.reject('splines not reticulated');
|
||||
delete(prev, channelID) {
|
||||
if (channelID == "ca3054e8-b59b-4ea0-9c23-4a3c518f3161") {
|
||||
return Promise.reject("splines not reticulated");
|
||||
}
|
||||
return prev.call(this, channelID);
|
||||
},
|
||||
getByIdentifiers(prev, identifiers) {
|
||||
if (identifiers.scope == 'https://example.com/get/fail') {
|
||||
return Promise.reject('qualia unsynchronized');
|
||||
if (identifiers.scope == "https://example.com/get/fail") {
|
||||
return Promise.reject("qualia unsynchronized");
|
||||
}
|
||||
return prev.call(this, identifiers);
|
||||
},
|
||||
|
@ -386,7 +387,7 @@ var setUpServiceInParent = async function(service, db) {
|
|||
return new MockWebSocket(uri, {
|
||||
onHello(request) {
|
||||
this.serverSendMsg(JSON.stringify({
|
||||
messageType: 'hello',
|
||||
messageType: "hello",
|
||||
uaid: userAgentID,
|
||||
status: 200,
|
||||
}));
|
||||
|
@ -398,20 +399,20 @@ var setUpServiceInParent = async function(service, db) {
|
|||
padding: "require",
|
||||
})
|
||||
);
|
||||
equal(appServerKey.length, 65, 'Wrong app server key length');
|
||||
equal(appServerKey[0], 4, 'Wrong app server key format');
|
||||
equal(appServerKey.length, 65, "Wrong app server key length");
|
||||
equal(appServerKey[0], 4, "Wrong app server key format");
|
||||
}
|
||||
this.serverSendMsg(JSON.stringify({
|
||||
messageType: 'register',
|
||||
messageType: "register",
|
||||
uaid: userAgentID,
|
||||
channelID: request.channelID,
|
||||
status: 200,
|
||||
pushEndpoint: 'https://example.org/push/' + request.channelID,
|
||||
pushEndpoint: "https://example.org/push/" + request.channelID,
|
||||
}));
|
||||
},
|
||||
onUnregister(request) {
|
||||
this.serverSendMsg(JSON.stringify({
|
||||
messageType: 'unregister',
|
||||
messageType: "unregister",
|
||||
channelID: request.channelID,
|
||||
status: 200,
|
||||
}));
|
||||
|
@ -427,26 +428,26 @@ var tearDownServiceInParent = async function(db) {
|
|||
}
|
||||
|
||||
let record = await db.getByIdentifiers({
|
||||
scope: 'https://example.com/sub/ok',
|
||||
originAttributes: '',
|
||||
scope: "https://example.com/sub/ok",
|
||||
originAttributes: "",
|
||||
});
|
||||
ok(record.pushEndpoint.startsWith('https://example.org/push'),
|
||||
'Wrong push endpoint in subscription record');
|
||||
ok(record.pushEndpoint.startsWith("https://example.org/push"),
|
||||
"Wrong push endpoint in subscription record");
|
||||
|
||||
record = await db.getByKeyID('3a414737-2fd0-44c0-af05-7efc172475fc');
|
||||
ok(!record, 'Unsubscribed record should not exist');
|
||||
record = await db.getByKeyID("3a414737-2fd0-44c0-af05-7efc172475fc");
|
||||
ok(!record, "Unsubscribed record should not exist");
|
||||
};
|
||||
|
||||
function putTestRecord(db, keyID, scope, quota) {
|
||||
return db.put({
|
||||
channelID: keyID,
|
||||
pushEndpoint: 'https://example.org/push/' + keyID,
|
||||
scope: scope,
|
||||
pushEndpoint: "https://example.org/push/" + keyID,
|
||||
scope,
|
||||
pushCount: 0,
|
||||
lastPush: 0,
|
||||
version: null,
|
||||
originAttributes: '',
|
||||
quota: quota,
|
||||
originAttributes: "",
|
||||
quota,
|
||||
systemRecord: quota == Infinity,
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
'use strict';
|
||||
"use strict";
|
||||
|
||||
const {PushDB, PushService, PushServiceWebSocket} = serviceExports;
|
||||
const {BroadcastService} = ChromeUtils.import("resource://gre/modules/PushBroadcastService.jsm", null);
|
||||
|
@ -12,8 +12,8 @@ const {broadcastHandler} = ChromeUtils.import("resource://test/broadcast_handler
|
|||
|
||||
const broadcastService = pushBroadcastService;
|
||||
const assert = Assert;
|
||||
const userAgentID = 'bd744428-f125-436a-b6d0-dd0c9845837f';
|
||||
const channelID = '0ef2ad4a-6c49-41ad-af6e-95d2425276bf';
|
||||
const userAgentID = "bd744428-f125-436a-b6d0-dd0c9845837f";
|
||||
const channelID = "0ef2ad4a-6c49-41ad-af6e-95d2425276bf";
|
||||
|
||||
function run_test() {
|
||||
do_get_profile();
|
||||
|
@ -21,7 +21,7 @@ function run_test() {
|
|||
userAgentID,
|
||||
alwaysConnect: true,
|
||||
requestTimeout: 1000,
|
||||
retryBaseInterval: 150
|
||||
retryBaseInterval: 150,
|
||||
});
|
||||
run_next_test();
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ function run_test() {
|
|||
function getPushServiceMock() {
|
||||
return {
|
||||
subscribed: [],
|
||||
subscribeBroadcast: function(broadcastId, version) {
|
||||
subscribeBroadcast(broadcastId, version) {
|
||||
this.subscribed.push([broadcastId, version]);
|
||||
},
|
||||
};
|
||||
|
@ -41,7 +41,7 @@ add_task(async function test_register_success() {
|
|||
broadcastHandler.reset();
|
||||
let notifications = broadcastHandler.notifications;
|
||||
let socket;
|
||||
registerCleanupFunction(() => {return db.drop().then(_ => db.close());});
|
||||
registerCleanupFunction(() => { return db.drop().then(_ => db.close()); });
|
||||
|
||||
await broadcastService.addListener("broadcast-test", "2018-02-01", {
|
||||
moduleURI: "resource://test/broadcast_handler.jsm",
|
||||
|
@ -60,12 +60,12 @@ add_task(async function test_register_success() {
|
|||
onHello(data) {
|
||||
socket = this;
|
||||
deepEqual(data.broadcasts, {"broadcast-test": "2018-02-01"}, "Handshake: doesn't consult listeners");
|
||||
equal(data.messageType, 'hello', 'Handshake: wrong message type');
|
||||
equal(data.uaid, userAgentID, 'Handshake: wrong device ID');
|
||||
equal(data.messageType, "hello", "Handshake: wrong message type");
|
||||
equal(data.uaid, userAgentID, "Handshake: wrong device ID");
|
||||
this.serverSendMsg(JSON.stringify({
|
||||
messageType: 'hello',
|
||||
messageType: "hello",
|
||||
status: 200,
|
||||
uaid: userAgentID
|
||||
uaid: userAgentID,
|
||||
}));
|
||||
},
|
||||
|
||||
|
@ -73,14 +73,14 @@ add_task(async function test_register_success() {
|
|||
broadcastSubscriptions.push(data);
|
||||
},
|
||||
});
|
||||
}
|
||||
})
|
||||
},
|
||||
});
|
||||
|
||||
socket.serverSendMsg(JSON.stringify({
|
||||
messageType: "broadcast",
|
||||
broadcasts: {
|
||||
"broadcast-test": "2018-03-02"
|
||||
}
|
||||
"broadcast-test": "2018-03-02",
|
||||
},
|
||||
}));
|
||||
|
||||
await broadcastHandler.wasNotified;
|
||||
|
@ -88,17 +88,17 @@ add_task(async function test_register_success() {
|
|||
deepEqual(notifications, [["2018-03-02", "broadcast-test"]], "Broadcast notification didn't get delivered");
|
||||
|
||||
deepEqual(await broadcastService.getListeners(), {
|
||||
"broadcast-test": "2018-03-02"
|
||||
"broadcast-test": "2018-03-02",
|
||||
}, "Broadcast version wasn't updated");
|
||||
|
||||
await broadcastService.addListener("example-listener", "2018-03-01", {
|
||||
moduleURI: "resource://gre/modules/not-real-example.jsm",
|
||||
symbolName: "doesntExist"
|
||||
symbolName: "doesntExist",
|
||||
});
|
||||
|
||||
deepEqual(broadcastSubscriptions, [{
|
||||
messageType: "broadcast_subscribe",
|
||||
broadcasts: {"example-listener": "2018-03-01"}
|
||||
broadcasts: {"example-listener": "2018-03-01"},
|
||||
}]);
|
||||
});
|
||||
|
||||
|
@ -108,7 +108,7 @@ add_task(async function test_handle_hello_broadcasts() {
|
|||
let db = PushServiceWebSocket.newPushDB();
|
||||
broadcastHandler.reset();
|
||||
let notifications = broadcastHandler.notifications;
|
||||
registerCleanupFunction(() => {return db.drop().then(_ => db.close());});
|
||||
registerCleanupFunction(() => { return db.drop().then(_ => db.close()); });
|
||||
|
||||
await broadcastService.addListener("broadcast-test", "2018-02-01", {
|
||||
moduleURI: "resource://test/broadcast_handler.jsm",
|
||||
|
@ -124,31 +124,29 @@ add_task(async function test_handle_hello_broadcasts() {
|
|||
return new MockWebSocket(uri, {
|
||||
onHello(data) {
|
||||
deepEqual(data.broadcasts, {"broadcast-test": "2018-02-01"}, "Handshake: doesn't consult listeners");
|
||||
equal(data.messageType, 'hello', 'Handshake: wrong message type');
|
||||
equal(data.uaid, userAgentID, 'Handshake: wrong device ID');
|
||||
equal(data.messageType, "hello", "Handshake: wrong message type");
|
||||
equal(data.uaid, userAgentID, "Handshake: wrong device ID");
|
||||
this.serverSendMsg(JSON.stringify({
|
||||
messageType: 'hello',
|
||||
messageType: "hello",
|
||||
status: 200,
|
||||
uaid: userAgentID,
|
||||
broadcasts: {
|
||||
"broadcast-test": "2018-02-02"
|
||||
}
|
||||
"broadcast-test": "2018-02-02",
|
||||
},
|
||||
}));
|
||||
},
|
||||
|
||||
onBroadcastSubscribe(data) {
|
||||
broadcastSubscriptions.push(data);
|
||||
},
|
||||
onBroadcastSubscribe(data) {},
|
||||
});
|
||||
}
|
||||
})
|
||||
},
|
||||
});
|
||||
|
||||
await broadcastHandler.wasNotified;
|
||||
|
||||
deepEqual(notifications, [["2018-02-02", "broadcast-test"]], "Broadcast notification on hello was delivered");
|
||||
|
||||
deepEqual(await broadcastService.getListeners(), {
|
||||
"broadcast-test": "2018-02-02"
|
||||
"broadcast-test": "2018-02-02",
|
||||
}, "Broadcast version wasn't updated");
|
||||
});
|
||||
|
||||
|
@ -158,16 +156,16 @@ add_task(async function test_broadcast_unit() {
|
|||
version: "2018-03-04",
|
||||
sourceInfo: {
|
||||
moduleURI: "resource://gre/modules/abc.jsm",
|
||||
symbolName: "getAbc"
|
||||
}
|
||||
symbolName: "getAbc",
|
||||
},
|
||||
},
|
||||
"def": {
|
||||
version: "2018-04-05",
|
||||
sourceInfo: {
|
||||
moduleURI: "resource://gre/modules/def.jsm",
|
||||
symbolName: "getDef"
|
||||
}
|
||||
}
|
||||
symbolName: "getDef",
|
||||
},
|
||||
},
|
||||
};
|
||||
const path = FileTestUtils.getTempFile("broadcast-listeners.json").path;
|
||||
|
||||
|
@ -179,23 +177,23 @@ add_task(async function test_broadcast_unit() {
|
|||
|
||||
const pushServiceMock = getPushServiceMock();
|
||||
|
||||
const broadcastService = new BroadcastService(pushServiceMock, path);
|
||||
const listeners = await broadcastService.getListeners();
|
||||
const mockBroadcastService = new BroadcastService(pushServiceMock, path);
|
||||
const listeners = await mockBroadcastService.getListeners();
|
||||
deepEqual(listeners, {
|
||||
"abc": "2018-03-04",
|
||||
"def": "2018-04-05"
|
||||
"def": "2018-04-05",
|
||||
});
|
||||
|
||||
await broadcastService.addListener("ghi", "2018-05-06", {
|
||||
await mockBroadcastService.addListener("ghi", "2018-05-06", {
|
||||
moduleURI: "resource://gre/modules/ghi.jsm",
|
||||
symbolName: "getGhi"
|
||||
symbolName: "getGhi",
|
||||
});
|
||||
|
||||
deepEqual(pushServiceMock.subscribed, [
|
||||
["ghi", "2018-05-06"]
|
||||
["ghi", "2018-05-06"],
|
||||
]);
|
||||
|
||||
await broadcastService._saveImmediately();
|
||||
await mockBroadcastService._saveImmediately();
|
||||
|
||||
const newJSONFile = new JSONFile({path});
|
||||
await newJSONFile.load();
|
||||
|
@ -207,36 +205,36 @@ add_task(async function test_broadcast_unit() {
|
|||
version: "2018-05-06",
|
||||
sourceInfo: {
|
||||
moduleURI: "resource://gre/modules/ghi.jsm",
|
||||
symbolName: "getGhi"
|
||||
}
|
||||
}
|
||||
symbolName: "getGhi",
|
||||
},
|
||||
},
|
||||
},
|
||||
version: 1,
|
||||
});
|
||||
|
||||
deepEqual(await broadcastService.getListeners(), {
|
||||
deepEqual(await mockBroadcastService.getListeners(), {
|
||||
"abc": "2018-03-04",
|
||||
"def": "2018-04-05",
|
||||
"ghi": "2018-05-06"
|
||||
"ghi": "2018-05-06",
|
||||
});
|
||||
});
|
||||
|
||||
add_task(async function test_broadcast_initialize_sane() {
|
||||
const path = FileTestUtils.getTempFile("broadcast-listeners.json").path;
|
||||
const broadcastService = new BroadcastService(getPushServiceMock(), path);
|
||||
deepEqual(await broadcastService.getListeners(), {}, "listeners should start out sane");
|
||||
await broadcastService._saveImmediately();
|
||||
const mockBroadcastService = new BroadcastService(getPushServiceMock(), path);
|
||||
deepEqual(await mockBroadcastService.getListeners(), {}, "listeners should start out sane");
|
||||
await mockBroadcastService._saveImmediately();
|
||||
let onDiskJSONFile = new JSONFile({path});
|
||||
await onDiskJSONFile.load();
|
||||
deepEqual(onDiskJSONFile.data, {listeners: {}, version: 1},
|
||||
"written JSON file has listeners and version fields");
|
||||
|
||||
await broadcastService.addListener("ghi", "2018-05-06", {
|
||||
await mockBroadcastService.addListener("ghi", "2018-05-06", {
|
||||
moduleURI: "resource://gre/modules/ghi.jsm",
|
||||
symbolName: "getGhi"
|
||||
symbolName: "getGhi",
|
||||
});
|
||||
|
||||
await broadcastService._saveImmediately();
|
||||
await mockBroadcastService._saveImmediately();
|
||||
|
||||
onDiskJSONFile = new JSONFile({path});
|
||||
await onDiskJSONFile.load();
|
||||
|
@ -247,9 +245,9 @@ add_task(async function test_broadcast_initialize_sane() {
|
|||
version: "2018-05-06",
|
||||
sourceInfo: {
|
||||
moduleURI: "resource://gre/modules/ghi.jsm",
|
||||
symbolName: "getGhi"
|
||||
}
|
||||
}
|
||||
symbolName: "getGhi",
|
||||
},
|
||||
},
|
||||
},
|
||||
version: 1,
|
||||
}, "adding listeners to initial state is written OK");
|
||||
|
@ -257,24 +255,24 @@ add_task(async function test_broadcast_initialize_sane() {
|
|||
|
||||
add_task(async function test_broadcast_reject_invalid_sourceinfo() {
|
||||
const path = FileTestUtils.getTempFile("broadcast-listeners.json").path;
|
||||
const broadcastService = new BroadcastService(getPushServiceMock(), path);
|
||||
const mockBroadcastService = new BroadcastService(getPushServiceMock(), path);
|
||||
|
||||
await assert.rejects(broadcastService.addListener("ghi", "2018-05-06", {
|
||||
await assert.rejects(mockBroadcastService.addListener("ghi", "2018-05-06", {
|
||||
moduleName: "resource://gre/modules/ghi.jsm",
|
||||
symbolName: "getGhi"
|
||||
symbolName: "getGhi",
|
||||
}), /moduleURI must be a string/, "rejects sourceInfo that doesn't have moduleURI");
|
||||
});
|
||||
|
||||
add_task(async function test_broadcast_reject_version_not_string() {
|
||||
await assert.rejects(broadcastService.addListener("ghi", {}, {
|
||||
moduleURI: "resource://gre/modules/ghi.jsm",
|
||||
symbolName: "getGhi"
|
||||
symbolName: "getGhi",
|
||||
}), /version should be a string/, "rejects version that isn't a string");
|
||||
});
|
||||
|
||||
add_task(async function test_broadcast_reject_version_empty_string() {
|
||||
await assert.rejects(broadcastService.addListener("ghi", "", {
|
||||
moduleURI: "resource://gre/modules/ghi.jsm",
|
||||
symbolName: "getGhi"
|
||||
symbolName: "getGhi",
|
||||
}), /version should not be an empty string/, "rejects version that is an empty string");
|
||||
});
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
'use strict';
|
||||
"use strict";
|
||||
|
||||
const {PushDB, PushService, PushServiceWebSocket} = serviceExports;
|
||||
|
||||
var db;
|
||||
var unregisterDefers = {};
|
||||
var userAgentID = '4ce480ef-55b2-4f83-924c-dcd35ab978b4';
|
||||
var userAgentID = "4ce480ef-55b2-4f83-924c-dcd35ab978b4";
|
||||
|
||||
function promiseUnregister(keyID, code) {
|
||||
return new Promise(r => unregisterDefers[keyID] = r);
|
||||
|
@ -16,36 +16,36 @@ function promiseUnregister(keyID, code) {
|
|||
function run_test() {
|
||||
do_get_profile();
|
||||
setPrefs({
|
||||
userAgentID: userAgentID,
|
||||
userAgentID,
|
||||
});
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
add_task(async function setup() {
|
||||
db = PushServiceWebSocket.newPushDB();
|
||||
registerCleanupFunction(_ => db.drop().then(_ => db.close()));
|
||||
registerCleanupFunction(() => db.drop().then(() => db.close()));
|
||||
|
||||
// Active subscriptions; should be expired then dropped.
|
||||
await putTestRecord(db, 'active-1', 'https://example.info/some-page', 8);
|
||||
await putTestRecord(db, 'active-2', 'https://example.com/another-page', 16);
|
||||
await putTestRecord(db, "active-1", "https://example.info/some-page", 8);
|
||||
await putTestRecord(db, "active-2", "https://example.com/another-page", 16);
|
||||
|
||||
// Expired subscription; should be dropped.
|
||||
await putTestRecord(db, 'expired', 'https://example.net/yet-another-page', 0);
|
||||
await putTestRecord(db, "expired", "https://example.net/yet-another-page", 0);
|
||||
|
||||
// A privileged subscription that should not be affected by sanitizing data
|
||||
// because its quota is set to `Infinity`.
|
||||
await putTestRecord(db, 'privileged', 'app://chrome/only', Infinity);
|
||||
await putTestRecord(db, "privileged", "app://chrome/only", Infinity);
|
||||
|
||||
let handshakeDone;
|
||||
let handshakePromise = new Promise(r => handshakeDone = r);
|
||||
PushService.init({
|
||||
serverURI: 'wss://push.example.org/',
|
||||
db: db,
|
||||
serverURI: "wss://push.example.org/",
|
||||
db,
|
||||
makeWebSocket(uri) {
|
||||
return new MockWebSocket(uri, {
|
||||
onHello(request) {
|
||||
this.serverSendMsg(JSON.stringify({
|
||||
messageType: 'hello',
|
||||
messageType: "hello",
|
||||
uaid: userAgentID,
|
||||
status: 200,
|
||||
use_webpush: true,
|
||||
|
@ -54,13 +54,13 @@ add_task(async function setup() {
|
|||
},
|
||||
onUnregister(request) {
|
||||
let resolve = unregisterDefers[request.channelID];
|
||||
equal(typeof resolve, 'function',
|
||||
'Dropped unexpected channel ID ' + request.channelID);
|
||||
equal(typeof resolve, "function",
|
||||
"Dropped unexpected channel ID " + request.channelID);
|
||||
delete unregisterDefers[request.channelID];
|
||||
equal(request.code, 200,
|
||||
'Expected manual unregister reason');
|
||||
"Expected manual unregister reason");
|
||||
this.serverSendMsg(JSON.stringify({
|
||||
messageType: 'unregister',
|
||||
messageType: "unregister",
|
||||
channelID: request.channelID,
|
||||
status: 200,
|
||||
}));
|
||||
|
@ -78,8 +78,8 @@ add_task(async function test_sanitize() {
|
|||
|
||||
let promiseCleared = Promise.all([
|
||||
// Active subscriptions should be unregistered.
|
||||
promiseUnregister('active-1'),
|
||||
promiseUnregister('active-2'),
|
||||
promiseUnregister("active-1"),
|
||||
promiseUnregister("active-2"),
|
||||
promiseObserverNotification(
|
||||
PushServiceComponent.subscriptionModifiedTopic, (subject, data) => {
|
||||
modifiedScopes.push(data);
|
||||
|
@ -87,7 +87,7 @@ add_task(async function test_sanitize() {
|
|||
}),
|
||||
|
||||
// Privileged should be recreated.
|
||||
promiseUnregister('privileged'),
|
||||
promiseUnregister("privileged"),
|
||||
promiseObserverNotification(
|
||||
PushServiceComponent.subscriptionChangeTopic, (subject, data) => {
|
||||
changeScopes.push(data);
|
||||
|
@ -96,20 +96,20 @@ add_task(async function test_sanitize() {
|
|||
]);
|
||||
|
||||
await PushService.clear({
|
||||
domain: '*',
|
||||
domain: "*",
|
||||
});
|
||||
|
||||
await promiseCleared;
|
||||
|
||||
deepEqual(modifiedScopes.sort(compareAscending), [
|
||||
'app://chrome/only',
|
||||
'https://example.com/another-page',
|
||||
'https://example.info/some-page',
|
||||
], 'Should modify active subscription scopes');
|
||||
"app://chrome/only",
|
||||
"https://example.com/another-page",
|
||||
"https://example.info/some-page",
|
||||
], "Should modify active subscription scopes");
|
||||
|
||||
deepEqual(changeScopes, ['app://chrome/only'],
|
||||
'Should fire change notification for privileged scope');
|
||||
deepEqual(changeScopes, ["app://chrome/only"],
|
||||
"Should fire change notification for privileged scope");
|
||||
|
||||
let remainingIDs = await getAllKeyIDs(db);
|
||||
deepEqual(remainingIDs, [], 'Should drop all subscriptions');
|
||||
deepEqual(remainingIDs, [], "Should drop all subscriptions");
|
||||
});
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
'use strict';
|
||||
"use strict";
|
||||
|
||||
const {PushService, PushServiceWebSocket} = serviceExports;
|
||||
const {ForgetAboutSite} = ChromeUtils.import("resource://gre/modules/ForgetAboutSite.jsm");
|
||||
|
||||
var db;
|
||||
var unregisterDefers = {};
|
||||
var userAgentID = '4fe01c2d-72ac-4c13-93d2-bb072caf461d';
|
||||
var userAgentID = "4fe01c2d-72ac-4c13-93d2-bb072caf461d";
|
||||
|
||||
function promiseUnregister(keyID) {
|
||||
return new Promise(r => unregisterDefers[keyID] = r);
|
||||
|
@ -14,40 +14,40 @@ function promiseUnregister(keyID) {
|
|||
function run_test() {
|
||||
do_get_profile();
|
||||
setPrefs({
|
||||
userAgentID: userAgentID,
|
||||
userAgentID,
|
||||
});
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
add_task(async function setup() {
|
||||
db = PushServiceWebSocket.newPushDB();
|
||||
registerCleanupFunction(_ => db.drop().then(_ => db.close()));
|
||||
registerCleanupFunction(() => db.drop().then(() => db.close()));
|
||||
|
||||
// Active and expired subscriptions for a subdomain. The active subscription
|
||||
// should be expired, then removed; the expired subscription should be
|
||||
// removed immediately.
|
||||
await putTestRecord(db, 'active-sub', 'https://sub.example.com/sub-page', 4);
|
||||
await putTestRecord(db, 'expired-sub', 'https://sub.example.com/yet-another-page', 0);
|
||||
await putTestRecord(db, "active-sub", "https://sub.example.com/sub-page", 4);
|
||||
await putTestRecord(db, "expired-sub", "https://sub.example.com/yet-another-page", 0);
|
||||
|
||||
// Active subscriptions for another subdomain. Should be unsubscribed and
|
||||
// dropped.
|
||||
await putTestRecord(db, 'active-1', 'https://sub2.example.com/some-page', 8);
|
||||
await putTestRecord(db, 'active-2', 'https://sub3.example.com/another-page', 16);
|
||||
await putTestRecord(db, "active-1", "https://sub2.example.com/some-page", 8);
|
||||
await putTestRecord(db, "active-2", "https://sub3.example.com/another-page", 16);
|
||||
|
||||
// A privileged subscription with a real URL that should not be affected
|
||||
// because its quota is set to `Infinity`.
|
||||
await putTestRecord(db, 'privileged', 'https://sub.example.com/real-url', Infinity);
|
||||
await putTestRecord(db, "privileged", "https://sub.example.com/real-url", Infinity);
|
||||
|
||||
let handshakeDone;
|
||||
let handshakePromise = new Promise(r => handshakeDone = r);
|
||||
PushService.init({
|
||||
serverURI: 'wss://push.example.org/',
|
||||
db: db,
|
||||
serverURI: "wss://push.example.org/",
|
||||
db,
|
||||
makeWebSocket(uri) {
|
||||
return new MockWebSocket(uri, {
|
||||
onHello(request) {
|
||||
this.serverSendMsg(JSON.stringify({
|
||||
messageType: 'hello',
|
||||
messageType: "hello",
|
||||
uaid: userAgentID,
|
||||
status: 200,
|
||||
use_webpush: true,
|
||||
|
@ -56,14 +56,14 @@ add_task(async function setup() {
|
|||
},
|
||||
onUnregister(request) {
|
||||
let resolve = unregisterDefers[request.channelID];
|
||||
equal(typeof resolve, 'function',
|
||||
'Dropped unexpected channel ID ' + request.channelID);
|
||||
equal(typeof resolve, "function",
|
||||
"Dropped unexpected channel ID " + request.channelID);
|
||||
delete unregisterDefers[request.channelID];
|
||||
equal(request.code, 200,
|
||||
'Expected manual unregister reason');
|
||||
"Expected manual unregister reason");
|
||||
resolve();
|
||||
this.serverSendMsg(JSON.stringify({
|
||||
messageType: 'unregister',
|
||||
messageType: "unregister",
|
||||
status: 200,
|
||||
channelID: request.channelID,
|
||||
}));
|
||||
|
@ -80,7 +80,7 @@ add_task(async function test_forgetAboutSubdomain() {
|
|||
let modifiedScopes = [];
|
||||
let promiseForgetSubs = Promise.all([
|
||||
// Active subscriptions should be dropped.
|
||||
promiseUnregister('active-sub'),
|
||||
promiseUnregister("active-sub"),
|
||||
promiseObserverNotification(
|
||||
PushServiceComponent.subscriptionModifiedTopic, (subject, data) => {
|
||||
modifiedScopes.push(data);
|
||||
|
@ -88,23 +88,23 @@ add_task(async function test_forgetAboutSubdomain() {
|
|||
}
|
||||
),
|
||||
]);
|
||||
await ForgetAboutSite.removeDataFromDomain('sub.example.com');
|
||||
await ForgetAboutSite.removeDataFromDomain("sub.example.com");
|
||||
await promiseForgetSubs;
|
||||
|
||||
deepEqual(modifiedScopes.sort(compareAscending), [
|
||||
'https://sub.example.com/sub-page',
|
||||
], 'Should fire modified notifications for active subscriptions');
|
||||
"https://sub.example.com/sub-page",
|
||||
], "Should fire modified notifications for active subscriptions");
|
||||
|
||||
let remainingIDs = await getAllKeyIDs(db);
|
||||
deepEqual(remainingIDs, ['active-1', 'active-2', 'privileged'],
|
||||
'Should only forget subscriptions for subdomain');
|
||||
deepEqual(remainingIDs, ["active-1", "active-2", "privileged"],
|
||||
"Should only forget subscriptions for subdomain");
|
||||
});
|
||||
|
||||
add_task(async function test_forgetAboutRootDomain() {
|
||||
let modifiedScopes = [];
|
||||
let promiseForgetSubs = Promise.all([
|
||||
promiseUnregister('active-1'),
|
||||
promiseUnregister('active-2'),
|
||||
promiseUnregister("active-1"),
|
||||
promiseUnregister("active-2"),
|
||||
promiseObserverNotification(
|
||||
PushServiceComponent.subscriptionModifiedTopic, (subject, data) => {
|
||||
modifiedScopes.push(data);
|
||||
|
@ -113,15 +113,15 @@ add_task(async function test_forgetAboutRootDomain() {
|
|||
),
|
||||
]);
|
||||
|
||||
await ForgetAboutSite.removeDataFromDomain('example.com');
|
||||
await ForgetAboutSite.removeDataFromDomain("example.com");
|
||||
await promiseForgetSubs;
|
||||
|
||||
deepEqual(modifiedScopes.sort(compareAscending), [
|
||||
'https://sub2.example.com/some-page',
|
||||
'https://sub3.example.com/another-page',
|
||||
], 'Should fire modified notifications for entire domain');
|
||||
"https://sub2.example.com/some-page",
|
||||
"https://sub3.example.com/another-page",
|
||||
], "Should fire modified notifications for entire domain");
|
||||
|
||||
let remainingIDs = await getAllKeyIDs(db);
|
||||
deepEqual(remainingIDs, ['privileged'],
|
||||
'Should ignore privileged records with a real URL');
|
||||
deepEqual(remainingIDs, ["privileged"],
|
||||
"Should ignore privileged records with a real URL");
|
||||
});
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
'use strict';
|
||||
"use strict";
|
||||
|
||||
const {PushDB, PushService, PushServiceWebSocket} = serviceExports;
|
||||
|
||||
const userAgentID = 'bd744428-f125-436a-b6d0-dd0c9845837f';
|
||||
const userAgentID = "bd744428-f125-436a-b6d0-dd0c9845837f";
|
||||
|
||||
let clearForPattern = async function(testRecords, pattern) {
|
||||
let patternString = JSON.stringify(pattern);
|
||||
|
@ -24,12 +24,12 @@ let clearForPattern = async function(testRecords, pattern) {
|
|||
let url = test.scope + originSuffix;
|
||||
|
||||
if (ObjectUtils.deepEqual(test.clearIf, pattern)) {
|
||||
ok(!registration, 'Should clear registration ' + url +
|
||||
' for pattern ' + patternString);
|
||||
ok(!registration, "Should clear registration " + url +
|
||||
" for pattern " + patternString);
|
||||
testRecords.splice(length, 1);
|
||||
} else {
|
||||
ok(registration, 'Should not clear registration ' + url +
|
||||
' for pattern ' + patternString);
|
||||
ok(registration, "Should not clear registration " + url +
|
||||
" for pattern " + patternString);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -39,41 +39,41 @@ function run_test() {
|
|||
setPrefs({
|
||||
userAgentID,
|
||||
requestTimeout: 1000,
|
||||
retryBaseInterval: 150
|
||||
retryBaseInterval: 150,
|
||||
});
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
add_task(async function test_webapps_cleardata() {
|
||||
let db = PushServiceWebSocket.newPushDB();
|
||||
registerCleanupFunction(() => {return db.drop().then(_ => db.close());});
|
||||
registerCleanupFunction(() => { return db.drop().then(_ => db.close()); });
|
||||
|
||||
let testRecords = [{
|
||||
scope: 'https://example.org/1',
|
||||
scope: "https://example.org/1",
|
||||
originAttributes: { appId: 1 },
|
||||
clearIf: { appId: 1, inIsolatedMozBrowser: false },
|
||||
}, {
|
||||
scope: 'https://example.org/1',
|
||||
scope: "https://example.org/1",
|
||||
originAttributes: { appId: 1, inIsolatedMozBrowser: true },
|
||||
clearIf: { appId: 1 },
|
||||
}, {
|
||||
scope: 'https://example.org/1',
|
||||
scope: "https://example.org/1",
|
||||
originAttributes: { appId: 2, inIsolatedMozBrowser: true },
|
||||
clearIf: { appId: 2, inIsolatedMozBrowser: true },
|
||||
}, {
|
||||
scope: 'https://example.org/2',
|
||||
scope: "https://example.org/2",
|
||||
originAttributes: { appId: 1 },
|
||||
clearIf: { appId: 1, inIsolatedMozBrowser: false },
|
||||
}, {
|
||||
scope: 'https://example.org/2',
|
||||
scope: "https://example.org/2",
|
||||
originAttributes: { appId: 2, inIsolatedMozBrowser: true },
|
||||
clearIf: { appId: 2, inIsolatedMozBrowser: true },
|
||||
}, {
|
||||
scope: 'https://example.org/3',
|
||||
scope: "https://example.org/3",
|
||||
originAttributes: { appId: 3, inIsolatedMozBrowser: true },
|
||||
clearIf: { inIsolatedMozBrowser: true },
|
||||
}, {
|
||||
scope: 'https://example.org/3',
|
||||
scope: "https://example.org/3",
|
||||
originAttributes: { appId: 4, inIsolatedMozBrowser: true },
|
||||
clearIf: { inIsolatedMozBrowser: true },
|
||||
}];
|
||||
|
@ -88,30 +88,30 @@ add_task(async function test_webapps_cleardata() {
|
|||
makeWebSocket(uri) {
|
||||
return new MockWebSocket(uri, {
|
||||
onHello(data) {
|
||||
equal(data.messageType, 'hello', 'Handshake: wrong message type');
|
||||
equal(data.uaid, userAgentID, 'Handshake: wrong device ID');
|
||||
equal(data.messageType, "hello", "Handshake: wrong message type");
|
||||
equal(data.uaid, userAgentID, "Handshake: wrong device ID");
|
||||
this.serverSendMsg(JSON.stringify({
|
||||
messageType: 'hello',
|
||||
messageType: "hello",
|
||||
status: 200,
|
||||
uaid: userAgentID
|
||||
uaid: userAgentID,
|
||||
}));
|
||||
},
|
||||
onRegister(data) {
|
||||
equal(data.messageType, 'register', 'Register: wrong message type');
|
||||
equal(data.messageType, "register", "Register: wrong message type");
|
||||
this.serverSendMsg(JSON.stringify({
|
||||
messageType: 'register',
|
||||
messageType: "register",
|
||||
status: 200,
|
||||
channelID: data.channelID,
|
||||
uaid: userAgentID,
|
||||
pushEndpoint: 'https://example.com/update/' + Math.random(),
|
||||
pushEndpoint: "https://example.com/update/" + Math.random(),
|
||||
}));
|
||||
},
|
||||
onUnregister(data) {
|
||||
equal(data.code, 200, 'Expected manual unregister reason');
|
||||
equal(data.code, 200, "Expected manual unregister reason");
|
||||
unregisterDone();
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
await Promise.all(testRecords.map(test =>
|
||||
|
@ -136,6 +136,6 @@ add_task(async function test_webapps_cleardata() {
|
|||
// Removes all records where `inIsolatedMozBrowser` is true.
|
||||
await clearForPattern(testRecords, { inIsolatedMozBrowser: true });
|
||||
|
||||
equal(testRecords.length, 0, 'Should remove all test records');
|
||||
equal(testRecords.length, 0, "Should remove all test records");
|
||||
await unregisterPromise;
|
||||
});
|
||||
|
|
|
@ -1,24 +1,24 @@
|
|||
'use strict';
|
||||
"use strict";
|
||||
|
||||
const {
|
||||
getCryptoParamsFromHeaders,
|
||||
PushCrypto,
|
||||
} = ChromeUtils.import("resource://gre/modules/PushCrypto.jsm", null);
|
||||
|
||||
const REJECT_PADDING = { padding: 'reject' };
|
||||
const REJECT_PADDING = { padding: "reject" };
|
||||
|
||||
// A common key to decrypt some aesgcm and aesgcm128 messages. Other decryption
|
||||
// tests have their own keys.
|
||||
const LEGACY_PRIVATE_KEY = {
|
||||
kty: 'EC',
|
||||
crv: 'P-256',
|
||||
d: '4h23G_KkXC9TvBSK2v0Q7ImpS2YAuRd8hQyN0rFAwBg',
|
||||
x: 'sd85ZCbEG6dEkGMCmDyGBIt454Qy-Yo-1xhbaT2Jlk4',
|
||||
y: 'vr3cKpQ-Sp1kpZ9HipNjUCwSA55yy0uM8N9byE8dmLs',
|
||||
kty: "EC",
|
||||
crv: "P-256",
|
||||
d: "4h23G_KkXC9TvBSK2v0Q7ImpS2YAuRd8hQyN0rFAwBg",
|
||||
x: "sd85ZCbEG6dEkGMCmDyGBIt454Qy-Yo-1xhbaT2Jlk4",
|
||||
y: "vr3cKpQ-Sp1kpZ9HipNjUCwSA55yy0uM8N9byE8dmLs",
|
||||
ext: true,
|
||||
};
|
||||
|
||||
const LEGACY_PUBLIC_KEY = 'BLHfOWQmxBunRJBjApg8hgSLeOeEMvmKPtcYW2k9iZZOvr3cKpQ-Sp1kpZ9HipNjUCwSA55yy0uM8N9byE8dmLs';
|
||||
const LEGACY_PUBLIC_KEY = "BLHfOWQmxBunRJBjApg8hgSLeOeEMvmKPtcYW2k9iZZOvr3cKpQ-Sp1kpZ9HipNjUCwSA55yy0uM8N9byE8dmLs";
|
||||
|
||||
async function assertDecrypts(test, headers) {
|
||||
let privateKey = test.privateKey;
|
||||
|
@ -30,7 +30,7 @@ async function assertDecrypts(test, headers) {
|
|||
let payload = ChromeUtils.base64URLDecode(test.data, REJECT_PADDING);
|
||||
let result = await PushCrypto.decrypt(privateKey, publicKey, authSecret,
|
||||
headers, payload);
|
||||
let decoder = new TextDecoder('utf-8');
|
||||
let decoder = new TextDecoder("utf-8");
|
||||
equal(decoder.decode(new Uint8Array(result)), test.result, test.desc);
|
||||
}
|
||||
|
||||
|
@ -43,71 +43,71 @@ async function assertNotDecrypts(test, headers) {
|
|||
let publicKey = ChromeUtils.base64URLDecode(test.publicKey, REJECT_PADDING);
|
||||
let promise = PushCrypto.decrypt(test.privateKey, publicKey, authSecret,
|
||||
headers, data);
|
||||
await rejects(promise, test.expected, test.desc);
|
||||
await Assert.rejects(promise, test.expected, test.desc);
|
||||
}
|
||||
|
||||
add_task(async function test_crypto_getCryptoParamsFromHeaders() {
|
||||
// These headers should parse correctly.
|
||||
let shouldParse = [{
|
||||
desc: 'aesgcm with multiple keys',
|
||||
desc: "aesgcm with multiple keys",
|
||||
headers: {
|
||||
encoding: 'aesgcm',
|
||||
crypto_key: 'keyid=p256dh;dh=Iy1Je2Kv11A,p256ecdsa=o2M8QfiEKuI',
|
||||
encryption: 'keyid=p256dh;salt=upk1yFkp1xI',
|
||||
encoding: "aesgcm",
|
||||
crypto_key: "keyid=p256dh;dh=Iy1Je2Kv11A,p256ecdsa=o2M8QfiEKuI",
|
||||
encryption: "keyid=p256dh;salt=upk1yFkp1xI",
|
||||
},
|
||||
params: {
|
||||
senderKey: 'Iy1Je2Kv11A',
|
||||
salt: 'upk1yFkp1xI',
|
||||
senderKey: "Iy1Je2Kv11A",
|
||||
salt: "upk1yFkp1xI",
|
||||
rs: 4096,
|
||||
},
|
||||
}, {
|
||||
desc: 'aesgcm with quoted key param',
|
||||
desc: "aesgcm with quoted key param",
|
||||
headers: {
|
||||
encoding: 'aesgcm',
|
||||
encoding: "aesgcm",
|
||||
crypto_key: 'dh="byfHbUffc-k"',
|
||||
encryption: 'salt=C11AvAsp6Gc',
|
||||
encryption: "salt=C11AvAsp6Gc",
|
||||
},
|
||||
params: {
|
||||
senderKey: 'byfHbUffc-k',
|
||||
salt: 'C11AvAsp6Gc',
|
||||
senderKey: "byfHbUffc-k",
|
||||
salt: "C11AvAsp6Gc",
|
||||
rs: 4096,
|
||||
},
|
||||
}, {
|
||||
desc: 'aesgcm with Crypto-Key and rs = 24',
|
||||
desc: "aesgcm with Crypto-Key and rs = 24",
|
||||
headers: {
|
||||
encoding: 'aesgcm',
|
||||
encoding: "aesgcm",
|
||||
crypto_key: 'dh="ybuT4VDz-Bg"',
|
||||
encryption: 'salt=H7U7wcIoIKs; rs=24',
|
||||
encryption: "salt=H7U7wcIoIKs; rs=24",
|
||||
},
|
||||
params: {
|
||||
senderKey: 'ybuT4VDz-Bg',
|
||||
salt: 'H7U7wcIoIKs',
|
||||
senderKey: "ybuT4VDz-Bg",
|
||||
salt: "H7U7wcIoIKs",
|
||||
rs: 24,
|
||||
},
|
||||
}, {
|
||||
desc: 'aesgcm128 with Encryption-Key and rs = 2',
|
||||
desc: "aesgcm128 with Encryption-Key and rs = 2",
|
||||
headers: {
|
||||
encoding: 'aesgcm128',
|
||||
encryption_key: 'keyid=legacy; dh=LqrDQuVl9lY',
|
||||
encryption: 'keyid=legacy; salt=YngI8B7YapM; rs=2',
|
||||
encoding: "aesgcm128",
|
||||
encryption_key: "keyid=legacy; dh=LqrDQuVl9lY",
|
||||
encryption: "keyid=legacy; salt=YngI8B7YapM; rs=2",
|
||||
},
|
||||
params: {
|
||||
senderKey: 'LqrDQuVl9lY',
|
||||
salt: 'YngI8B7YapM',
|
||||
senderKey: "LqrDQuVl9lY",
|
||||
salt: "YngI8B7YapM",
|
||||
rs: 2,
|
||||
},
|
||||
}, {
|
||||
desc: 'aesgcm128 with Encryption-Key',
|
||||
desc: "aesgcm128 with Encryption-Key",
|
||||
headers: {
|
||||
encoding: 'aesgcm128',
|
||||
encryption_key: 'keyid=v2; dh=VA6wmY1IpiE',
|
||||
encryption: 'keyid=v2; salt=khtpyXhpDKM',
|
||||
encoding: "aesgcm128",
|
||||
encryption_key: "keyid=v2; dh=VA6wmY1IpiE",
|
||||
encryption: "keyid=v2; salt=khtpyXhpDKM",
|
||||
},
|
||||
params: {
|
||||
senderKey: 'VA6wmY1IpiE',
|
||||
salt: 'khtpyXhpDKM',
|
||||
senderKey: "VA6wmY1IpiE",
|
||||
salt: "khtpyXhpDKM",
|
||||
rs: 4096,
|
||||
}
|
||||
},
|
||||
}];
|
||||
for (let test of shouldParse) {
|
||||
let params = getCryptoParamsFromHeaders(test.headers);
|
||||
|
@ -124,33 +124,33 @@ add_task(async function test_crypto_getCryptoParamsFromHeaders() {
|
|||
|
||||
// These headers should be rejected.
|
||||
let shouldThrow = [{
|
||||
desc: 'aesgcm128 with Crypto-Key',
|
||||
desc: "aesgcm128 with Crypto-Key",
|
||||
headers: {
|
||||
encoding: 'aesgcm128',
|
||||
crypto_key: 'keyid=v2; dh=VA6wmY1IpiE',
|
||||
encryption: 'keyid=v2; salt=F0Im7RtGgNY',
|
||||
encoding: "aesgcm128",
|
||||
crypto_key: "keyid=v2; dh=VA6wmY1IpiE",
|
||||
encryption: "keyid=v2; salt=F0Im7RtGgNY",
|
||||
},
|
||||
exception: /Missing Encryption-Key header/,
|
||||
}, {
|
||||
desc: 'Invalid encoding',
|
||||
desc: "Invalid encoding",
|
||||
headers: {
|
||||
encoding: 'nonexistent',
|
||||
encoding: "nonexistent",
|
||||
},
|
||||
exception: /Missing encryption header/,
|
||||
}, {
|
||||
desc: 'Invalid record size',
|
||||
desc: "Invalid record size",
|
||||
headers: {
|
||||
encoding: 'aesgcm',
|
||||
crypto_key: 'dh=pbmv1QkcEDY',
|
||||
encryption: 'dh=Esao8aTBfIk;rs=bad',
|
||||
encoding: "aesgcm",
|
||||
crypto_key: "dh=pbmv1QkcEDY",
|
||||
encryption: "dh=Esao8aTBfIk;rs=bad",
|
||||
},
|
||||
exception: /Invalid salt parameter/,
|
||||
}, {
|
||||
desc: 'aesgcm with Encryption-Key',
|
||||
desc: "aesgcm with Encryption-Key",
|
||||
headers: {
|
||||
encoding: 'aesgcm',
|
||||
encryption_key: 'dh=FplK5KkvUF0',
|
||||
encryption: 'salt=p6YHhFF3BQY',
|
||||
encoding: "aesgcm",
|
||||
encryption_key: "dh=FplK5KkvUF0",
|
||||
encryption: "salt=p6YHhFF3BQY",
|
||||
},
|
||||
exception: /Missing Crypto-Key header/,
|
||||
}];
|
||||
|
@ -161,77 +161,77 @@ add_task(async function test_crypto_getCryptoParamsFromHeaders() {
|
|||
|
||||
add_task(async function test_aes128gcm_ok() {
|
||||
let expectedSuccesses = [{
|
||||
desc: 'Example from draft-ietf-webpush-encryption-latest',
|
||||
result: 'When I grow up, I want to be a watermelon',
|
||||
data: 'DGv6ra1nlYgDCS1FRnbzlwAAEABBBP4z9KsN6nGRTbVYI_c7VJSPQTBtkgcy27mlmlMoZIIgDll6e3vCYLocInmYWAmS6TlzAC8wEqKK6PBru3jl7A_yl95bQpu6cVPTpK4Mqgkf1CXztLVBSt2Ks3oZwbuwXPXLWyouBWLVWGNWQexSgSxsj_Qulcy4a-fN',
|
||||
authSecret: 'BTBZMqHH6r4Tts7J_aSIgg',
|
||||
desc: "Example from draft-ietf-webpush-encryption-latest",
|
||||
result: "When I grow up, I want to be a watermelon",
|
||||
data: "DGv6ra1nlYgDCS1FRnbzlwAAEABBBP4z9KsN6nGRTbVYI_c7VJSPQTBtkgcy27mlmlMoZIIgDll6e3vCYLocInmYWAmS6TlzAC8wEqKK6PBru3jl7A_yl95bQpu6cVPTpK4Mqgkf1CXztLVBSt2Ks3oZwbuwXPXLWyouBWLVWGNWQexSgSxsj_Qulcy4a-fN",
|
||||
authSecret: "BTBZMqHH6r4Tts7J_aSIgg",
|
||||
privateKey: {
|
||||
kty: 'EC',
|
||||
crv: 'P-256',
|
||||
d: 'q1dXpw3UpT5VOmu_cf_v6ih07Aems3njxI-JWgLcM94',
|
||||
x: 'JXGyvs3942BVGq8e0PTNNmwRzr5VX4m8t7GGpTM5FzE',
|
||||
y: 'aOzi6-AYWXvTBHm4bjyPjs7Vd8pZGH6SRpkNtoIAiw4',
|
||||
kty: "EC",
|
||||
crv: "P-256",
|
||||
d: "q1dXpw3UpT5VOmu_cf_v6ih07Aems3njxI-JWgLcM94",
|
||||
x: "JXGyvs3942BVGq8e0PTNNmwRzr5VX4m8t7GGpTM5FzE",
|
||||
y: "aOzi6-AYWXvTBHm4bjyPjs7Vd8pZGH6SRpkNtoIAiw4",
|
||||
ext: true,
|
||||
},
|
||||
publicKey: 'BCVxsr7N_eNgVRqvHtD0zTZsEc6-VV-JvLexhqUzORcxaOzi6-AYWXvTBHm4bjyPjs7Vd8pZGH6SRpkNtoIAiw4',
|
||||
publicKey: "BCVxsr7N_eNgVRqvHtD0zTZsEc6-VV-JvLexhqUzORcxaOzi6-AYWXvTBHm4bjyPjs7Vd8pZGH6SRpkNtoIAiw4",
|
||||
}, {
|
||||
desc: 'rs = 24, pad = 0',
|
||||
desc: "rs = 24, pad = 0",
|
||||
result: "I am the very model of a modern Major-General; I've information vegetable, animal, and mineral",
|
||||
data: 'goagSH7PP0ZGwUsgShmdkwAAABhBBDJVyIuUJbOSVMeWHP8VNPnxY-dZSw86doqOkEzZZZY1ALBWVXTVf0rUDH3oi68I9Hrp-01zA-mr8XKWl5kcH8cX0KiV2PtCwdkEyaQ73YF5fsDxgoWDiaTA3wPqMvuLDqGsZWHnE9Psnfoy7UMEqKlh2a1nE7ZOXiXcOBHLNj260jYzSJnEPV2eXixSXfyWpaSJHAwfj4wVdAAocmViIg6ywk8wFB1hgJpnX2UVEU_qIOcaP6AOIOr1UUQPfosQqC2MEHe5u9gHXF5pi-E267LAlkoYefq01KV_xK_vjbxpw8GAYfSjQEm0L8FG-CN37c8pnQ2Yf61MkihaXac9OctfNeWq_22cN6hn4qsOq0F7QoWIiZqWhB1vS9cJ3KUlyPQvKI9cvevDxw0fJHWeTFzhuwT9BjdILjjb2Vkqc0-qTDOawqD4c8WXsvdGDQCec5Y1x3UhdQXdjR_mhXypxFM37OZTvKJBr1vPCpRXl-bI6iOd7KScgtMM1x5luKhGzZyz25HyuFyj1ec82A',
|
||||
authSecret: '_tK2LDGoIt6be6agJ_nvGA',
|
||||
data: "goagSH7PP0ZGwUsgShmdkwAAABhBBDJVyIuUJbOSVMeWHP8VNPnxY-dZSw86doqOkEzZZZY1ALBWVXTVf0rUDH3oi68I9Hrp-01zA-mr8XKWl5kcH8cX0KiV2PtCwdkEyaQ73YF5fsDxgoWDiaTA3wPqMvuLDqGsZWHnE9Psnfoy7UMEqKlh2a1nE7ZOXiXcOBHLNj260jYzSJnEPV2eXixSXfyWpaSJHAwfj4wVdAAocmViIg6ywk8wFB1hgJpnX2UVEU_qIOcaP6AOIOr1UUQPfosQqC2MEHe5u9gHXF5pi-E267LAlkoYefq01KV_xK_vjbxpw8GAYfSjQEm0L8FG-CN37c8pnQ2Yf61MkihaXac9OctfNeWq_22cN6hn4qsOq0F7QoWIiZqWhB1vS9cJ3KUlyPQvKI9cvevDxw0fJHWeTFzhuwT9BjdILjjb2Vkqc0-qTDOawqD4c8WXsvdGDQCec5Y1x3UhdQXdjR_mhXypxFM37OZTvKJBr1vPCpRXl-bI6iOd7KScgtMM1x5luKhGzZyz25HyuFyj1ec82A",
|
||||
authSecret: "_tK2LDGoIt6be6agJ_nvGA",
|
||||
privateKey: {
|
||||
kty: 'EC',
|
||||
crv: 'P-256',
|
||||
d: 'bGViEe3PvjjFJg8lcnLsqu71b2yqWGnZN9J2MTed-9s',
|
||||
x: 'auB0GHF0AZ2LAocFnvOXDS7EeCMopnzbg-tS21FMHrU',
|
||||
y: 'GpbhrW-_xKj3XhhXA-kDZSicKZ0kn0BuVhqzhLOB-Cc',
|
||||
kty: "EC",
|
||||
crv: "P-256",
|
||||
d: "bGViEe3PvjjFJg8lcnLsqu71b2yqWGnZN9J2MTed-9s",
|
||||
x: "auB0GHF0AZ2LAocFnvOXDS7EeCMopnzbg-tS21FMHrU",
|
||||
y: "GpbhrW-_xKj3XhhXA-kDZSicKZ0kn0BuVhqzhLOB-Cc",
|
||||
ext: true,
|
||||
},
|
||||
publicKey: 'BGrgdBhxdAGdiwKHBZ7zlw0uxHgjKKZ824PrUttRTB61GpbhrW-_xKj3XhhXA-kDZSicKZ0kn0BuVhqzhLOB-Cc',
|
||||
publicKey: "BGrgdBhxdAGdiwKHBZ7zlw0uxHgjKKZ824PrUttRTB61GpbhrW-_xKj3XhhXA-kDZSicKZ0kn0BuVhqzhLOB-Cc",
|
||||
}, {
|
||||
desc: 'rs = 49, pad = 84; ciphertext length falls on record boundary',
|
||||
result: 'Hello, world',
|
||||
data: '-yiDzsHE_K3W0TcfbqSR4AAAADFBBC1EHuf5_2oDKaZJJ9BST9vnsixvtl4Qq0_cA4-UQgoMo_oo2tNshOyRoWLq4Hj6rSwc7XjegRPhlgKyDolPSXa5c-L89oL6DIzNmvPVv_Ht4W-tWjHOGdOLXh_h94pPrYQrvBAlTCxs3ZaitVKE2XLFPK2MO6yxD19X6w1KQzO2BBAroRfK4pEI-9n2Kai6aWDdAZRbOe03unBsQ0oQ_SvSCU_5JJvNrUUTX1_kX804Bx-LLTlBr9pDmBDXeqyvfOULVDJb9YyVAzN9BzeFoyPfo0M',
|
||||
authSecret: 'lfF1cOUI72orKtG09creMw',
|
||||
desc: "rs = 49, pad = 84; ciphertext length falls on record boundary",
|
||||
result: "Hello, world",
|
||||
data: "-yiDzsHE_K3W0TcfbqSR4AAAADFBBC1EHuf5_2oDKaZJJ9BST9vnsixvtl4Qq0_cA4-UQgoMo_oo2tNshOyRoWLq4Hj6rSwc7XjegRPhlgKyDolPSXa5c-L89oL6DIzNmvPVv_Ht4W-tWjHOGdOLXh_h94pPrYQrvBAlTCxs3ZaitVKE2XLFPK2MO6yxD19X6w1KQzO2BBAroRfK4pEI-9n2Kai6aWDdAZRbOe03unBsQ0oQ_SvSCU_5JJvNrUUTX1_kX804Bx-LLTlBr9pDmBDXeqyvfOULVDJb9YyVAzN9BzeFoyPfo0M",
|
||||
authSecret: "lfF1cOUI72orKtG09creMw",
|
||||
privateKey: {
|
||||
kty: 'EC',
|
||||
crv: 'P-256',
|
||||
d: 'ZwBKTqgg3u2OSdtelIDmPT6jzOGujhpgYJcT1SfQAe8',
|
||||
x: 'AU6PFLktoHzgg7k_ljZ-h7IXpH9-8u6TqdNDqgY-V1o',
|
||||
y: 'nzDVnGkMajmz_IFbFQyn3RSWAXQTN7U1B6UfQbFzpyE',
|
||||
kty: "EC",
|
||||
crv: "P-256",
|
||||
d: "ZwBKTqgg3u2OSdtelIDmPT6jzOGujhpgYJcT1SfQAe8",
|
||||
x: "AU6PFLktoHzgg7k_ljZ-h7IXpH9-8u6TqdNDqgY-V1o",
|
||||
y: "nzDVnGkMajmz_IFbFQyn3RSWAXQTN7U1B6UfQbFzpyE",
|
||||
ext: true,
|
||||
},
|
||||
publicKey: 'BAFOjxS5LaB84IO5P5Y2foeyF6R_fvLuk6nTQ6oGPldanzDVnGkMajmz_IFbFQyn3RSWAXQTN7U1B6UfQbFzpyE',
|
||||
publicKey: "BAFOjxS5LaB84IO5P5Y2foeyF6R_fvLuk6nTQ6oGPldanzDVnGkMajmz_IFbFQyn3RSWAXQTN7U1B6UfQbFzpyE",
|
||||
}, {
|
||||
desc: 'rs = 18, pad = 0',
|
||||
result: '1',
|
||||
data: 'fK69vCCTjuNAqUbxvU9o8QAAABJBBDfP21Ij2fleqgL27ZQP8i6vBbNiLpSdw86fM15u-bJq6qzKD3QICos2RZLyzMbV7d1DAEtwuRiH0UTZ-pPxbDvH6mj0_VR6lOyoSxbhOKYIAXc',
|
||||
authSecret: '1loE35Xy215gSDn3F9zeeQ',
|
||||
desc: "rs = 18, pad = 0",
|
||||
result: "1",
|
||||
data: "fK69vCCTjuNAqUbxvU9o8QAAABJBBDfP21Ij2fleqgL27ZQP8i6vBbNiLpSdw86fM15u-bJq6qzKD3QICos2RZLyzMbV7d1DAEtwuRiH0UTZ-pPxbDvH6mj0_VR6lOyoSxbhOKYIAXc",
|
||||
authSecret: "1loE35Xy215gSDn3F9zeeQ",
|
||||
privateKey: {
|
||||
kty: 'EC',
|
||||
crv: 'P-256',
|
||||
d: 'J0M_q4lws8tShLYRg--0YoZWLNKnMw2MrpYJEaVXHQw',
|
||||
x: 'UV1DJjVWUjmdoksr6SQeYztc8U-vDPOm_WAxe5VMCi8',
|
||||
y: 'SEhUgASyewz3SAvIEMa-wDqPt5yOoA_IsF4A-INFY-8',
|
||||
kty: "EC",
|
||||
crv: "P-256",
|
||||
d: "J0M_q4lws8tShLYRg--0YoZWLNKnMw2MrpYJEaVXHQw",
|
||||
x: "UV1DJjVWUjmdoksr6SQeYztc8U-vDPOm_WAxe5VMCi8",
|
||||
y: "SEhUgASyewz3SAvIEMa-wDqPt5yOoA_IsF4A-INFY-8",
|
||||
ext: true,
|
||||
},
|
||||
publicKey: 'BFFdQyY1VlI5naJLK-kkHmM7XPFPrwzzpv1gMXuVTAovSEhUgASyewz3SAvIEMa-wDqPt5yOoA_IsF4A-INFY-8',
|
||||
publicKey: "BFFdQyY1VlI5naJLK-kkHmM7XPFPrwzzpv1gMXuVTAovSEhUgASyewz3SAvIEMa-wDqPt5yOoA_IsF4A-INFY-8",
|
||||
}];
|
||||
for (let test of expectedSuccesses) {
|
||||
let privateKey = test.privateKey;
|
||||
let publicKey = ChromeUtils.base64URLDecode(test.publicKey, {
|
||||
padding: 'reject',
|
||||
padding: "reject",
|
||||
});
|
||||
let authSecret = ChromeUtils.base64URLDecode(test.authSecret, {
|
||||
padding: 'reject',
|
||||
padding: "reject",
|
||||
});
|
||||
let payload = ChromeUtils.base64URLDecode(test.data, {
|
||||
padding: 'reject',
|
||||
padding: "reject",
|
||||
});
|
||||
let result = await PushCrypto.decrypt(privateKey, publicKey, authSecret, {
|
||||
encoding: 'aes128gcm',
|
||||
encoding: "aes128gcm",
|
||||
}, payload);
|
||||
let decoder = new TextDecoder('utf-8');
|
||||
let decoder = new TextDecoder("utf-8");
|
||||
equal(decoder.decode(new Uint8Array(result)), test.result, test.desc);
|
||||
}
|
||||
});
|
||||
|
@ -239,127 +239,127 @@ add_task(async function test_aes128gcm_ok() {
|
|||
add_task(async function test_aes128gcm_err() {
|
||||
let expectedFailures = [{
|
||||
// Just the payload; no header at all.
|
||||
desc: 'Missing header block',
|
||||
data: 'RbdNK2m-mwdN47NaqH58FWEd',
|
||||
desc: "Missing header block",
|
||||
data: "RbdNK2m-mwdN47NaqH58FWEd",
|
||||
privateKey: {
|
||||
kty: 'EC',
|
||||
crv: 'P-256',
|
||||
d: 'G-g_ODMu8JaB-vPzB7H_LhDKt4zHzatoOsDukqw_buE',
|
||||
x: '26mRyiFTQ_Nr3T6FfK_ePRi_V_GDWygzutQU8IhBYgU',
|
||||
y: 'GslqCyRJADfQfPUo5OGOEAoaZOt0R0hUS_HiINq6zyw',
|
||||
kty: "EC",
|
||||
crv: "P-256",
|
||||
d: "G-g_ODMu8JaB-vPzB7H_LhDKt4zHzatoOsDukqw_buE",
|
||||
x: "26mRyiFTQ_Nr3T6FfK_ePRi_V_GDWygzutQU8IhBYgU",
|
||||
y: "GslqCyRJADfQfPUo5OGOEAoaZOt0R0hUS_HiINq6zyw",
|
||||
ext: true,
|
||||
},
|
||||
publicKey: 'BNupkcohU0Pza90-hXyv3j0Yv1fxg1soM7rUFPCIQWIFGslqCyRJADfQfPUo5OGOEAoaZOt0R0hUS_HiINq6zyw',
|
||||
authSecret: 'NHG7mEgeAlM785VCvPPbpA',
|
||||
publicKey: "BNupkcohU0Pza90-hXyv3j0Yv1fxg1soM7rUFPCIQWIFGslqCyRJADfQfPUo5OGOEAoaZOt0R0hUS_HiINq6zyw",
|
||||
authSecret: "NHG7mEgeAlM785VCvPPbpA",
|
||||
expected: /Truncated header/,
|
||||
}, {
|
||||
// The sender key should be 65 bytes; this header contains an invalid key
|
||||
// that's only 1 byte.
|
||||
desc: 'Truncated sender key',
|
||||
data: '3ltpa4fxoVy2revdedb5ngAAABIBALa8GCbDfJ9z3WtIWcK1BRgZUg',
|
||||
desc: "Truncated sender key",
|
||||
data: "3ltpa4fxoVy2revdedb5ngAAABIBALa8GCbDfJ9z3WtIWcK1BRgZUg",
|
||||
privateKey: {
|
||||
kty: 'EC',
|
||||
crv: 'P-256',
|
||||
d: 'zojo4LMFekdS60yPqTHrYhwwLaWtA7ga9FnPZzVWDK4',
|
||||
x: 'oyXZkITEDeDOcioELESNlKMmkXIcp54890XnjGmIYZQ',
|
||||
y: 'sCzqGSJBdnlanU27sgc68szW-m8KTHxJaFVr5QKjuoE',
|
||||
kty: "EC",
|
||||
crv: "P-256",
|
||||
d: "zojo4LMFekdS60yPqTHrYhwwLaWtA7ga9FnPZzVWDK4",
|
||||
x: "oyXZkITEDeDOcioELESNlKMmkXIcp54890XnjGmIYZQ",
|
||||
y: "sCzqGSJBdnlanU27sgc68szW-m8KTHxJaFVr5QKjuoE",
|
||||
ext: true,
|
||||
},
|
||||
publicKey: 'BKMl2ZCExA3gznIqBCxEjZSjJpFyHKeePPdF54xpiGGUsCzqGSJBdnlanU27sgc68szW-m8KTHxJaFVr5QKjuoE',
|
||||
authSecret: 'XDHg2W2aE5iZrAlp01n3QA',
|
||||
publicKey: "BKMl2ZCExA3gznIqBCxEjZSjJpFyHKeePPdF54xpiGGUsCzqGSJBdnlanU27sgc68szW-m8KTHxJaFVr5QKjuoE",
|
||||
authSecret: "XDHg2W2aE5iZrAlp01n3QA",
|
||||
expected: /Invalid sender public key/,
|
||||
}, {
|
||||
// The message is encrypted with only the first 12 bytes of the 16-byte
|
||||
// auth secret, so the derived decryption key and nonce won't match.
|
||||
desc: 'Encrypted with mismatched auth secret',
|
||||
data: 'gRX0mIuMOSp7rLQ8jxrFZQAAABJBBBmUSDxUHpvDmmrwP_cTqndFwoThOKQqJDW3l7IMS2mM9RGLT4VVMXwZDqvr-rdJwWTT9r3r4NRBcZExo1fYiQoTxNvUsW_z3VqD98ka1uBArEJzCn8LPNMkXp-Nb_McdR1BDP0',
|
||||
desc: "Encrypted with mismatched auth secret",
|
||||
data: "gRX0mIuMOSp7rLQ8jxrFZQAAABJBBBmUSDxUHpvDmmrwP_cTqndFwoThOKQqJDW3l7IMS2mM9RGLT4VVMXwZDqvr-rdJwWTT9r3r4NRBcZExo1fYiQoTxNvUsW_z3VqD98ka1uBArEJzCn8LPNMkXp-Nb_McdR1BDP0",
|
||||
privateKey: {
|
||||
kty: 'EC',
|
||||
crv: 'P-256',
|
||||
d: 'YMdjalF95wOaCsLQ4wZEAHlMeOfgSTmBKaInzuD5qAE',
|
||||
x: '_dBBKKhcBYltf4H-EYvcuIe588H_QYOtxMgk0ShgcwA',
|
||||
y: '6Yay37WmEOWvQ-QIoAcwWE-T49_d_ERzfV8I-y1viRY',
|
||||
kty: "EC",
|
||||
crv: "P-256",
|
||||
d: "YMdjalF95wOaCsLQ4wZEAHlMeOfgSTmBKaInzuD5qAE",
|
||||
x: "_dBBKKhcBYltf4H-EYvcuIe588H_QYOtxMgk0ShgcwA",
|
||||
y: "6Yay37WmEOWvQ-QIoAcwWE-T49_d_ERzfV8I-y1viRY",
|
||||
ext: true,
|
||||
},
|
||||
publicKey: 'BP3QQSioXAWJbX-B_hGL3LiHufPB_0GDrcTIJNEoYHMA6Yay37WmEOWvQ-QIoAcwWE-T49_d_ERzfV8I-y1viRY',
|
||||
authSecret: 'NVo4zW2b7xWZDi0zCNvWAA',
|
||||
publicKey: "BP3QQSioXAWJbX-B_hGL3LiHufPB_0GDrcTIJNEoYHMA6Yay37WmEOWvQ-QIoAcwWE-T49_d_ERzfV8I-y1viRY",
|
||||
authSecret: "NVo4zW2b7xWZDi0zCNvWAA",
|
||||
expected: /Bad encryption/,
|
||||
}, {
|
||||
// Multiple records; the first has padding delimiter = 2, but should be 1.
|
||||
desc: 'Early final record',
|
||||
data: '2-IVUH0a09Lq6r6ubodNjwAAABJBBHvEND80qDSM3E5GL_x8QKpqjGGnOcTEHUUSVQX3Dp_F-e-oaFLdSI3Pjo6iyvt14Hq9XufJ1cA4uv7weVcbC9opRBHOmMdt0DHA5YBXekmAo3XkXtMEKb4OLunafm34aW0BuOw',
|
||||
desc: "Early final record",
|
||||
data: "2-IVUH0a09Lq6r6ubodNjwAAABJBBHvEND80qDSM3E5GL_x8QKpqjGGnOcTEHUUSVQX3Dp_F-e-oaFLdSI3Pjo6iyvt14Hq9XufJ1cA4uv7weVcbC9opRBHOmMdt0DHA5YBXekmAo3XkXtMEKb4OLunafm34aW0BuOw",
|
||||
privateKey: {
|
||||
kty: 'EC',
|
||||
crv: 'P-256',
|
||||
d: 'XdodkYvEB7o82hLLgBTUmqfgJpACggMERmvIADTKkkA',
|
||||
x: 'yVxlINrRHo9qG_gDGkDCpO4QRcGQO-BqHfp_gpzOst4',
|
||||
y: 'Akga5r0EdhIbEsVTLQsjF4gHfvoGg6W_4NYjObJRyzU',
|
||||
kty: "EC",
|
||||
crv: "P-256",
|
||||
d: "XdodkYvEB7o82hLLgBTUmqfgJpACggMERmvIADTKkkA",
|
||||
x: "yVxlINrRHo9qG_gDGkDCpO4QRcGQO-BqHfp_gpzOst4",
|
||||
y: "Akga5r0EdhIbEsVTLQsjF4gHfvoGg6W_4NYjObJRyzU",
|
||||
ext: true,
|
||||
},
|
||||
publicKey: 'BMlcZSDa0R6Pahv4AxpAwqTuEEXBkDvgah36f4KczrLeAkga5r0EdhIbEsVTLQsjF4gHfvoGg6W_4NYjObJRyzU',
|
||||
authSecret: 'QMJB_eQmnuHm1yVZLZgnGA',
|
||||
publicKey: "BMlcZSDa0R6Pahv4AxpAwqTuEEXBkDvgah36f4KczrLeAkga5r0EdhIbEsVTLQsjF4gHfvoGg6W_4NYjObJRyzU",
|
||||
authSecret: "QMJB_eQmnuHm1yVZLZgnGA",
|
||||
expected: /Padding is wrong!/,
|
||||
}];
|
||||
for (let test of expectedFailures) {
|
||||
await assertNotDecrypts(test, { encoding: 'aes128gcm' });
|
||||
await assertNotDecrypts(test, { encoding: "aes128gcm" });
|
||||
}
|
||||
});
|
||||
|
||||
add_task(async function test_aesgcm_ok() {
|
||||
let expectedSuccesses = [{
|
||||
desc: 'padSize = 2, rs = 24, pad = 0',
|
||||
result: 'Some message',
|
||||
data: 'Oo34w2F9VVnTMFfKtdx48AZWQ9Li9M6DauWJVgXU',
|
||||
authSecret: 'aTDc6JebzR6eScy2oLo4RQ',
|
||||
desc: "padSize = 2, rs = 24, pad = 0",
|
||||
result: "Some message",
|
||||
data: "Oo34w2F9VVnTMFfKtdx48AZWQ9Li9M6DauWJVgXU",
|
||||
authSecret: "aTDc6JebzR6eScy2oLo4RQ",
|
||||
privateKey: LEGACY_PRIVATE_KEY,
|
||||
publicKey: LEGACY_PUBLIC_KEY,
|
||||
headers: {
|
||||
crypto_key: 'dh=BCHFVrflyxibGLlgztLwKelsRZp4gqX3tNfAKFaxAcBhpvYeN1yIUMrxaDKiLh4LNKPtj0BOXGdr-IQ-QP82Wjo',
|
||||
encryption: 'salt=zCU18Rw3A5aB_Xi-vfixmA; rs=24',
|
||||
encoding: 'aesgcm',
|
||||
crypto_key: "dh=BCHFVrflyxibGLlgztLwKelsRZp4gqX3tNfAKFaxAcBhpvYeN1yIUMrxaDKiLh4LNKPtj0BOXGdr-IQ-QP82Wjo",
|
||||
encryption: "salt=zCU18Rw3A5aB_Xi-vfixmA; rs=24",
|
||||
encoding: "aesgcm",
|
||||
},
|
||||
}, {
|
||||
desc: 'padSize = 2, rs = 8, pad = 16',
|
||||
result: 'Yet another message',
|
||||
data: 'uEC5B_tR-fuQ3delQcrzrDCp40W6ipMZjGZ78USDJ5sMj-6bAOVG3AK6JqFl9E6AoWiBYYvMZfwThVxmDnw6RHtVeLKFM5DWgl1EwkOohwH2EhiDD0gM3io-d79WKzOPZE9rDWUSv64JstImSfX_ADQfABrvbZkeaWxh53EG59QMOElFJqHue4dMURpsMXg',
|
||||
authSecret: '6plwZnSpVUbF7APDXus3UQ',
|
||||
desc: "padSize = 2, rs = 8, pad = 16",
|
||||
result: "Yet another message",
|
||||
data: "uEC5B_tR-fuQ3delQcrzrDCp40W6ipMZjGZ78USDJ5sMj-6bAOVG3AK6JqFl9E6AoWiBYYvMZfwThVxmDnw6RHtVeLKFM5DWgl1EwkOohwH2EhiDD0gM3io-d79WKzOPZE9rDWUSv64JstImSfX_ADQfABrvbZkeaWxh53EG59QMOElFJqHue4dMURpsMXg",
|
||||
authSecret: "6plwZnSpVUbF7APDXus3UQ",
|
||||
privateKey: LEGACY_PRIVATE_KEY,
|
||||
publicKey: LEGACY_PUBLIC_KEY,
|
||||
headers: {
|
||||
crypto_key: 'dh=BEaA4gzA3i0JDuirGhiLgymS4hfFX7TNTdEhSk_HBlLpkjgCpjPL5c-GL9uBGIfa_fhGNKKFhXz1k9Kyens2ZpQ',
|
||||
encryption: 'salt=ZFhzj0S-n29g9P2p4-I7tA; rs=8',
|
||||
encoding: 'aesgcm',
|
||||
crypto_key: "dh=BEaA4gzA3i0JDuirGhiLgymS4hfFX7TNTdEhSk_HBlLpkjgCpjPL5c-GL9uBGIfa_fhGNKKFhXz1k9Kyens2ZpQ",
|
||||
encryption: "salt=ZFhzj0S-n29g9P2p4-I7tA; rs=8",
|
||||
encoding: "aesgcm",
|
||||
},
|
||||
}, {
|
||||
desc: 'padSize = 2, rs = 3, pad = 0',
|
||||
result: 'Small record size',
|
||||
data: 'oY4e5eDatDVt2fpQylxbPJM-3vrfhDasfPc8Q1PWt4tPfMVbz_sDNL_cvr0DXXkdFzS1lxsJsj550USx4MMl01ihjImXCjrw9R5xFgFrCAqJD3GwXA1vzS4T5yvGVbUp3SndMDdT1OCcEofTn7VC6xZ-zP8rzSQfDCBBxmPU7OISzr8Z4HyzFCGJeBfqiZ7yUfNlKF1x5UaZ4X6iU_TXx5KlQy_toV1dXZ2eEAMHJUcSdArvB6zRpFdEIxdcHcJyo1BIYgAYTDdAIy__IJVCPY_b2CE5W_6ohlYKB7xDyH8giNuWWXAgBozUfScLUVjPC38yJTpAUi6w6pXgXUWffende5FreQpnMFL1L4G-38wsI_-ISIOzdO8QIrXHxmtc1S5xzYu8bMqSgCinvCEwdeGFCmighRjj8t1zRWo0D14rHbQLPR_b1P5SvEeJTtS9Nm3iibM',
|
||||
authSecret: 'g2rWVHUCpUxgcL9Tz7vyeQ',
|
||||
desc: "padSize = 2, rs = 3, pad = 0",
|
||||
result: "Small record size",
|
||||
data: "oY4e5eDatDVt2fpQylxbPJM-3vrfhDasfPc8Q1PWt4tPfMVbz_sDNL_cvr0DXXkdFzS1lxsJsj550USx4MMl01ihjImXCjrw9R5xFgFrCAqJD3GwXA1vzS4T5yvGVbUp3SndMDdT1OCcEofTn7VC6xZ-zP8rzSQfDCBBxmPU7OISzr8Z4HyzFCGJeBfqiZ7yUfNlKF1x5UaZ4X6iU_TXx5KlQy_toV1dXZ2eEAMHJUcSdArvB6zRpFdEIxdcHcJyo1BIYgAYTDdAIy__IJVCPY_b2CE5W_6ohlYKB7xDyH8giNuWWXAgBozUfScLUVjPC38yJTpAUi6w6pXgXUWffende5FreQpnMFL1L4G-38wsI_-ISIOzdO8QIrXHxmtc1S5xzYu8bMqSgCinvCEwdeGFCmighRjj8t1zRWo0D14rHbQLPR_b1P5SvEeJTtS9Nm3iibM",
|
||||
authSecret: "g2rWVHUCpUxgcL9Tz7vyeQ",
|
||||
privateKey: LEGACY_PRIVATE_KEY,
|
||||
publicKey: LEGACY_PUBLIC_KEY,
|
||||
headers: {
|
||||
crypto_key: 'dh=BCg6ZIGuE2ZNm2ti6Arf4CDVD_8--aLXAGLYhpghwjl1xxVjTLLpb7zihuEOGGbyt8Qj0_fYHBP4ObxwJNl56bk',
|
||||
encryption: 'salt=5LIDBXbvkBvvb7ZdD-T4PQ; rs=3',
|
||||
encoding: 'aesgcm',
|
||||
crypto_key: "dh=BCg6ZIGuE2ZNm2ti6Arf4CDVD_8--aLXAGLYhpghwjl1xxVjTLLpb7zihuEOGGbyt8Qj0_fYHBP4ObxwJNl56bk",
|
||||
encryption: "salt=5LIDBXbvkBvvb7ZdD-T4PQ; rs=3",
|
||||
encoding: "aesgcm",
|
||||
},
|
||||
}, {
|
||||
desc: 'Example from draft-ietf-httpbis-encryption-encoding-02',
|
||||
result: 'I am the walrus',
|
||||
data: '6nqAQUME8hNqw5J3kl8cpVVJylXKYqZOeseZG8UueKpA',
|
||||
authSecret: 'R29vIGdvbyBnJyBqb29iIQ',
|
||||
desc: "Example from draft-ietf-httpbis-encryption-encoding-02",
|
||||
result: "I am the walrus",
|
||||
data: "6nqAQUME8hNqw5J3kl8cpVVJylXKYqZOeseZG8UueKpA",
|
||||
authSecret: "R29vIGdvbyBnJyBqb29iIQ",
|
||||
privateKey: {
|
||||
kty: 'EC',
|
||||
crv: 'P-256',
|
||||
d: '9FWl15_QUQAWDaD3k3l50ZBZQJ4au27F1V4F0uLSD_M',
|
||||
x: 'ISQGPMvxncL6iLZDugTm3Y2n6nuiyMYuD3epQ_TC-pE',
|
||||
y: 'T21EEWyf0cQDQcakQMqz4hQKYOQ3il2nNZct4HgAUQU',
|
||||
kty: "EC",
|
||||
crv: "P-256",
|
||||
d: "9FWl15_QUQAWDaD3k3l50ZBZQJ4au27F1V4F0uLSD_M",
|
||||
x: "ISQGPMvxncL6iLZDugTm3Y2n6nuiyMYuD3epQ_TC-pE",
|
||||
y: "T21EEWyf0cQDQcakQMqz4hQKYOQ3il2nNZct4HgAUQU",
|
||||
ext: true,
|
||||
},
|
||||
publicKey: 'BCEkBjzL8Z3C-oi2Q7oE5t2Np-p7osjGLg93qUP0wvqRT21EEWyf0cQDQcakQMqz4hQKYOQ3il2nNZct4HgAUQU',
|
||||
publicKey: "BCEkBjzL8Z3C-oi2Q7oE5t2Np-p7osjGLg93qUP0wvqRT21EEWyf0cQDQcakQMqz4hQKYOQ3il2nNZct4HgAUQU",
|
||||
headers: {
|
||||
crypto_key: 'keyid="dhkey"; dh="BNoRDbb84JGm8g5Z5CFxurSqsXWJ11ItfXEWYVLE85Y7CYkDjXsIEc4aqxYaQ1G8BqkXCJ6DPpDrWtdWj_mugHU"',
|
||||
encryption: 'keyid="dhkey"; salt="lngarbyKfMoi9Z75xYXmkg"',
|
||||
encoding: 'aesgcm',
|
||||
encoding: "aesgcm",
|
||||
},
|
||||
}];
|
||||
for (let test of expectedSuccesses) {
|
||||
|
@ -369,120 +369,120 @@ add_task(async function test_aesgcm_ok() {
|
|||
|
||||
add_task(async function test_aesgcm_err() {
|
||||
let expectedFailures = [{
|
||||
desc: 'aesgcm128 message decrypted as aesgcm',
|
||||
data: 'fwkuwTTChcLnrzsbDI78Y2EoQzfnbMI8Ax9Z27_rwX8',
|
||||
authSecret: 'BhbpNTWyO5wVJmVKTV6XaA',
|
||||
desc: "aesgcm128 message decrypted as aesgcm",
|
||||
data: "fwkuwTTChcLnrzsbDI78Y2EoQzfnbMI8Ax9Z27_rwX8",
|
||||
authSecret: "BhbpNTWyO5wVJmVKTV6XaA",
|
||||
privateKey: LEGACY_PRIVATE_KEY,
|
||||
publicKey: LEGACY_PUBLIC_KEY,
|
||||
headers: {
|
||||
crypto_key: 'dh=BCHn-I-J3dfPRLJBlNZ3xFoAqaBLZ6qdhpaz9W7Q00JW1oD-hTxyEECn6KYJNK8AxKUyIDwn6Icx_PYWJiEYjQ0',
|
||||
encryption: 'salt=c6JQl9eJ0VvwrUVCQDxY7Q',
|
||||
encoding: 'aesgcm',
|
||||
crypto_key: "dh=BCHn-I-J3dfPRLJBlNZ3xFoAqaBLZ6qdhpaz9W7Q00JW1oD-hTxyEECn6KYJNK8AxKUyIDwn6Icx_PYWJiEYjQ0",
|
||||
encryption: "salt=c6JQl9eJ0VvwrUVCQDxY7Q",
|
||||
encoding: "aesgcm",
|
||||
},
|
||||
expected: /Bad encryption/,
|
||||
}, {
|
||||
// The plaintext is "O hai". The ciphertext is exactly `rs + 16` bytes,
|
||||
// but we didn't include the empty trailing block that aesgcm requires for
|
||||
// exact multiples.
|
||||
desc: 'rs = 7, no trailing block',
|
||||
data: 'YG4F-b06y590hRlnSsw_vuOw62V9Iz8',
|
||||
authSecret: 'QoDi0u6vcslIVJKiouXMXw',
|
||||
desc: "rs = 7, no trailing block",
|
||||
data: "YG4F-b06y590hRlnSsw_vuOw62V9Iz8",
|
||||
authSecret: "QoDi0u6vcslIVJKiouXMXw",
|
||||
privateKey: {
|
||||
kty: 'EC',
|
||||
crv: 'P-256',
|
||||
d: '2bu4paOAZbL2ef1u-wTzONuTIcDPc00o0zUJgg46XTc',
|
||||
x: 'uEvLZUMVn1my0cwnLdcFT0mj1gSU5uzI3HeGwXC7jX8',
|
||||
y: 'SfNVLGL-FurydsuzciDfw8K1cUHyoDWnJJ_16UG6Dbo',
|
||||
kty: "EC",
|
||||
crv: "P-256",
|
||||
d: "2bu4paOAZbL2ef1u-wTzONuTIcDPc00o0zUJgg46XTc",
|
||||
x: "uEvLZUMVn1my0cwnLdcFT0mj1gSU5uzI3HeGwXC7jX8",
|
||||
y: "SfNVLGL-FurydsuzciDfw8K1cUHyoDWnJJ_16UG6Dbo",
|
||||
ext: true,
|
||||
},
|
||||
publicKey: 'BLhLy2VDFZ9ZstHMJy3XBU9Jo9YElObsyNx3hsFwu41_SfNVLGL-FurydsuzciDfw8K1cUHyoDWnJJ_16UG6Dbo',
|
||||
publicKey: "BLhLy2VDFZ9ZstHMJy3XBU9Jo9YElObsyNx3hsFwu41_SfNVLGL-FurydsuzciDfw8K1cUHyoDWnJJ_16UG6Dbo",
|
||||
headers: {
|
||||
crypto_key: 'dh=BD_bsTUpxBMvSv8eksith3vijMLj44D4jhJjO51y7wK1ytbUlsyYBBYYyB5AAe5bnREA_WipTgemDVz00LiWcfM',
|
||||
encryption: 'salt=xKWvs_jWWeg4KOsot_uBhA; rs=7',
|
||||
encoding: 'aesgcm',
|
||||
crypto_key: "dh=BD_bsTUpxBMvSv8eksith3vijMLj44D4jhJjO51y7wK1ytbUlsyYBBYYyB5AAe5bnREA_WipTgemDVz00LiWcfM",
|
||||
encryption: "salt=xKWvs_jWWeg4KOsot_uBhA; rs=7",
|
||||
encoding: "aesgcm",
|
||||
},
|
||||
expected: /Encrypted data truncated/,
|
||||
}, {
|
||||
// The last block is only 1 byte, but valid blocks must be at least 2 bytes.
|
||||
desc: 'Pad size > last block length',
|
||||
data: 'JvX9HsJ4lL5gzP8_uCKc6s15iRIaNhD4pFCgq5-dfwbUqEcNUkqv',
|
||||
authSecret: 'QtGZeY8MQfCaq-XwKOVGBQ',
|
||||
desc: "Pad size > last block length",
|
||||
data: "JvX9HsJ4lL5gzP8_uCKc6s15iRIaNhD4pFCgq5-dfwbUqEcNUkqv",
|
||||
authSecret: "QtGZeY8MQfCaq-XwKOVGBQ",
|
||||
privateKey: {
|
||||
kty: 'EC',
|
||||
crv: 'P-256',
|
||||
d: 'CosERAVXgvTvoh7UkrRC2V-iXoNs0bXle9I68qzkles',
|
||||
x: '_D0YqEwirvTJQJdjG6xXrjstMVpeAzf221cUqZz6hgY',
|
||||
y: '9MnFbM7U14uiYMDI5e2I4jN29tYmsM9F66QodhKmA-c',
|
||||
kty: "EC",
|
||||
crv: "P-256",
|
||||
d: "CosERAVXgvTvoh7UkrRC2V-iXoNs0bXle9I68qzkles",
|
||||
x: "_D0YqEwirvTJQJdjG6xXrjstMVpeAzf221cUqZz6hgY",
|
||||
y: "9MnFbM7U14uiYMDI5e2I4jN29tYmsM9F66QodhKmA-c",
|
||||
ext: true,
|
||||
},
|
||||
publicKey: 'BPw9GKhMIq70yUCXYxusV647LTFaXgM39ttXFKmc-oYG9MnFbM7U14uiYMDI5e2I4jN29tYmsM9F66QodhKmA-c',
|
||||
publicKey: "BPw9GKhMIq70yUCXYxusV647LTFaXgM39ttXFKmc-oYG9MnFbM7U14uiYMDI5e2I4jN29tYmsM9F66QodhKmA-c",
|
||||
headers: {
|
||||
crypto_key: 'dh=BBNZNEi5Ew_ID5S4Y9jWBi1NeVDje6Mjs7SDLViUn6A8VAZj-6X3QAuYQ3j20BblqjwTgYst7PRnY6UGrKyLbmU',
|
||||
encryption: 'salt=ot8hzbwOo6CYe6ZhdlwKtg; rs=6',
|
||||
encoding: 'aesgcm',
|
||||
crypto_key: "dh=BBNZNEi5Ew_ID5S4Y9jWBi1NeVDje6Mjs7SDLViUn6A8VAZj-6X3QAuYQ3j20BblqjwTgYst7PRnY6UGrKyLbmU",
|
||||
encryption: "salt=ot8hzbwOo6CYe6ZhdlwKtg; rs=6",
|
||||
encoding: "aesgcm",
|
||||
},
|
||||
expected: /Decoded array is too short/,
|
||||
}, {
|
||||
// The last block is 3 bytes (2 bytes for the pad length; 1 byte of data),
|
||||
// but claims its pad length is 2.
|
||||
desc: 'Padding length > last block length',
|
||||
data: 'oWSOFA-UO5oWq-kI79RHaFfwAejLiQJ4C7eTmrSTBl4gArLXfx7lZ-Y',
|
||||
authSecret: 'gKG_P6-de5pyzS8hyH_NyQ',
|
||||
desc: "Padding length > last block length",
|
||||
data: "oWSOFA-UO5oWq-kI79RHaFfwAejLiQJ4C7eTmrSTBl4gArLXfx7lZ-Y",
|
||||
authSecret: "gKG_P6-de5pyzS8hyH_NyQ",
|
||||
privateKey: {
|
||||
kty: 'EC',
|
||||
crv: 'P-256',
|
||||
d: '9l-ahcBM-I0ykwbWiDS9KRrPdhyvTZ0SxKiPpj2aeaI',
|
||||
x: 'qx0tU4EDaQv6ayFA3xvLLBdMmn4mLxjn7SK6mIeIxeg',
|
||||
y: 'ymbMcmUOEyh_-rLrBsi26NG4UFCis2MTDs5FG2VdDPI',
|
||||
kty: "EC",
|
||||
crv: "P-256",
|
||||
d: "9l-ahcBM-I0ykwbWiDS9KRrPdhyvTZ0SxKiPpj2aeaI",
|
||||
x: "qx0tU4EDaQv6ayFA3xvLLBdMmn4mLxjn7SK6mIeIxeg",
|
||||
y: "ymbMcmUOEyh_-rLrBsi26NG4UFCis2MTDs5FG2VdDPI",
|
||||
ext: true,
|
||||
},
|
||||
publicKey: 'BKsdLVOBA2kL-mshQN8byywXTJp-Ji8Y5-0iupiHiMXoymbMcmUOEyh_-rLrBsi26NG4UFCis2MTDs5FG2VdDPI',
|
||||
publicKey: "BKsdLVOBA2kL-mshQN8byywXTJp-Ji8Y5-0iupiHiMXoymbMcmUOEyh_-rLrBsi26NG4UFCis2MTDs5FG2VdDPI",
|
||||
headers: {
|
||||
crypto_key: 'dh=BKe2IBO_cwmEzQyTVscSbQcj0Y3uBSzGZ_mHlANMciS8uGpb7U8_Bw7TNdlYfpwWDLd0cxM8YYWNDbNJ_p2Rp4o',
|
||||
encryption: 'salt=z7QJ6UR89SiFRkd4RsC4Vg; rs=6',
|
||||
encoding: 'aesgcm',
|
||||
crypto_key: "dh=BKe2IBO_cwmEzQyTVscSbQcj0Y3uBSzGZ_mHlANMciS8uGpb7U8_Bw7TNdlYfpwWDLd0cxM8YYWNDbNJ_p2Rp4o",
|
||||
encryption: "salt=z7QJ6UR89SiFRkd4RsC4Vg; rs=6",
|
||||
encoding: "aesgcm",
|
||||
},
|
||||
expected: /Padding is wrong/,
|
||||
}, {
|
||||
// The first block has no padding, but claims its pad length is 1.
|
||||
desc: 'Non-zero padding',
|
||||
data: 'Qdvjh0LkZXKu_1Hvv56D0rOSF6Mww3y0F8xkxUNlwVu2U1iakOUUGRs',
|
||||
authSecret: 'cMpWQW58BrpDbJ8KqbS9ig',
|
||||
desc: "Non-zero padding",
|
||||
data: "Qdvjh0LkZXKu_1Hvv56D0rOSF6Mww3y0F8xkxUNlwVu2U1iakOUUGRs",
|
||||
authSecret: "cMpWQW58BrpDbJ8KqbS9ig",
|
||||
privateKey: {
|
||||
kty: 'EC',
|
||||
crv: 'P-256',
|
||||
d: 'IzuaxLqFJmjSu8GjLCo2oEaDZjDButW4m4T0qx02XsM',
|
||||
x: 'Xy7vt_TJTynxwWsQyY069BcKmrhkRjhKPFuTi-AphoY',
|
||||
y: '0M10IVM1ourR7Q5AUX2b2fgdmGyTWcYsdHcdFK_b4Hk',
|
||||
kty: "EC",
|
||||
crv: "P-256",
|
||||
d: "IzuaxLqFJmjSu8GjLCo2oEaDZjDButW4m4T0qx02XsM",
|
||||
x: "Xy7vt_TJTynxwWsQyY069BcKmrhkRjhKPFuTi-AphoY",
|
||||
y: "0M10IVM1ourR7Q5AUX2b2fgdmGyTWcYsdHcdFK_b4Hk",
|
||||
ext: true,
|
||||
},
|
||||
publicKey: 'BF8u77f0yU8p8cFrEMmNOvQXCpq4ZEY4Sjxbk4vgKYaG0M10IVM1ourR7Q5AUX2b2fgdmGyTWcYsdHcdFK_b4Hk',
|
||||
publicKey: "BF8u77f0yU8p8cFrEMmNOvQXCpq4ZEY4Sjxbk4vgKYaG0M10IVM1ourR7Q5AUX2b2fgdmGyTWcYsdHcdFK_b4Hk",
|
||||
headers: {
|
||||
crypto_key: 'dh=BBicj01QI0ryiFzAaty9VpW_crgq9XbU1bOCtEZI9UNE6tuOgp4lyN_UN0N905ECnLWK5v_sCPUIxnQgOuCseSo',
|
||||
encryption: 'salt=SbkGHONbQBBsBcj9dLyIUw; rs=6',
|
||||
encoding: 'aesgcm',
|
||||
crypto_key: "dh=BBicj01QI0ryiFzAaty9VpW_crgq9XbU1bOCtEZI9UNE6tuOgp4lyN_UN0N905ECnLWK5v_sCPUIxnQgOuCseSo",
|
||||
encryption: "salt=SbkGHONbQBBsBcj9dLyIUw; rs=6",
|
||||
encoding: "aesgcm",
|
||||
},
|
||||
expected: /Padding is wrong/,
|
||||
}, {
|
||||
// The first record is 22 bytes: 2 bytes for the pad length, 4 bytes of
|
||||
// data, and a 16-byte auth tag. The second "record" is missing the pad
|
||||
// and data, and contains just the auth tag.
|
||||
desc: 'rs = 6, second record truncated to only auth tag',
|
||||
data: 'C7u3j5AL4Yzh2yYB_umN6tzrVHxrt7D5baTEW9DE1Bk3up9fY4w',
|
||||
authSecret: '3rWhsRCU_KdaqfKPbd3zBQ',
|
||||
desc: "rs = 6, second record truncated to only auth tag",
|
||||
data: "C7u3j5AL4Yzh2yYB_umN6tzrVHxrt7D5baTEW9DE1Bk3up9fY4w",
|
||||
authSecret: "3rWhsRCU_KdaqfKPbd3zBQ",
|
||||
privateKey: {
|
||||
kty: 'EC',
|
||||
crv: 'P-256',
|
||||
d: 'nhOT9171xuoQBJGkiZ3aqT5qw_ILJ94_PPiVNu1LFSY',
|
||||
x: 'lCj7ctQTmRfwzTMcODlNfHjFMAHmgdI44OhTQXX_xpE',
|
||||
y: 'WBdgz4GWGtGAisC63O9DtP5l--hnCzPZiV-YZ-a6Lcw',
|
||||
kty: "EC",
|
||||
crv: "P-256",
|
||||
d: "nhOT9171xuoQBJGkiZ3aqT5qw_ILJ94_PPiVNu1LFSY",
|
||||
x: "lCj7ctQTmRfwzTMcODlNfHjFMAHmgdI44OhTQXX_xpE",
|
||||
y: "WBdgz4GWGtGAisC63O9DtP5l--hnCzPZiV-YZ-a6Lcw",
|
||||
ext: true,
|
||||
},
|
||||
publicKey: 'BJQo-3LUE5kX8M0zHDg5TXx4xTAB5oHSOODoU0F1_8aRWBdgz4GWGtGAisC63O9DtP5l--hnCzPZiV-YZ-a6Lcw',
|
||||
publicKey: "BJQo-3LUE5kX8M0zHDg5TXx4xTAB5oHSOODoU0F1_8aRWBdgz4GWGtGAisC63O9DtP5l--hnCzPZiV-YZ-a6Lcw",
|
||||
headers: {
|
||||
crypto_key: 'dh=BI38Qs_OhDmQIxbszc6Nako-MrX3FzAE_8HzxM1wgoEIG4ocxyF-YAAVhfkpJUvDpRyKW2LDHIaoylaZuxQfRhE',
|
||||
encryption: 'salt=QClh48OlvGpSjZ0Mg0e8rg; rs=6',
|
||||
encoding: 'aesgcm',
|
||||
crypto_key: "dh=BI38Qs_OhDmQIxbszc6Nako-MrX3FzAE_8HzxM1wgoEIG4ocxyF-YAAVhfkpJUvDpRyKW2LDHIaoylaZuxQfRhE",
|
||||
encryption: "salt=QClh48OlvGpSjZ0Mg0e8rg; rs=6",
|
||||
encoding: "aesgcm",
|
||||
},
|
||||
expected: /Decoded array is too short/,
|
||||
}];
|
||||
|
@ -493,15 +493,15 @@ add_task(async function test_aesgcm_err() {
|
|||
|
||||
add_task(async function test_aesgcm128_ok() {
|
||||
let expectedSuccesses = [{
|
||||
desc: 'padSize = 1, rs = 4096, pad = 2',
|
||||
result: 'aesgcm128 encrypted message',
|
||||
data: 'ljBJ44NPzJFH9EuyT5xWMU4vpZ90MdAqaq1TC1kOLRoPNHtNFXeJ0GtuSaE',
|
||||
desc: "padSize = 1, rs = 4096, pad = 2",
|
||||
result: "aesgcm128 encrypted message",
|
||||
data: "ljBJ44NPzJFH9EuyT5xWMU4vpZ90MdAqaq1TC1kOLRoPNHtNFXeJ0GtuSaE",
|
||||
privateKey: LEGACY_PRIVATE_KEY,
|
||||
publicKey: LEGACY_PUBLIC_KEY,
|
||||
headers: {
|
||||
encryption_key: 'dh=BOmnfg02vNd6RZ7kXWWrCGFF92bI-rQ-bV0Pku3-KmlHwbGv4ejWqgasEdLGle5Rhmp6SKJunZw2l2HxKvrIjfI',
|
||||
encryption: 'salt=btxxUtclbmgcc30b9rT3Bg; rs=4096',
|
||||
encoding: 'aesgcm128',
|
||||
encryption_key: "dh=BOmnfg02vNd6RZ7kXWWrCGFF92bI-rQ-bV0Pku3-KmlHwbGv4ejWqgasEdLGle5Rhmp6SKJunZw2l2HxKvrIjfI",
|
||||
encryption: "salt=btxxUtclbmgcc30b9rT3Bg; rs=4096",
|
||||
encoding: "aesgcm128",
|
||||
},
|
||||
}];
|
||||
for (let test of expectedSuccesses) {
|
||||
|
@ -513,49 +513,49 @@ add_task(async function test_aesgcm128_err() {
|
|||
let expectedFailures = [{
|
||||
// aesgcm128 doesn't use an auth secret, but we've mixed one in during
|
||||
// encryption, so the decryption key and nonce won't match.
|
||||
desc: 'padSize = 1, rs = 4096, auth secret, pad = 8',
|
||||
data: 'h0FmyldY8aT5EQ6CJrbfRn_IdDvytoLeHb9_q5CjtdFRfgDRknxLmOzavLaVG4oOiS0r',
|
||||
authSecret: 'Sxb6u0gJIhGEogyLawjmCw',
|
||||
desc: "padSize = 1, rs = 4096, auth secret, pad = 8",
|
||||
data: "h0FmyldY8aT5EQ6CJrbfRn_IdDvytoLeHb9_q5CjtdFRfgDRknxLmOzavLaVG4oOiS0r",
|
||||
authSecret: "Sxb6u0gJIhGEogyLawjmCw",
|
||||
privateKey: LEGACY_PRIVATE_KEY,
|
||||
publicKey: LEGACY_PUBLIC_KEY,
|
||||
headers: {
|
||||
crypto_key: 'dh=BCXHk7O8CE-9AOp6xx7g7c-NCaNpns1PyyHpdcmDaijLbT6IdGq0ezGatBwtFc34BBfscFxdk4Tjksa2Mx5rRCM',
|
||||
encryption: 'salt=aGBpoKklLtrLcAUCcCr7JQ',
|
||||
encoding: 'aesgcm128',
|
||||
crypto_key: "dh=BCXHk7O8CE-9AOp6xx7g7c-NCaNpns1PyyHpdcmDaijLbT6IdGq0ezGatBwtFc34BBfscFxdk4Tjksa2Mx5rRCM",
|
||||
encryption: "salt=aGBpoKklLtrLcAUCcCr7JQ",
|
||||
encoding: "aesgcm128",
|
||||
},
|
||||
expected: /Missing Encryption-Key header/,
|
||||
}, {
|
||||
// The first byte of each record must be the pad length.
|
||||
desc: 'Missing padding',
|
||||
data: 'anvsHj7oBQTPMhv7XSJEsvyMS4-8EtbC7HgFZsKaTg',
|
||||
desc: "Missing padding",
|
||||
data: "anvsHj7oBQTPMhv7XSJEsvyMS4-8EtbC7HgFZsKaTg",
|
||||
privateKey: LEGACY_PRIVATE_KEY,
|
||||
publicKey: LEGACY_PUBLIC_KEY,
|
||||
headers: {
|
||||
crypto_key: 'dh=BMSqfc3ohqw2DDgu3nsMESagYGWubswQPGxrW1bAbYKD18dIHQBUmD3ul_lu7MyQiT5gNdzn5JTXQvCcpf-oZE4',
|
||||
encryption: 'salt=Czx2i18rar8XWOXAVDnUuw',
|
||||
encoding: 'aesgcm128',
|
||||
crypto_key: "dh=BMSqfc3ohqw2DDgu3nsMESagYGWubswQPGxrW1bAbYKD18dIHQBUmD3ul_lu7MyQiT5gNdzn5JTXQvCcpf-oZE4",
|
||||
encryption: "salt=Czx2i18rar8XWOXAVDnUuw",
|
||||
encoding: "aesgcm128",
|
||||
},
|
||||
expected: /Missing Encryption-Key header/,
|
||||
}, {
|
||||
desc: 'Truncated input',
|
||||
data: 'AlDjj6NvT5HGyrHbT8M5D6XBFSra6xrWS9B2ROaCIjwSu3RyZ1iyuv0',
|
||||
desc: "Truncated input",
|
||||
data: "AlDjj6NvT5HGyrHbT8M5D6XBFSra6xrWS9B2ROaCIjwSu3RyZ1iyuv0",
|
||||
privateKey: LEGACY_PRIVATE_KEY,
|
||||
publicKey: LEGACY_PUBLIC_KEY,
|
||||
headers: {
|
||||
crypto_key: 'dh=BCHn-I-J3dfPRLJBlNZ3xFoAqaBLZ6qdhpaz9W7Q00JW1oD-hTxyEECn6KYJNK8AxKUyIDwn6Icx_PYWJiEYjQ0',
|
||||
encryption: 'salt=c6JQl9eJ0VvwrUVCQDxY7Q; rs=25',
|
||||
encoding: 'aesgcm128',
|
||||
crypto_key: "dh=BCHn-I-J3dfPRLJBlNZ3xFoAqaBLZ6qdhpaz9W7Q00JW1oD-hTxyEECn6KYJNK8AxKUyIDwn6Icx_PYWJiEYjQ0",
|
||||
encryption: "salt=c6JQl9eJ0VvwrUVCQDxY7Q; rs=25",
|
||||
encoding: "aesgcm128",
|
||||
},
|
||||
expected: /Missing Encryption-Key header/,
|
||||
}, {
|
||||
desc: 'Padding length > rs',
|
||||
data: 'Ct_h1g7O55e6GvuhmpjLsGnv8Rmwvxgw8iDESNKGxk_8E99iHKDzdV8wJPyHA-6b2E6kzuVa5UWiQ7s4Zms1xzJ4FKgoxvBObXkc_r_d4mnb-j245z3AcvRmcYGk5_HZ0ci26SfhAN3lCgxGzTHS4nuHBRkGwOb4Tj4SFyBRlLoTh2jyVK2jYugNjH9tTrGOBg7lP5lajLTQlxOi91-RYZSfFhsLX3LrAkXuRoN7G1CdiI7Y3_eTgbPIPabDcLCnGzmFBTvoJSaQF17huMl_UnWoCj2WovA4BwK_TvWSbdgElNnQ4CbArJ1h9OqhDOphVu5GUGr94iitXRQR-fqKPMad0ULLjKQWZOnjuIdV1RYEZ873r62Yyd31HoveJcSDb1T8l_QK2zVF8V4k0xmK9hGuC0rF5YJPYPHgl5__usknzxMBnRrfV5_MOL5uPZwUEFsu',
|
||||
desc: "Padding length > rs",
|
||||
data: "Ct_h1g7O55e6GvuhmpjLsGnv8Rmwvxgw8iDESNKGxk_8E99iHKDzdV8wJPyHA-6b2E6kzuVa5UWiQ7s4Zms1xzJ4FKgoxvBObXkc_r_d4mnb-j245z3AcvRmcYGk5_HZ0ci26SfhAN3lCgxGzTHS4nuHBRkGwOb4Tj4SFyBRlLoTh2jyVK2jYugNjH9tTrGOBg7lP5lajLTQlxOi91-RYZSfFhsLX3LrAkXuRoN7G1CdiI7Y3_eTgbPIPabDcLCnGzmFBTvoJSaQF17huMl_UnWoCj2WovA4BwK_TvWSbdgElNnQ4CbArJ1h9OqhDOphVu5GUGr94iitXRQR-fqKPMad0ULLjKQWZOnjuIdV1RYEZ873r62Yyd31HoveJcSDb1T8l_QK2zVF8V4k0xmK9hGuC0rF5YJPYPHgl5__usknzxMBnRrfV5_MOL5uPZwUEFsu",
|
||||
privateKey: LEGACY_PRIVATE_KEY,
|
||||
publicKey: LEGACY_PUBLIC_KEY,
|
||||
headers: {
|
||||
crypto_key: 'dh=BAcMdWLJRGx-kPpeFtwqR3GE1LWzd1TYh2rg6CEFu53O-y3DNLkNe_BtGtKRR4f7ZqpBMVS6NgfE2NwNPm3Ndls',
|
||||
encryption: 'salt=NQVTKhB0rpL7ZzKkotTGlA; rs=1',
|
||||
encoding: 'aesgcm128',
|
||||
crypto_key: "dh=BAcMdWLJRGx-kPpeFtwqR3GE1LWzd1TYh2rg6CEFu53O-y3DNLkNe_BtGtKRR4f7ZqpBMVS6NgfE2NwNPm3Ndls",
|
||||
encryption: "salt=NQVTKhB0rpL7ZzKkotTGlA; rs=1",
|
||||
encoding: "aesgcm128",
|
||||
},
|
||||
expected: /Missing Encryption-Key header/,
|
||||
}];
|
||||
|
|
|
@ -7,9 +7,9 @@ const {PushCrypto} = ChromeUtils.import("resource://gre/modules/PushCrypto.jsm")
|
|||
|
||||
let from64 = v => {
|
||||
// allow whitespace in the strings.
|
||||
let stripped = v.replace(/ |\t|\r|\n/g, '');
|
||||
let stripped = v.replace(/ |\t|\r|\n/g, "");
|
||||
return new Uint8Array(ChromeUtils.base64URLDecode(stripped, {padding: "reject"}));
|
||||
}
|
||||
};
|
||||
|
||||
let to64 = v => ChromeUtils.base64URLEncode(v, {pad: false});
|
||||
|
||||
|
@ -24,13 +24,13 @@ async function importKeyPair(publicKeyBuffer, privateKeyBuffer) {
|
|||
y: to64(publicKeyBuffer.slice(33, 65)),
|
||||
ext: true,
|
||||
};
|
||||
let publicKey = await crypto.subtle.importKey('jwk', jwk,
|
||||
{ name: 'ECDH', namedCurve: 'P-256' },
|
||||
let publicKey = await crypto.subtle.importKey("jwk", jwk,
|
||||
{ name: "ECDH", namedCurve: "P-256" },
|
||||
true, []);
|
||||
jwk.d = to64(privateKeyBuffer);
|
||||
let privateKey = await crypto.subtle.importKey('jwk', jwk,
|
||||
{ name: 'ECDH', namedCurve: 'P-256' },
|
||||
true, ['deriveBits']);
|
||||
let privateKey = await crypto.subtle.importKey("jwk", jwk,
|
||||
{ name: "ECDH", namedCurve: "P-256" },
|
||||
true, ["deriveBits"]);
|
||||
return {publicKey, privateKey};
|
||||
}
|
||||
|
||||
|
@ -55,14 +55,10 @@ add_task(async function static_aes128gcm() {
|
|||
salt: from64("DGv6ra1nlYgDCS1FRnbzlw"),
|
||||
};
|
||||
|
||||
|
||||
let publicKeyBuffer = from64(`BP4z9KsN6nGRTbVYI_c7VJSPQTBtkgcy27mlmlMoZ
|
||||
IIgDll6e3vCYLocInmYWAmS6TlzAC8wEqKK6PBru3jl7A8`);
|
||||
let privateKeyBuffer = from64("yfWPiYE-n46HLnH0KqZOF1fJJU3MYrct3AELtAQ-oRw");
|
||||
let options = {
|
||||
senderKeyPair: await importKeyPair(fixture.sender.public, fixture.sender.private),
|
||||
salt: fixture.salt,
|
||||
}
|
||||
};
|
||||
|
||||
let {ciphertext, encoding} = await PushCrypto.encrypt(fixture.plaintext,
|
||||
fixture.receiver.public,
|
||||
|
@ -130,7 +126,7 @@ add_task(async function aes128gcm_rs() {
|
|||
add_task(async function aes128gcm_edgecases() {
|
||||
let [recvPublicKey, recvPrivateKey] = await PushCrypto.generateKeys();
|
||||
|
||||
for (let size of [0, 4096-16, 4096-16-1, 4096-16+1,
|
||||
for (let size of [0, 4096 - 16, 4096 - 16 - 1, 4096 - 16 + 1,
|
||||
4095, 4096, 4097, 10240]) {
|
||||
info(`testing encryption of ${size} byte payload`);
|
||||
let message = new TextEncoder("utf-8").encode("x".repeat(size));
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
'use strict';
|
||||
"use strict";
|
||||
|
||||
const {PushDB, PushService, PushServiceWebSocket} = serviceExports;
|
||||
|
||||
const userAgentID = '2c43af06-ab6e-476a-adc4-16cbda54fb89';
|
||||
const userAgentID = "2c43af06-ab6e-476a-adc4-16cbda54fb89";
|
||||
|
||||
var db;
|
||||
var quotaURI;
|
||||
|
@ -13,33 +13,33 @@ var permURI;
|
|||
|
||||
function visitURI(uri, timestamp) {
|
||||
return PlacesTestUtils.addVisits({
|
||||
uri: uri,
|
||||
uri,
|
||||
title: uri.spec,
|
||||
visitDate: timestamp * 1000,
|
||||
transition: Ci.nsINavHistoryService.TRANSITION_LINK
|
||||
transition: Ci.nsINavHistoryService.TRANSITION_LINK,
|
||||
});
|
||||
}
|
||||
|
||||
var putRecord = async function({scope, perm, quota, lastPush, lastVisit}) {
|
||||
let uri = Services.io.newURI(scope);
|
||||
|
||||
Services.perms.add(uri, 'desktop-notification',
|
||||
Services.perms.add(uri, "desktop-notification",
|
||||
Ci.nsIPermissionManager[perm]);
|
||||
registerCleanupFunction(() => {
|
||||
Services.perms.remove(uri, 'desktop-notification');
|
||||
Services.perms.remove(uri, "desktop-notification");
|
||||
});
|
||||
|
||||
await visitURI(uri, lastVisit);
|
||||
|
||||
await db.put({
|
||||
channelID: uri.pathQueryRef,
|
||||
pushEndpoint: 'https://example.org/push' + uri.pathQueryRef,
|
||||
pushEndpoint: "https://example.org/push" + uri.pathQueryRef,
|
||||
scope: uri.spec,
|
||||
pushCount: 0,
|
||||
lastPush: lastPush,
|
||||
lastPush,
|
||||
version: null,
|
||||
originAttributes: '',
|
||||
quota: quota,
|
||||
originAttributes: "",
|
||||
quota,
|
||||
});
|
||||
|
||||
return uri;
|
||||
|
@ -48,11 +48,11 @@ var putRecord = async function({scope, perm, quota, lastPush, lastVisit}) {
|
|||
function run_test() {
|
||||
do_get_profile();
|
||||
setPrefs({
|
||||
userAgentID: userAgentID,
|
||||
userAgentID,
|
||||
});
|
||||
|
||||
db = PushServiceWebSocket.newPushDB();
|
||||
registerCleanupFunction(() => {return db.drop().then(_ => db.close());});
|
||||
registerCleanupFunction(() => { return db.drop().then(_ => db.close()); });
|
||||
|
||||
run_next_test();
|
||||
}
|
||||
|
@ -62,8 +62,8 @@ add_task(async function setUp() {
|
|||
// granted for this origin, and the last visit is more recent than the last
|
||||
// push message.
|
||||
await putRecord({
|
||||
scope: 'https://example.com/expired-quota-restored',
|
||||
perm: 'ALLOW_ACTION',
|
||||
scope: "https://example.com/expired-quota-restored",
|
||||
perm: "ALLOW_ACTION",
|
||||
quota: 0,
|
||||
lastPush: Date.now() - 10,
|
||||
lastVisit: Date.now(),
|
||||
|
@ -72,8 +72,8 @@ add_task(async function setUp() {
|
|||
// An expired registration that we should evict when the origin is visited
|
||||
// again.
|
||||
quotaURI = await putRecord({
|
||||
scope: 'https://example.xyz/expired-quota-exceeded',
|
||||
perm: 'ALLOW_ACTION',
|
||||
scope: "https://example.xyz/expired-quota-exceeded",
|
||||
perm: "ALLOW_ACTION",
|
||||
quota: 0,
|
||||
lastPush: Date.now() - 10,
|
||||
lastVisit: Date.now() - 20,
|
||||
|
@ -82,8 +82,8 @@ add_task(async function setUp() {
|
|||
// An expired registration that we should evict when permission is granted
|
||||
// again.
|
||||
permURI = await putRecord({
|
||||
scope: 'https://example.info/expired-perm-revoked',
|
||||
perm: 'DENY_ACTION',
|
||||
scope: "https://example.info/expired-perm-revoked",
|
||||
perm: "DENY_ACTION",
|
||||
quota: 0,
|
||||
lastPush: Date.now() - 10,
|
||||
lastVisit: Date.now(),
|
||||
|
@ -91,8 +91,8 @@ add_task(async function setUp() {
|
|||
|
||||
// An active registration that we should leave alone.
|
||||
await putRecord({
|
||||
scope: 'https://example.ninja/active',
|
||||
perm: 'ALLOW_ACTION',
|
||||
scope: "https://example.ninja/active",
|
||||
perm: "ALLOW_ACTION",
|
||||
quota: 16,
|
||||
lastPush: Date.now() - 10,
|
||||
lastVisit: Date.now() - 20,
|
||||
|
@ -100,24 +100,24 @@ add_task(async function setUp() {
|
|||
|
||||
let subChangePromise = promiseObserverNotification(
|
||||
PushServiceComponent.subscriptionChangeTopic,
|
||||
(subject, data) => data == 'https://example.com/expired-quota-restored'
|
||||
(subject, data) => data == "https://example.com/expired-quota-restored"
|
||||
);
|
||||
|
||||
PushService.init({
|
||||
serverURI: 'wss://push.example.org/',
|
||||
serverURI: "wss://push.example.org/",
|
||||
db,
|
||||
makeWebSocket(uri) {
|
||||
return new MockWebSocket(uri, {
|
||||
onHello(request) {
|
||||
this.serverSendMsg(JSON.stringify({
|
||||
messageType: 'hello',
|
||||
messageType: "hello",
|
||||
status: 200,
|
||||
uaid: userAgentID,
|
||||
}));
|
||||
},
|
||||
onUnregister(request) {
|
||||
this.serverSendMsg(JSON.stringify({
|
||||
messageType: 'unregister',
|
||||
messageType: "unregister",
|
||||
channelID: request.channelID,
|
||||
status: 200,
|
||||
}));
|
||||
|
@ -132,11 +132,11 @@ add_task(async function setUp() {
|
|||
add_task(async function test_site_visited() {
|
||||
let subChangePromise = promiseObserverNotification(
|
||||
PushServiceComponent.subscriptionChangeTopic,
|
||||
(subject, data) => data == 'https://example.xyz/expired-quota-exceeded'
|
||||
(subject, data) => data == "https://example.xyz/expired-quota-exceeded"
|
||||
);
|
||||
|
||||
await visitURI(quotaURI, Date.now());
|
||||
PushService.observe(null, 'idle-daily', '');
|
||||
PushService.observe(null, "idle-daily", "");
|
||||
|
||||
await subChangePromise;
|
||||
});
|
||||
|
@ -144,10 +144,10 @@ add_task(async function test_site_visited() {
|
|||
add_task(async function test_perm_restored() {
|
||||
let subChangePromise = promiseObserverNotification(
|
||||
PushServiceComponent.subscriptionChangeTopic,
|
||||
(subject, data) => data == 'https://example.info/expired-perm-revoked'
|
||||
(subject, data) => data == "https://example.info/expired-perm-revoked"
|
||||
);
|
||||
|
||||
Services.perms.add(permURI, 'desktop-notification',
|
||||
Services.perms.add(permURI, "desktop-notification",
|
||||
Ci.nsIPermissionManager.ALLOW_ACTION);
|
||||
|
||||
await subChangePromise;
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
'use strict';
|
||||
"use strict";
|
||||
|
||||
const {PushDB, PushService, PushServiceWebSocket} = serviceExports;
|
||||
|
||||
var userAgentID = '5ab1d1df-7a3d-4024-a469-b9e1bb399fad';
|
||||
var userAgentID = "5ab1d1df-7a3d-4024-a469-b9e1bb399fad";
|
||||
|
||||
function run_test() {
|
||||
do_get_profile();
|
||||
|
@ -15,28 +15,28 @@ function run_test() {
|
|||
|
||||
add_task(async function test_notification_ack() {
|
||||
let db = PushServiceWebSocket.newPushDB();
|
||||
registerCleanupFunction(() => {return db.drop().then(_ => db.close());});
|
||||
registerCleanupFunction(() => { return db.drop().then(_ => db.close()); });
|
||||
let records = [{
|
||||
channelID: '21668e05-6da8-42c9-b8ab-9cc3f4d5630c',
|
||||
pushEndpoint: 'https://example.com/update/1',
|
||||
scope: 'https://example.org/1',
|
||||
originAttributes: '',
|
||||
channelID: "21668e05-6da8-42c9-b8ab-9cc3f4d5630c",
|
||||
pushEndpoint: "https://example.com/update/1",
|
||||
scope: "https://example.org/1",
|
||||
originAttributes: "",
|
||||
version: 1,
|
||||
quota: Infinity,
|
||||
systemRecord: true,
|
||||
}, {
|
||||
channelID: '9a5ff87f-47c9-4215-b2b8-0bdd38b4b305',
|
||||
pushEndpoint: 'https://example.com/update/2',
|
||||
scope: 'https://example.org/2',
|
||||
originAttributes: '',
|
||||
channelID: "9a5ff87f-47c9-4215-b2b8-0bdd38b4b305",
|
||||
pushEndpoint: "https://example.com/update/2",
|
||||
scope: "https://example.org/2",
|
||||
originAttributes: "",
|
||||
version: 2,
|
||||
quota: Infinity,
|
||||
systemRecord: true,
|
||||
}, {
|
||||
channelID: '5477bfda-22db-45d4-9614-fee369630260',
|
||||
pushEndpoint: 'https://example.com/update/3',
|
||||
scope: 'https://example.org/3',
|
||||
originAttributes: '',
|
||||
channelID: "5477bfda-22db-45d4-9614-fee369630260",
|
||||
pushEndpoint: "https://example.com/update/3",
|
||||
scope: "https://example.org/3",
|
||||
originAttributes: "",
|
||||
version: 3,
|
||||
quota: Infinity,
|
||||
systemRecord: true,
|
||||
|
@ -59,65 +59,65 @@ add_task(async function test_notification_ack() {
|
|||
return new MockWebSocket(uri, {
|
||||
onHello(request) {
|
||||
equal(request.uaid, userAgentID,
|
||||
'Should send matching device IDs in handshake');
|
||||
"Should send matching device IDs in handshake");
|
||||
this.serverSendMsg(JSON.stringify({
|
||||
messageType: 'hello',
|
||||
messageType: "hello",
|
||||
uaid: userAgentID,
|
||||
status: 200
|
||||
status: 200,
|
||||
}));
|
||||
this.serverSendMsg(JSON.stringify({
|
||||
messageType: 'notification',
|
||||
messageType: "notification",
|
||||
updates: [{
|
||||
channelID: '21668e05-6da8-42c9-b8ab-9cc3f4d5630c',
|
||||
version: 2
|
||||
}]
|
||||
channelID: "21668e05-6da8-42c9-b8ab-9cc3f4d5630c",
|
||||
version: 2,
|
||||
}],
|
||||
}));
|
||||
},
|
||||
onACK(request) {
|
||||
equal(request.messageType, 'ack', 'Should send acknowledgements');
|
||||
equal(request.messageType, "ack", "Should send acknowledgements");
|
||||
let updates = request.updates;
|
||||
switch (++acks) {
|
||||
case 1:
|
||||
deepEqual([{
|
||||
channelID: '21668e05-6da8-42c9-b8ab-9cc3f4d5630c',
|
||||
channelID: "21668e05-6da8-42c9-b8ab-9cc3f4d5630c",
|
||||
version: 2,
|
||||
code: 100,
|
||||
}], updates, 'Wrong updates for acknowledgement 1');
|
||||
}], updates, "Wrong updates for acknowledgement 1");
|
||||
this.serverSendMsg(JSON.stringify({
|
||||
messageType: 'notification',
|
||||
messageType: "notification",
|
||||
updates: [{
|
||||
channelID: '9a5ff87f-47c9-4215-b2b8-0bdd38b4b305',
|
||||
version: 4
|
||||
channelID: "9a5ff87f-47c9-4215-b2b8-0bdd38b4b305",
|
||||
version: 4,
|
||||
}, {
|
||||
channelID: '5477bfda-22db-45d4-9614-fee369630260',
|
||||
version: 6
|
||||
}]
|
||||
channelID: "5477bfda-22db-45d4-9614-fee369630260",
|
||||
version: 6,
|
||||
}],
|
||||
}));
|
||||
break;
|
||||
|
||||
case 2:
|
||||
deepEqual([{
|
||||
channelID: '9a5ff87f-47c9-4215-b2b8-0bdd38b4b305',
|
||||
channelID: "9a5ff87f-47c9-4215-b2b8-0bdd38b4b305",
|
||||
version: 4,
|
||||
code: 100,
|
||||
}], updates, 'Wrong updates for acknowledgement 2');
|
||||
}], updates, "Wrong updates for acknowledgement 2");
|
||||
break;
|
||||
|
||||
case 3:
|
||||
deepEqual([{
|
||||
channelID: '5477bfda-22db-45d4-9614-fee369630260',
|
||||
channelID: "5477bfda-22db-45d4-9614-fee369630260",
|
||||
version: 6,
|
||||
code: 100,
|
||||
}], updates, 'Wrong updates for acknowledgement 3');
|
||||
}], updates, "Wrong updates for acknowledgement 3");
|
||||
ackDone();
|
||||
break;
|
||||
|
||||
default:
|
||||
ok(false, 'Unexpected acknowledgement ' + acks);
|
||||
ok(false, "Unexpected acknowledgement " + acks);
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
await notifyPromise;
|
||||
|
|
|
@ -1,29 +1,29 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
'use strict';
|
||||
"use strict";
|
||||
|
||||
const {PushDB, PushService, PushServiceWebSocket} = serviceExports;
|
||||
|
||||
let db;
|
||||
let userAgentID = 'f5b47f8d-771f-4ea3-b999-91c135f8766d';
|
||||
let userAgentID = "f5b47f8d-771f-4ea3-b999-91c135f8766d";
|
||||
|
||||
function run_test() {
|
||||
do_get_profile();
|
||||
setPrefs({
|
||||
userAgentID: userAgentID,
|
||||
userAgentID,
|
||||
});
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
function putRecord(channelID, scope, publicKey, privateKey, authSecret) {
|
||||
return db.put({
|
||||
channelID: channelID,
|
||||
pushEndpoint: 'https://example.org/push/' + channelID,
|
||||
scope: scope,
|
||||
channelID,
|
||||
pushEndpoint: "https://example.org/push/" + channelID,
|
||||
scope,
|
||||
pushCount: 0,
|
||||
lastPush: 0,
|
||||
originAttributes: '',
|
||||
originAttributes: "",
|
||||
quota: Infinity,
|
||||
systemRecord: true,
|
||||
p256dhPublicKey: ChromeUtils.base64URLDecode(publicKey, {
|
||||
|
@ -40,52 +40,52 @@ let ackDone;
|
|||
let server;
|
||||
add_task(async function test_notification_ack_data_setup() {
|
||||
db = PushServiceWebSocket.newPushDB();
|
||||
registerCleanupFunction(() => {return db.drop().then(_ => db.close());});
|
||||
registerCleanupFunction(() => { return db.drop().then(_ => db.close()); });
|
||||
|
||||
await putRecord(
|
||||
'subscription1',
|
||||
'https://example.com/page/1',
|
||||
'BPCd4gNQkjwRah61LpdALdzZKLLnU5UAwDztQ5_h0QsT26jk0IFbqcK6-JxhHAm-rsHEwy0CyVJjtnfOcqc1tgA',
|
||||
"subscription1",
|
||||
"https://example.com/page/1",
|
||||
"BPCd4gNQkjwRah61LpdALdzZKLLnU5UAwDztQ5_h0QsT26jk0IFbqcK6-JxhHAm-rsHEwy0CyVJjtnfOcqc1tgA",
|
||||
{
|
||||
crv: 'P-256',
|
||||
d: '1jUPhzVsRkzV0vIzwL4ZEsOlKdNOWm7TmaTfzitJkgM',
|
||||
crv: "P-256",
|
||||
d: "1jUPhzVsRkzV0vIzwL4ZEsOlKdNOWm7TmaTfzitJkgM",
|
||||
ext: true,
|
||||
key_ops: ["deriveBits"],
|
||||
kty: "EC",
|
||||
x: '8J3iA1CSPBFqHrUul0At3NkosudTlQDAPO1Dn-HRCxM',
|
||||
y: '26jk0IFbqcK6-JxhHAm-rsHEwy0CyVJjtnfOcqc1tgA'
|
||||
x: "8J3iA1CSPBFqHrUul0At3NkosudTlQDAPO1Dn-HRCxM",
|
||||
y: "26jk0IFbqcK6-JxhHAm-rsHEwy0CyVJjtnfOcqc1tgA",
|
||||
},
|
||||
'c_sGN6uCv9Hu7JOQT34jAQ'
|
||||
"c_sGN6uCv9Hu7JOQT34jAQ"
|
||||
);
|
||||
await putRecord(
|
||||
'subscription2',
|
||||
'https://example.com/page/2',
|
||||
'BPnWyUo7yMnuMlyKtERuLfWE8a09dtdjHSW2lpC9_BqR5TZ1rK8Ldih6ljyxVwnBA-nygQHGRpEmu1jV5K8437E',
|
||||
"subscription2",
|
||||
"https://example.com/page/2",
|
||||
"BPnWyUo7yMnuMlyKtERuLfWE8a09dtdjHSW2lpC9_BqR5TZ1rK8Ldih6ljyxVwnBA-nygQHGRpEmu1jV5K8437E",
|
||||
{
|
||||
crv: 'P-256',
|
||||
d: 'lFm4nPsUKYgNGBJb5nXXKxl8bspCSp0bAhCYxbveqT4',
|
||||
crv: "P-256",
|
||||
d: "lFm4nPsUKYgNGBJb5nXXKxl8bspCSp0bAhCYxbveqT4",
|
||||
ext: true,
|
||||
key_ops: ["deriveBits"],
|
||||
kty: 'EC',
|
||||
x: '-dbJSjvIye4yXIq0RG4t9YTxrT1212MdJbaWkL38GpE',
|
||||
y: '5TZ1rK8Ldih6ljyxVwnBA-nygQHGRpEmu1jV5K8437E'
|
||||
kty: "EC",
|
||||
x: "-dbJSjvIye4yXIq0RG4t9YTxrT1212MdJbaWkL38GpE",
|
||||
y: "5TZ1rK8Ldih6ljyxVwnBA-nygQHGRpEmu1jV5K8437E",
|
||||
},
|
||||
't3P246Gj9vjKDHHRYaY6hw'
|
||||
"t3P246Gj9vjKDHHRYaY6hw"
|
||||
);
|
||||
await putRecord(
|
||||
'subscription3',
|
||||
'https://example.com/page/3',
|
||||
'BDhUHITSeVrWYybFnb7ylVTCDDLPdQWMpf8gXhcWwvaaJa6n3YH8TOcH8narDF6t8mKVvg2ioLW-8MH5O4dzGcI',
|
||||
"subscription3",
|
||||
"https://example.com/page/3",
|
||||
"BDhUHITSeVrWYybFnb7ylVTCDDLPdQWMpf8gXhcWwvaaJa6n3YH8TOcH8narDF6t8mKVvg2ioLW-8MH5O4dzGcI",
|
||||
{
|
||||
crv: 'P-256',
|
||||
d: 'Q1_SE1NySTYzjbqgWwPgrYh7XRg3adqZLkQPsy319G8',
|
||||
crv: "P-256",
|
||||
d: "Q1_SE1NySTYzjbqgWwPgrYh7XRg3adqZLkQPsy319G8",
|
||||
ext: true,
|
||||
key_ops: ["deriveBits"],
|
||||
kty: 'EC',
|
||||
x: 'OFQchNJ5WtZjJsWdvvKVVMIMMs91BYyl_yBeFxbC9po',
|
||||
y: 'Ja6n3YH8TOcH8narDF6t8mKVvg2ioLW-8MH5O4dzGcI'
|
||||
kty: "EC",
|
||||
x: "OFQchNJ5WtZjJsWdvvKVVMIMMs91BYyl_yBeFxbC9po",
|
||||
y: "Ja6n3YH8TOcH8narDF6t8mKVvg2ioLW-8MH5O4dzGcI",
|
||||
},
|
||||
'E0qiXGWvFSR0PS352ES1_Q'
|
||||
"E0qiXGWvFSR0PS352ES1_Q"
|
||||
);
|
||||
|
||||
let setupDone;
|
||||
|
@ -98,9 +98,9 @@ add_task(async function test_notification_ack_data_setup() {
|
|||
return new MockWebSocket(uri, {
|
||||
onHello(request) {
|
||||
equal(request.uaid, userAgentID,
|
||||
'Should send matching device IDs in handshake');
|
||||
"Should send matching device IDs in handshake");
|
||||
this.serverSendMsg(JSON.stringify({
|
||||
messageType: 'hello',
|
||||
messageType: "hello",
|
||||
uaid: userAgentID,
|
||||
status: 200,
|
||||
use_webpush: true,
|
||||
|
@ -112,9 +112,9 @@ add_task(async function test_notification_ack_data_setup() {
|
|||
if (ackDone) {
|
||||
ackDone(request);
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
await setupDonePromise;
|
||||
});
|
||||
|
@ -122,121 +122,121 @@ add_task(async function test_notification_ack_data_setup() {
|
|||
add_task(async function test_notification_ack_data() {
|
||||
let allTestData = [
|
||||
{
|
||||
channelID: 'subscription1',
|
||||
version: 'v1',
|
||||
channelID: "subscription1",
|
||||
version: "v1",
|
||||
send: {
|
||||
headers: {
|
||||
encryption_key: 'keyid="notification1"; dh="BO_tgGm-yvYAGLeRe16AvhzaUcpYRiqgsGOlXpt0DRWDRGGdzVLGlEVJMygqAUECarLnxCiAOHTP_znkedrlWoU"',
|
||||
encryption: 'keyid="notification1";salt="uAZaiXpOSfOLJxtOCZ09dA"',
|
||||
encoding: 'aesgcm128',
|
||||
encoding: "aesgcm128",
|
||||
},
|
||||
data: 'NwrrOWPxLE8Sv5Rr0Kep7n0-r_j3rsYrUw_CXPo',
|
||||
version: 'v1',
|
||||
data: "NwrrOWPxLE8Sv5Rr0Kep7n0-r_j3rsYrUw_CXPo",
|
||||
version: "v1",
|
||||
},
|
||||
ackCode: 100,
|
||||
receive: {
|
||||
scope: 'https://example.com/page/1',
|
||||
data: 'Some message'
|
||||
}
|
||||
scope: "https://example.com/page/1",
|
||||
data: "Some message",
|
||||
},
|
||||
},
|
||||
{
|
||||
channelID: 'subscription2',
|
||||
version: 'v2',
|
||||
channelID: "subscription2",
|
||||
version: "v2",
|
||||
send: {
|
||||
headers: {
|
||||
encryption_key: 'keyid="notification2"; dh="BKVdQcgfncpNyNWsGrbecX0zq3eHIlHu5XbCGmVcxPnRSbhjrA6GyBIeGdqsUL69j5Z2CvbZd-9z1UBH0akUnGQ"',
|
||||
encryption: 'keyid="notification2";salt="vFn3t3M_k42zHBdpch3VRw"',
|
||||
encoding: 'aesgcm128',
|
||||
encoding: "aesgcm128",
|
||||
},
|
||||
data: 'Zt9dEdqgHlyAL_l83385aEtb98ZBilz5tgnGgmwEsl5AOCNgesUUJ4p9qUU',
|
||||
data: "Zt9dEdqgHlyAL_l83385aEtb98ZBilz5tgnGgmwEsl5AOCNgesUUJ4p9qUU",
|
||||
},
|
||||
ackCode: 100,
|
||||
receive: {
|
||||
scope: 'https://example.com/page/2',
|
||||
data: 'Some message'
|
||||
}
|
||||
scope: "https://example.com/page/2",
|
||||
data: "Some message",
|
||||
},
|
||||
},
|
||||
{
|
||||
channelID: 'subscription3',
|
||||
version: 'v3',
|
||||
channelID: "subscription3",
|
||||
version: "v3",
|
||||
send: {
|
||||
headers: {
|
||||
encryption_key: 'keyid="notification3";dh="BD3xV_ACT8r6hdIYES3BJj1qhz9wyv7MBrG9vM2UCnjPzwE_YFVpkD-SGqE-BR2--0M-Yf31wctwNsO1qjBUeMg"',
|
||||
encryption: 'keyid="notification3"; salt="DFq188piWU7osPBgqn4Nlg"; rs=24',
|
||||
encoding: 'aesgcm128',
|
||||
encoding: "aesgcm128",
|
||||
},
|
||||
data: 'LKru3ZzxBZuAxYtsaCfaj_fehkrIvqbVd1iSwnwAUgnL-cTeDD-83blxHXTq7r0z9ydTdMtC3UjAcWi8LMnfY-BFzi0qJAjGYIikDA',
|
||||
data: "LKru3ZzxBZuAxYtsaCfaj_fehkrIvqbVd1iSwnwAUgnL-cTeDD-83blxHXTq7r0z9ydTdMtC3UjAcWi8LMnfY-BFzi0qJAjGYIikDA",
|
||||
},
|
||||
ackCode: 100,
|
||||
receive: {
|
||||
scope: 'https://example.com/page/3',
|
||||
data: 'Some message'
|
||||
}
|
||||
scope: "https://example.com/page/3",
|
||||
data: "Some message",
|
||||
},
|
||||
},
|
||||
// A message encoded with `aesgcm` (2 bytes of padding, authenticated).
|
||||
{
|
||||
channelID: 'subscription1',
|
||||
version: 'v5',
|
||||
channelID: "subscription1",
|
||||
version: "v5",
|
||||
send: {
|
||||
headers: {
|
||||
crypto_key: 'keyid=v4;dh="BMh_vsnqu79ZZkMTYkxl4gWDLdPSGE72Lr4w2hksSFW398xCMJszjzdblAWXyhSwakRNEU_GopAm4UGzyMVR83w"',
|
||||
encryption: 'keyid="v4";salt="C14Wb7rQTlXzrgcPHtaUzw"',
|
||||
encoding: 'aesgcm',
|
||||
encoding: "aesgcm",
|
||||
},
|
||||
data: 'pus4kUaBWzraH34M-d_oN8e0LPpF_X6acx695AMXovDe',
|
||||
data: "pus4kUaBWzraH34M-d_oN8e0LPpF_X6acx695AMXovDe",
|
||||
},
|
||||
ackCode: 100,
|
||||
receive: {
|
||||
scope: 'https://example.com/page/1',
|
||||
data: 'Another message'
|
||||
}
|
||||
scope: "https://example.com/page/1",
|
||||
data: "Another message",
|
||||
},
|
||||
},
|
||||
// A message with 17 bytes of padding and rs of 24
|
||||
{
|
||||
channelID: 'subscription2',
|
||||
version: 'v5',
|
||||
channelID: "subscription2",
|
||||
version: "v5",
|
||||
send: {
|
||||
headers: {
|
||||
crypto_key: 'keyid="v5"; dh="BOp-DpyR9eLY5Ci11_loIFqeHzWfc_0evJmq7N8NKzgp60UAMMM06XIi2VZp2_TSdw1omk7E19SyeCCwRp76E-U"',
|
||||
encryption: 'keyid=v5;salt="TvjOou1TqJOQY_ZsOYV3Ww";rs=24',
|
||||
encoding: 'aesgcm',
|
||||
encoding: "aesgcm",
|
||||
},
|
||||
data: 'rG9WYQ2ZwUgfj_tMlZ0vcIaNpBN05FW-9RUBZAM-UUZf0_9eGpuENBpUDAw3mFmd2XJpmvPvAtLVs54l3rGwg1o',
|
||||
data: "rG9WYQ2ZwUgfj_tMlZ0vcIaNpBN05FW-9RUBZAM-UUZf0_9eGpuENBpUDAw3mFmd2XJpmvPvAtLVs54l3rGwg1o",
|
||||
},
|
||||
ackCode: 100,
|
||||
receive: {
|
||||
scope: 'https://example.com/page/2',
|
||||
data: 'Some message'
|
||||
}
|
||||
scope: "https://example.com/page/2",
|
||||
data: "Some message",
|
||||
},
|
||||
},
|
||||
// A message without key identifiers.
|
||||
{
|
||||
channelID: 'subscription3',
|
||||
version: 'v6',
|
||||
channelID: "subscription3",
|
||||
version: "v6",
|
||||
send: {
|
||||
headers: {
|
||||
crypto_key: 'dh="BEEjwWbF5jZKCgW0kmUWgG-wNcRvaa9_3zZElHAF8przHwd4cp5_kQsc-IMNZcVA0iUix31jxuMOytU-5DwWtyQ"',
|
||||
encryption: 'salt=aAQcr2khAksgNspPiFEqiQ',
|
||||
encoding: 'aesgcm',
|
||||
encryption: "salt=aAQcr2khAksgNspPiFEqiQ",
|
||||
encoding: "aesgcm",
|
||||
},
|
||||
data: 'pEYgefdI-7L46CYn5dR9TIy2AXGxe07zxclbhstY',
|
||||
data: "pEYgefdI-7L46CYn5dR9TIy2AXGxe07zxclbhstY",
|
||||
},
|
||||
ackCode: 100,
|
||||
receive: {
|
||||
scope: 'https://example.com/page/3',
|
||||
data: 'Some message'
|
||||
}
|
||||
scope: "https://example.com/page/3",
|
||||
data: "Some message",
|
||||
},
|
||||
},
|
||||
// A malformed encrypted message.
|
||||
{
|
||||
channelID: 'subscription3',
|
||||
version: 'v7',
|
||||
channelID: "subscription3",
|
||||
version: "v7",
|
||||
send: {
|
||||
headers: {
|
||||
crypto_key: 'dh=AAAAAAAA',
|
||||
encryption: 'salt=AAAAAAAA',
|
||||
crypto_key: "dh=AAAAAAAA",
|
||||
encryption: "salt=AAAAAAAA",
|
||||
},
|
||||
data: 'AAAAAAAA',
|
||||
data: "AAAAAAAA",
|
||||
},
|
||||
ackCode: 101,
|
||||
receive: null,
|
||||
|
@ -247,26 +247,26 @@ add_task(async function test_notification_ack_data() {
|
|||
let messageReceived = testData.receive ? promiseObserverNotification(PushServiceComponent.pushTopic, (subject, data) => {
|
||||
let notification = subject.QueryInterface(Ci.nsIPushMessage).data;
|
||||
equal(notification.text(), testData.receive.data,
|
||||
'Check data for notification ' + testData.version);
|
||||
"Check data for notification " + testData.version);
|
||||
equal(data, testData.receive.scope,
|
||||
'Check scope for notification ' + testData.version);
|
||||
"Check scope for notification " + testData.version);
|
||||
return true;
|
||||
}) : Promise.resolve();
|
||||
|
||||
let ackReceived = new Promise(resolve => ackDone = resolve)
|
||||
.then(ackData => {
|
||||
deepEqual({
|
||||
messageType: 'ack',
|
||||
messageType: "ack",
|
||||
updates: [{
|
||||
channelID: testData.channelID,
|
||||
version: testData.version,
|
||||
code: testData.ackCode,
|
||||
}],
|
||||
}, ackData, 'Check updates for acknowledgment ' + testData.version);
|
||||
}, ackData, "Check updates for acknowledgment " + testData.version);
|
||||
});
|
||||
|
||||
let msg = JSON.parse(JSON.stringify(testData.send));
|
||||
msg.messageType = 'notification';
|
||||
msg.messageType = "notification";
|
||||
msg.channelID = testData.channelID;
|
||||
msg.version = testData.version;
|
||||
server.serverSendMsg(JSON.stringify(msg));
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
'use strict';
|
||||
"use strict";
|
||||
|
||||
const {PushDB, PushService, PushServiceWebSocket} = serviceExports;
|
||||
|
||||
const userAgentID = '1500e7d9-8cbe-4ee6-98da-7fa5d6a39852';
|
||||
const userAgentID = "1500e7d9-8cbe-4ee6-98da-7fa5d6a39852";
|
||||
|
||||
function run_test() {
|
||||
do_get_profile();
|
||||
setPrefs({
|
||||
maxRecentMessageIDsPerSubscription: 4,
|
||||
userAgentID: userAgentID,
|
||||
userAgentID,
|
||||
});
|
||||
run_next_test();
|
||||
}
|
||||
|
@ -19,28 +19,28 @@ function run_test() {
|
|||
// Should acknowledge duplicate notifications, but not notify apps.
|
||||
add_task(async function test_notification_duplicate() {
|
||||
let db = PushServiceWebSocket.newPushDB();
|
||||
registerCleanupFunction(() => {return db.drop().then(_ => db.close());});
|
||||
registerCleanupFunction(() => { return db.drop().then(_ => db.close()); });
|
||||
let records = [{
|
||||
channelID: 'has-recents',
|
||||
pushEndpoint: 'https://example.org/update/1',
|
||||
scope: 'https://example.com/1',
|
||||
channelID: "has-recents",
|
||||
pushEndpoint: "https://example.org/update/1",
|
||||
scope: "https://example.com/1",
|
||||
originAttributes: "",
|
||||
recentMessageIDs: ['dupe'],
|
||||
recentMessageIDs: ["dupe"],
|
||||
quota: Infinity,
|
||||
systemRecord: true,
|
||||
}, {
|
||||
channelID: 'no-recents',
|
||||
pushEndpoint: 'https://example.org/update/2',
|
||||
scope: 'https://example.com/2',
|
||||
channelID: "no-recents",
|
||||
pushEndpoint: "https://example.org/update/2",
|
||||
scope: "https://example.com/2",
|
||||
originAttributes: "",
|
||||
quota: Infinity,
|
||||
systemRecord: true,
|
||||
}, {
|
||||
channelID: 'dropped-recents',
|
||||
pushEndpoint: 'https://example.org/update/3',
|
||||
scope: 'https://example.com/3',
|
||||
originAttributes: '',
|
||||
recentMessageIDs: ['newest', 'newer', 'older', 'oldest'],
|
||||
channelID: "dropped-recents",
|
||||
pushEndpoint: "https://example.org/update/3",
|
||||
scope: "https://example.com/3",
|
||||
originAttributes: "",
|
||||
recentMessageIDs: ["newest", "newer", "older", "oldest"],
|
||||
quota: Infinity,
|
||||
systemRecord: true,
|
||||
}];
|
||||
|
@ -49,35 +49,35 @@ add_task(async function test_notification_duplicate() {
|
|||
}
|
||||
|
||||
let testData = [{
|
||||
channelID: 'has-recents',
|
||||
channelID: "has-recents",
|
||||
updates: 1,
|
||||
acks: [{
|
||||
version: 'dupe',
|
||||
version: "dupe",
|
||||
code: 102,
|
||||
}, {
|
||||
version: 'not-dupe',
|
||||
version: "not-dupe",
|
||||
code: 100,
|
||||
}],
|
||||
recents: ['not-dupe', 'dupe'],
|
||||
recents: ["not-dupe", "dupe"],
|
||||
}, {
|
||||
channelID: 'no-recents',
|
||||
channelID: "no-recents",
|
||||
updates: 1,
|
||||
acks: [{
|
||||
version: 'not-dupe',
|
||||
version: "not-dupe",
|
||||
code: 100,
|
||||
}],
|
||||
recents: ['not-dupe'],
|
||||
recents: ["not-dupe"],
|
||||
}, {
|
||||
channelID: 'dropped-recents',
|
||||
channelID: "dropped-recents",
|
||||
acks: [{
|
||||
version: 'overflow',
|
||||
version: "overflow",
|
||||
code: 100,
|
||||
}, {
|
||||
version: 'oldest',
|
||||
version: "oldest",
|
||||
code: 100,
|
||||
}],
|
||||
updates: 2,
|
||||
recents: ['oldest', 'overflow', 'newest', 'newer'],
|
||||
recents: ["oldest", "overflow", "newest", "newer"],
|
||||
}];
|
||||
|
||||
let expectedUpdates = testData.reduce((sum, {updates}) => sum + updates, 0);
|
||||
|
@ -97,7 +97,7 @@ add_task(async function test_notification_duplicate() {
|
|||
return new MockWebSocket(uri, {
|
||||
onHello(request) {
|
||||
this.serverSendMsg(JSON.stringify({
|
||||
messageType: 'hello',
|
||||
messageType: "hello",
|
||||
status: 200,
|
||||
uaid: userAgentID,
|
||||
use_webpush: true,
|
||||
|
@ -105,10 +105,10 @@ add_task(async function test_notification_duplicate() {
|
|||
for (let {channelID, acks} of testData) {
|
||||
for (let {version} of acks) {
|
||||
this.serverSendMsg(JSON.stringify({
|
||||
messageType: 'notification',
|
||||
channelID: channelID,
|
||||
version: version,
|
||||
}))
|
||||
messageType: "notification",
|
||||
channelID,
|
||||
version,
|
||||
}));
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -117,8 +117,7 @@ add_task(async function test_notification_duplicate() {
|
|||
let expectedData = testData.find(test =>
|
||||
test.channelID == ack.channelID);
|
||||
ok(expectedData, `Unexpected channel ${ack.channelID}`);
|
||||
let expectedAck = expectedData.acks.find(expectedAck =>
|
||||
expectedAck.version == ack.version);
|
||||
let expectedAck = expectedData.acks.find(a => a.version == ack.version);
|
||||
ok(expectedAck, `Unexpected ack for message ${
|
||||
ack.version} on ${ack.channelID}`);
|
||||
equal(expectedAck.code, ack.code, `Wrong ack status for message ${
|
||||
|
@ -126,7 +125,7 @@ add_task(async function test_notification_duplicate() {
|
|||
ackDone();
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
await notifyPromise;
|
||||
|
|
|
@ -1,46 +1,46 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
'use strict';
|
||||
"use strict";
|
||||
|
||||
const {PushDB, PushService, PushServiceWebSocket} = serviceExports;
|
||||
|
||||
const userAgentID = '3c7462fc-270f-45be-a459-b9d631b0d093';
|
||||
const userAgentID = "3c7462fc-270f-45be-a459-b9d631b0d093";
|
||||
|
||||
function run_test() {
|
||||
do_get_profile();
|
||||
setPrefs({
|
||||
userAgentID: userAgentID,
|
||||
userAgentID,
|
||||
});
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
add_task(async function test_notification_error() {
|
||||
let db = PushServiceWebSocket.newPushDB();
|
||||
registerCleanupFunction(() => {return db.drop().then(_ => db.close());});
|
||||
registerCleanupFunction(() => { return db.drop().then(_ => db.close()); });
|
||||
|
||||
let originAttributes = '';
|
||||
let originAttributes = "";
|
||||
let records = [{
|
||||
channelID: 'f04f1e46-9139-4826-b2d1-9411b0821283',
|
||||
pushEndpoint: 'https://example.org/update/success-1',
|
||||
scope: 'https://example.com/a',
|
||||
originAttributes: originAttributes,
|
||||
channelID: "f04f1e46-9139-4826-b2d1-9411b0821283",
|
||||
pushEndpoint: "https://example.org/update/success-1",
|
||||
scope: "https://example.com/a",
|
||||
originAttributes,
|
||||
version: 1,
|
||||
quota: Infinity,
|
||||
systemRecord: true,
|
||||
}, {
|
||||
channelID: '3c3930ba-44de-40dc-a7ca-8a133ec1a866',
|
||||
pushEndpoint: 'https://example.org/update/error',
|
||||
scope: 'https://example.com/b',
|
||||
originAttributes: originAttributes,
|
||||
channelID: "3c3930ba-44de-40dc-a7ca-8a133ec1a866",
|
||||
pushEndpoint: "https://example.org/update/error",
|
||||
scope: "https://example.com/b",
|
||||
originAttributes,
|
||||
version: 2,
|
||||
quota: Infinity,
|
||||
systemRecord: true,
|
||||
}, {
|
||||
channelID: 'b63f7bef-0a0d-4236-b41e-086a69dfd316',
|
||||
pushEndpoint: 'https://example.org/update/success-2',
|
||||
scope: 'https://example.com/c',
|
||||
originAttributes: originAttributes,
|
||||
channelID: "b63f7bef-0a0d-4236-b41e-086a69dfd316",
|
||||
pushEndpoint: "https://example.org/update/success-2",
|
||||
scope: "https://example.com/c",
|
||||
originAttributes,
|
||||
version: 3,
|
||||
quota: Infinity,
|
||||
systemRecord: true,
|
||||
|
@ -59,59 +59,59 @@ add_task(async function test_notification_error() {
|
|||
serverURI: "wss://push.example.org/",
|
||||
db: makeStub(db, {
|
||||
getByKeyID(prev, channelID) {
|
||||
if (channelID == '3c3930ba-44de-40dc-a7ca-8a133ec1a866') {
|
||||
return Promise.reject('splines not reticulated');
|
||||
if (channelID == "3c3930ba-44de-40dc-a7ca-8a133ec1a866") {
|
||||
return Promise.reject("splines not reticulated");
|
||||
}
|
||||
return prev.call(this, channelID);
|
||||
}
|
||||
},
|
||||
}),
|
||||
makeWebSocket(uri) {
|
||||
return new MockWebSocket(uri, {
|
||||
onHello(request) {
|
||||
this.serverSendMsg(JSON.stringify({
|
||||
messageType: 'hello',
|
||||
messageType: "hello",
|
||||
status: 200,
|
||||
uaid: userAgentID,
|
||||
}));
|
||||
this.serverSendMsg(JSON.stringify({
|
||||
messageType: 'notification',
|
||||
messageType: "notification",
|
||||
updates: records.map(({channelID, version}) =>
|
||||
({channelID, version: ++version}))
|
||||
({channelID, version: ++version})),
|
||||
}));
|
||||
},
|
||||
// Should acknowledge all received updates, even if updating
|
||||
// IndexedDB fails.
|
||||
onACK: ackDone
|
||||
onACK: ackDone,
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
await notifyPromise;
|
||||
ok(scopes.includes('https://example.com/a'),
|
||||
'Missing scope for notification A');
|
||||
ok(scopes.includes('https://example.com/c'),
|
||||
'Missing scope for notification C');
|
||||
ok(scopes.includes("https://example.com/a"),
|
||||
"Missing scope for notification A");
|
||||
ok(scopes.includes("https://example.com/c"),
|
||||
"Missing scope for notification C");
|
||||
|
||||
await ackPromise;
|
||||
|
||||
let aRecord = await db.getByIdentifiers({scope: 'https://example.com/a',
|
||||
originAttributes: originAttributes });
|
||||
equal(aRecord.channelID, 'f04f1e46-9139-4826-b2d1-9411b0821283',
|
||||
'Wrong channel ID for record A');
|
||||
let aRecord = await db.getByIdentifiers({scope: "https://example.com/a",
|
||||
originAttributes });
|
||||
equal(aRecord.channelID, "f04f1e46-9139-4826-b2d1-9411b0821283",
|
||||
"Wrong channel ID for record A");
|
||||
strictEqual(aRecord.version, 2,
|
||||
'Should return the new version for record A');
|
||||
"Should return the new version for record A");
|
||||
|
||||
let bRecord = await db.getByIdentifiers({scope: 'https://example.com/b',
|
||||
originAttributes: originAttributes });
|
||||
equal(bRecord.channelID, '3c3930ba-44de-40dc-a7ca-8a133ec1a866',
|
||||
'Wrong channel ID for record B');
|
||||
let bRecord = await db.getByIdentifiers({scope: "https://example.com/b",
|
||||
originAttributes });
|
||||
equal(bRecord.channelID, "3c3930ba-44de-40dc-a7ca-8a133ec1a866",
|
||||
"Wrong channel ID for record B");
|
||||
strictEqual(bRecord.version, 2,
|
||||
'Should return the previous version for record B');
|
||||
"Should return the previous version for record B");
|
||||
|
||||
let cRecord = await db.getByIdentifiers({scope: 'https://example.com/c',
|
||||
originAttributes: originAttributes });
|
||||
equal(cRecord.channelID, 'b63f7bef-0a0d-4236-b41e-086a69dfd316',
|
||||
'Wrong channel ID for record C');
|
||||
let cRecord = await db.getByIdentifiers({scope: "https://example.com/c",
|
||||
originAttributes });
|
||||
equal(cRecord.channelID, "b63f7bef-0a0d-4236-b41e-086a69dfd316",
|
||||
"Wrong channel ID for record C");
|
||||
strictEqual(cRecord.version, 4,
|
||||
'Should return the new version for record C');
|
||||
"Should return the new version for record C");
|
||||
});
|
||||
|
|
|
@ -1,12 +1,10 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
'use strict';
|
||||
"use strict";
|
||||
|
||||
const {PushDB, PushService, PushServiceHttp2} = serviceExports;
|
||||
|
||||
var prefs;
|
||||
|
||||
var serverPort = -1;
|
||||
|
||||
function run_test() {
|
||||
|
@ -14,25 +12,22 @@ function run_test() {
|
|||
|
||||
do_get_profile();
|
||||
setPrefs({
|
||||
'testing.allowInsecureServerURL': true,
|
||||
"testing.allowInsecureServerURL": true,
|
||||
});
|
||||
prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
|
||||
|
||||
// Set to allow the cert presented by our H2 server
|
||||
var oldPref = prefs.getIntPref("network.http.speculative-parallel-limit");
|
||||
prefs.setIntPref("network.http.speculative-parallel-limit", 0);
|
||||
prefs.setBoolPref("dom.push.enabled", true);
|
||||
prefs.setBoolPref("dom.push.connection.enabled", true);
|
||||
var oldPref = Services.prefs.getIntPref("network.http.speculative-parallel-limit");
|
||||
Services.prefs.setIntPref("network.http.speculative-parallel-limit", 0);
|
||||
Services.prefs.setBoolPref("dom.push.enabled", true);
|
||||
Services.prefs.setBoolPref("dom.push.connection.enabled", true);
|
||||
|
||||
trustHttp2CA();
|
||||
|
||||
prefs.setIntPref("network.http.speculative-parallel-limit", oldPref);
|
||||
Services.prefs.setIntPref("network.http.speculative-parallel-limit", oldPref);
|
||||
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
add_task(async function test_pushNotifications() {
|
||||
|
||||
// /pushNotifications/subscription1 will send a message with no rs and padding
|
||||
// length 1.
|
||||
// /pushNotifications/subscription2 will send a message with no rs and padding
|
||||
|
@ -50,80 +45,80 @@ add_task(async function test_pushNotifications() {
|
|||
var serverURL = "https://localhost:" + serverPort;
|
||||
|
||||
let records = [{
|
||||
subscriptionUri: serverURL + '/pushNotifications/subscription1',
|
||||
pushEndpoint: serverURL + '/pushEndpoint1',
|
||||
pushReceiptEndpoint: serverURL + '/pushReceiptEndpoint1',
|
||||
scope: 'https://example.com/page/1',
|
||||
p256dhPublicKey: 'BPCd4gNQkjwRah61LpdALdzZKLLnU5UAwDztQ5_h0QsT26jk0IFbqcK6-JxhHAm-rsHEwy0CyVJjtnfOcqc1tgA',
|
||||
subscriptionUri: serverURL + "/pushNotifications/subscription1",
|
||||
pushEndpoint: serverURL + "/pushEndpoint1",
|
||||
pushReceiptEndpoint: serverURL + "/pushReceiptEndpoint1",
|
||||
scope: "https://example.com/page/1",
|
||||
p256dhPublicKey: "BPCd4gNQkjwRah61LpdALdzZKLLnU5UAwDztQ5_h0QsT26jk0IFbqcK6-JxhHAm-rsHEwy0CyVJjtnfOcqc1tgA",
|
||||
p256dhPrivateKey: {
|
||||
crv: 'P-256',
|
||||
d: '1jUPhzVsRkzV0vIzwL4ZEsOlKdNOWm7TmaTfzitJkgM',
|
||||
crv: "P-256",
|
||||
d: "1jUPhzVsRkzV0vIzwL4ZEsOlKdNOWm7TmaTfzitJkgM",
|
||||
ext: true,
|
||||
key_ops: ["deriveBits"],
|
||||
kty: "EC",
|
||||
x: '8J3iA1CSPBFqHrUul0At3NkosudTlQDAPO1Dn-HRCxM',
|
||||
y: '26jk0IFbqcK6-JxhHAm-rsHEwy0CyVJjtnfOcqc1tgA'
|
||||
x: "8J3iA1CSPBFqHrUul0At3NkosudTlQDAPO1Dn-HRCxM",
|
||||
y: "26jk0IFbqcK6-JxhHAm-rsHEwy0CyVJjtnfOcqc1tgA",
|
||||
},
|
||||
originAttributes: ChromeUtils.originAttributesToSuffix(
|
||||
{ appId: Ci.nsIScriptSecurityManager.NO_APP_ID, inIsolatedMozBrowser: false }),
|
||||
quota: Infinity,
|
||||
systemRecord: true,
|
||||
}, {
|
||||
subscriptionUri: serverURL + '/pushNotifications/subscription2',
|
||||
pushEndpoint: serverURL + '/pushEndpoint2',
|
||||
pushReceiptEndpoint: serverURL + '/pushReceiptEndpoint2',
|
||||
scope: 'https://example.com/page/2',
|
||||
p256dhPublicKey: 'BPnWyUo7yMnuMlyKtERuLfWE8a09dtdjHSW2lpC9_BqR5TZ1rK8Ldih6ljyxVwnBA-nygQHGRpEmu1jV5K8437E',
|
||||
subscriptionUri: serverURL + "/pushNotifications/subscription2",
|
||||
pushEndpoint: serverURL + "/pushEndpoint2",
|
||||
pushReceiptEndpoint: serverURL + "/pushReceiptEndpoint2",
|
||||
scope: "https://example.com/page/2",
|
||||
p256dhPublicKey: "BPnWyUo7yMnuMlyKtERuLfWE8a09dtdjHSW2lpC9_BqR5TZ1rK8Ldih6ljyxVwnBA-nygQHGRpEmu1jV5K8437E",
|
||||
p256dhPrivateKey: {
|
||||
crv: 'P-256',
|
||||
d: 'lFm4nPsUKYgNGBJb5nXXKxl8bspCSp0bAhCYxbveqT4',
|
||||
crv: "P-256",
|
||||
d: "lFm4nPsUKYgNGBJb5nXXKxl8bspCSp0bAhCYxbveqT4",
|
||||
ext: true,
|
||||
key_ops: ["deriveBits"],
|
||||
kty: 'EC',
|
||||
x: '-dbJSjvIye4yXIq0RG4t9YTxrT1212MdJbaWkL38GpE',
|
||||
y: '5TZ1rK8Ldih6ljyxVwnBA-nygQHGRpEmu1jV5K8437E'
|
||||
kty: "EC",
|
||||
x: "-dbJSjvIye4yXIq0RG4t9YTxrT1212MdJbaWkL38GpE",
|
||||
y: "5TZ1rK8Ldih6ljyxVwnBA-nygQHGRpEmu1jV5K8437E",
|
||||
},
|
||||
originAttributes: ChromeUtils.originAttributesToSuffix(
|
||||
{ appId: Ci.nsIScriptSecurityManager.NO_APP_ID, inIsolatedMozBrowser: false }),
|
||||
quota: Infinity,
|
||||
systemRecord: true,
|
||||
}, {
|
||||
subscriptionUri: serverURL + '/pushNotifications/subscription3',
|
||||
pushEndpoint: serverURL + '/pushEndpoint3',
|
||||
pushReceiptEndpoint: serverURL + '/pushReceiptEndpoint3',
|
||||
scope: 'https://example.com/page/3',
|
||||
p256dhPublicKey: 'BDhUHITSeVrWYybFnb7ylVTCDDLPdQWMpf8gXhcWwvaaJa6n3YH8TOcH8narDF6t8mKVvg2ioLW-8MH5O4dzGcI',
|
||||
subscriptionUri: serverURL + "/pushNotifications/subscription3",
|
||||
pushEndpoint: serverURL + "/pushEndpoint3",
|
||||
pushReceiptEndpoint: serverURL + "/pushReceiptEndpoint3",
|
||||
scope: "https://example.com/page/3",
|
||||
p256dhPublicKey: "BDhUHITSeVrWYybFnb7ylVTCDDLPdQWMpf8gXhcWwvaaJa6n3YH8TOcH8narDF6t8mKVvg2ioLW-8MH5O4dzGcI",
|
||||
p256dhPrivateKey: {
|
||||
crv: 'P-256',
|
||||
d: 'Q1_SE1NySTYzjbqgWwPgrYh7XRg3adqZLkQPsy319G8',
|
||||
crv: "P-256",
|
||||
d: "Q1_SE1NySTYzjbqgWwPgrYh7XRg3adqZLkQPsy319G8",
|
||||
ext: true,
|
||||
key_ops: ["deriveBits"],
|
||||
kty: 'EC',
|
||||
x: 'OFQchNJ5WtZjJsWdvvKVVMIMMs91BYyl_yBeFxbC9po',
|
||||
y: 'Ja6n3YH8TOcH8narDF6t8mKVvg2ioLW-8MH5O4dzGcI'
|
||||
kty: "EC",
|
||||
x: "OFQchNJ5WtZjJsWdvvKVVMIMMs91BYyl_yBeFxbC9po",
|
||||
y: "Ja6n3YH8TOcH8narDF6t8mKVvg2ioLW-8MH5O4dzGcI",
|
||||
},
|
||||
originAttributes: ChromeUtils.originAttributesToSuffix(
|
||||
{ appId: Ci.nsIScriptSecurityManager.NO_APP_ID, inIsolatedMozBrowser: false }),
|
||||
quota: Infinity,
|
||||
systemRecord: true,
|
||||
}, {
|
||||
subscriptionUri: serverURL + '/pushNotifications/subscription4',
|
||||
pushEndpoint: serverURL + '/pushEndpoint4',
|
||||
pushReceiptEndpoint: serverURL + '/pushReceiptEndpoint4',
|
||||
scope: 'https://example.com/page/4',
|
||||
p256dhPublicKey: ChromeUtils.base64URLDecode('BEcvDzkWCrUtjU_wygL98sbQCQrW1lY9irtgGnlCc4B0JJXLCHB9MTM73qD6GZYfL0YOvKo8XLOflh-J4dMGklU', {
|
||||
subscriptionUri: serverURL + "/pushNotifications/subscription4",
|
||||
pushEndpoint: serverURL + "/pushEndpoint4",
|
||||
pushReceiptEndpoint: serverURL + "/pushReceiptEndpoint4",
|
||||
scope: "https://example.com/page/4",
|
||||
p256dhPublicKey: ChromeUtils.base64URLDecode("BEcvDzkWCrUtjU_wygL98sbQCQrW1lY9irtgGnlCc4B0JJXLCHB9MTM73qD6GZYfL0YOvKo8XLOflh-J4dMGklU", {
|
||||
padding: "reject",
|
||||
}),
|
||||
p256dhPrivateKey: {
|
||||
crv: 'P-256',
|
||||
d: 'fWi7tZaX0Pk6WnLrjQ3kiRq_g5XStL5pdH4pllNCqXw',
|
||||
crv: "P-256",
|
||||
d: "fWi7tZaX0Pk6WnLrjQ3kiRq_g5XStL5pdH4pllNCqXw",
|
||||
ext: true,
|
||||
key_ops: ["deriveBits"],
|
||||
kty: 'EC',
|
||||
x: 'Ry8PORYKtS2NT_DKAv3yxtAJCtbWVj2Ku2AaeUJzgHQ',
|
||||
y: 'JJXLCHB9MTM73qD6GZYfL0YOvKo8XLOflh-J4dMGklU'
|
||||
kty: "EC",
|
||||
x: "Ry8PORYKtS2NT_DKAv3yxtAJCtbWVj2Ku2AaeUJzgHQ",
|
||||
y: "JJXLCHB9MTM73qD6GZYfL0YOvKo8XLOflh-J4dMGklU",
|
||||
},
|
||||
authenticationSecret: ChromeUtils.base64URLDecode('cwDVC1iwAn8E37mkR3tMSg', {
|
||||
authenticationSecret: ChromeUtils.base64URLDecode("cwDVC1iwAn8E37mkR3tMSg", {
|
||||
padding: "reject",
|
||||
}),
|
||||
originAttributes: ChromeUtils.originAttributesToSuffix(
|
||||
|
@ -139,37 +134,41 @@ add_task(async function test_pushNotifications() {
|
|||
let notifyPromise = Promise.all([
|
||||
promiseObserverNotification(PushServiceComponent.pushTopic, function(subject, data) {
|
||||
var message = subject.QueryInterface(Ci.nsIPushMessage).data;
|
||||
if (message && (data == "https://example.com/page/1")){
|
||||
if (message && (data == "https://example.com/page/1")) {
|
||||
equal(message.text(), "Some message", "decoded message is incorrect");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}),
|
||||
promiseObserverNotification(PushServiceComponent.pushTopic, function(subject, data) {
|
||||
var message = subject.QueryInterface(Ci.nsIPushMessage).data;
|
||||
if (message && (data == "https://example.com/page/2")){
|
||||
if (message && (data == "https://example.com/page/2")) {
|
||||
equal(message.text(), "Some message", "decoded message is incorrect");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}),
|
||||
promiseObserverNotification(PushServiceComponent.pushTopic, function(subject, data) {
|
||||
var message = subject.QueryInterface(Ci.nsIPushMessage).data;
|
||||
if (message && (data == "https://example.com/page/3")){
|
||||
if (message && (data == "https://example.com/page/3")) {
|
||||
equal(message.text(), "Some message", "decoded message is incorrect");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}),
|
||||
promiseObserverNotification(PushServiceComponent.pushTopic, function(subject, data) {
|
||||
var message = subject.QueryInterface(Ci.nsIPushMessage).data;
|
||||
if (message && (data == "https://example.com/page/4")){
|
||||
if (message && (data == "https://example.com/page/4")) {
|
||||
equal(message.text(), "Yet another message", "decoded message is incorrect");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}),
|
||||
]);
|
||||
|
||||
PushService.init({
|
||||
serverURI: serverURL,
|
||||
db
|
||||
db,
|
||||
});
|
||||
|
||||
await notifyPromise;
|
||||
|
|
|
@ -1,50 +1,50 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
'use strict';
|
||||
"use strict";
|
||||
|
||||
const {PushDB, PushService, PushServiceWebSocket} = serviceExports;
|
||||
|
||||
const userAgentID = '1ca1cf66-eeb4-4df7-87c1-d5c92906ab90';
|
||||
const userAgentID = "1ca1cf66-eeb4-4df7-87c1-d5c92906ab90";
|
||||
|
||||
function run_test() {
|
||||
do_get_profile();
|
||||
setPrefs({
|
||||
userAgentID: userAgentID,
|
||||
userAgentID,
|
||||
});
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
add_task(async function test_notification_incomplete() {
|
||||
let db = PushServiceWebSocket.newPushDB();
|
||||
registerCleanupFunction(() => {return db.drop().then(_ => db.close());});
|
||||
registerCleanupFunction(() => { return db.drop().then(_ => db.close()); });
|
||||
let records = [{
|
||||
channelID: '123',
|
||||
pushEndpoint: 'https://example.org/update/1',
|
||||
scope: 'https://example.com/page/1',
|
||||
channelID: "123",
|
||||
pushEndpoint: "https://example.org/update/1",
|
||||
scope: "https://example.com/page/1",
|
||||
version: 1,
|
||||
originAttributes: '',
|
||||
originAttributes: "",
|
||||
quota: Infinity,
|
||||
}, {
|
||||
channelID: '3ad1ed95-d37a-4d88-950f-22cbe2e240d7',
|
||||
pushEndpoint: 'https://example.org/update/2',
|
||||
scope: 'https://example.com/page/2',
|
||||
channelID: "3ad1ed95-d37a-4d88-950f-22cbe2e240d7",
|
||||
pushEndpoint: "https://example.org/update/2",
|
||||
scope: "https://example.com/page/2",
|
||||
version: 1,
|
||||
originAttributes: '',
|
||||
originAttributes: "",
|
||||
quota: Infinity,
|
||||
}, {
|
||||
channelID: 'd239498b-1c85-4486-b99b-205866e82d1f',
|
||||
pushEndpoint: 'https://example.org/update/3',
|
||||
scope: 'https://example.com/page/3',
|
||||
channelID: "d239498b-1c85-4486-b99b-205866e82d1f",
|
||||
pushEndpoint: "https://example.org/update/3",
|
||||
scope: "https://example.com/page/3",
|
||||
version: 3,
|
||||
originAttributes: '',
|
||||
originAttributes: "",
|
||||
quota: Infinity,
|
||||
}, {
|
||||
channelID: 'a50de97d-b496-43ce-8b53-05522feb78db',
|
||||
pushEndpoint: 'https://example.org/update/4',
|
||||
scope: 'https://example.com/page/4',
|
||||
channelID: "a50de97d-b496-43ce-8b53-05522feb78db",
|
||||
pushEndpoint: "https://example.org/update/4",
|
||||
scope: "https://example.com/page/4",
|
||||
version: 10,
|
||||
originAttributes: '',
|
||||
originAttributes: "",
|
||||
quota: Infinity,
|
||||
}];
|
||||
for (let record of records) {
|
||||
|
@ -52,7 +52,7 @@ add_task(async function test_notification_incomplete() {
|
|||
}
|
||||
|
||||
function observeMessage(subject, topic, data) {
|
||||
ok(false, 'Should not deliver malformed updates');
|
||||
ok(false, "Should not deliver malformed updates");
|
||||
}
|
||||
registerCleanupFunction(() =>
|
||||
Services.obs.removeObserver(observeMessage, PushServiceComponent.pushTopic));
|
||||
|
@ -72,39 +72,39 @@ add_task(async function test_notification_incomplete() {
|
|||
return new MockWebSocket(uri, {
|
||||
onHello(request) {
|
||||
this.serverSendMsg(JSON.stringify({
|
||||
messageType: 'hello',
|
||||
messageType: "hello",
|
||||
status: 200,
|
||||
uaid: userAgentID,
|
||||
}));
|
||||
this.serverSendMsg(JSON.stringify({
|
||||
// Missing "updates" field; should ignore message.
|
||||
messageType: 'notification'
|
||||
messageType: "notification",
|
||||
}));
|
||||
this.serverSendMsg(JSON.stringify({
|
||||
messageType: 'notification',
|
||||
messageType: "notification",
|
||||
updates: [{
|
||||
// Wrong channel ID field type.
|
||||
channelID: 123,
|
||||
version: 3
|
||||
version: 3,
|
||||
}, {
|
||||
// Missing version field.
|
||||
channelID: '3ad1ed95-d37a-4d88-950f-22cbe2e240d7'
|
||||
channelID: "3ad1ed95-d37a-4d88-950f-22cbe2e240d7",
|
||||
}, {
|
||||
// Wrong version field type.
|
||||
channelID: 'd239498b-1c85-4486-b99b-205866e82d1f',
|
||||
version: true
|
||||
channelID: "d239498b-1c85-4486-b99b-205866e82d1f",
|
||||
version: true,
|
||||
}, {
|
||||
// Negative versions should be ignored.
|
||||
channelID: 'a50de97d-b496-43ce-8b53-05522feb78db',
|
||||
version: -5
|
||||
}]
|
||||
channelID: "a50de97d-b496-43ce-8b53-05522feb78db",
|
||||
version: -5,
|
||||
}],
|
||||
}));
|
||||
},
|
||||
onACK() {
|
||||
ok(false, 'Should not acknowledge malformed updates');
|
||||
}
|
||||
ok(false, "Should not acknowledge malformed updates");
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
await notificationPromise;
|
||||
|
@ -116,14 +116,14 @@ add_task(async function test_notification_incomplete() {
|
|||
});
|
||||
|
||||
function recordIsEqual(a, b) {
|
||||
strictEqual(a.channelID, b.channelID, 'Wrong channel ID in record');
|
||||
strictEqual(a.pushEndpoint, b.pushEndpoint, 'Wrong push endpoint in record');
|
||||
strictEqual(a.scope, b.scope, 'Wrong scope in record');
|
||||
strictEqual(a.version, b.version, 'Wrong version in record');
|
||||
strictEqual(a.channelID, b.channelID, "Wrong channel ID in record");
|
||||
strictEqual(a.pushEndpoint, b.pushEndpoint, "Wrong push endpoint in record");
|
||||
strictEqual(a.scope, b.scope, "Wrong scope in record");
|
||||
strictEqual(a.version, b.version, "Wrong version in record");
|
||||
}
|
||||
|
||||
function recordsAreEqual(a, b) {
|
||||
equal(a.length, b.length, 'Mismatched record count');
|
||||
equal(a.length, b.length, "Mismatched record count");
|
||||
for (let i = 0; i < a.length; i++) {
|
||||
recordIsEqual(a[i], b[i]);
|
||||
}
|
||||
|
|
|
@ -1,28 +1,28 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
'use strict';
|
||||
"use strict";
|
||||
|
||||
const {PushDB, PushService, PushServiceWebSocket} = serviceExports;
|
||||
|
||||
const userAgentID = 'ba31ac13-88d4-4984-8e6b-8731315a7cf8';
|
||||
const userAgentID = "ba31ac13-88d4-4984-8e6b-8731315a7cf8";
|
||||
|
||||
function run_test() {
|
||||
do_get_profile();
|
||||
setPrefs({
|
||||
userAgentID: userAgentID,
|
||||
userAgentID,
|
||||
});
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
add_task(async function test_notification_version_string() {
|
||||
let db = PushServiceWebSocket.newPushDB();
|
||||
registerCleanupFunction(() => {return db.drop().then(_ => db.close());});
|
||||
registerCleanupFunction(() => { return db.drop().then(_ => db.close()); });
|
||||
await db.put({
|
||||
channelID: '6ff97d56-d0c0-43bc-8f5b-61b855e1d93b',
|
||||
pushEndpoint: 'https://example.org/updates/1',
|
||||
scope: 'https://example.com/page/1',
|
||||
originAttributes: '',
|
||||
channelID: "6ff97d56-d0c0-43bc-8f5b-61b855e1d93b",
|
||||
pushEndpoint: "https://example.org/updates/1",
|
||||
scope: "https://example.com/page/1",
|
||||
originAttributes: "",
|
||||
version: 2,
|
||||
quota: Infinity,
|
||||
systemRecord: true,
|
||||
|
@ -39,31 +39,31 @@ add_task(async function test_notification_version_string() {
|
|||
return new MockWebSocket(uri, {
|
||||
onHello(request) {
|
||||
this.serverSendMsg(JSON.stringify({
|
||||
messageType: 'hello',
|
||||
messageType: "hello",
|
||||
status: 200,
|
||||
uaid: userAgentID,
|
||||
}));
|
||||
this.serverSendMsg(JSON.stringify({
|
||||
messageType: 'notification',
|
||||
messageType: "notification",
|
||||
updates: [{
|
||||
channelID: '6ff97d56-d0c0-43bc-8f5b-61b855e1d93b',
|
||||
version: '4'
|
||||
}]
|
||||
channelID: "6ff97d56-d0c0-43bc-8f5b-61b855e1d93b",
|
||||
version: "4",
|
||||
}],
|
||||
}));
|
||||
},
|
||||
onACK: ackDone
|
||||
onACK: ackDone,
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
let {subject: message, data: scope} = await notifyPromise;
|
||||
let {subject: message} = await notifyPromise;
|
||||
equal(message.QueryInterface(Ci.nsIPushMessage).data, null,
|
||||
'Unexpected data for Simple Push message');
|
||||
"Unexpected data for Simple Push message");
|
||||
|
||||
await ackPromise;
|
||||
|
||||
let storeRecord = await db.getByKeyID(
|
||||
'6ff97d56-d0c0-43bc-8f5b-61b855e1d93b');
|
||||
strictEqual(storeRecord.version, 4, 'Wrong record version');
|
||||
equal(storeRecord.quota, Infinity, 'Wrong quota');
|
||||
"6ff97d56-d0c0-43bc-8f5b-61b855e1d93b");
|
||||
strictEqual(storeRecord.version, 4, "Wrong record version");
|
||||
equal(storeRecord.quota, Infinity, "Wrong quota");
|
||||
});
|
||||
|
|
|
@ -1,43 +1,39 @@
|
|||
'use strict';
|
||||
"use strict";
|
||||
|
||||
var pushNotifier = Cc['@mozilla.org/push/Notifier;1']
|
||||
var pushNotifier = Cc["@mozilla.org/push/Notifier;1"]
|
||||
.getService(Ci.nsIPushNotifier);
|
||||
var systemPrincipal = Services.scriptSecurityManager.getSystemPrincipal();
|
||||
|
||||
function run_test() {
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
add_task(async function test_notifyWithData() {
|
||||
let textData = '{"hello":"world"}';
|
||||
let payload = new TextEncoder('utf-8').encode(textData);
|
||||
let payload = new TextEncoder("utf-8").encode(textData);
|
||||
|
||||
let notifyPromise =
|
||||
promiseObserverNotification(PushServiceComponent.pushTopic);
|
||||
pushNotifier.notifyPushWithData('chrome://notify-test', systemPrincipal,
|
||||
'' /* messageId */, payload.length, payload);
|
||||
pushNotifier.notifyPushWithData("chrome://notify-test", systemPrincipal,
|
||||
"" /* messageId */, payload.length, payload);
|
||||
|
||||
let data = (await notifyPromise).subject.QueryInterface(
|
||||
Ci.nsIPushMessage).data;
|
||||
deepEqual(data.json(), {
|
||||
hello: 'world',
|
||||
}, 'Should extract JSON values');
|
||||
hello: "world",
|
||||
}, "Should extract JSON values");
|
||||
deepEqual(data.binary(), Array.from(payload),
|
||||
'Should extract raw binary data');
|
||||
equal(data.text(), textData, 'Should extract text data');
|
||||
"Should extract raw binary data");
|
||||
equal(data.text(), textData, "Should extract text data");
|
||||
});
|
||||
|
||||
add_task(async function test_empty_notifyWithData() {
|
||||
let notifyPromise =
|
||||
promiseObserverNotification(PushServiceComponent.pushTopic);
|
||||
pushNotifier.notifyPushWithData('chrome://notify-test', systemPrincipal,
|
||||
'' /* messageId */, 0, null);
|
||||
pushNotifier.notifyPushWithData("chrome://notify-test", systemPrincipal,
|
||||
"" /* messageId */, 0, null);
|
||||
|
||||
let data = (await notifyPromise).subject.QueryInterface(
|
||||
Ci.nsIPushMessage).data;
|
||||
throws(_ => data.json(),
|
||||
/InvalidStateError/,
|
||||
'Should throw an error when parsing an empty string as JSON');
|
||||
strictEqual(data.text(), '', 'Should return an empty string');
|
||||
deepEqual(data.binary(), [], 'Should return an empty array');
|
||||
"Should throw an error when parsing an empty string as JSON");
|
||||
strictEqual(data.text(), "", "Should return an empty string");
|
||||
deepEqual(data.binary(), [], "Should return an empty array");
|
||||
});
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
'use strict';
|
||||
"use strict";
|
||||
|
||||
const pushNotifier = Cc['@mozilla.org/push/Notifier;1']
|
||||
const pushNotifier = Cc["@mozilla.org/push/Notifier;1"]
|
||||
.getService(Ci.nsIPushNotifier);
|
||||
|
||||
add_task(async function test_observer_remoting() {
|
||||
|
@ -13,12 +13,12 @@ add_task(async function test_observer_remoting() {
|
|||
});
|
||||
|
||||
const childTests = [{
|
||||
text: 'Hello from child!',
|
||||
text: "Hello from child!",
|
||||
principal: Services.scriptSecurityManager.getSystemPrincipal(),
|
||||
}];
|
||||
|
||||
const parentTests = [{
|
||||
text: 'Hello from parent!',
|
||||
text: "Hello from parent!",
|
||||
principal: Services.scriptSecurityManager.getSystemPrincipal(),
|
||||
}];
|
||||
|
||||
|
@ -30,11 +30,11 @@ async function testInParent() {
|
|||
(p, test) => p.then(_ => waitForNotifierObservers(test, /* shouldNotify = */ false)),
|
||||
Promise.resolve()
|
||||
);
|
||||
let promiseFinished = run_test_in_child('./test_observer_remoting.js');
|
||||
let promiseFinished = run_test_in_child("./test_observer_remoting.js");
|
||||
await promiseNotifications;
|
||||
|
||||
// Wait until the child is listening for notifications from the parent.
|
||||
await do_await_remote_message('push_test_observer_remoting_child_ready');
|
||||
await do_await_remote_message("push_test_observer_remoting_child_ready");
|
||||
|
||||
// Fire an observer notification in the parent that should be forwarded to
|
||||
// the child.
|
||||
|
@ -61,7 +61,7 @@ async function testInChild() {
|
|||
(p, test) => p.then(_ => waitForNotifierObservers(test, /* shouldNotify = */ false)),
|
||||
Promise.resolve()
|
||||
);
|
||||
do_send_remote_message('push_test_observer_remoting_child_ready');
|
||||
do_send_remote_message("push_test_observer_remoting_child_ready");
|
||||
await promiseNotifierObservers;
|
||||
}
|
||||
|
||||
|
@ -73,11 +73,11 @@ var waitForNotifierObservers = async function({ text, principal }, shouldNotify
|
|||
let subModifiedPromise = promiseObserverNotification(
|
||||
PushServiceComponent.subscriptionModifiedTopic);
|
||||
|
||||
let scope = 'chrome://test-scope';
|
||||
let data = new TextEncoder('utf-8').encode(text);
|
||||
let scope = "chrome://test-scope";
|
||||
let data = new TextEncoder("utf-8").encode(text);
|
||||
|
||||
if (shouldNotify) {
|
||||
pushNotifier.notifyPushWithData(scope, principal, '', data.length, data);
|
||||
pushNotifier.notifyPushWithData(scope, principal, "", data.length, data);
|
||||
pushNotifier.notifySubscriptionChange(scope, principal);
|
||||
pushNotifier.notifySubscriptionModified(scope, principal);
|
||||
}
|
||||
|
@ -87,27 +87,27 @@ var waitForNotifierObservers = async function({ text, principal }, shouldNotify
|
|||
subject: notifySubject,
|
||||
} = await notifyPromise;
|
||||
equal(notifyScope, scope,
|
||||
'Should fire push notifications with the correct scope');
|
||||
"Should fire push notifications with the correct scope");
|
||||
let message = notifySubject.QueryInterface(Ci.nsIPushMessage);
|
||||
equal(message.principal, principal,
|
||||
'Should include the principal in the push message');
|
||||
strictEqual(message.data.text(), text, 'Should include data');
|
||||
"Should include the principal in the push message");
|
||||
strictEqual(message.data.text(), text, "Should include data");
|
||||
|
||||
let {
|
||||
data: subChangeScope,
|
||||
subject: subChangePrincipal,
|
||||
} = await subChangePromise;
|
||||
equal(subChangeScope, scope,
|
||||
'Should fire subscription change notifications with the correct scope');
|
||||
"Should fire subscription change notifications with the correct scope");
|
||||
equal(subChangePrincipal, principal,
|
||||
'Should pass the principal as the subject of a change notification');
|
||||
"Should pass the principal as the subject of a change notification");
|
||||
|
||||
let {
|
||||
data: subModifiedScope,
|
||||
subject: subModifiedPrincipal,
|
||||
} = await subModifiedPromise;
|
||||
equal(subModifiedScope, scope,
|
||||
'Should fire subscription modified notifications with the correct scope');
|
||||
"Should fire subscription modified notifications with the correct scope");
|
||||
equal(subModifiedPrincipal, principal,
|
||||
'Should pass the principal as the subject of a modified notification');
|
||||
"Should pass the principal as the subject of a modified notification");
|
||||
};
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
'use strict';
|
||||
"use strict";
|
||||
|
||||
const {PushDB, PushService, PushServiceWebSocket} = serviceExports;
|
||||
|
||||
const userAgentID = '2c43af06-ab6e-476a-adc4-16cbda54fb89';
|
||||
const userAgentID = "2c43af06-ab6e-476a-adc4-16cbda54fb89";
|
||||
|
||||
let db;
|
||||
|
||||
|
@ -16,7 +16,7 @@ function run_test() {
|
|||
});
|
||||
|
||||
db = PushServiceWebSocket.newPushDB();
|
||||
registerCleanupFunction(() => {return db.drop().then(_ => db.close());});
|
||||
registerCleanupFunction(() => { return db.drop().then(_ => db.close()); });
|
||||
|
||||
run_next_test();
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ function makePushPermission(url, capability) {
|
|||
principal: Services.scriptSecurityManager.createCodebasePrincipal(
|
||||
Services.io.newURI(url), {}
|
||||
),
|
||||
type: 'desktop-notification',
|
||||
type: "desktop-notification",
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -70,43 +70,43 @@ function allExpired(...keyIDs) {
|
|||
add_task(async function setUp() {
|
||||
// Active registration; quota should be reset to 16. Since the quota isn't
|
||||
// exposed to content, we shouldn't receive a subscription change event.
|
||||
await putTestRecord(db, 'active-allow', 'https://example.info/page/1', 8);
|
||||
await putTestRecord(db, "active-allow", "https://example.info/page/1", 8);
|
||||
|
||||
// Expired registration; should be dropped.
|
||||
await putTestRecord(db, 'expired-allow', 'https://example.info/page/2', 0);
|
||||
await putTestRecord(db, "expired-allow", "https://example.info/page/2", 0);
|
||||
|
||||
// Active registration; should be expired when we change the permission
|
||||
// to "deny".
|
||||
await putTestRecord(db, 'active-deny-changed', 'https://example.xyz/page/1', 16);
|
||||
await putTestRecord(db, "active-deny-changed", "https://example.xyz/page/1", 16);
|
||||
|
||||
// Two active registrations for a visited site. These will expire when we
|
||||
// add a "deny" permission.
|
||||
await putTestRecord(db, 'active-deny-added-1', 'https://example.net/ham', 16);
|
||||
await putTestRecord(db, 'active-deny-added-2', 'https://example.net/green', 8);
|
||||
await putTestRecord(db, "active-deny-added-1", "https://example.net/ham", 16);
|
||||
await putTestRecord(db, "active-deny-added-2", "https://example.net/green", 8);
|
||||
|
||||
// An already-expired registration for a visited site. We shouldn't send an
|
||||
// `unregister` request for this one, but still receive an observer
|
||||
// notification when we restore permissions.
|
||||
await putTestRecord(db, 'expired-deny-added', 'https://example.net/eggs', 0);
|
||||
await putTestRecord(db, "expired-deny-added", "https://example.net/eggs", 0);
|
||||
|
||||
// A registration that should not be affected by permission list changes
|
||||
// because its quota is set to `Infinity`.
|
||||
await putTestRecord(db, 'never-expires', 'app://chrome/only', Infinity);
|
||||
await putTestRecord(db, "never-expires", "app://chrome/only", Infinity);
|
||||
|
||||
// A registration that should be dropped when we clear the permission
|
||||
// list.
|
||||
await putTestRecord(db, 'drop-on-clear', 'https://example.edu/lonely', 16);
|
||||
await putTestRecord(db, "drop-on-clear", "https://example.edu/lonely", 16);
|
||||
|
||||
let handshakeDone;
|
||||
let handshakePromise = new Promise(resolve => handshakeDone = resolve);
|
||||
PushService.init({
|
||||
serverURI: 'wss://push.example.org/',
|
||||
serverURI: "wss://push.example.org/",
|
||||
db,
|
||||
makeWebSocket(uri) {
|
||||
return new MockWebSocket(uri, {
|
||||
onHello(request) {
|
||||
this.serverSendMsg(JSON.stringify({
|
||||
messageType: 'hello',
|
||||
messageType: "hello",
|
||||
status: 200,
|
||||
uaid: userAgentID,
|
||||
}));
|
||||
|
@ -114,21 +114,21 @@ add_task(async function setUp() {
|
|||
},
|
||||
onUnregister(request) {
|
||||
let resolve = unregisterDefers[request.channelID];
|
||||
equal(typeof resolve, 'function',
|
||||
'Dropped unexpected channel ID ' + request.channelID);
|
||||
equal(typeof resolve, "function",
|
||||
"Dropped unexpected channel ID " + request.channelID);
|
||||
delete unregisterDefers[request.channelID];
|
||||
equal(request.code, 202,
|
||||
'Expected permission revoked unregister reason');
|
||||
"Expected permission revoked unregister reason");
|
||||
resolve();
|
||||
this.serverSendMsg(JSON.stringify({
|
||||
messageType: 'unregister',
|
||||
messageType: "unregister",
|
||||
status: 200,
|
||||
channelID: request.channelID,
|
||||
}));
|
||||
},
|
||||
onACK(request) {},
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
await handshakePromise;
|
||||
});
|
||||
|
@ -137,160 +137,160 @@ add_task(async function test_permissions_allow_added() {
|
|||
let subChangePromise = promiseSubscriptionChanges(1);
|
||||
|
||||
await PushService._onPermissionChange(
|
||||
makePushPermission('https://example.info', 'ALLOW_ACTION'),
|
||||
'added'
|
||||
makePushPermission("https://example.info", "ALLOW_ACTION"),
|
||||
"added"
|
||||
);
|
||||
let notifiedScopes = await subChangePromise;
|
||||
|
||||
deepEqual(notifiedScopes, [
|
||||
'https://example.info/page/2',
|
||||
], 'Wrong scopes after adding allow');
|
||||
"https://example.info/page/2",
|
||||
], "Wrong scopes after adding allow");
|
||||
|
||||
let record = await db.getByKeyID('active-allow');
|
||||
let record = await db.getByKeyID("active-allow");
|
||||
equal(record.quota, 16,
|
||||
'Should reset quota for active records after adding allow');
|
||||
"Should reset quota for active records after adding allow");
|
||||
|
||||
record = await db.getByKeyID('expired-allow');
|
||||
ok(!record, 'Should drop expired records after adding allow');
|
||||
record = await db.getByKeyID("expired-allow");
|
||||
ok(!record, "Should drop expired records after adding allow");
|
||||
});
|
||||
|
||||
add_task(async function test_permissions_allow_deleted() {
|
||||
let subModifiedPromise = promiseSubscriptionModifications(1);
|
||||
|
||||
let unregisterPromise = promiseUnregister('active-allow');
|
||||
let unregisterPromise = promiseUnregister("active-allow");
|
||||
|
||||
await PushService._onPermissionChange(
|
||||
makePushPermission('https://example.info', 'ALLOW_ACTION'),
|
||||
'deleted'
|
||||
makePushPermission("https://example.info", "ALLOW_ACTION"),
|
||||
"deleted"
|
||||
);
|
||||
|
||||
await unregisterPromise;
|
||||
|
||||
let notifiedScopes = await subModifiedPromise;
|
||||
deepEqual(notifiedScopes, [
|
||||
'https://example.info/page/1',
|
||||
], 'Wrong scopes modified after deleting allow');
|
||||
"https://example.info/page/1",
|
||||
], "Wrong scopes modified after deleting allow");
|
||||
|
||||
let record = await db.getByKeyID('active-allow');
|
||||
let record = await db.getByKeyID("active-allow");
|
||||
ok(record.isExpired(),
|
||||
'Should expire active record after deleting allow');
|
||||
"Should expire active record after deleting allow");
|
||||
});
|
||||
|
||||
add_task(async function test_permissions_deny_added() {
|
||||
let subModifiedPromise = promiseSubscriptionModifications(2);
|
||||
|
||||
let unregisterPromise = Promise.all([
|
||||
promiseUnregister('active-deny-added-1'),
|
||||
promiseUnregister('active-deny-added-2'),
|
||||
promiseUnregister("active-deny-added-1"),
|
||||
promiseUnregister("active-deny-added-2"),
|
||||
]);
|
||||
|
||||
await PushService._onPermissionChange(
|
||||
makePushPermission('https://example.net', 'DENY_ACTION'),
|
||||
'added'
|
||||
makePushPermission("https://example.net", "DENY_ACTION"),
|
||||
"added"
|
||||
);
|
||||
await unregisterPromise;
|
||||
|
||||
let notifiedScopes = await subModifiedPromise;
|
||||
deepEqual(notifiedScopes, [
|
||||
'https://example.net/green',
|
||||
'https://example.net/ham',
|
||||
], 'Wrong scopes modified after adding deny');
|
||||
"https://example.net/green",
|
||||
"https://example.net/ham",
|
||||
], "Wrong scopes modified after adding deny");
|
||||
|
||||
let isExpired = await allExpired(
|
||||
'active-deny-added-1',
|
||||
'expired-deny-added'
|
||||
"active-deny-added-1",
|
||||
"expired-deny-added"
|
||||
);
|
||||
ok(isExpired, 'Should expire all registrations after adding deny');
|
||||
ok(isExpired, "Should expire all registrations after adding deny");
|
||||
});
|
||||
|
||||
add_task(async function test_permissions_deny_deleted() {
|
||||
await PushService._onPermissionChange(
|
||||
makePushPermission('https://example.net', 'DENY_ACTION'),
|
||||
'deleted'
|
||||
makePushPermission("https://example.net", "DENY_ACTION"),
|
||||
"deleted"
|
||||
);
|
||||
|
||||
let isExpired = await allExpired(
|
||||
'active-deny-added-1',
|
||||
'expired-deny-added'
|
||||
"active-deny-added-1",
|
||||
"expired-deny-added"
|
||||
);
|
||||
ok(isExpired, 'Should retain expired registrations after deleting deny');
|
||||
ok(isExpired, "Should retain expired registrations after deleting deny");
|
||||
});
|
||||
|
||||
add_task(async function test_permissions_allow_changed() {
|
||||
let subChangePromise = promiseSubscriptionChanges(3);
|
||||
|
||||
await PushService._onPermissionChange(
|
||||
makePushPermission('https://example.net', 'ALLOW_ACTION'),
|
||||
'changed'
|
||||
makePushPermission("https://example.net", "ALLOW_ACTION"),
|
||||
"changed"
|
||||
);
|
||||
|
||||
let notifiedScopes = await subChangePromise;
|
||||
|
||||
deepEqual(notifiedScopes, [
|
||||
'https://example.net/eggs',
|
||||
'https://example.net/green',
|
||||
'https://example.net/ham'
|
||||
], 'Wrong scopes after changing to allow');
|
||||
"https://example.net/eggs",
|
||||
"https://example.net/green",
|
||||
"https://example.net/ham",
|
||||
], "Wrong scopes after changing to allow");
|
||||
|
||||
let droppedRecords = await Promise.all([
|
||||
db.getByKeyID('active-deny-added-1'),
|
||||
db.getByKeyID('active-deny-added-2'),
|
||||
db.getByKeyID('expired-deny-added'),
|
||||
db.getByKeyID("active-deny-added-1"),
|
||||
db.getByKeyID("active-deny-added-2"),
|
||||
db.getByKeyID("expired-deny-added"),
|
||||
]);
|
||||
ok(!droppedRecords.some(Boolean),
|
||||
'Should drop all expired registrations after changing to allow');
|
||||
"Should drop all expired registrations after changing to allow");
|
||||
});
|
||||
|
||||
add_task(async function test_permissions_deny_changed() {
|
||||
let subModifiedPromise = promiseSubscriptionModifications(1);
|
||||
|
||||
let unregisterPromise = promiseUnregister('active-deny-changed');
|
||||
let unregisterPromise = promiseUnregister("active-deny-changed");
|
||||
|
||||
await PushService._onPermissionChange(
|
||||
makePushPermission('https://example.xyz', 'DENY_ACTION'),
|
||||
'changed'
|
||||
makePushPermission("https://example.xyz", "DENY_ACTION"),
|
||||
"changed"
|
||||
);
|
||||
|
||||
await unregisterPromise;
|
||||
|
||||
let notifiedScopes = await subModifiedPromise;
|
||||
deepEqual(notifiedScopes, [
|
||||
'https://example.xyz/page/1',
|
||||
], 'Wrong scopes modified after changing to deny');
|
||||
"https://example.xyz/page/1",
|
||||
], "Wrong scopes modified after changing to deny");
|
||||
|
||||
let record = await db.getByKeyID('active-deny-changed');
|
||||
let record = await db.getByKeyID("active-deny-changed");
|
||||
ok(record.isExpired(),
|
||||
'Should expire active record after changing to deny');
|
||||
"Should expire active record after changing to deny");
|
||||
});
|
||||
|
||||
add_task(async function test_permissions_clear() {
|
||||
let subModifiedPromise = promiseSubscriptionModifications(3);
|
||||
|
||||
deepEqual(await getAllKeyIDs(db), [
|
||||
'active-allow',
|
||||
'active-deny-changed',
|
||||
'drop-on-clear',
|
||||
'never-expires',
|
||||
], 'Wrong records in database before clearing');
|
||||
"active-allow",
|
||||
"active-deny-changed",
|
||||
"drop-on-clear",
|
||||
"never-expires",
|
||||
], "Wrong records in database before clearing");
|
||||
|
||||
let unregisterPromise = Promise.all([
|
||||
promiseUnregister('active-allow'),
|
||||
promiseUnregister('active-deny-changed'),
|
||||
promiseUnregister('drop-on-clear'),
|
||||
promiseUnregister("active-allow"),
|
||||
promiseUnregister("active-deny-changed"),
|
||||
promiseUnregister("drop-on-clear"),
|
||||
]);
|
||||
|
||||
await PushService._onPermissionChange(null, 'cleared');
|
||||
await PushService._onPermissionChange(null, "cleared");
|
||||
|
||||
await unregisterPromise;
|
||||
|
||||
let notifiedScopes = await subModifiedPromise;
|
||||
deepEqual(notifiedScopes, [
|
||||
'https://example.edu/lonely',
|
||||
'https://example.info/page/1',
|
||||
'https://example.xyz/page/1',
|
||||
], 'Wrong scopes modified after clearing registrations');
|
||||
"https://example.edu/lonely",
|
||||
"https://example.info/page/1",
|
||||
"https://example.xyz/page/1",
|
||||
], "Wrong scopes modified after clearing registrations");
|
||||
|
||||
deepEqual(await getAllKeyIDs(db), [
|
||||
'never-expires',
|
||||
], 'Unrestricted registrations should not be dropped');
|
||||
"never-expires",
|
||||
], "Unrestricted registrations should not be dropped");
|
||||
});
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
'use strict';
|
||||
"use strict";
|
||||
|
||||
const {PushDB, PushService, PushServiceWebSocket} = serviceExports;
|
||||
|
||||
|
||||
const userAgentID = '7eb873f9-8d47-4218-804b-fff78dc04e88';
|
||||
const userAgentID = "7eb873f9-8d47-4218-804b-fff78dc04e88";
|
||||
|
||||
function run_test() {
|
||||
do_get_profile();
|
||||
setPrefs({
|
||||
userAgentID,
|
||||
'testing.ignorePermission': true,
|
||||
"testing.ignorePermission": true,
|
||||
});
|
||||
run_next_test();
|
||||
}
|
||||
|
@ -22,23 +22,23 @@ add_task(async function test_expiration_origin_threshold() {
|
|||
registerCleanupFunction(() => db.drop().then(_ => db.close()));
|
||||
|
||||
await db.put({
|
||||
channelID: 'eb33fc90-c883-4267-b5cb-613969e8e349',
|
||||
pushEndpoint: 'https://example.org/push/1',
|
||||
scope: 'https://example.com/auctions',
|
||||
channelID: "eb33fc90-c883-4267-b5cb-613969e8e349",
|
||||
pushEndpoint: "https://example.org/push/1",
|
||||
scope: "https://example.com/auctions",
|
||||
pushCount: 0,
|
||||
lastPush: 0,
|
||||
version: null,
|
||||
originAttributes: '',
|
||||
originAttributes: "",
|
||||
quota: 16,
|
||||
});
|
||||
await db.put({
|
||||
channelID: '46cc6f6a-c106-4ffa-bb7c-55c60bd50c41',
|
||||
pushEndpoint: 'https://example.org/push/2',
|
||||
scope: 'https://example.com/deals',
|
||||
channelID: "46cc6f6a-c106-4ffa-bb7c-55c60bd50c41",
|
||||
pushEndpoint: "https://example.org/push/2",
|
||||
scope: "https://example.com/deals",
|
||||
pushCount: 0,
|
||||
lastPush: 0,
|
||||
version: null,
|
||||
originAttributes: '',
|
||||
originAttributes: "",
|
||||
quota: 16,
|
||||
});
|
||||
|
||||
|
@ -46,31 +46,31 @@ add_task(async function test_expiration_origin_threshold() {
|
|||
// workers for different scopes.
|
||||
await PlacesTestUtils.addVisits([
|
||||
{
|
||||
uri: 'https://example.com/login',
|
||||
title: 'Sign in to see your auctions',
|
||||
uri: "https://example.com/login",
|
||||
title: "Sign in to see your auctions",
|
||||
visitDate: (Date.now() - 7 * 24 * 60 * 60 * 1000) * 1000,
|
||||
transition: Ci.nsINavHistoryService.TRANSITION_LINK
|
||||
transition: Ci.nsINavHistoryService.TRANSITION_LINK,
|
||||
},
|
||||
// We'll always use your most recent visit to an origin.
|
||||
{
|
||||
uri: 'https://example.com/auctions',
|
||||
title: 'Your auctions',
|
||||
uri: "https://example.com/auctions",
|
||||
title: "Your auctions",
|
||||
visitDate: (Date.now() - 2 * 24 * 60 * 60 * 1000) * 1000,
|
||||
transition: Ci.nsINavHistoryService.TRANSITION_LINK
|
||||
transition: Ci.nsINavHistoryService.TRANSITION_LINK,
|
||||
},
|
||||
// ...But we won't count downloads or embeds.
|
||||
{
|
||||
uri: 'https://example.com/invoices/invoice.pdf',
|
||||
title: 'Invoice #123',
|
||||
uri: "https://example.com/invoices/invoice.pdf",
|
||||
title: "Invoice #123",
|
||||
visitDate: (Date.now() - 1 * 24 * 60 * 60 * 1000) * 1000,
|
||||
transition: Ci.nsINavHistoryService.TRANSITION_EMBED
|
||||
transition: Ci.nsINavHistoryService.TRANSITION_EMBED,
|
||||
},
|
||||
{
|
||||
uri: 'https://example.com/invoices/invoice.pdf',
|
||||
title: 'Invoice #123',
|
||||
uri: "https://example.com/invoices/invoice.pdf",
|
||||
title: "Invoice #123",
|
||||
visitDate: Date.now() * 1000,
|
||||
transition: Ci.nsINavHistoryService.TRANSITION_DOWNLOAD
|
||||
}
|
||||
transition: Ci.nsINavHistoryService.TRANSITION_DOWNLOAD,
|
||||
},
|
||||
]);
|
||||
|
||||
// We expect to receive 6 notifications: 5 on the `auctions` channel,
|
||||
|
@ -87,13 +87,13 @@ add_task(async function test_expiration_origin_threshold() {
|
|||
let unregisterPromise = new Promise(resolve => unregisterDone = resolve);
|
||||
|
||||
PushService.init({
|
||||
serverURI: 'wss://push.example.org/',
|
||||
serverURI: "wss://push.example.org/",
|
||||
db,
|
||||
makeWebSocket(uri) {
|
||||
return new MockWebSocket(uri, {
|
||||
onHello(request) {
|
||||
this.serverSendMsg(JSON.stringify({
|
||||
messageType: 'hello',
|
||||
messageType: "hello",
|
||||
status: 200,
|
||||
uaid: userAgentID,
|
||||
}));
|
||||
|
@ -102,9 +102,9 @@ add_task(async function test_expiration_origin_threshold() {
|
|||
// drop the registration.
|
||||
for (let version = 1; version <= 6; version++) {
|
||||
this.serverSendMsg(JSON.stringify({
|
||||
messageType: 'notification',
|
||||
messageType: "notification",
|
||||
updates: [{
|
||||
channelID: 'eb33fc90-c883-4267-b5cb-613969e8e349',
|
||||
channelID: "eb33fc90-c883-4267-b5cb-613969e8e349",
|
||||
version,
|
||||
}],
|
||||
}));
|
||||
|
@ -112,16 +112,16 @@ add_task(async function test_expiration_origin_threshold() {
|
|||
// But the limits are per-channel, so we can send 5 more
|
||||
// notifications on a different channel.
|
||||
this.serverSendMsg(JSON.stringify({
|
||||
messageType: 'notification',
|
||||
messageType: "notification",
|
||||
updates: [{
|
||||
channelID: '46cc6f6a-c106-4ffa-bb7c-55c60bd50c41',
|
||||
channelID: "46cc6f6a-c106-4ffa-bb7c-55c60bd50c41",
|
||||
version: 1,
|
||||
}],
|
||||
}));
|
||||
},
|
||||
onUnregister(request) {
|
||||
equal(request.channelID, 'eb33fc90-c883-4267-b5cb-613969e8e349', 'Unregistered wrong channel ID');
|
||||
equal(request.code, 201, 'Expected quota exceeded unregister reason');
|
||||
equal(request.channelID, "eb33fc90-c883-4267-b5cb-613969e8e349", "Unregistered wrong channel ID");
|
||||
equal(request.code, 201, "Expected quota exceeded unregister reason");
|
||||
unregisterDone();
|
||||
},
|
||||
// We expect to receive acks, but don't care about their
|
||||
|
@ -135,6 +135,6 @@ add_task(async function test_expiration_origin_threshold() {
|
|||
|
||||
await notifyPromise;
|
||||
|
||||
let expiredRecord = await db.getByKeyID('eb33fc90-c883-4267-b5cb-613969e8e349');
|
||||
strictEqual(expiredRecord.quota, 0, 'Expired record not updated');
|
||||
let expiredRecord = await db.getByKeyID("eb33fc90-c883-4267-b5cb-613969e8e349");
|
||||
strictEqual(expiredRecord.quota, 0, "Expired record not updated");
|
||||
});
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
'use strict';
|
||||
"use strict";
|
||||
|
||||
const {PushDB, PushService, PushServiceWebSocket} = serviceExports;
|
||||
|
||||
const userAgentID = '28cd09e2-7506-42d8-9e50-b02785adc7ef';
|
||||
const userAgentID = "28cd09e2-7506-42d8-9e50-b02785adc7ef";
|
||||
|
||||
var db;
|
||||
|
||||
|
@ -20,10 +20,10 @@ function run_test() {
|
|||
let putRecord = async function(perm, record) {
|
||||
let uri = Services.io.newURI(record.scope);
|
||||
|
||||
Services.perms.add(uri, 'desktop-notification',
|
||||
Services.perms.add(uri, "desktop-notification",
|
||||
Ci.nsIPermissionManager[perm]);
|
||||
registerCleanupFunction(() => {
|
||||
Services.perms.remove(uri, 'desktop-notification');
|
||||
Services.perms.remove(uri, "desktop-notification");
|
||||
});
|
||||
|
||||
await db.put(record);
|
||||
|
@ -34,75 +34,75 @@ add_task(async function test_expiration_history_observer() {
|
|||
registerCleanupFunction(() => db.drop().then(_ => db.close()));
|
||||
|
||||
// A registration that we'll expire...
|
||||
await putRecord('ALLOW_ACTION', {
|
||||
channelID: '379c0668-8323-44d2-a315-4ee83f1a9ee9',
|
||||
pushEndpoint: 'https://example.org/push/1',
|
||||
scope: 'https://example.com/deals',
|
||||
await putRecord("ALLOW_ACTION", {
|
||||
channelID: "379c0668-8323-44d2-a315-4ee83f1a9ee9",
|
||||
pushEndpoint: "https://example.org/push/1",
|
||||
scope: "https://example.com/deals",
|
||||
pushCount: 0,
|
||||
lastPush: 0,
|
||||
version: null,
|
||||
originAttributes: '',
|
||||
originAttributes: "",
|
||||
quota: 16,
|
||||
});
|
||||
|
||||
// ...And a registration that we'll evict on startup.
|
||||
await putRecord('ALLOW_ACTION', {
|
||||
channelID: '4cb6e454-37cf-41c4-a013-4e3a7fdd0bf1',
|
||||
pushEndpoint: 'https://example.org/push/3',
|
||||
scope: 'https://example.com/stuff',
|
||||
await putRecord("ALLOW_ACTION", {
|
||||
channelID: "4cb6e454-37cf-41c4-a013-4e3a7fdd0bf1",
|
||||
pushEndpoint: "https://example.org/push/3",
|
||||
scope: "https://example.com/stuff",
|
||||
pushCount: 0,
|
||||
lastPush: 0,
|
||||
version: null,
|
||||
originAttributes: '',
|
||||
originAttributes: "",
|
||||
quota: 0,
|
||||
});
|
||||
|
||||
await PlacesTestUtils.addVisits({
|
||||
uri: 'https://example.com/infrequent',
|
||||
title: 'Infrequently-visited page',
|
||||
uri: "https://example.com/infrequent",
|
||||
title: "Infrequently-visited page",
|
||||
visitDate: (Date.now() - 14 * 24 * 60 * 60 * 1000) * 1000,
|
||||
transition: Ci.nsINavHistoryService.TRANSITION_LINK
|
||||
transition: Ci.nsINavHistoryService.TRANSITION_LINK,
|
||||
});
|
||||
|
||||
let unregisterDone;
|
||||
let unregisterPromise = new Promise(resolve => unregisterDone = resolve);
|
||||
let subChangePromise = promiseObserverNotification(PushServiceComponent.subscriptionChangeTopic, (subject, data) =>
|
||||
data == 'https://example.com/stuff');
|
||||
data == "https://example.com/stuff");
|
||||
|
||||
PushService.init({
|
||||
serverURI: 'wss://push.example.org/',
|
||||
serverURI: "wss://push.example.org/",
|
||||
db,
|
||||
makeWebSocket(uri) {
|
||||
return new MockWebSocket(uri, {
|
||||
onHello(request) {
|
||||
this.serverSendMsg(JSON.stringify({
|
||||
messageType: 'hello',
|
||||
messageType: "hello",
|
||||
status: 200,
|
||||
uaid: userAgentID,
|
||||
}));
|
||||
this.serverSendMsg(JSON.stringify({
|
||||
messageType: 'notification',
|
||||
messageType: "notification",
|
||||
updates: [{
|
||||
channelID: '379c0668-8323-44d2-a315-4ee83f1a9ee9',
|
||||
channelID: "379c0668-8323-44d2-a315-4ee83f1a9ee9",
|
||||
version: 2,
|
||||
}],
|
||||
}));
|
||||
},
|
||||
onUnregister(request) {
|
||||
equal(request.channelID, '379c0668-8323-44d2-a315-4ee83f1a9ee9', 'Dropped wrong channel ID');
|
||||
equal(request.code, 201, 'Expected quota exceeded unregister reason');
|
||||
equal(request.channelID, "379c0668-8323-44d2-a315-4ee83f1a9ee9", "Dropped wrong channel ID");
|
||||
equal(request.code, 201, "Expected quota exceeded unregister reason");
|
||||
unregisterDone();
|
||||
},
|
||||
onACK(request) {},
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
await subChangePromise;
|
||||
await unregisterPromise;
|
||||
|
||||
let expiredRecord = await db.getByKeyID('379c0668-8323-44d2-a315-4ee83f1a9ee9');
|
||||
strictEqual(expiredRecord.quota, 0, 'Expired record not updated');
|
||||
let expiredRecord = await db.getByKeyID("379c0668-8323-44d2-a315-4ee83f1a9ee9");
|
||||
strictEqual(expiredRecord.quota, 0, "Expired record not updated");
|
||||
|
||||
let notifiedScopes = [];
|
||||
subChangePromise = promiseObserverNotification(PushServiceComponent.subscriptionChangeTopic, (subject, data) => {
|
||||
|
@ -112,72 +112,73 @@ add_task(async function test_expiration_history_observer() {
|
|||
|
||||
// Add an expired registration that we'll revive later using the idle
|
||||
// observer.
|
||||
await putRecord('ALLOW_ACTION', {
|
||||
channelID: 'eb33fc90-c883-4267-b5cb-613969e8e349',
|
||||
pushEndpoint: 'https://example.org/push/2',
|
||||
scope: 'https://example.com/auctions',
|
||||
await putRecord("ALLOW_ACTION", {
|
||||
channelID: "eb33fc90-c883-4267-b5cb-613969e8e349",
|
||||
pushEndpoint: "https://example.org/push/2",
|
||||
scope: "https://example.com/auctions",
|
||||
pushCount: 0,
|
||||
lastPush: 0,
|
||||
version: null,
|
||||
originAttributes: '',
|
||||
originAttributes: "",
|
||||
quota: 0,
|
||||
});
|
||||
// ...And an expired registration that we'll revive on fetch.
|
||||
await putRecord('ALLOW_ACTION', {
|
||||
channelID: '6b2d13fe-d848-4c5f-bdda-e9fc89727dca',
|
||||
pushEndpoint: 'https://example.org/push/4',
|
||||
scope: 'https://example.net/sales',
|
||||
await putRecord("ALLOW_ACTION", {
|
||||
channelID: "6b2d13fe-d848-4c5f-bdda-e9fc89727dca",
|
||||
pushEndpoint: "https://example.org/push/4",
|
||||
scope: "https://example.net/sales",
|
||||
pushCount: 0,
|
||||
lastPush: 0,
|
||||
version: null,
|
||||
originAttributes: '',
|
||||
originAttributes: "",
|
||||
quota: 0,
|
||||
});
|
||||
|
||||
// Now visit the site...
|
||||
await PlacesTestUtils.addVisits({
|
||||
uri: 'https://example.com/another-page',
|
||||
title: 'Infrequently-visited page',
|
||||
uri: "https://example.com/another-page",
|
||||
title: "Infrequently-visited page",
|
||||
visitDate: Date.now() * 1000,
|
||||
transition: Ci.nsINavHistoryService.TRANSITION_LINK
|
||||
transition: Ci.nsINavHistoryService.TRANSITION_LINK,
|
||||
});
|
||||
Services.obs.notifyObservers(null, 'idle-daily');
|
||||
Services.obs.notifyObservers(null, "idle-daily");
|
||||
|
||||
// And we should receive notifications for both scopes.
|
||||
await subChangePromise;
|
||||
deepEqual(notifiedScopes.sort(), [
|
||||
'https://example.com/auctions',
|
||||
'https://example.com/deals'
|
||||
], 'Wrong scopes for subscription changes');
|
||||
"https://example.com/auctions",
|
||||
"https://example.com/deals",
|
||||
], "Wrong scopes for subscription changes");
|
||||
|
||||
let aRecord = await db.getByKeyID('379c0668-8323-44d2-a315-4ee83f1a9ee9');
|
||||
ok(!aRecord, 'Should drop expired record');
|
||||
let aRecord = await db.getByKeyID("379c0668-8323-44d2-a315-4ee83f1a9ee9");
|
||||
ok(!aRecord, "Should drop expired record");
|
||||
|
||||
let bRecord = await db.getByKeyID('eb33fc90-c883-4267-b5cb-613969e8e349');
|
||||
ok(!bRecord, 'Should drop evicted record');
|
||||
let bRecord = await db.getByKeyID("eb33fc90-c883-4267-b5cb-613969e8e349");
|
||||
ok(!bRecord, "Should drop evicted record");
|
||||
|
||||
// Simulate a visit to a site with an expired registration, then fetch the
|
||||
// record. This should drop the expired record and fire an observer
|
||||
// notification.
|
||||
await PlacesTestUtils.addVisits({
|
||||
uri: 'https://example.net/sales',
|
||||
title: 'Firefox plushies, 99% off',
|
||||
uri: "https://example.net/sales",
|
||||
title: "Firefox plushies, 99% off",
|
||||
visitDate: Date.now() * 1000,
|
||||
transition: Ci.nsINavHistoryService.TRANSITION_LINK
|
||||
transition: Ci.nsINavHistoryService.TRANSITION_LINK,
|
||||
});
|
||||
subChangePromise = promiseObserverNotification(PushServiceComponent.subscriptionChangeTopic, (subject, data) => {
|
||||
if (data == 'https://example.net/sales') {
|
||||
if (data == "https://example.net/sales") {
|
||||
ok(subject.isCodebasePrincipal,
|
||||
'Should pass subscription principal as the subject');
|
||||
"Should pass subscription principal as the subject");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
let record = await PushService.registration({
|
||||
scope: 'https://example.net/sales',
|
||||
originAttributes: '',
|
||||
scope: "https://example.net/sales",
|
||||
originAttributes: "",
|
||||
});
|
||||
ok(!record, 'Should not return evicted record');
|
||||
ok(!(await db.getByKeyID('6b2d13fe-d848-4c5f-bdda-e9fc89727dca')),
|
||||
'Should drop evicted record on fetch');
|
||||
ok(!record, "Should not return evicted record");
|
||||
ok(!(await db.getByKeyID("6b2d13fe-d848-4c5f-bdda-e9fc89727dca")),
|
||||
"Should drop evicted record on fetch");
|
||||
await subChangePromise;
|
||||
});
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
'use strict';
|
||||
"use strict";
|
||||
|
||||
const {PushDB, PushService, PushServiceWebSocket} = serviceExports;
|
||||
|
||||
|
||||
const userAgentID = 'aaabf1f8-2f68-44f1-a920-b88e9e7d7559';
|
||||
const userAgentID = "aaabf1f8-2f68-44f1-a920-b88e9e7d7559";
|
||||
const nsIPushQuotaManager = Ci.nsIPushQuotaManager;
|
||||
|
||||
function run_test() {
|
||||
do_get_profile();
|
||||
setPrefs({
|
||||
userAgentID,
|
||||
'testing.ignorePermission': true,
|
||||
"testing.ignorePermission": true,
|
||||
});
|
||||
run_next_test();
|
||||
}
|
||||
|
@ -31,22 +31,22 @@ add_task(async function test_expiration_origin_threshold() {
|
|||
PushService.notificationForOriginShown("https://example.com");
|
||||
|
||||
await db.put({
|
||||
channelID: 'f56645a9-1f32-4655-92ad-ddc37f6d54fb',
|
||||
pushEndpoint: 'https://example.org/push/1',
|
||||
scope: 'https://example.com/quota',
|
||||
channelID: "f56645a9-1f32-4655-92ad-ddc37f6d54fb",
|
||||
pushEndpoint: "https://example.org/push/1",
|
||||
scope: "https://example.com/quota",
|
||||
pushCount: 0,
|
||||
lastPush: 0,
|
||||
version: null,
|
||||
originAttributes: '',
|
||||
originAttributes: "",
|
||||
quota: 16,
|
||||
});
|
||||
|
||||
// A visit one day ago should provide a quota of 8 messages.
|
||||
await PlacesTestUtils.addVisits({
|
||||
uri: 'https://example.com/login',
|
||||
title: 'Sign in to see your auctions',
|
||||
uri: "https://example.com/login",
|
||||
title: "Sign in to see your auctions",
|
||||
visitDate: (Date.now() - MS_IN_ONE_DAY) * 1000,
|
||||
transition: Ci.nsINavHistoryService.TRANSITION_LINK
|
||||
transition: Ci.nsINavHistoryService.TRANSITION_LINK,
|
||||
});
|
||||
|
||||
let numMessages = 10;
|
||||
|
@ -76,13 +76,13 @@ add_task(async function test_expiration_origin_threshold() {
|
|||
});
|
||||
|
||||
PushService.init({
|
||||
serverURI: 'wss://push.example.org/',
|
||||
serverURI: "wss://push.example.org/",
|
||||
db,
|
||||
makeWebSocket(uri) {
|
||||
return new MockWebSocket(uri, {
|
||||
onHello(request) {
|
||||
this.serverSendMsg(JSON.stringify({
|
||||
messageType: 'hello',
|
||||
messageType: "hello",
|
||||
status: 200,
|
||||
uaid: userAgentID,
|
||||
}));
|
||||
|
@ -91,9 +91,9 @@ add_task(async function test_expiration_origin_threshold() {
|
|||
// message should not affect quota.
|
||||
for (let version = 1; version <= 10; version++) {
|
||||
this.serverSendMsg(JSON.stringify({
|
||||
messageType: 'notification',
|
||||
messageType: "notification",
|
||||
updates: [{
|
||||
channelID: 'f56645a9-1f32-4655-92ad-ddc37f6d54fb',
|
||||
channelID: "f56645a9-1f32-4655-92ad-ddc37f6d54fb",
|
||||
version,
|
||||
}],
|
||||
}));
|
||||
|
@ -114,6 +114,6 @@ add_task(async function test_expiration_origin_threshold() {
|
|||
await updateQuotaPromise;
|
||||
await modifiedPromise;
|
||||
|
||||
let expiredRecord = await db.getByKeyID('f56645a9-1f32-4655-92ad-ddc37f6d54fb');
|
||||
notStrictEqual(expiredRecord.quota, 0, 'Expired record not updated');
|
||||
let expiredRecord = await db.getByKeyID("f56645a9-1f32-4655-92ad-ddc37f6d54fb");
|
||||
notStrictEqual(expiredRecord.quota, 0, "Expired record not updated");
|
||||
});
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
'use strict';
|
||||
"use strict";
|
||||
|
||||
const {PushDB, PushService, PushServiceWebSocket} = serviceExports;
|
||||
|
||||
|
@ -9,14 +9,14 @@ function run_test() {
|
|||
do_get_profile();
|
||||
setPrefs({
|
||||
requestTimeout: 10000,
|
||||
retryBaseInterval: 150
|
||||
retryBaseInterval: 150,
|
||||
});
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
add_task(async function test_reconnect_retry() {
|
||||
let db = PushServiceWebSocket.newPushDB();
|
||||
registerCleanupFunction(() => {return db.drop().then(_ => db.close());});
|
||||
registerCleanupFunction(() => { return db.drop().then(_ => db.close()); });
|
||||
|
||||
let registers = 0;
|
||||
let channelID;
|
||||
|
@ -27,9 +27,9 @@ add_task(async function test_reconnect_retry() {
|
|||
return new MockWebSocket(uri, {
|
||||
onHello(request) {
|
||||
this.serverSendMsg(JSON.stringify({
|
||||
messageType: 'hello',
|
||||
messageType: "hello",
|
||||
status: 200,
|
||||
uaid: '083e6c17-1063-4677-8638-ab705aebebc2'
|
||||
uaid: "083e6c17-1063-4677-8638-ab705aebebc2",
|
||||
}));
|
||||
},
|
||||
onRegister(request) {
|
||||
|
@ -41,33 +41,33 @@ add_task(async function test_reconnect_retry() {
|
|||
}
|
||||
if (registers == 2) {
|
||||
equal(request.channelID, channelID,
|
||||
'Should retry registers after reconnect');
|
||||
"Should retry registers after reconnect");
|
||||
}
|
||||
this.serverSendMsg(JSON.stringify({
|
||||
messageType: 'register',
|
||||
messageType: "register",
|
||||
channelID: request.channelID,
|
||||
pushEndpoint: 'https://example.org/push/' + request.channelID,
|
||||
pushEndpoint: "https://example.org/push/" + request.channelID,
|
||||
status: 200,
|
||||
}));
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
let registration = await PushService.register({
|
||||
scope: 'https://example.com/page/1',
|
||||
scope: "https://example.com/page/1",
|
||||
originAttributes: ChromeUtils.originAttributesToSuffix(
|
||||
{ appId: Ci.nsIScriptSecurityManager.NO_APP_ID, inIsolatedMozBrowser: false }),
|
||||
});
|
||||
let retryEndpoint = 'https://example.org/push/' + channelID;
|
||||
equal(registration.endpoint, retryEndpoint, 'Wrong endpoint for retried request');
|
||||
let retryEndpoint = "https://example.org/push/" + channelID;
|
||||
equal(registration.endpoint, retryEndpoint, "Wrong endpoint for retried request");
|
||||
|
||||
registration = await PushService.register({
|
||||
scope: 'https://example.com/page/2',
|
||||
scope: "https://example.com/page/2",
|
||||
originAttributes: ChromeUtils.originAttributesToSuffix(
|
||||
{ appId: Ci.nsIScriptSecurityManager.NO_APP_ID, inIsolatedMozBrowser: false }),
|
||||
});
|
||||
notEqual(registration.endpoint, retryEndpoint, 'Wrong endpoint for new request');
|
||||
notEqual(registration.endpoint, retryEndpoint, "Wrong endpoint for new request");
|
||||
|
||||
equal(registers, 3, 'Wrong registration count');
|
||||
equal(registers, 3, "Wrong registration count");
|
||||
});
|
||||
|
|
|
@ -1,11 +1,7 @@
|
|||
'use strict';
|
||||
"use strict";
|
||||
|
||||
const {PushRecord} = ChromeUtils.import("resource://gre/modules/PushRecord.jsm");
|
||||
|
||||
function run_test() {
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
add_task(async function test_updateQuota() {
|
||||
let record = new PushRecord({
|
||||
quota: 8,
|
||||
|
@ -14,26 +10,26 @@ add_task(async function test_updateQuota() {
|
|||
|
||||
record.updateQuota(Date.now() - 2 * MS_IN_ONE_DAY);
|
||||
equal(record.quota, 8,
|
||||
'Should not update quota if last visit is older than last push');
|
||||
"Should not update quota if last visit is older than last push");
|
||||
|
||||
record.updateQuota(Date.now());
|
||||
equal(record.quota, 16,
|
||||
'Should reset quota if last visit is newer than last push');
|
||||
"Should reset quota if last visit is newer than last push");
|
||||
|
||||
record.reduceQuota();
|
||||
equal(record.quota, 15, 'Should reduce quota');
|
||||
equal(record.quota, 15, "Should reduce quota");
|
||||
|
||||
// Make sure we calculate the quota correctly for visit dates in the
|
||||
// future (bug 1206424).
|
||||
record.updateQuota(Date.now() + 1 * MS_IN_ONE_DAY);
|
||||
equal(record.quota, 16,
|
||||
'Should reset quota to maximum if last visit is in the future');
|
||||
"Should reset quota to maximum if last visit is in the future");
|
||||
|
||||
record.updateQuota(-1);
|
||||
strictEqual(record.quota, 0, 'Should set quota to 0 if history was cleared');
|
||||
ok(record.isExpired(), 'Should expire records once the quota reaches 0');
|
||||
strictEqual(record.quota, 0, "Should set quota to 0 if history was cleared");
|
||||
ok(record.isExpired(), "Should expire records once the quota reaches 0");
|
||||
record.reduceQuota();
|
||||
strictEqual(record.quota, 0, 'Quota should never be negative');
|
||||
strictEqual(record.quota, 0, "Quota should never be negative");
|
||||
});
|
||||
|
||||
add_task(async function test_systemRecord_updateQuota() {
|
||||
|
@ -43,13 +39,13 @@ add_task(async function test_systemRecord_updateQuota() {
|
|||
});
|
||||
systemRecord.updateQuota(Date.now() - 3 * MS_IN_ONE_DAY);
|
||||
equal(systemRecord.quota, Infinity,
|
||||
'System subscriptions should ignore quota updates');
|
||||
"System subscriptions should ignore quota updates");
|
||||
systemRecord.updateQuota(-1);
|
||||
equal(systemRecord.quota, Infinity,
|
||||
'System subscriptions should ignore the last visit time');
|
||||
"System subscriptions should ignore the last visit time");
|
||||
systemRecord.reduceQuota();
|
||||
equal(systemRecord.quota, Infinity,
|
||||
'System subscriptions should ignore quota reductions');
|
||||
"System subscriptions should ignore quota reductions");
|
||||
});
|
||||
|
||||
function testPermissionCheck(props) {
|
||||
|
@ -65,27 +61,27 @@ function testPermissionCheck(props) {
|
|||
ok(!record.hasPermission(), `Record ${
|
||||
JSON.stringify(props)} should not have permission yet`);
|
||||
let permURI = Services.io.newURI(props.scope);
|
||||
Services.perms.add(permURI, 'desktop-notification',
|
||||
Services.perms.add(permURI, "desktop-notification",
|
||||
Ci.nsIPermissionManager.ALLOW_ACTION);
|
||||
try {
|
||||
ok(record.hasPermission(), `Record ${
|
||||
JSON.stringify(props)} should have permission`);
|
||||
} finally {
|
||||
Services.perms.remove(permURI, 'desktop-notification');
|
||||
Services.perms.remove(permURI, "desktop-notification");
|
||||
}
|
||||
}
|
||||
|
||||
add_task(async function test_principal_permissions() {
|
||||
let testProps = [{
|
||||
scope: 'https://example.com/',
|
||||
scope: "https://example.com/",
|
||||
}, {
|
||||
scope: 'https://example.com/',
|
||||
originAttributes: '^userContextId=1',
|
||||
scope: "https://example.com/",
|
||||
originAttributes: "^userContextId=1",
|
||||
}, {
|
||||
scope: 'https://xn--90aexm.xn--80ag3aejvc.xn--p1ai/',
|
||||
scope: "https://xn--90aexm.xn--80ag3aejvc.xn--p1ai/",
|
||||
}, {
|
||||
scope: 'https://xn--90aexm.xn--80ag3aejvc.xn--p1ai/',
|
||||
originAttributes: '^userContextId=1',
|
||||
scope: "https://xn--90aexm.xn--80ag3aejvc.xn--p1ai/",
|
||||
originAttributes: "^userContextId=1",
|
||||
}];
|
||||
for (let props of testProps) {
|
||||
testPermissionCheck(props);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
'use strict';
|
||||
"use strict";
|
||||
|
||||
const {HttpServer} = ChromeUtils.import("resource://testing-common/httpd.js");
|
||||
|
||||
|
@ -13,19 +13,19 @@ XPCOMUtils.defineLazyGetter(this, "serverPort", function() {
|
|||
return httpServer.identity.primaryPort;
|
||||
});
|
||||
|
||||
var retries = 0
|
||||
var retries = 0;
|
||||
|
||||
function subscribe5xxCodeHandler(metadata, response) {
|
||||
if (retries == 0) {
|
||||
ok(true, "Subscribe 5xx code");
|
||||
do_test_finished();
|
||||
response.setHeader("Retry-After", '1');
|
||||
response.setHeader("Retry-After", "1");
|
||||
response.setStatusLine(metadata.httpVersion, 500, "Retry");
|
||||
} else {
|
||||
ok(true, "Subscribed");
|
||||
do_test_finished();
|
||||
response.setHeader("Location",
|
||||
'http://localhost:' + serverPort + '/subscription')
|
||||
"http://localhost:" + serverPort + "/subscription");
|
||||
response.setHeader("Link",
|
||||
'</pushEndpoint>; rel="urn:ietf:params:push", ' +
|
||||
'</receiptPushEndpoint>; rel="urn:ietf:params:push:receipt"');
|
||||
|
@ -38,7 +38,7 @@ function listenSuccessHandler(metadata, response) {
|
|||
Assert.ok(true, "New listener point");
|
||||
ok(retries == 2, "Should try 2 times.");
|
||||
do_test_finished();
|
||||
response.setHeader("Retry-After", '10');
|
||||
response.setHeader("Retry-After", "10");
|
||||
response.setStatusLine(metadata.httpVersion, 500, "Retry");
|
||||
}
|
||||
|
||||
|
@ -49,19 +49,17 @@ httpServer.registerPathHandler("/subscription", listenSuccessHandler);
|
|||
httpServer.start(-1);
|
||||
|
||||
function run_test() {
|
||||
|
||||
do_get_profile();
|
||||
setPrefs({
|
||||
'testing.allowInsecureServerURL': true,
|
||||
'http2.retryInterval': 1000,
|
||||
'http2.maxRetries': 2
|
||||
"testing.allowInsecureServerURL": true,
|
||||
"http2.retryInterval": 1000,
|
||||
"http2.maxRetries": 2,
|
||||
});
|
||||
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
add_task(async function test1() {
|
||||
|
||||
let db = PushServiceHttp2.newPushDB();
|
||||
registerCleanupFunction(() => {
|
||||
return db.drop().then(_ => db.close());
|
||||
|
@ -76,7 +74,7 @@ add_task(async function test1() {
|
|||
|
||||
PushService.init({
|
||||
serverURI: serverURL + "/subscribe5xxCode",
|
||||
db
|
||||
db,
|
||||
});
|
||||
|
||||
let originAttributes = ChromeUtils.originAttributesToSuffix({
|
||||
|
@ -84,28 +82,28 @@ add_task(async function test1() {
|
|||
inIsolatedMozBrowser: false,
|
||||
});
|
||||
let newRecord = await PushService.register({
|
||||
scope: 'https://example.com/retry5xxCode',
|
||||
originAttributes: originAttributes,
|
||||
scope: "https://example.com/retry5xxCode",
|
||||
originAttributes,
|
||||
});
|
||||
|
||||
var subscriptionUri = serverURL + '/subscription';
|
||||
var pushEndpoint = serverURL + '/pushEndpoint';
|
||||
var pushReceiptEndpoint = serverURL + '/receiptPushEndpoint';
|
||||
var subscriptionUri = serverURL + "/subscription";
|
||||
var pushEndpoint = serverURL + "/pushEndpoint";
|
||||
var pushReceiptEndpoint = serverURL + "/receiptPushEndpoint";
|
||||
equal(newRecord.endpoint, pushEndpoint,
|
||||
'Wrong push endpoint in registration record');
|
||||
"Wrong push endpoint in registration record");
|
||||
|
||||
equal(newRecord.pushReceiptEndpoint, pushReceiptEndpoint,
|
||||
'Wrong push endpoint receipt in registration record');
|
||||
"Wrong push endpoint receipt in registration record");
|
||||
|
||||
let record = await db.getByKeyID(subscriptionUri);
|
||||
equal(record.subscriptionUri, subscriptionUri,
|
||||
'Wrong subscription ID in database record');
|
||||
"Wrong subscription ID in database record");
|
||||
equal(record.pushEndpoint, pushEndpoint,
|
||||
'Wrong push endpoint in database record');
|
||||
"Wrong push endpoint in database record");
|
||||
equal(record.pushReceiptEndpoint, pushReceiptEndpoint,
|
||||
'Wrong push endpoint receipt in database record');
|
||||
equal(record.scope, 'https://example.com/retry5xxCode',
|
||||
'Wrong scope in database record');
|
||||
"Wrong push endpoint receipt in database record");
|
||||
equal(record.scope, "https://example.com/retry5xxCode",
|
||||
"Wrong scope in database record");
|
||||
|
||||
httpServer.stop(do_test_finished);
|
||||
});
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
'use strict';
|
||||
"use strict";
|
||||
|
||||
const {PushDB, PushService, PushServiceWebSocket} = serviceExports;
|
||||
|
||||
const userAgentID = '1760b1f5-c3ba-40e3-9344-adef7c18ab12';
|
||||
const userAgentID = "1760b1f5-c3ba-40e3-9344-adef7c18ab12";
|
||||
|
||||
function run_test() {
|
||||
do_get_profile();
|
||||
|
@ -15,7 +15,7 @@ function run_test() {
|
|||
|
||||
add_task(async function test_register_case() {
|
||||
let db = PushServiceWebSocket.newPushDB();
|
||||
registerCleanupFunction(() => {return db.drop().then(_ => db.close());});
|
||||
registerCleanupFunction(() => { return db.drop().then(_ => db.close()); });
|
||||
|
||||
PushService.init({
|
||||
serverURI: "wss://push.example.org/",
|
||||
|
@ -24,33 +24,33 @@ add_task(async function test_register_case() {
|
|||
return new MockWebSocket(uri, {
|
||||
onHello(request) {
|
||||
this.serverSendMsg(JSON.stringify({
|
||||
messageType: 'HELLO',
|
||||
messageType: "HELLO",
|
||||
uaid: userAgentID,
|
||||
status: 200
|
||||
status: 200,
|
||||
}));
|
||||
},
|
||||
onRegister(request) {
|
||||
this.serverSendMsg(JSON.stringify({
|
||||
messageType: 'ReGiStEr',
|
||||
messageType: "ReGiStEr",
|
||||
uaid: userAgentID,
|
||||
channelID: request.channelID,
|
||||
status: 200,
|
||||
pushEndpoint: 'https://example.com/update/case'
|
||||
pushEndpoint: "https://example.com/update/case",
|
||||
}));
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
let newRecord = await PushService.register({
|
||||
scope: 'https://example.net/case',
|
||||
scope: "https://example.net/case",
|
||||
originAttributes: ChromeUtils.originAttributesToSuffix(
|
||||
{ appId: Ci.nsIScriptSecurityManager.NO_APP_ID, inIsolatedMozBrowser: false }),
|
||||
});
|
||||
equal(newRecord.endpoint, 'https://example.com/update/case',
|
||||
'Wrong push endpoint in registration record');
|
||||
equal(newRecord.endpoint, "https://example.com/update/case",
|
||||
"Wrong push endpoint in registration record");
|
||||
|
||||
let record = await db.getByPushEndpoint('https://example.com/update/case');
|
||||
equal(record.scope, 'https://example.net/case',
|
||||
'Wrong scope in database record');
|
||||
let record = await db.getByPushEndpoint("https://example.com/update/case");
|
||||
equal(record.scope, "https://example.net/case",
|
||||
"Wrong scope in database record");
|
||||
});
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
'use strict';
|
||||
"use strict";
|
||||
|
||||
const {PushDB, PushService, PushServiceHttp2} = serviceExports;
|
||||
|
||||
var prefs;
|
||||
var serverURL;
|
||||
|
||||
var serverPort = -1;
|
||||
|
@ -14,7 +13,6 @@ function run_test() {
|
|||
serverPort = getTestServerPort();
|
||||
|
||||
do_get_profile();
|
||||
prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
|
||||
|
||||
serverURL = "https://localhost:" + serverPort;
|
||||
|
||||
|
@ -23,7 +21,6 @@ function run_test() {
|
|||
|
||||
// Connection will fail because of the certificates.
|
||||
add_task(async function test_pushSubscriptionNoConnection() {
|
||||
|
||||
let db = PushServiceHttp2.newPushDB();
|
||||
registerCleanupFunction(() => {
|
||||
return db.drop().then(_ => db.close());
|
||||
|
@ -31,17 +28,17 @@ add_task(async function test_pushSubscriptionNoConnection() {
|
|||
|
||||
PushService.init({
|
||||
serverURI: serverURL + "/pushSubscriptionNoConnection/subscribe",
|
||||
db
|
||||
db,
|
||||
});
|
||||
|
||||
await rejects(
|
||||
await Assert.rejects(
|
||||
PushService.register({
|
||||
scope: 'https://example.net/page/invalid-response',
|
||||
scope: "https://example.net/page/invalid-response",
|
||||
originAttributes: ChromeUtils.originAttributesToSuffix(
|
||||
{ appId: Ci.nsIScriptSecurityManager.NO_APP_ID, inIsolatedMozBrowser: false }),
|
||||
}),
|
||||
/Registration error/,
|
||||
'Expected error for not being able to establish connecion.'
|
||||
"Expected error for not being able to establish connecion."
|
||||
);
|
||||
|
||||
let record = await db.getAllKeyIDs();
|
||||
|
@ -51,16 +48,15 @@ add_task(async function test_pushSubscriptionNoConnection() {
|
|||
|
||||
add_task(async function test_TLS() {
|
||||
// Set to allow the cert presented by our H2 server
|
||||
var oldPref = prefs.getIntPref("network.http.speculative-parallel-limit");
|
||||
prefs.setIntPref("network.http.speculative-parallel-limit", 0);
|
||||
var oldPref = Services.prefs.getIntPref("network.http.speculative-parallel-limit");
|
||||
Services.prefs.setIntPref("network.http.speculative-parallel-limit", 0);
|
||||
|
||||
trustHttp2CA();
|
||||
|
||||
prefs.setIntPref("network.http.speculative-parallel-limit", oldPref);
|
||||
Services.prefs.setIntPref("network.http.speculative-parallel-limit", oldPref);
|
||||
});
|
||||
|
||||
add_task(async function test_pushSubscriptionMissingLocation() {
|
||||
|
||||
let db = PushServiceHttp2.newPushDB();
|
||||
registerCleanupFunction(() => {
|
||||
return db.drop().then(_ => db.close());
|
||||
|
@ -68,26 +64,25 @@ add_task(async function test_pushSubscriptionMissingLocation() {
|
|||
|
||||
PushService.init({
|
||||
serverURI: serverURL + "/pushSubscriptionMissingLocation/subscribe",
|
||||
db
|
||||
db,
|
||||
});
|
||||
|
||||
await rejects(
|
||||
await Assert.rejects(
|
||||
PushService.register({
|
||||
scope: 'https://example.net/page/invalid-response',
|
||||
scope: "https://example.net/page/invalid-response",
|
||||
originAttributes: ChromeUtils.originAttributesToSuffix(
|
||||
{ appId: Ci.nsIScriptSecurityManager.NO_APP_ID, inIsolatedMozBrowser: false }),
|
||||
}),
|
||||
/Registration error/,
|
||||
'Expected error for the missing location header.'
|
||||
"Expected error for the missing location header."
|
||||
);
|
||||
|
||||
let record = await db.getAllKeyIDs();
|
||||
ok(record.length === 0, 'Should not store records when the location header is missing.');
|
||||
ok(record.length === 0, "Should not store records when the location header is missing.");
|
||||
PushService.uninit();
|
||||
});
|
||||
|
||||
add_task(async function test_pushSubscriptionMissingLink() {
|
||||
|
||||
let db = PushServiceHttp2.newPushDB();
|
||||
registerCleanupFunction(() => {
|
||||
return db.drop().then(_ => db.close());
|
||||
|
@ -95,26 +90,25 @@ add_task(async function test_pushSubscriptionMissingLink() {
|
|||
|
||||
PushService.init({
|
||||
serverURI: serverURL + "/pushSubscriptionMissingLink/subscribe",
|
||||
db
|
||||
db,
|
||||
});
|
||||
|
||||
await rejects(
|
||||
await Assert.rejects(
|
||||
PushService.register({
|
||||
scope: 'https://example.net/page/invalid-response',
|
||||
scope: "https://example.net/page/invalid-response",
|
||||
originAttributes: ChromeUtils.originAttributesToSuffix(
|
||||
{ appId: Ci.nsIScriptSecurityManager.NO_APP_ID, inIsolatedMozBrowser: false }),
|
||||
}),
|
||||
/Registration error/,
|
||||
'Expected error for the missing link header.'
|
||||
"Expected error for the missing link header."
|
||||
);
|
||||
|
||||
let record = await db.getAllKeyIDs();
|
||||
ok(record.length === 0, 'Should not store records when a link header is missing.');
|
||||
ok(record.length === 0, "Should not store records when a link header is missing.");
|
||||
PushService.uninit();
|
||||
});
|
||||
|
||||
add_task(async function test_pushSubscriptionMissingLink1() {
|
||||
|
||||
let db = PushServiceHttp2.newPushDB();
|
||||
registerCleanupFunction(() => {
|
||||
return db.drop().then(_ => db.close());
|
||||
|
@ -122,26 +116,25 @@ add_task(async function test_pushSubscriptionMissingLink1() {
|
|||
|
||||
PushService.init({
|
||||
serverURI: serverURL + "/pushSubscriptionMissingLink1/subscribe",
|
||||
db
|
||||
db,
|
||||
});
|
||||
|
||||
await rejects(
|
||||
await Assert.rejects(
|
||||
PushService.register({
|
||||
scope: 'https://example.net/page/invalid-response',
|
||||
scope: "https://example.net/page/invalid-response",
|
||||
originAttributes: ChromeUtils.originAttributesToSuffix(
|
||||
{ appId: Ci.nsIScriptSecurityManager.NO_APP_ID, inIsolatedMozBrowser: false }),
|
||||
}),
|
||||
/Registration error/,
|
||||
'Expected error for the missing push endpoint.'
|
||||
"Expected error for the missing push endpoint."
|
||||
);
|
||||
|
||||
let record = await db.getAllKeyIDs();
|
||||
ok(record.length === 0, 'Should not store records when the push endpoint is missing.');
|
||||
ok(record.length === 0, "Should not store records when the push endpoint is missing.");
|
||||
PushService.uninit();
|
||||
});
|
||||
|
||||
add_task(async function test_pushSubscriptionLocationBogus() {
|
||||
|
||||
let db = PushServiceHttp2.newPushDB();
|
||||
registerCleanupFunction(() => {
|
||||
return db.drop().then(_ => db.close());
|
||||
|
@ -149,26 +142,25 @@ add_task(async function test_pushSubscriptionLocationBogus() {
|
|||
|
||||
PushService.init({
|
||||
serverURI: serverURL + "/pushSubscriptionLocationBogus/subscribe",
|
||||
db
|
||||
db,
|
||||
});
|
||||
|
||||
await rejects(
|
||||
await Assert.rejects(
|
||||
PushService.register({
|
||||
scope: 'https://example.net/page/invalid-response',
|
||||
scope: "https://example.net/page/invalid-response",
|
||||
originAttributes: ChromeUtils.originAttributesToSuffix(
|
||||
{ appId: Ci.nsIScriptSecurityManager.NO_APP_ID, inIsolatedMozBrowser: false }),
|
||||
}),
|
||||
/Registration error/,
|
||||
'Expected error for the bogus location'
|
||||
"Expected error for the bogus location"
|
||||
);
|
||||
|
||||
let record = await db.getAllKeyIDs();
|
||||
ok(record.length === 0, 'Should not store records when location header is bogus.');
|
||||
ok(record.length === 0, "Should not store records when location header is bogus.");
|
||||
PushService.uninit();
|
||||
});
|
||||
|
||||
add_task(async function test_pushSubscriptionNot2xxCode() {
|
||||
|
||||
let db = PushServiceHttp2.newPushDB();
|
||||
registerCleanupFunction(() => {
|
||||
return db.drop().then(_ => db.close());
|
||||
|
@ -176,19 +168,19 @@ add_task(async function test_pushSubscriptionNot2xxCode() {
|
|||
|
||||
PushService.init({
|
||||
serverURI: serverURL + "/pushSubscriptionNot201Code/subscribe",
|
||||
db
|
||||
db,
|
||||
});
|
||||
|
||||
await rejects(
|
||||
await Assert.rejects(
|
||||
PushService.register({
|
||||
scope: 'https://example.net/page/invalid-response',
|
||||
scope: "https://example.net/page/invalid-response",
|
||||
originAttributes: ChromeUtils.originAttributesToSuffix(
|
||||
{ appId: Ci.nsIScriptSecurityManager.NO_APP_ID, inIsolatedMozBrowser: false }),
|
||||
}),
|
||||
/Registration error/,
|
||||
'Expected error for not 201 responce code.'
|
||||
"Expected error for not 201 responce code."
|
||||
);
|
||||
|
||||
let record = await db.getAllKeyIDs();
|
||||
ok(record.length === 0, 'Should not store records when respons code is not 201.');
|
||||
ok(record.length === 0, "Should not store records when respons code is not 201.");
|
||||
});
|
||||
|
|
|
@ -1,31 +1,31 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
'use strict';
|
||||
"use strict";
|
||||
|
||||
const {PushDB, PushService, PushServiceWebSocket} = serviceExports;
|
||||
|
||||
const userAgentID = '9ce1e6d3-7bdb-4fe9-90a5-def1d64716f1';
|
||||
const channelID = 'c26892c5-6e08-4c16-9f0c-0044697b4d85';
|
||||
const userAgentID = "9ce1e6d3-7bdb-4fe9-90a5-def1d64716f1";
|
||||
const channelID = "c26892c5-6e08-4c16-9f0c-0044697b4d85";
|
||||
|
||||
function run_test() {
|
||||
do_get_profile();
|
||||
setPrefs({
|
||||
userAgentID,
|
||||
requestTimeout: 1000,
|
||||
retryBaseInterval: 150
|
||||
retryBaseInterval: 150,
|
||||
});
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
add_task(async function test_register_flush() {
|
||||
let db = PushServiceWebSocket.newPushDB();
|
||||
registerCleanupFunction(() => {return db.drop().then(_ => db.close());});
|
||||
registerCleanupFunction(() => { return db.drop().then(_ => db.close()); });
|
||||
let record = {
|
||||
channelID: '9bcc7efb-86c7-4457-93ea-e24e6eb59b74',
|
||||
pushEndpoint: 'https://example.org/update/1',
|
||||
scope: 'https://example.com/page/1',
|
||||
originAttributes: '',
|
||||
channelID: "9bcc7efb-86c7-4457-93ea-e24e6eb59b74",
|
||||
pushEndpoint: "https://example.org/update/1",
|
||||
scope: "https://example.com/page/1",
|
||||
originAttributes: "",
|
||||
version: 2,
|
||||
quota: Infinity,
|
||||
systemRecord: true,
|
||||
|
@ -43,54 +43,54 @@ add_task(async function test_register_flush() {
|
|||
return new MockWebSocket(uri, {
|
||||
onHello(request) {
|
||||
this.serverSendMsg(JSON.stringify({
|
||||
messageType: 'hello',
|
||||
messageType: "hello",
|
||||
status: 200,
|
||||
uaid: userAgentID
|
||||
uaid: userAgentID,
|
||||
}));
|
||||
},
|
||||
onRegister(request) {
|
||||
this.serverSendMsg(JSON.stringify({
|
||||
messageType: 'notification',
|
||||
messageType: "notification",
|
||||
updates: [{
|
||||
channelID: request.channelID,
|
||||
version: 2
|
||||
version: 2,
|
||||
}, {
|
||||
channelID: '9bcc7efb-86c7-4457-93ea-e24e6eb59b74',
|
||||
version: 3
|
||||
}]
|
||||
channelID: "9bcc7efb-86c7-4457-93ea-e24e6eb59b74",
|
||||
version: 3,
|
||||
}],
|
||||
}));
|
||||
this.serverSendMsg(JSON.stringify({
|
||||
messageType: 'register',
|
||||
messageType: "register",
|
||||
status: 200,
|
||||
channelID: request.channelID,
|
||||
uaid: userAgentID,
|
||||
pushEndpoint: 'https://example.org/update/2'
|
||||
pushEndpoint: "https://example.org/update/2",
|
||||
}));
|
||||
},
|
||||
onACK: ackDone
|
||||
onACK: ackDone,
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
let newRecord = await PushService.register({
|
||||
scope: 'https://example.com/page/2',
|
||||
originAttributes: '',
|
||||
scope: "https://example.com/page/2",
|
||||
originAttributes: "",
|
||||
});
|
||||
equal(newRecord.endpoint, 'https://example.org/update/2',
|
||||
'Wrong push endpoint in record');
|
||||
equal(newRecord.endpoint, "https://example.org/update/2",
|
||||
"Wrong push endpoint in record");
|
||||
|
||||
let {data: scope} = await notifyPromise;
|
||||
equal(scope, 'https://example.com/page/1', 'Wrong notification scope');
|
||||
equal(scope, "https://example.com/page/1", "Wrong notification scope");
|
||||
|
||||
await ackPromise;
|
||||
|
||||
let prevRecord = await db.getByKeyID(
|
||||
'9bcc7efb-86c7-4457-93ea-e24e6eb59b74');
|
||||
equal(prevRecord.pushEndpoint, 'https://example.org/update/1',
|
||||
'Wrong existing push endpoint');
|
||||
"9bcc7efb-86c7-4457-93ea-e24e6eb59b74");
|
||||
equal(prevRecord.pushEndpoint, "https://example.org/update/1",
|
||||
"Wrong existing push endpoint");
|
||||
strictEqual(prevRecord.version, 3,
|
||||
'Should record version updates sent before register responses');
|
||||
"Should record version updates sent before register responses");
|
||||
|
||||
let registeredRecord = await db.getByPushEndpoint('https://example.org/update/2');
|
||||
ok(!registeredRecord.version, 'Should not record premature updates');
|
||||
let registeredRecord = await db.getByPushEndpoint("https://example.org/update/2");
|
||||
ok(!registeredRecord.version, "Should not record premature updates");
|
||||
});
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
'use strict';
|
||||
"use strict";
|
||||
|
||||
const {PushDB, PushService, PushServiceWebSocket} = serviceExports;
|
||||
|
||||
const userAgentID = '52b2b04c-b6cc-42c6-abdf-bef9cbdbea00';
|
||||
const channelID = 'cafed00d';
|
||||
const userAgentID = "52b2b04c-b6cc-42c6-abdf-bef9cbdbea00";
|
||||
const channelID = "cafed00d";
|
||||
|
||||
function run_test() {
|
||||
do_get_profile();
|
||||
|
@ -16,7 +16,7 @@ function run_test() {
|
|||
|
||||
add_task(async function test_register_invalid_channel() {
|
||||
let db = PushServiceWebSocket.newPushDB();
|
||||
registerCleanupFunction(() => {return db.drop().then(_ => db.close());});
|
||||
registerCleanupFunction(() => { return db.drop().then(_ => db.close()); });
|
||||
|
||||
PushServiceWebSocket._generateID = () => channelID;
|
||||
PushService.init({
|
||||
|
@ -26,33 +26,33 @@ add_task(async function test_register_invalid_channel() {
|
|||
return new MockWebSocket(uri, {
|
||||
onHello(request) {
|
||||
this.serverSendMsg(JSON.stringify({
|
||||
messageType: 'hello',
|
||||
messageType: "hello",
|
||||
uaid: userAgentID,
|
||||
status: 200
|
||||
status: 200,
|
||||
}));
|
||||
},
|
||||
onRegister(request) {
|
||||
this.serverSendMsg(JSON.stringify({
|
||||
messageType: 'register',
|
||||
messageType: "register",
|
||||
status: 403,
|
||||
channelID,
|
||||
error: 'Invalid channel ID'
|
||||
error: "Invalid channel ID",
|
||||
}));
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
await rejects(
|
||||
await Assert.rejects(
|
||||
PushService.register({
|
||||
scope: 'https://example.com/invalid-channel',
|
||||
scope: "https://example.com/invalid-channel",
|
||||
originAttributes: ChromeUtils.originAttributesToSuffix(
|
||||
{ appId: Ci.nsIScriptSecurityManager.NO_APP_ID, inIsolatedMozBrowser: false }),
|
||||
}),
|
||||
/Registration error/,
|
||||
'Expected error for invalid channel ID'
|
||||
"Expected error for invalid channel ID"
|
||||
);
|
||||
|
||||
let record = await db.getByKeyID(channelID);
|
||||
ok(!record, 'Should not store records for error responses');
|
||||
ok(!record, "Should not store records for error responses");
|
||||
});
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
'use strict';
|
||||
"use strict";
|
||||
|
||||
const {PushDB, PushService, PushServiceWebSocket} = serviceExports;
|
||||
|
||||
const userAgentID = 'c9a12e81-ea5e-40f9-8bf4-acee34621671';
|
||||
const channelID = 'c0660af8-b532-4931-81f0-9fd27a12d6ab';
|
||||
const userAgentID = "c9a12e81-ea5e-40f9-8bf4-acee34621671";
|
||||
const channelID = "c0660af8-b532-4931-81f0-9fd27a12d6ab";
|
||||
|
||||
function run_test() {
|
||||
do_get_profile();
|
||||
|
@ -16,7 +16,7 @@ function run_test() {
|
|||
|
||||
add_task(async function test_register_invalid_endpoint() {
|
||||
let db = PushServiceWebSocket.newPushDB();
|
||||
registerCleanupFunction(() => {return db.drop().then(_ => db.close());});
|
||||
registerCleanupFunction(() => { return db.drop().then(_ => db.close()); });
|
||||
|
||||
PushServiceWebSocket._generateID = () => channelID;
|
||||
PushService.init({
|
||||
|
@ -26,34 +26,34 @@ add_task(async function test_register_invalid_endpoint() {
|
|||
return new MockWebSocket(uri, {
|
||||
onHello(request) {
|
||||
this.serverSendMsg(JSON.stringify({
|
||||
messageType: 'hello',
|
||||
messageType: "hello",
|
||||
status: 200,
|
||||
uaid: userAgentID,
|
||||
}));
|
||||
},
|
||||
onRegister(request) {
|
||||
this.serverSendMsg(JSON.stringify({
|
||||
messageType: 'register',
|
||||
messageType: "register",
|
||||
status: 200,
|
||||
channelID,
|
||||
uaid: userAgentID,
|
||||
pushEndpoint: '!@#$%^&*'
|
||||
pushEndpoint: "!@#$%^&*",
|
||||
}));
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
await rejects(
|
||||
await Assert.rejects(
|
||||
PushService.register({
|
||||
scope: 'https://example.net/page/invalid-endpoint',
|
||||
scope: "https://example.net/page/invalid-endpoint",
|
||||
originAttributes: ChromeUtils.originAttributesToSuffix(
|
||||
{ appId: Ci.nsIScriptSecurityManager.NO_APP_ID, inIsolatedMozBrowser: false }),
|
||||
}),
|
||||
/Registration error/,
|
||||
'Expected error for invalid endpoint'
|
||||
"Expected error for invalid endpoint"
|
||||
);
|
||||
|
||||
let record = await db.getByKeyID(channelID);
|
||||
ok(!record, 'Should not store records with invalid endpoints');
|
||||
ok(!record, "Should not store records with invalid endpoints");
|
||||
});
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
'use strict';
|
||||
"use strict";
|
||||
|
||||
const {PushDB, PushService, PushServiceWebSocket} = serviceExports;
|
||||
|
||||
const userAgentID = '8271186b-8073-43a3-adf6-225bd44a8b0a';
|
||||
const channelID = '2d08571e-feab-48a0-9f05-8254c3c7e61f';
|
||||
const userAgentID = "8271186b-8073-43a3-adf6-225bd44a8b0a";
|
||||
const channelID = "2d08571e-feab-48a0-9f05-8254c3c7e61f";
|
||||
|
||||
function run_test() {
|
||||
do_get_profile();
|
||||
setPrefs({
|
||||
requestTimeout: 1000,
|
||||
retryBaseInterval: 150
|
||||
retryBaseInterval: 150,
|
||||
});
|
||||
run_next_test();
|
||||
}
|
||||
|
@ -29,31 +29,31 @@ add_task(async function test_register_invalid_json() {
|
|||
return new MockWebSocket(uri, {
|
||||
onHello(request) {
|
||||
this.serverSendMsg(JSON.stringify({
|
||||
messageType: 'hello',
|
||||
messageType: "hello",
|
||||
status: 200,
|
||||
uaid: userAgentID
|
||||
uaid: userAgentID,
|
||||
}));
|
||||
helloDone();
|
||||
},
|
||||
onRegister(request) {
|
||||
equal(request.channelID, channelID, 'Register: wrong channel ID');
|
||||
this.serverSendMsg(');alert(1);(');
|
||||
equal(request.channelID, channelID, "Register: wrong channel ID");
|
||||
this.serverSendMsg(");alert(1);(");
|
||||
registers++;
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
await rejects(
|
||||
await Assert.rejects(
|
||||
PushService.register({
|
||||
scope: 'https://example.net/page/invalid-json',
|
||||
scope: "https://example.net/page/invalid-json",
|
||||
originAttributes: ChromeUtils.originAttributesToSuffix(
|
||||
{ appId: Ci.nsIScriptSecurityManager.NO_APP_ID, inIsolatedMozBrowser: false }),
|
||||
}),
|
||||
/Registration error/,
|
||||
'Expected error for invalid JSON response'
|
||||
"Expected error for invalid JSON response"
|
||||
);
|
||||
|
||||
await helloPromise;
|
||||
equal(registers, 1, 'Wrong register count');
|
||||
equal(registers, 1, "Wrong register count");
|
||||
});
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
'use strict';
|
||||
"use strict";
|
||||
|
||||
const {PushDB, PushService, PushServiceWebSocket} = serviceExports;
|
||||
|
||||
var userAgentID = '9a2f9efe-2ebb-4bcb-a5d9-9e2b73d30afe';
|
||||
var channelID = '264c2ba0-f6db-4e84-acdb-bd225b62d9e3';
|
||||
var userAgentID = "9a2f9efe-2ebb-4bcb-a5d9-9e2b73d30afe";
|
||||
var channelID = "264c2ba0-f6db-4e84-acdb-bd225b62d9e3";
|
||||
|
||||
function run_test() {
|
||||
do_get_profile();
|
||||
setPrefs({
|
||||
userAgentID,
|
||||
requestTimeout: 1000,
|
||||
retryBaseInterval: 150
|
||||
retryBaseInterval: 150,
|
||||
});
|
||||
run_next_test();
|
||||
}
|
||||
|
@ -30,34 +30,34 @@ add_task(async function test_register_no_id() {
|
|||
return new MockWebSocket(uri, {
|
||||
onHello(request) {
|
||||
this.serverSendMsg(JSON.stringify({
|
||||
messageType: 'hello',
|
||||
messageType: "hello",
|
||||
status: 200,
|
||||
uaid: userAgentID
|
||||
uaid: userAgentID,
|
||||
}));
|
||||
helloDone();
|
||||
},
|
||||
onRegister(request) {
|
||||
registers++;
|
||||
equal(request.channelID, channelID, 'Register: wrong channel ID');
|
||||
equal(request.channelID, channelID, "Register: wrong channel ID");
|
||||
this.serverSendMsg(JSON.stringify({
|
||||
messageType: 'register',
|
||||
status: 200
|
||||
messageType: "register",
|
||||
status: 200,
|
||||
}));
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
await rejects(
|
||||
await Assert.rejects(
|
||||
PushService.register({
|
||||
scope: 'https://example.com/incomplete',
|
||||
scope: "https://example.com/incomplete",
|
||||
originAttributes: ChromeUtils.originAttributesToSuffix(
|
||||
{ appId: Ci.nsIScriptSecurityManager.NO_APP_ID, inIsolatedMozBrowser: false }),
|
||||
}),
|
||||
/Registration error/,
|
||||
'Expected error for incomplete register response'
|
||||
"Expected error for incomplete register response"
|
||||
);
|
||||
|
||||
await helloPromise;
|
||||
equal(registers, 1, 'Wrong register count');
|
||||
equal(registers, 1, "Wrong register count");
|
||||
});
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
'use strict';
|
||||
"use strict";
|
||||
|
||||
const {PushDB, PushService, PushServiceWebSocket} = serviceExports;
|
||||
|
||||
|
@ -9,21 +9,21 @@ function run_test() {
|
|||
do_get_profile();
|
||||
setPrefs({
|
||||
requestTimeout: 1000,
|
||||
retryBaseInterval: 150
|
||||
retryBaseInterval: 150,
|
||||
});
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
add_task(async function test_register_request_queue() {
|
||||
let db = PushServiceWebSocket.newPushDB();
|
||||
registerCleanupFunction(() => {return db.drop().then(_ => db.close());});
|
||||
registerCleanupFunction(() => { return db.drop().then(_ => db.close()); });
|
||||
|
||||
let onHello;
|
||||
let helloPromise = new Promise(resolve => onHello = after(2, function onHello(request) {
|
||||
let helloPromise = new Promise(resolve => onHello = after(2, function onHelloReceived(request) {
|
||||
this.serverSendMsg(JSON.stringify({
|
||||
messageType: 'hello',
|
||||
messageType: "hello",
|
||||
status: 200,
|
||||
uaid: '54b08a9e-59c6-4ed7-bb54-f4fd60d6f606'
|
||||
uaid: "54b08a9e-59c6-4ed7-bb54-f4fd60d6f606",
|
||||
}));
|
||||
resolve();
|
||||
}));
|
||||
|
@ -35,26 +35,28 @@ add_task(async function test_register_request_queue() {
|
|||
return new MockWebSocket(uri, {
|
||||
onHello,
|
||||
onRegister() {
|
||||
ok(false, 'Should cancel timed-out requests');
|
||||
}
|
||||
ok(false, "Should cancel timed-out requests");
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
let firstRegister = PushService.register({
|
||||
scope: 'https://example.com/page/1',
|
||||
scope: "https://example.com/page/1",
|
||||
originAttributes: ChromeUtils.originAttributesToSuffix(
|
||||
{ appId: Ci.nsIScriptSecurityManager.NO_APP_ID, inIsolatedMozBrowser: false }),
|
||||
});
|
||||
let secondRegister = PushService.register({
|
||||
scope: 'https://example.com/page/1',
|
||||
scope: "https://example.com/page/1",
|
||||
originAttributes: ChromeUtils.originAttributesToSuffix(
|
||||
{ appId: Ci.nsIScriptSecurityManager.NO_APP_ID, inIsolatedMozBrowser: false }),
|
||||
});
|
||||
|
||||
await Promise.all([
|
||||
rejects(firstRegister, /Registration error/, 'Should time out the first request'),
|
||||
rejects(secondRegister, /Registration error/, 'Should time out the second request')
|
||||
// eslint-disable-next-line mozilla/rejects-requires-await
|
||||
Assert.rejects(firstRegister, /Registration error/, "Should time out the first request"),
|
||||
// eslint-disable-next-line mozilla/rejects-requires-await
|
||||
Assert.rejects(secondRegister, /Registration error/, "Should time out the second request"),
|
||||
]);
|
||||
|
||||
await helloPromise;
|
||||
|
|
|
@ -1,26 +1,26 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
'use strict';
|
||||
"use strict";
|
||||
|
||||
const {PushDB, PushService, PushServiceWebSocket} = serviceExports;
|
||||
|
||||
const userAgentID = 'b2546987-4f63-49b1-99f7-739cd3c40e44';
|
||||
const channelID = '35a820f7-d7dd-43b3-af21-d65352212ae3';
|
||||
const userAgentID = "b2546987-4f63-49b1-99f7-739cd3c40e44";
|
||||
const channelID = "35a820f7-d7dd-43b3-af21-d65352212ae3";
|
||||
|
||||
function run_test() {
|
||||
do_get_profile();
|
||||
setPrefs({
|
||||
userAgentID,
|
||||
requestTimeout: 1000,
|
||||
retryBaseInterval: 150
|
||||
retryBaseInterval: 150,
|
||||
});
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
add_task(async function test_register_rollback() {
|
||||
let db = PushServiceWebSocket.newPushDB();
|
||||
registerCleanupFunction(() => {return db.drop().then(_ => db.close());});
|
||||
registerCleanupFunction(() => { return db.drop().then(_ => db.close()); });
|
||||
|
||||
let handshakes = 0;
|
||||
let registers = 0;
|
||||
|
@ -31,58 +31,58 @@ add_task(async function test_register_rollback() {
|
|||
serverURI: "wss://push.example.org/",
|
||||
db: makeStub(db, {
|
||||
put(prev, record) {
|
||||
return Promise.reject('universe has imploded');
|
||||
}
|
||||
return Promise.reject("universe has imploded");
|
||||
},
|
||||
}),
|
||||
makeWebSocket(uri) {
|
||||
return new MockWebSocket(uri, {
|
||||
onHello(request) {
|
||||
handshakes++;
|
||||
equal(request.uaid, userAgentID, 'Handshake: wrong device ID');
|
||||
equal(request.uaid, userAgentID, "Handshake: wrong device ID");
|
||||
this.serverSendMsg(JSON.stringify({
|
||||
messageType: 'hello',
|
||||
messageType: "hello",
|
||||
status: 200,
|
||||
uaid: userAgentID
|
||||
uaid: userAgentID,
|
||||
}));
|
||||
},
|
||||
onRegister(request) {
|
||||
equal(request.channelID, channelID, 'Register: wrong channel ID');
|
||||
equal(request.channelID, channelID, "Register: wrong channel ID");
|
||||
registers++;
|
||||
this.serverSendMsg(JSON.stringify({
|
||||
messageType: 'register',
|
||||
messageType: "register",
|
||||
status: 200,
|
||||
uaid: userAgentID,
|
||||
channelID,
|
||||
pushEndpoint: 'https://example.com/update/rollback'
|
||||
pushEndpoint: "https://example.com/update/rollback",
|
||||
}));
|
||||
},
|
||||
onUnregister(request) {
|
||||
equal(request.channelID, channelID, 'Unregister: wrong channel ID');
|
||||
equal(request.code, 200, 'Expected manual unregister reason');
|
||||
equal(request.channelID, channelID, "Unregister: wrong channel ID");
|
||||
equal(request.code, 200, "Expected manual unregister reason");
|
||||
this.serverSendMsg(JSON.stringify({
|
||||
messageType: 'unregister',
|
||||
messageType: "unregister",
|
||||
status: 200,
|
||||
channelID
|
||||
channelID,
|
||||
}));
|
||||
unregisterDone();
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
// Should return a rejected promise if storage fails.
|
||||
await rejects(
|
||||
await Assert.rejects(
|
||||
PushService.register({
|
||||
scope: 'https://example.com/storage-error',
|
||||
scope: "https://example.com/storage-error",
|
||||
originAttributes: ChromeUtils.originAttributesToSuffix(
|
||||
{ appId: Ci.nsIScriptSecurityManager.NO_APP_ID, inIsolatedMozBrowser: false }),
|
||||
}),
|
||||
/universe has imploded/,
|
||||
'Expected error for unregister database failure'
|
||||
"Expected error for unregister database failure"
|
||||
);
|
||||
|
||||
// Should send an out-of-band unregister request.
|
||||
await unregisterPromise;
|
||||
equal(handshakes, 1, 'Wrong handshake count');
|
||||
equal(registers, 1, 'Wrong register count');
|
||||
equal(handshakes, 1, "Wrong handshake count");
|
||||
equal(registers, 1, "Wrong register count");
|
||||
});
|
||||
|
|
|
@ -1,26 +1,26 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
'use strict';
|
||||
"use strict";
|
||||
|
||||
const {PushDB, PushService, PushServiceWebSocket} = serviceExports;
|
||||
|
||||
const userAgentID = 'bd744428-f125-436a-b6d0-dd0c9845837f';
|
||||
const channelID = '0ef2ad4a-6c49-41ad-af6e-95d2425276bf';
|
||||
const userAgentID = "bd744428-f125-436a-b6d0-dd0c9845837f";
|
||||
const channelID = "0ef2ad4a-6c49-41ad-af6e-95d2425276bf";
|
||||
|
||||
function run_test() {
|
||||
do_get_profile();
|
||||
setPrefs({
|
||||
userAgentID,
|
||||
requestTimeout: 1000,
|
||||
retryBaseInterval: 150
|
||||
retryBaseInterval: 150,
|
||||
});
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
add_task(async function test_register_success() {
|
||||
let db = PushServiceWebSocket.newPushDB();
|
||||
registerCleanupFunction(() => {return db.drop().then(_ => db.close());});
|
||||
registerCleanupFunction(() => { return db.drop().then(_ => db.close()); });
|
||||
|
||||
PushServiceWebSocket._generateID = () => channelID;
|
||||
PushService.init({
|
||||
|
@ -29,49 +29,49 @@ add_task(async function test_register_success() {
|
|||
makeWebSocket(uri) {
|
||||
return new MockWebSocket(uri, {
|
||||
onHello(data) {
|
||||
equal(data.messageType, 'hello', 'Handshake: wrong message type');
|
||||
equal(data.uaid, userAgentID, 'Handshake: wrong device ID');
|
||||
equal(data.messageType, "hello", "Handshake: wrong message type");
|
||||
equal(data.uaid, userAgentID, "Handshake: wrong device ID");
|
||||
this.serverSendMsg(JSON.stringify({
|
||||
messageType: 'hello',
|
||||
messageType: "hello",
|
||||
status: 200,
|
||||
uaid: userAgentID
|
||||
uaid: userAgentID,
|
||||
}));
|
||||
},
|
||||
onRegister(data) {
|
||||
equal(data.messageType, 'register', 'Register: wrong message type');
|
||||
equal(data.channelID, channelID, 'Register: wrong channel ID');
|
||||
equal(data.messageType, "register", "Register: wrong message type");
|
||||
equal(data.channelID, channelID, "Register: wrong channel ID");
|
||||
this.serverSendMsg(JSON.stringify({
|
||||
messageType: 'register',
|
||||
messageType: "register",
|
||||
status: 200,
|
||||
channelID: channelID,
|
||||
channelID,
|
||||
uaid: userAgentID,
|
||||
pushEndpoint: 'https://example.com/update/1',
|
||||
pushEndpoint: "https://example.com/update/1",
|
||||
}));
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
let subModifiedPromise = promiseObserverNotification(
|
||||
PushServiceComponent.subscriptionModifiedTopic);
|
||||
|
||||
let newRecord = await PushService.register({
|
||||
scope: 'https://example.org/1',
|
||||
scope: "https://example.org/1",
|
||||
originAttributes: ChromeUtils.originAttributesToSuffix(
|
||||
{ appId: Ci.nsIScriptSecurityManager.NO_APP_ID, inIsolatedMozBrowser: false }),
|
||||
});
|
||||
equal(newRecord.endpoint, 'https://example.com/update/1',
|
||||
'Wrong push endpoint in registration record');
|
||||
equal(newRecord.endpoint, "https://example.com/update/1",
|
||||
"Wrong push endpoint in registration record");
|
||||
|
||||
let {data: subModifiedScope} = await subModifiedPromise;
|
||||
equal(subModifiedScope, 'https://example.org/1',
|
||||
'Should fire a subscription modified event after subscribing');
|
||||
equal(subModifiedScope, "https://example.org/1",
|
||||
"Should fire a subscription modified event after subscribing");
|
||||
|
||||
let record = await db.getByKeyID(channelID);
|
||||
equal(record.channelID, channelID,
|
||||
'Wrong channel ID in database record');
|
||||
equal(record.pushEndpoint, 'https://example.com/update/1',
|
||||
'Wrong push endpoint in database record');
|
||||
"Wrong channel ID in database record");
|
||||
equal(record.pushEndpoint, "https://example.com/update/1",
|
||||
"Wrong push endpoint in database record");
|
||||
equal(record.quota, 16,
|
||||
'Wrong quota in database record');
|
||||
"Wrong quota in database record");
|
||||
});
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
'use strict';
|
||||
"use strict";
|
||||
|
||||
const {PushDB, PushService, PushServiceHttp2} = serviceExports;
|
||||
|
||||
var prefs;
|
||||
var serverURL;
|
||||
var serverPort = -1;
|
||||
var pushEnabled;
|
||||
|
@ -16,20 +15,18 @@ function run_test() {
|
|||
serverPort = getTestServerPort();
|
||||
|
||||
do_get_profile();
|
||||
prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
|
||||
|
||||
pushEnabled = prefs.getBoolPref("dom.push.enabled");
|
||||
pushConnectionEnabled = prefs.getBoolPref("dom.push.connection.enabled");
|
||||
pushEnabled = Services.prefs.getBoolPref("dom.push.enabled");
|
||||
pushConnectionEnabled = Services.prefs.getBoolPref("dom.push.connection.enabled");
|
||||
|
||||
// Set to allow the cert presented by our H2 server
|
||||
var oldPref = prefs.getIntPref("network.http.speculative-parallel-limit");
|
||||
prefs.setIntPref("network.http.speculative-parallel-limit", 0);
|
||||
prefs.setBoolPref("dom.push.enabled", true);
|
||||
prefs.setBoolPref("dom.push.connection.enabled", true);
|
||||
var oldPref = Services.prefs.getIntPref("network.http.speculative-parallel-limit");
|
||||
Services.prefs.setIntPref("network.http.speculative-parallel-limit", 0);
|
||||
Services.prefs.setBoolPref("dom.push.enabled", true);
|
||||
Services.prefs.setBoolPref("dom.push.connection.enabled", true);
|
||||
|
||||
trustHttp2CA();
|
||||
|
||||
prefs.setIntPref("network.http.speculative-parallel-limit", oldPref);
|
||||
Services.prefs.setIntPref("network.http.speculative-parallel-limit", oldPref);
|
||||
|
||||
serverURL = "https://localhost:" + serverPort;
|
||||
|
||||
|
@ -37,83 +34,79 @@ function run_test() {
|
|||
}
|
||||
|
||||
add_task(async function test_setup() {
|
||||
|
||||
db = PushServiceHttp2.newPushDB();
|
||||
registerCleanupFunction(() => {
|
||||
return db.drop().then(_ => db.close());
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
add_task(async function test_pushSubscriptionSuccess() {
|
||||
|
||||
PushService.init({
|
||||
serverURI: serverURL + "/pushSubscriptionSuccess/subscribe",
|
||||
db
|
||||
db,
|
||||
});
|
||||
|
||||
let newRecord = await PushService.register({
|
||||
scope: 'https://example.org/1',
|
||||
scope: "https://example.org/1",
|
||||
originAttributes: ChromeUtils.originAttributesToSuffix(
|
||||
{ appId: Ci.nsIScriptSecurityManager.NO_APP_ID, inIsolatedMozBrowser: false }),
|
||||
});
|
||||
|
||||
var subscriptionUri = serverURL + '/pushSubscriptionSuccesss';
|
||||
var pushEndpoint = serverURL + '/pushEndpointSuccess';
|
||||
var pushReceiptEndpoint = serverURL + '/receiptPushEndpointSuccess';
|
||||
var subscriptionUri = serverURL + "/pushSubscriptionSuccesss";
|
||||
var pushEndpoint = serverURL + "/pushEndpointSuccess";
|
||||
var pushReceiptEndpoint = serverURL + "/receiptPushEndpointSuccess";
|
||||
equal(newRecord.endpoint, pushEndpoint,
|
||||
'Wrong push endpoint in registration record');
|
||||
"Wrong push endpoint in registration record");
|
||||
|
||||
equal(newRecord.pushReceiptEndpoint, pushReceiptEndpoint,
|
||||
'Wrong push endpoint receipt in registration record');
|
||||
"Wrong push endpoint receipt in registration record");
|
||||
|
||||
let record = await db.getByKeyID(subscriptionUri);
|
||||
equal(record.subscriptionUri, subscriptionUri,
|
||||
'Wrong subscription ID in database record');
|
||||
"Wrong subscription ID in database record");
|
||||
equal(record.pushEndpoint, pushEndpoint,
|
||||
'Wrong push endpoint in database record');
|
||||
"Wrong push endpoint in database record");
|
||||
equal(record.pushReceiptEndpoint, pushReceiptEndpoint,
|
||||
'Wrong push endpoint receipt in database record');
|
||||
equal(record.scope, 'https://example.org/1',
|
||||
'Wrong scope in database record');
|
||||
"Wrong push endpoint receipt in database record");
|
||||
equal(record.scope, "https://example.org/1",
|
||||
"Wrong scope in database record");
|
||||
|
||||
PushService.uninit()
|
||||
PushService.uninit();
|
||||
});
|
||||
|
||||
add_task(async function test_pushSubscriptionMissingLink2() {
|
||||
|
||||
PushService.init({
|
||||
serverURI: serverURL + "/pushSubscriptionMissingLink2/subscribe",
|
||||
db
|
||||
db,
|
||||
});
|
||||
|
||||
let newRecord = await PushService.register({
|
||||
scope: 'https://example.org/no_receiptEndpoint',
|
||||
scope: "https://example.org/no_receiptEndpoint",
|
||||
originAttributes: ChromeUtils.originAttributesToSuffix(
|
||||
{ appId: Ci.nsIScriptSecurityManager.NO_APP_ID, inIsolatedMozBrowser: false }),
|
||||
});
|
||||
|
||||
var subscriptionUri = serverURL + '/subscriptionMissingLink2';
|
||||
var pushEndpoint = serverURL + '/pushEndpointMissingLink2';
|
||||
var pushReceiptEndpoint = '';
|
||||
var subscriptionUri = serverURL + "/subscriptionMissingLink2";
|
||||
var pushEndpoint = serverURL + "/pushEndpointMissingLink2";
|
||||
var pushReceiptEndpoint = "";
|
||||
equal(newRecord.endpoint, pushEndpoint,
|
||||
'Wrong push endpoint in registration record');
|
||||
"Wrong push endpoint in registration record");
|
||||
|
||||
equal(newRecord.pushReceiptEndpoint, pushReceiptEndpoint,
|
||||
'Wrong push endpoint receipt in registration record');
|
||||
"Wrong push endpoint receipt in registration record");
|
||||
|
||||
let record = await db.getByKeyID(subscriptionUri);
|
||||
equal(record.subscriptionUri, subscriptionUri,
|
||||
'Wrong subscription ID in database record');
|
||||
"Wrong subscription ID in database record");
|
||||
equal(record.pushEndpoint, pushEndpoint,
|
||||
'Wrong push endpoint in database record');
|
||||
"Wrong push endpoint in database record");
|
||||
equal(record.pushReceiptEndpoint, pushReceiptEndpoint,
|
||||
'Wrong push endpoint receipt in database record');
|
||||
equal(record.scope, 'https://example.org/no_receiptEndpoint',
|
||||
'Wrong scope in database record');
|
||||
"Wrong push endpoint receipt in database record");
|
||||
equal(record.scope, "https://example.org/no_receiptEndpoint",
|
||||
"Wrong scope in database record");
|
||||
});
|
||||
|
||||
add_task(async function test_complete() {
|
||||
prefs.setBoolPref("dom.push.enabled", pushEnabled);
|
||||
prefs.setBoolPref("dom.push.connection.enabled", pushConnectionEnabled);
|
||||
Services.prefs.setBoolPref("dom.push.enabled", pushEnabled);
|
||||
Services.prefs.setBoolPref("dom.push.connection.enabled", pushConnectionEnabled);
|
||||
});
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
'use strict';
|
||||
"use strict";
|
||||
|
||||
const {PushDB, PushService, PushServiceWebSocket} = serviceExports;
|
||||
|
||||
const userAgentID = 'a4be0df9-b16d-4b5f-8f58-0f93b6f1e23d';
|
||||
const channelID = 'e1944e0b-48df-45e7-bdc0-d1fbaa7986d3';
|
||||
const userAgentID = "a4be0df9-b16d-4b5f-8f58-0f93b6f1e23d";
|
||||
const channelID = "e1944e0b-48df-45e7-bdc0-d1fbaa7986d3";
|
||||
|
||||
function run_test() {
|
||||
do_get_profile();
|
||||
setPrefs({
|
||||
requestTimeout: 1000,
|
||||
retryBaseInterval: 150
|
||||
retryBaseInterval: 150,
|
||||
});
|
||||
run_next_test();
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ add_task(async function test_register_timeout() {
|
|||
let registers = 0;
|
||||
|
||||
let db = PushServiceWebSocket.newPushDB();
|
||||
registerCleanupFunction(() => {return db.drop().then(_ => db.close());});
|
||||
registerCleanupFunction(() => { return db.drop().then(_ => db.close()); });
|
||||
|
||||
PushServiceWebSocket._generateID = () => channelID;
|
||||
PushService.init({
|
||||
|
@ -34,55 +34,56 @@ add_task(async function test_register_timeout() {
|
|||
return new MockWebSocket(uri, {
|
||||
onHello(request) {
|
||||
if (handshakes === 0) {
|
||||
equal(request.uaid, null, 'Should not include device ID');
|
||||
equal(request.uaid, null, "Should not include device ID");
|
||||
} else if (handshakes === 1) {
|
||||
// Should use the previously-issued device ID when reconnecting,
|
||||
// but should not include the timed-out channel ID.
|
||||
equal(request.uaid, userAgentID,
|
||||
'Should include device ID on reconnect');
|
||||
"Should include device ID on reconnect");
|
||||
} else {
|
||||
ok(false, 'Unexpected reconnect attempt ' + handshakes);
|
||||
ok(false, "Unexpected reconnect attempt " + handshakes);
|
||||
}
|
||||
handshakes++;
|
||||
this.serverSendMsg(JSON.stringify({
|
||||
messageType: 'hello',
|
||||
messageType: "hello",
|
||||
status: 200,
|
||||
uaid: userAgentID,
|
||||
}));
|
||||
},
|
||||
onRegister(request) {
|
||||
equal(request.channelID, channelID,
|
||||
'Wrong channel ID in register request');
|
||||
"Wrong channel ID in register request");
|
||||
// eslint-disable-next-line mozilla/no-arbitrary-setTimeout
|
||||
setTimeout(() => {
|
||||
// Should ignore replies for timed-out requests.
|
||||
this.serverSendMsg(JSON.stringify({
|
||||
messageType: 'register',
|
||||
messageType: "register",
|
||||
status: 200,
|
||||
channelID: channelID,
|
||||
channelID,
|
||||
uaid: userAgentID,
|
||||
pushEndpoint: 'https://example.com/update/timeout',
|
||||
pushEndpoint: "https://example.com/update/timeout",
|
||||
}));
|
||||
timeoutDone();
|
||||
}, 2000);
|
||||
registers++;
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
await rejects(
|
||||
await Assert.rejects(
|
||||
PushService.register({
|
||||
scope: 'https://example.net/page/timeout',
|
||||
scope: "https://example.net/page/timeout",
|
||||
originAttributes: ChromeUtils.originAttributesToSuffix(
|
||||
{ appId: Ci.nsIScriptSecurityManager.NO_APP_ID, inIsolatedMozBrowser: false }),
|
||||
}),
|
||||
/Registration error/,
|
||||
'Expected error for request timeout'
|
||||
"Expected error for request timeout"
|
||||
);
|
||||
|
||||
let record = await db.getByKeyID(channelID);
|
||||
ok(!record, 'Should not store records for timed-out responses');
|
||||
ok(!record, "Should not store records for timed-out responses");
|
||||
|
||||
await timeoutPromise;
|
||||
equal(registers, 1, 'Should not handle timed-out register requests');
|
||||
equal(registers, 1, "Should not handle timed-out register requests");
|
||||
});
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
'use strict';
|
||||
"use strict";
|
||||
|
||||
const {PushDB, PushService, PushServiceWebSocket} = serviceExports;
|
||||
|
||||
const userAgentID = '84afc774-6995-40d1-9c90-8c34ddcd0cb4';
|
||||
const clientChannelID = '4b42a681c99e4dfbbb166a7e01a09b8b';
|
||||
const serverChannelID = '3f5aeb89c6e8405a9569619522783436';
|
||||
const userAgentID = "84afc774-6995-40d1-9c90-8c34ddcd0cb4";
|
||||
const clientChannelID = "4b42a681c99e4dfbbb166a7e01a09b8b";
|
||||
const serverChannelID = "3f5aeb89c6e8405a9569619522783436";
|
||||
|
||||
function run_test() {
|
||||
do_get_profile();
|
||||
setPrefs({
|
||||
userAgentID,
|
||||
requestTimeout: 1000,
|
||||
retryBaseInterval: 150
|
||||
retryBaseInterval: 150,
|
||||
});
|
||||
run_next_test();
|
||||
}
|
||||
|
@ -32,38 +32,38 @@ add_task(async function test_register_wrong_id() {
|
|||
return new MockWebSocket(uri, {
|
||||
onHello(request) {
|
||||
this.serverSendMsg(JSON.stringify({
|
||||
messageType: 'hello',
|
||||
messageType: "hello",
|
||||
status: 200,
|
||||
uaid: userAgentID
|
||||
uaid: userAgentID,
|
||||
}));
|
||||
helloDone();
|
||||
},
|
||||
onRegister(request) {
|
||||
equal(request.channelID, clientChannelID,
|
||||
'Register: wrong channel ID');
|
||||
"Register: wrong channel ID");
|
||||
registers++;
|
||||
this.serverSendMsg(JSON.stringify({
|
||||
messageType: 'register',
|
||||
messageType: "register",
|
||||
status: 200,
|
||||
// Reply with a different channel ID. Since the ID is used as a
|
||||
// nonce, the registration request will time out.
|
||||
channelID: serverChannelID
|
||||
channelID: serverChannelID,
|
||||
}));
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
await rejects(
|
||||
await Assert.rejects(
|
||||
PushService.register({
|
||||
scope: 'https://example.com/mismatched',
|
||||
scope: "https://example.com/mismatched",
|
||||
originAttributes: ChromeUtils.originAttributesToSuffix(
|
||||
{ appId: Ci.nsIScriptSecurityManager.NO_APP_ID, inIsolatedMozBrowser: false }),
|
||||
}),
|
||||
/Registration error/,
|
||||
'Expected error for mismatched register reply'
|
||||
"Expected error for mismatched register reply"
|
||||
);
|
||||
|
||||
await helloPromise;
|
||||
equal(registers, 1, 'Wrong register count');
|
||||
equal(registers, 1, "Wrong register count");
|
||||
});
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
'use strict';
|
||||
"use strict";
|
||||
|
||||
const {PushDB, PushService} = serviceExports;
|
||||
|
||||
const userAgentID = 'c293fdc5-a75e-4eb1-af88-a203991c0787';
|
||||
const userAgentID = "c293fdc5-a75e-4eb1-af88-a203991c0787";
|
||||
|
||||
function run_test() {
|
||||
do_get_profile();
|
||||
setPrefs({
|
||||
requestTimeout: 1000,
|
||||
retryBaseInterval: 150
|
||||
retryBaseInterval: 150,
|
||||
});
|
||||
run_next_test();
|
||||
}
|
||||
|
@ -21,43 +21,43 @@ add_task(async function test_register_wrong_type() {
|
|||
let helloDone;
|
||||
let helloPromise = new Promise(resolve => helloDone = after(2, resolve));
|
||||
|
||||
PushService._generateID = () => '1234';
|
||||
PushService._generateID = () => "1234";
|
||||
PushService.init({
|
||||
serverURI: "wss://push.example.org/",
|
||||
makeWebSocket(uri) {
|
||||
return new MockWebSocket(uri, {
|
||||
onHello(request) {
|
||||
this.serverSendMsg(JSON.stringify({
|
||||
messageType: 'hello',
|
||||
messageType: "hello",
|
||||
status: 200,
|
||||
uaid: userAgentID
|
||||
uaid: userAgentID,
|
||||
}));
|
||||
helloDone();
|
||||
},
|
||||
onRegister(request) {
|
||||
registers++;
|
||||
this.serverSendMsg(JSON.stringify({
|
||||
messageType: 'register',
|
||||
messageType: "register",
|
||||
status: 200,
|
||||
channelID: 1234,
|
||||
uaid: userAgentID,
|
||||
pushEndpoint: 'https://example.org/update/wrong-type'
|
||||
pushEndpoint: "https://example.org/update/wrong-type",
|
||||
}));
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
await rejects(
|
||||
await Assert.rejects(
|
||||
PushService.register({
|
||||
scope: 'https://example.com/mistyped',
|
||||
scope: "https://example.com/mistyped",
|
||||
originAttributes: ChromeUtils.originAttributesToSuffix(
|
||||
{ appId: Ci.nsIScriptSecurityManager.NO_APP_ID, inIsolatedMozBrowser: false }),
|
||||
}),
|
||||
/Registration error/,
|
||||
'Expected error for non-string channel ID'
|
||||
"Expected error for non-string channel ID"
|
||||
);
|
||||
|
||||
await helloPromise;
|
||||
equal(registers, 1, 'Wrong register count');
|
||||
equal(registers, 1, "Wrong register count");
|
||||
});
|
||||
|
|
|
@ -1,43 +1,43 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
'use strict';
|
||||
"use strict";
|
||||
|
||||
const {PushDB, PushService, PushServiceWebSocket} = serviceExports;
|
||||
|
||||
function run_test() {
|
||||
do_get_profile();
|
||||
setPrefs({
|
||||
userAgentID: '6faed1f0-1439-4aac-a978-db21c81cd5eb'
|
||||
userAgentID: "6faed1f0-1439-4aac-a978-db21c81cd5eb",
|
||||
});
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
add_task(async function test_registrations_error() {
|
||||
let db = PushServiceWebSocket.newPushDB();
|
||||
registerCleanupFunction(() => {return db.drop().then(_ => db.close());});
|
||||
registerCleanupFunction(() => { return db.drop().then(_ => db.close()); });
|
||||
|
||||
PushService.init({
|
||||
serverURI: "wss://push.example.org/",
|
||||
db: makeStub(db, {
|
||||
getByIdentifiers(prev, scope) {
|
||||
return Promise.reject('Database error');
|
||||
}
|
||||
return Promise.reject("Database error");
|
||||
},
|
||||
}),
|
||||
makeWebSocket(uri) {
|
||||
return new MockWebSocket(uri);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
await rejects(
|
||||
await Assert.rejects(
|
||||
PushService.registration({
|
||||
scope: 'https://example.net/1',
|
||||
scope: "https://example.net/1",
|
||||
originAttributes: ChromeUtils.originAttributesToSuffix(
|
||||
{ appId: Ci.nsIScriptSecurityManager.NO_APP_ID, inIsolatedMozBrowser: false }),
|
||||
}),
|
||||
function(error) {
|
||||
return error == 'Database error';
|
||||
return error == "Database error";
|
||||
},
|
||||
'Wrong message'
|
||||
"Wrong message"
|
||||
);
|
||||
});
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
'use strict';
|
||||
"use strict";
|
||||
|
||||
const {PushDB, PushService, PushServiceHttp2} = serviceExports;
|
||||
|
||||
|
@ -12,26 +12,26 @@ function run_test() {
|
|||
|
||||
add_task(async function test_registrations_error() {
|
||||
let db = PushServiceHttp2.newPushDB();
|
||||
registerCleanupFunction(() => {return db.drop().then(_ => db.close());});
|
||||
registerCleanupFunction(() => { return db.drop().then(_ => db.close()); });
|
||||
|
||||
PushService.init({
|
||||
serverURI: "https://push.example.org/",
|
||||
db: makeStub(db, {
|
||||
getByIdentifiers() {
|
||||
return Promise.reject('Database error');
|
||||
}
|
||||
return Promise.reject("Database error");
|
||||
},
|
||||
}),
|
||||
});
|
||||
|
||||
await rejects(
|
||||
await Assert.rejects(
|
||||
PushService.registration({
|
||||
scope: 'https://example.net/1',
|
||||
scope: "https://example.net/1",
|
||||
originAttributes: ChromeUtils.originAttributesToSuffix(
|
||||
{ appId: Ci.nsIScriptSecurityManager.NO_APP_ID, inIsolatedMozBrowser: false }),
|
||||
}),
|
||||
function(error) {
|
||||
return error == 'Database error';
|
||||
return error == "Database error";
|
||||
},
|
||||
'Wrong message'
|
||||
"Wrong message"
|
||||
);
|
||||
});
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
'use strict';
|
||||
"use strict";
|
||||
|
||||
const {PushDB, PushService} = serviceExports;
|
||||
|
||||
|
@ -16,11 +16,11 @@ add_task(async function test_registration_missing_scope() {
|
|||
serverURI: "wss://push.example.org/",
|
||||
makeWebSocket(uri) {
|
||||
return new MockWebSocket(uri);
|
||||
}
|
||||
},
|
||||
});
|
||||
await rejects(
|
||||
PushService.registration({ scope: '', originAttributes: '' }),
|
||||
await Assert.rejects(
|
||||
PushService.registration({ scope: "", originAttributes: "" }),
|
||||
/Invalid page record/,
|
||||
'Record missing page and manifest URLs'
|
||||
"Record missing page and manifest URLs"
|
||||
);
|
||||
});
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
'use strict';
|
||||
"use strict";
|
||||
|
||||
const {PushDB, PushService} = serviceExports;
|
||||
|
||||
const userAgentID = 'a722e448-c481-4c48-aea0-fc411cb7c9ed';
|
||||
const userAgentID = "a722e448-c481-4c48-aea0-fc411cb7c9ed";
|
||||
|
||||
function run_test() {
|
||||
do_get_profile();
|
||||
|
@ -19,13 +19,13 @@ add_task(async function test_registration_none() {
|
|||
serverURI: "wss://push.example.org/",
|
||||
makeWebSocket(uri) {
|
||||
return new MockWebSocket(uri);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
let registration = await PushService.registration({
|
||||
scope: 'https://example.net/1',
|
||||
scope: "https://example.net/1",
|
||||
originAttributes: ChromeUtils.originAttributesToSuffix(
|
||||
{ appId: Ci.nsIScriptSecurityManager.NO_APP_ID, inIsolatedMozBrowser: false }),
|
||||
});
|
||||
ok(!registration, 'Should not open a connection without registration');
|
||||
ok(!registration, "Should not open a connection without registration");
|
||||
});
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
'use strict';
|
||||
"use strict";
|
||||
|
||||
const {PushDB, PushService, PushServiceWebSocket} = serviceExports;
|
||||
|
||||
const userAgentID = '997ee7ba-36b1-4526-ae9e-2d3f38d6efe8';
|
||||
const userAgentID = "997ee7ba-36b1-4526-ae9e-2d3f38d6efe8";
|
||||
|
||||
function run_test() {
|
||||
do_get_profile();
|
||||
|
@ -15,26 +15,26 @@ function run_test() {
|
|||
|
||||
add_task(async function test_registration_success() {
|
||||
let db = PushServiceWebSocket.newPushDB();
|
||||
registerCleanupFunction(() => {return db.drop().then(_ => db.close());});
|
||||
registerCleanupFunction(() => { return db.drop().then(_ => db.close()); });
|
||||
let records = [{
|
||||
channelID: 'bf001fe0-2684-42f2-bc4d-a3e14b11dd5b',
|
||||
pushEndpoint: 'https://example.com/update/same-manifest/1',
|
||||
scope: 'https://example.net/a',
|
||||
originAttributes: '',
|
||||
channelID: "bf001fe0-2684-42f2-bc4d-a3e14b11dd5b",
|
||||
pushEndpoint: "https://example.com/update/same-manifest/1",
|
||||
scope: "https://example.net/a",
|
||||
originAttributes: "",
|
||||
version: 5,
|
||||
quota: Infinity,
|
||||
}, {
|
||||
channelID: 'f6edfbcd-79d6-49b8-9766-48b9dcfeff0f',
|
||||
pushEndpoint: 'https://example.com/update/same-manifest/2',
|
||||
scope: 'https://example.net/b',
|
||||
channelID: "f6edfbcd-79d6-49b8-9766-48b9dcfeff0f",
|
||||
pushEndpoint: "https://example.com/update/same-manifest/2",
|
||||
scope: "https://example.net/b",
|
||||
originAttributes: ChromeUtils.originAttributesToSuffix(
|
||||
{ appId: 42 }),
|
||||
version: 10,
|
||||
quota: Infinity,
|
||||
}, {
|
||||
channelID: 'b1cf38c9-6836-4d29-8a30-a3e98d59b728',
|
||||
pushEndpoint: 'https://example.org/update/different-manifest',
|
||||
scope: 'https://example.org/c',
|
||||
channelID: "b1cf38c9-6836-4d29-8a30-a3e98d59b728",
|
||||
pushEndpoint: "https://example.org/update/different-manifest",
|
||||
scope: "https://example.org/c",
|
||||
originAttributes: ChromeUtils.originAttributesToSuffix(
|
||||
{ appId: 42, inIsolatedMozBrowser: true }),
|
||||
version: 15,
|
||||
|
@ -51,28 +51,28 @@ add_task(async function test_registration_success() {
|
|||
makeWebSocket(uri) {
|
||||
return new MockWebSocket(uri, {
|
||||
onHello(request) {
|
||||
equal(request.uaid, userAgentID, 'Wrong device ID in handshake');
|
||||
equal(request.uaid, userAgentID, "Wrong device ID in handshake");
|
||||
this.serverSendMsg(JSON.stringify({
|
||||
messageType: 'hello',
|
||||
messageType: "hello",
|
||||
status: 200,
|
||||
uaid: userAgentID
|
||||
uaid: userAgentID,
|
||||
}));
|
||||
handshakeDone();
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
await handshakePromise;
|
||||
|
||||
let registration = await PushService.registration({
|
||||
scope: 'https://example.net/a',
|
||||
originAttributes: '',
|
||||
scope: "https://example.net/a",
|
||||
originAttributes: "",
|
||||
});
|
||||
equal(
|
||||
registration.endpoint,
|
||||
'https://example.com/update/same-manifest/1',
|
||||
'Wrong push endpoint for scope'
|
||||
"https://example.com/update/same-manifest/1",
|
||||
"Wrong push endpoint for scope"
|
||||
);
|
||||
equal(registration.version, 5, 'Wrong version for scope');
|
||||
equal(registration.version, 5, "Wrong version for scope");
|
||||
});
|
||||
|
|
|
@ -1,25 +1,21 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
'use strict';
|
||||
"use strict";
|
||||
|
||||
const {PushDB, PushService, PushServiceHttp2} = serviceExports;
|
||||
|
||||
var prefs;
|
||||
|
||||
var serverPort = -1;
|
||||
|
||||
function run_test() {
|
||||
serverPort = getTestServerPort();
|
||||
|
||||
do_get_profile();
|
||||
prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
|
||||
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
add_task(async function test_pushNotifications() {
|
||||
|
||||
let db = PushServiceHttp2.newPushDB();
|
||||
registerCleanupFunction(() => {
|
||||
return db.drop().then(_ => db.close());
|
||||
|
@ -28,26 +24,26 @@ add_task(async function test_pushNotifications() {
|
|||
var serverURL = "https://localhost:" + serverPort;
|
||||
|
||||
let records = [{
|
||||
subscriptionUri: serverURL + '/subscriptionA',
|
||||
pushEndpoint: serverURL + '/pushEndpointA',
|
||||
pushReceiptEndpoint: serverURL + '/pushReceiptEndpointA',
|
||||
scope: 'https://example.net/a',
|
||||
subscriptionUri: serverURL + "/subscriptionA",
|
||||
pushEndpoint: serverURL + "/pushEndpointA",
|
||||
pushReceiptEndpoint: serverURL + "/pushReceiptEndpointA",
|
||||
scope: "https://example.net/a",
|
||||
originAttributes: ChromeUtils.originAttributesToSuffix(
|
||||
{ appId: Ci.nsIScriptSecurityManager.NO_APP_ID, inIsolatedMozBrowser: false }),
|
||||
quota: Infinity,
|
||||
}, {
|
||||
subscriptionUri: serverURL + '/subscriptionB',
|
||||
pushEndpoint: serverURL + '/pushEndpointB',
|
||||
pushReceiptEndpoint: serverURL + '/pushReceiptEndpointB',
|
||||
scope: 'https://example.net/b',
|
||||
subscriptionUri: serverURL + "/subscriptionB",
|
||||
pushEndpoint: serverURL + "/pushEndpointB",
|
||||
pushReceiptEndpoint: serverURL + "/pushReceiptEndpointB",
|
||||
scope: "https://example.net/b",
|
||||
originAttributes: ChromeUtils.originAttributesToSuffix(
|
||||
{ appId: Ci.nsIScriptSecurityManager.NO_APP_ID, inIsolatedMozBrowser: false }),
|
||||
quota: Infinity,
|
||||
}, {
|
||||
subscriptionUri: serverURL + '/subscriptionC',
|
||||
pushEndpoint: serverURL + '/pushEndpointC',
|
||||
pushReceiptEndpoint: serverURL + '/pushReceiptEndpointC',
|
||||
scope: 'https://example.net/c',
|
||||
subscriptionUri: serverURL + "/subscriptionC",
|
||||
pushEndpoint: serverURL + "/pushEndpointC",
|
||||
pushReceiptEndpoint: serverURL + "/pushReceiptEndpointC",
|
||||
scope: "https://example.net/c",
|
||||
originAttributes: ChromeUtils.originAttributesToSuffix(
|
||||
{ appId: Ci.nsIScriptSecurityManager.NO_APP_ID, inIsolatedMozBrowser: false }),
|
||||
quota: Infinity,
|
||||
|
@ -59,17 +55,17 @@ add_task(async function test_pushNotifications() {
|
|||
|
||||
PushService.init({
|
||||
serverURI: serverURL,
|
||||
db
|
||||
db,
|
||||
});
|
||||
|
||||
let registration = await PushService.registration({
|
||||
scope: 'https://example.net/a',
|
||||
scope: "https://example.net/a",
|
||||
originAttributes: ChromeUtils.originAttributesToSuffix(
|
||||
{ appId: Ci.nsIScriptSecurityManager.NO_APP_ID, inIsolatedMozBrowser: false }),
|
||||
});
|
||||
equal(
|
||||
registration.endpoint,
|
||||
serverURL + '/pushEndpointA',
|
||||
'Wrong push endpoint for scope'
|
||||
serverURL + "/pushEndpointA",
|
||||
"Wrong push endpoint for scope"
|
||||
);
|
||||
});
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
'use strict';
|
||||
"use strict";
|
||||
|
||||
const {HttpServer} = ChromeUtils.import("resource://testing-common/httpd.js");
|
||||
|
||||
|
@ -17,7 +17,7 @@ var handlerDone;
|
|||
var handlerPromise = new Promise(r => handlerDone = after(3, r));
|
||||
|
||||
function listen4xxCodeHandler(metadata, response) {
|
||||
ok(true, "Listener point error")
|
||||
ok(true, "Listener point error");
|
||||
handlerDone();
|
||||
response.setStatusLine(metadata.httpVersion, 410, "GONE");
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ function resubscribeHandler(metadata, response) {
|
|||
ok(true, "Ask for new subscription");
|
||||
handlerDone();
|
||||
response.setHeader("Location",
|
||||
'http://localhost:' + serverPort + '/newSubscription')
|
||||
"http://localhost:" + serverPort + "/newSubscription");
|
||||
response.setHeader("Link",
|
||||
'</newPushEndpoint>; rel="urn:ietf:params:push", ' +
|
||||
'</newReceiptPushEndpoint>; rel="urn:ietf:params:push:receipt"');
|
||||
|
@ -47,20 +47,18 @@ httpServer.registerPathHandler("/newSubscription", listenSuccessHandler);
|
|||
httpServer.start(-1);
|
||||
|
||||
function run_test() {
|
||||
|
||||
do_get_profile();
|
||||
|
||||
setPrefs({
|
||||
'testing.allowInsecureServerURL': true,
|
||||
'testing.notifyWorkers': false,
|
||||
'testing.notifyAllObservers': true,
|
||||
"testing.allowInsecureServerURL": true,
|
||||
"testing.notifyWorkers": false,
|
||||
"testing.notifyAllObservers": true,
|
||||
});
|
||||
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
add_task(async function test1() {
|
||||
|
||||
let db = PushServiceHttp2.newPushDB();
|
||||
registerCleanupFunction(() => {
|
||||
return db.drop().then(_ => db.close());
|
||||
|
@ -69,11 +67,11 @@ add_task(async function test1() {
|
|||
var serverURL = "http://localhost:" + httpServer.identity.primaryPort;
|
||||
|
||||
let records = [{
|
||||
subscriptionUri: serverURL + '/subscription4xxCode',
|
||||
pushEndpoint: serverURL + '/pushEndpoint',
|
||||
pushReceiptEndpoint: serverURL + '/pushReceiptEndpoint',
|
||||
scope: 'https://example.com/page',
|
||||
originAttributes: '',
|
||||
subscriptionUri: serverURL + "/subscription4xxCode",
|
||||
pushEndpoint: serverURL + "/pushEndpoint",
|
||||
pushReceiptEndpoint: serverURL + "/pushReceiptEndpoint",
|
||||
scope: "https://example.com/page",
|
||||
originAttributes: "",
|
||||
quota: Infinity,
|
||||
}];
|
||||
|
||||
|
@ -83,20 +81,19 @@ add_task(async function test1() {
|
|||
|
||||
PushService.init({
|
||||
serverURI: serverURL + "/subscribe",
|
||||
db
|
||||
db,
|
||||
});
|
||||
|
||||
await handlerPromise;
|
||||
|
||||
let record = await db.getByIdentifiers({
|
||||
scope: 'https://example.com/page',
|
||||
originAttributes: '',
|
||||
scope: "https://example.com/page",
|
||||
originAttributes: "",
|
||||
});
|
||||
equal(record.keyID, serverURL + '/newSubscription',
|
||||
'Should update subscription URL');
|
||||
equal(record.pushEndpoint, serverURL + '/newPushEndpoint',
|
||||
'Should update push endpoint');
|
||||
equal(record.pushReceiptEndpoint, serverURL + '/newReceiptPushEndpoint',
|
||||
'Should update push receipt endpoint');
|
||||
|
||||
equal(record.keyID, serverURL + "/newSubscription",
|
||||
"Should update subscription URL");
|
||||
equal(record.pushEndpoint, serverURL + "/newPushEndpoint",
|
||||
"Should update push endpoint");
|
||||
equal(record.pushReceiptEndpoint, serverURL + "/newReceiptPushEndpoint",
|
||||
"Should update push receipt endpoint");
|
||||
});
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
'use strict';
|
||||
"use strict";
|
||||
|
||||
const {HttpServer} = ChromeUtils.import("resource://testing-common/httpd.js");
|
||||
|
||||
|
@ -21,7 +21,7 @@ function listen5xxCodeHandler(metadata, response) {
|
|||
ok(true, "Listener 5xx code");
|
||||
handlerDone();
|
||||
retries++;
|
||||
response.setHeader("Retry-After", '1');
|
||||
response.setHeader("Retry-After", "1");
|
||||
response.setStatusLine(metadata.httpVersion, 500, "Retry");
|
||||
}
|
||||
|
||||
|
@ -30,7 +30,7 @@ function resubscribeHandler(metadata, response) {
|
|||
ok(retries == 3, "Should retry 2 times.");
|
||||
handlerDone();
|
||||
response.setHeader("Location",
|
||||
'http://localhost:' + serverPort + '/newSubscription')
|
||||
"http://localhost:" + serverPort + "/newSubscription");
|
||||
response.setHeader("Link",
|
||||
'</newPushEndpoint>; rel="urn:ietf:params:push", ' +
|
||||
'</newReceiptPushEndpoint>; rel="urn:ietf:params:push:receipt"');
|
||||
|
@ -51,19 +51,17 @@ httpServer.registerPathHandler("/newSubscription", listenSuccessHandler);
|
|||
httpServer.start(-1);
|
||||
|
||||
function run_test() {
|
||||
|
||||
do_get_profile();
|
||||
setPrefs({
|
||||
'testing.allowInsecureServerURL': true,
|
||||
'http2.retryInterval': 1000,
|
||||
'http2.maxRetries': 2
|
||||
"testing.allowInsecureServerURL": true,
|
||||
"http2.retryInterval": 1000,
|
||||
"http2.maxRetries": 2,
|
||||
});
|
||||
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
add_task(async function test1() {
|
||||
|
||||
let db = PushServiceHttp2.newPushDB();
|
||||
registerCleanupFunction(() => {
|
||||
return db.drop().then(_ => db.close());
|
||||
|
@ -72,11 +70,11 @@ add_task(async function test1() {
|
|||
var serverURL = "http://localhost:" + httpServer.identity.primaryPort;
|
||||
|
||||
let records = [{
|
||||
subscriptionUri: serverURL + '/subscription5xxCode',
|
||||
pushEndpoint: serverURL + '/pushEndpoint',
|
||||
pushReceiptEndpoint: serverURL + '/pushReceiptEndpoint',
|
||||
scope: 'https://example.com/page',
|
||||
originAttributes: '',
|
||||
subscriptionUri: serverURL + "/subscription5xxCode",
|
||||
pushEndpoint: serverURL + "/pushEndpoint",
|
||||
pushReceiptEndpoint: serverURL + "/pushReceiptEndpoint",
|
||||
scope: "https://example.com/page",
|
||||
originAttributes: "",
|
||||
quota: Infinity,
|
||||
}];
|
||||
|
||||
|
@ -86,20 +84,19 @@ add_task(async function test1() {
|
|||
|
||||
PushService.init({
|
||||
serverURI: serverURL + "/subscribe",
|
||||
db
|
||||
db,
|
||||
});
|
||||
|
||||
await handlerPromise;
|
||||
|
||||
let record = await db.getByIdentifiers({
|
||||
scope: 'https://example.com/page',
|
||||
originAttributes: '',
|
||||
scope: "https://example.com/page",
|
||||
originAttributes: "",
|
||||
});
|
||||
equal(record.keyID, serverURL + '/newSubscription',
|
||||
'Should update subscription URL');
|
||||
equal(record.pushEndpoint, serverURL + '/newPushEndpoint',
|
||||
'Should update push endpoint');
|
||||
equal(record.pushReceiptEndpoint, serverURL + '/newReceiptPushEndpoint',
|
||||
'Should update push receipt endpoint');
|
||||
|
||||
equal(record.keyID, serverURL + "/newSubscription",
|
||||
"Should update subscription URL");
|
||||
equal(record.pushEndpoint, serverURL + "/newPushEndpoint",
|
||||
"Should update push endpoint");
|
||||
equal(record.pushReceiptEndpoint, serverURL + "/newReceiptPushEndpoint",
|
||||
"Should update push receipt endpoint");
|
||||
});
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
'use strict';
|
||||
"use strict";
|
||||
|
||||
const {HttpServer} = ChromeUtils.import("resource://testing-common/httpd.js");
|
||||
|
||||
|
@ -20,7 +20,7 @@ function resubscribeHandler(metadata, response) {
|
|||
ok(true, "Ask for new subscription");
|
||||
handlerDone();
|
||||
response.setHeader("Location",
|
||||
'http://localhost:' + serverPort + '/newSubscription')
|
||||
"http://localhost:" + serverPort + "/newSubscription");
|
||||
response.setHeader("Link",
|
||||
'</newPushEndpoint>; rel="urn:ietf:params:push", ' +
|
||||
'</newReceiptPushEndpoint>; rel="urn:ietf:params:push:receipt"');
|
||||
|
@ -40,19 +40,17 @@ httpServer.registerPathHandler("/newSubscription", listenSuccessHandler);
|
|||
httpServer.start(-1);
|
||||
|
||||
function run_test() {
|
||||
|
||||
do_get_profile();
|
||||
setPrefs({
|
||||
'testing.allowInsecureServerURL': true,
|
||||
'http2.retryInterval': 1000,
|
||||
'http2.maxRetries': 2
|
||||
"testing.allowInsecureServerURL": true,
|
||||
"http2.retryInterval": 1000,
|
||||
"http2.maxRetries": 2,
|
||||
});
|
||||
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
add_task(async function test1() {
|
||||
|
||||
let db = PushServiceHttp2.newPushDB();
|
||||
registerCleanupFunction(() => {
|
||||
return db.drop().then(_ => db.close());
|
||||
|
@ -61,21 +59,21 @@ add_task(async function test1() {
|
|||
var serverURL = "http://localhost:" + httpServer.identity.primaryPort;
|
||||
|
||||
let records = [{
|
||||
subscriptionUri: 'http://localhost/subscriptionNotExist',
|
||||
pushEndpoint: serverURL + '/pushEndpoint',
|
||||
pushReceiptEndpoint: serverURL + '/pushReceiptEndpoint',
|
||||
scope: 'https://example.com/page',
|
||||
p256dhPublicKey: 'BPCd4gNQkjwRah61LpdALdzZKLLnU5UAwDztQ5_h0QsT26jk0IFbqcK6-JxhHAm-rsHEwy0CyVJjtnfOcqc1tgA',
|
||||
subscriptionUri: "http://localhost/subscriptionNotExist",
|
||||
pushEndpoint: serverURL + "/pushEndpoint",
|
||||
pushReceiptEndpoint: serverURL + "/pushReceiptEndpoint",
|
||||
scope: "https://example.com/page",
|
||||
p256dhPublicKey: "BPCd4gNQkjwRah61LpdALdzZKLLnU5UAwDztQ5_h0QsT26jk0IFbqcK6-JxhHAm-rsHEwy0CyVJjtnfOcqc1tgA",
|
||||
p256dhPrivateKey: {
|
||||
crv: 'P-256',
|
||||
d: '1jUPhzVsRkzV0vIzwL4ZEsOlKdNOWm7TmaTfzitJkgM',
|
||||
crv: "P-256",
|
||||
d: "1jUPhzVsRkzV0vIzwL4ZEsOlKdNOWm7TmaTfzitJkgM",
|
||||
ext: true,
|
||||
key_ops: ["deriveBits"],
|
||||
kty: "EC",
|
||||
x: '8J3iA1CSPBFqHrUul0At3NkosudTlQDAPO1Dn-HRCxM',
|
||||
y: '26jk0IFbqcK6-JxhHAm-rsHEwy0CyVJjtnfOcqc1tgA'
|
||||
x: "8J3iA1CSPBFqHrUul0At3NkosudTlQDAPO1Dn-HRCxM",
|
||||
y: "26jk0IFbqcK6-JxhHAm-rsHEwy0CyVJjtnfOcqc1tgA",
|
||||
},
|
||||
originAttributes: '',
|
||||
originAttributes: "",
|
||||
quota: Infinity,
|
||||
}];
|
||||
|
||||
|
@ -85,20 +83,19 @@ add_task(async function test1() {
|
|||
|
||||
PushService.init({
|
||||
serverURI: serverURL + "/subscribe",
|
||||
db
|
||||
db,
|
||||
});
|
||||
|
||||
await handlerPromise;
|
||||
|
||||
let record = await db.getByIdentifiers({
|
||||
scope: 'https://example.com/page',
|
||||
originAttributes: '',
|
||||
scope: "https://example.com/page",
|
||||
originAttributes: "",
|
||||
});
|
||||
equal(record.keyID, serverURL + '/newSubscription',
|
||||
'Should update subscription URL');
|
||||
equal(record.pushEndpoint, serverURL + '/newPushEndpoint',
|
||||
'Should update push endpoint');
|
||||
equal(record.pushReceiptEndpoint, serverURL + '/newReceiptPushEndpoint',
|
||||
'Should update push receipt endpoint');
|
||||
|
||||
equal(record.keyID, serverURL + "/newSubscription",
|
||||
"Should update subscription URL");
|
||||
equal(record.pushEndpoint, serverURL + "/newPushEndpoint",
|
||||
"Should update push endpoint");
|
||||
equal(record.pushReceiptEndpoint, serverURL + "/newReceiptPushEndpoint",
|
||||
"Should update push receipt endpoint");
|
||||
});
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
'use strict';
|
||||
"use strict";
|
||||
|
||||
const {PushDB, PushService, PushServiceWebSocket} = serviceExports;
|
||||
|
||||
const userAgentID = '05f7b940-51b6-4b6f-8032-b83ebb577ded';
|
||||
const userAgentID = "05f7b940-51b6-4b6f-8032-b83ebb577ded";
|
||||
|
||||
function run_test() {
|
||||
do_get_profile();
|
||||
setPrefs({
|
||||
userAgentID: userAgentID,
|
||||
userAgentID,
|
||||
pingInterval: 2000,
|
||||
retryBaseInterval: 25,
|
||||
});
|
||||
|
@ -19,14 +19,14 @@ function run_test() {
|
|||
|
||||
add_task(async function test_ws_retry() {
|
||||
let db = PushServiceWebSocket.newPushDB();
|
||||
registerCleanupFunction(() => {return db.drop().then(_ => db.close());});
|
||||
registerCleanupFunction(() => { return db.drop().then(_ => db.close()); });
|
||||
|
||||
await db.put({
|
||||
channelID: '61770ba9-2d57-4134-b949-d40404630d5b',
|
||||
pushEndpoint: 'https://example.org/push/1',
|
||||
scope: 'https://example.net/push/1',
|
||||
channelID: "61770ba9-2d57-4134-b949-d40404630d5b",
|
||||
pushEndpoint: "https://example.org/push/1",
|
||||
scope: "https://example.net/push/1",
|
||||
version: 1,
|
||||
originAttributes: '',
|
||||
originAttributes: "",
|
||||
quota: Infinity,
|
||||
});
|
||||
|
||||
|
@ -52,7 +52,7 @@ add_task(async function test_ws_retry() {
|
|||
onHello(request) {
|
||||
if (reconnects == 10) {
|
||||
this.serverSendMsg(JSON.stringify({
|
||||
messageType: 'hello',
|
||||
messageType: "hello",
|
||||
status: 200,
|
||||
uaid: userAgentID,
|
||||
}));
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
'use strict';
|
||||
"use strict";
|
||||
|
||||
Cu.importGlobalProperties(["crypto"]);
|
||||
|
||||
|
@ -33,7 +33,7 @@ function run_test() {
|
|||
if (isParent) {
|
||||
add_test(function setUp() {
|
||||
db = PushServiceWebSocket.newPushDB();
|
||||
registerCleanupFunction(() => {return db.drop().then(_ => db.close());});
|
||||
registerCleanupFunction(() => { return db.drop().then(_ => db.close()); });
|
||||
setUpServiceInParent(PushService, db).then(run_next_test, run_next_test);
|
||||
});
|
||||
}
|
||||
|
@ -41,15 +41,15 @@ if (isParent) {
|
|||
add_test(function test_subscribe_success() {
|
||||
do_test_pending();
|
||||
PushServiceComponent.subscribe(
|
||||
'https://example.com/sub/ok',
|
||||
"https://example.com/sub/ok",
|
||||
Services.scriptSecurityManager.getSystemPrincipal(),
|
||||
(result, subscription) => {
|
||||
ok(Components.isSuccessCode(result), 'Error creating subscription');
|
||||
ok(subscription.isSystemSubscription, 'Expected system subscription');
|
||||
ok(subscription.endpoint.startsWith('https://example.org/push'), 'Wrong endpoint prefix');
|
||||
equal(subscription.pushCount, 0, 'Wrong push count');
|
||||
equal(subscription.lastPush, 0, 'Wrong last push time');
|
||||
equal(subscription.quota, -1, 'Wrong quota for system subscription');
|
||||
ok(Components.isSuccessCode(result), "Error creating subscription");
|
||||
ok(subscription.isSystemSubscription, "Expected system subscription");
|
||||
ok(subscription.endpoint.startsWith("https://example.org/push"), "Wrong endpoint prefix");
|
||||
equal(subscription.pushCount, 0, "Wrong push count");
|
||||
equal(subscription.lastPush, 0, "Wrong last push time");
|
||||
equal(subscription.quota, -1, "Wrong quota for system subscription");
|
||||
|
||||
do_test_finished();
|
||||
run_next_test();
|
||||
|
@ -62,14 +62,14 @@ add_test(function test_subscribeWithKey_error() {
|
|||
|
||||
let invalidKey = [0, 1];
|
||||
PushServiceComponent.subscribeWithKey(
|
||||
'https://example.com/sub-key/invalid',
|
||||
"https://example.com/sub-key/invalid",
|
||||
Services.scriptSecurityManager.getSystemPrincipal(),
|
||||
invalidKey.length,
|
||||
invalidKey,
|
||||
(result, subscription) => {
|
||||
ok(!Components.isSuccessCode(result), 'Expected error creating subscription with invalid key');
|
||||
equal(result, Cr.NS_ERROR_DOM_PUSH_INVALID_KEY_ERR, 'Wrong error code for invalid key');
|
||||
strictEqual(subscription, null, 'Unexpected subscription');
|
||||
ok(!Components.isSuccessCode(result), "Expected error creating subscription with invalid key");
|
||||
equal(result, Cr.NS_ERROR_DOM_PUSH_INVALID_KEY_ERR, "Wrong error code for invalid key");
|
||||
strictEqual(subscription, null, "Unexpected subscription");
|
||||
|
||||
do_test_finished();
|
||||
run_next_test();
|
||||
|
@ -82,13 +82,13 @@ add_test(function test_subscribeWithKey_success() {
|
|||
|
||||
generateKey().then(key => {
|
||||
PushServiceComponent.subscribeWithKey(
|
||||
'https://example.com/sub-key/ok',
|
||||
"https://example.com/sub-key/ok",
|
||||
Services.scriptSecurityManager.getSystemPrincipal(),
|
||||
key.length,
|
||||
key,
|
||||
(result, subscription) => {
|
||||
ok(Components.isSuccessCode(result), 'Error creating subscription with key');
|
||||
notStrictEqual(subscription, null, 'Expected subscription');
|
||||
ok(Components.isSuccessCode(result), "Error creating subscription with key");
|
||||
notStrictEqual(subscription, null, "Expected subscription");
|
||||
done();
|
||||
}
|
||||
);
|
||||
|
@ -103,14 +103,14 @@ add_test(function test_subscribeWithKey_conflict() {
|
|||
|
||||
generateKey().then(differentKey => {
|
||||
PushServiceComponent.subscribeWithKey(
|
||||
'https://example.com/sub-key/ok',
|
||||
"https://example.com/sub-key/ok",
|
||||
Services.scriptSecurityManager.getSystemPrincipal(),
|
||||
differentKey.length,
|
||||
differentKey,
|
||||
(result, subscription) => {
|
||||
ok(!Components.isSuccessCode(result), 'Expected error creating subscription with conflicting key');
|
||||
equal(result, Cr.NS_ERROR_DOM_PUSH_MISMATCHED_KEY_ERR, 'Wrong error code for mismatched key');
|
||||
strictEqual(subscription, null, 'Unexpected subscription');
|
||||
ok(!Components.isSuccessCode(result), "Expected error creating subscription with conflicting key");
|
||||
equal(result, Cr.NS_ERROR_DOM_PUSH_MISMATCHED_KEY_ERR, "Wrong error code for mismatched key");
|
||||
strictEqual(subscription, null, "Unexpected subscription");
|
||||
done();
|
||||
}
|
||||
);
|
||||
|
@ -123,11 +123,11 @@ add_test(function test_subscribeWithKey_conflict() {
|
|||
add_test(function test_subscribe_error() {
|
||||
do_test_pending();
|
||||
PushServiceComponent.subscribe(
|
||||
'https://example.com/sub/fail',
|
||||
"https://example.com/sub/fail",
|
||||
Services.scriptSecurityManager.getSystemPrincipal(),
|
||||
(result, subscription) => {
|
||||
ok(!Components.isSuccessCode(result), 'Expected error creating subscription');
|
||||
strictEqual(subscription, null, 'Unexpected subscription');
|
||||
ok(!Components.isSuccessCode(result), "Expected error creating subscription");
|
||||
strictEqual(subscription, null, "Unexpected subscription");
|
||||
|
||||
do_test_finished();
|
||||
run_next_test();
|
||||
|
@ -138,15 +138,15 @@ add_test(function test_subscribe_error() {
|
|||
add_test(function test_getSubscription_exists() {
|
||||
do_test_pending();
|
||||
PushServiceComponent.getSubscription(
|
||||
'https://example.com/get/ok',
|
||||
"https://example.com/get/ok",
|
||||
Services.scriptSecurityManager.getSystemPrincipal(),
|
||||
(result, subscription) => {
|
||||
ok(Components.isSuccessCode(result), 'Error getting subscription');
|
||||
ok(Components.isSuccessCode(result), "Error getting subscription");
|
||||
|
||||
equal(subscription.endpoint, 'https://example.org/push/get', 'Wrong endpoint');
|
||||
equal(subscription.pushCount, 10, 'Wrong push count');
|
||||
equal(subscription.lastPush, 1438360548322, 'Wrong last push');
|
||||
equal(subscription.quota, 16, 'Wrong quota for subscription');
|
||||
equal(subscription.endpoint, "https://example.org/push/get", "Wrong endpoint");
|
||||
equal(subscription.pushCount, 10, "Wrong push count");
|
||||
equal(subscription.lastPush, 1438360548322, "Wrong last push");
|
||||
equal(subscription.quota, 16, "Wrong quota for subscription");
|
||||
|
||||
do_test_finished();
|
||||
run_next_test();
|
||||
|
@ -157,11 +157,11 @@ add_test(function test_getSubscription_exists() {
|
|||
add_test(function test_getSubscription_missing() {
|
||||
do_test_pending();
|
||||
PushServiceComponent.getSubscription(
|
||||
'https://example.com/get/missing',
|
||||
"https://example.com/get/missing",
|
||||
Services.scriptSecurityManager.getSystemPrincipal(),
|
||||
(result, subscription) => {
|
||||
ok(Components.isSuccessCode(result), 'Error getting nonexistent subscription');
|
||||
strictEqual(subscription, null, 'Nonexistent subscriptions should return null');
|
||||
ok(Components.isSuccessCode(result), "Error getting nonexistent subscription");
|
||||
strictEqual(subscription, null, "Nonexistent subscriptions should return null");
|
||||
|
||||
do_test_finished();
|
||||
run_next_test();
|
||||
|
@ -172,11 +172,11 @@ add_test(function test_getSubscription_missing() {
|
|||
add_test(function test_getSubscription_error() {
|
||||
do_test_pending();
|
||||
PushServiceComponent.getSubscription(
|
||||
'https://example.com/get/fail',
|
||||
"https://example.com/get/fail",
|
||||
Services.scriptSecurityManager.getSystemPrincipal(),
|
||||
(result, subscription) => {
|
||||
ok(!Components.isSuccessCode(result), 'Expected error getting subscription');
|
||||
strictEqual(subscription, null, 'Unexpected subscription');
|
||||
ok(!Components.isSuccessCode(result), "Expected error getting subscription");
|
||||
strictEqual(subscription, null, "Unexpected subscription");
|
||||
|
||||
do_test_finished();
|
||||
run_next_test();
|
||||
|
@ -187,11 +187,11 @@ add_test(function test_getSubscription_error() {
|
|||
add_test(function test_unsubscribe_success() {
|
||||
do_test_pending();
|
||||
PushServiceComponent.unsubscribe(
|
||||
'https://example.com/unsub/ok',
|
||||
"https://example.com/unsub/ok",
|
||||
Services.scriptSecurityManager.getSystemPrincipal(),
|
||||
(result, success) => {
|
||||
ok(Components.isSuccessCode(result), 'Error unsubscribing');
|
||||
strictEqual(success, true, 'Expected successful unsubscribe');
|
||||
ok(Components.isSuccessCode(result), "Error unsubscribing");
|
||||
strictEqual(success, true, "Expected successful unsubscribe");
|
||||
|
||||
do_test_finished();
|
||||
run_next_test();
|
||||
|
@ -202,11 +202,11 @@ add_test(function test_unsubscribe_success() {
|
|||
add_test(function test_unsubscribe_nonexistent() {
|
||||
do_test_pending();
|
||||
PushServiceComponent.unsubscribe(
|
||||
'https://example.com/unsub/ok',
|
||||
"https://example.com/unsub/ok",
|
||||
Services.scriptSecurityManager.getSystemPrincipal(),
|
||||
(result, success) => {
|
||||
ok(Components.isSuccessCode(result), 'Error removing nonexistent subscription');
|
||||
strictEqual(success, false, 'Nonexistent subscriptions should return false');
|
||||
ok(Components.isSuccessCode(result), "Error removing nonexistent subscription");
|
||||
strictEqual(success, false, "Nonexistent subscriptions should return false");
|
||||
|
||||
do_test_finished();
|
||||
run_next_test();
|
||||
|
@ -217,11 +217,11 @@ add_test(function test_unsubscribe_nonexistent() {
|
|||
add_test(function test_unsubscribe_error() {
|
||||
do_test_pending();
|
||||
PushServiceComponent.unsubscribe(
|
||||
'https://example.com/unsub/fail',
|
||||
"https://example.com/unsub/fail",
|
||||
Services.scriptSecurityManager.getSystemPrincipal(),
|
||||
(result, success) => {
|
||||
ok(!Components.isSuccessCode(result), 'Expected error unsubscribing');
|
||||
strictEqual(success, false, 'Unexpected successful unsubscribe');
|
||||
ok(!Components.isSuccessCode(result), "Expected error unsubscribing");
|
||||
strictEqual(success, false, "Unexpected successful unsubscribe");
|
||||
|
||||
do_test_finished();
|
||||
run_next_test();
|
||||
|
@ -230,17 +230,17 @@ add_test(function test_unsubscribe_error() {
|
|||
});
|
||||
|
||||
add_test(function test_subscribe_origin_principal() {
|
||||
let scope = 'https://example.net/origin-principal';
|
||||
let scope = "https://example.net/origin-principal";
|
||||
let principal =
|
||||
Services.scriptSecurityManager.createCodebasePrincipalFromOrigin(scope);
|
||||
|
||||
do_test_pending();
|
||||
PushServiceComponent.subscribe(scope, principal, (result, subscription) => {
|
||||
ok(Components.isSuccessCode(result),
|
||||
'Expected error creating subscription with origin principal');
|
||||
"Expected error creating subscription with origin principal");
|
||||
ok(!subscription.isSystemSubscription,
|
||||
'Unexpected system subscription for origin principal');
|
||||
equal(subscription.quota, 16, 'Wrong quota for origin subscription');
|
||||
"Unexpected system subscription for origin principal");
|
||||
equal(subscription.quota, 16, "Wrong quota for origin subscription");
|
||||
|
||||
do_test_finished();
|
||||
run_next_test();
|
||||
|
@ -250,13 +250,13 @@ add_test(function test_subscribe_origin_principal() {
|
|||
add_test(function test_subscribe_null_principal() {
|
||||
do_test_pending();
|
||||
PushServiceComponent.subscribe(
|
||||
'chrome://push/null-principal',
|
||||
"chrome://push/null-principal",
|
||||
Services.scriptSecurityManager.createNullPrincipal({}),
|
||||
(result, subscription) => {
|
||||
ok(!Components.isSuccessCode(result),
|
||||
'Expected error creating subscription with null principal');
|
||||
"Expected error creating subscription with null principal");
|
||||
strictEqual(subscription, null,
|
||||
'Unexpected subscription with null principal');
|
||||
"Unexpected subscription with null principal");
|
||||
|
||||
do_test_finished();
|
||||
run_next_test();
|
||||
|
@ -266,12 +266,12 @@ add_test(function test_subscribe_null_principal() {
|
|||
|
||||
add_test(function test_subscribe_missing_principal() {
|
||||
do_test_pending();
|
||||
PushServiceComponent.subscribe('chrome://push/missing-principal', null,
|
||||
PushServiceComponent.subscribe("chrome://push/missing-principal", null,
|
||||
(result, subscription) => {
|
||||
ok(!Components.isSuccessCode(result),
|
||||
'Expected error creating subscription without principal');
|
||||
"Expected error creating subscription without principal");
|
||||
strictEqual(subscription, null,
|
||||
'Unexpected subscription without principal');
|
||||
"Unexpected subscription without principal");
|
||||
|
||||
do_test_finished();
|
||||
run_next_test();
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
'use strict';
|
||||
"use strict";
|
||||
|
||||
const {PushDB, PushService, PushServiceWebSocket} = serviceExports;
|
||||
|
||||
|
@ -13,7 +13,7 @@ function run_test() {
|
|||
|
||||
add_task(async function test_service_parent() {
|
||||
let db = PushServiceWebSocket.newPushDB();
|
||||
registerCleanupFunction(() => {return db.drop().then(_ => db.close());});
|
||||
registerCleanupFunction(() => { return db.drop().then(() => db.close()); });
|
||||
await setUpServiceInParent(PushService, db);
|
||||
|
||||
// Accessing the lazy service getter will start the service in the main
|
||||
|
@ -23,7 +23,7 @@ add_task(async function test_service_parent() {
|
|||
equal(PushServiceComponent.subscriptionChangeTopic,
|
||||
"push-subscription-change", "Wrong subscription change observer topic");
|
||||
|
||||
await run_test_in_child('./test_service_child.js');
|
||||
await run_test_in_child("./test_service_child.js");
|
||||
|
||||
await tearDownServiceInParent(db);
|
||||
});
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
'use strict';
|
||||
"use strict";
|
||||
|
||||
const {PushDB, PushService} = serviceExports;
|
||||
|
||||
|
@ -18,22 +18,22 @@ add_task(async function test_unregister_empty_scope() {
|
|||
return new MockWebSocket(uri, {
|
||||
onHello(request) {
|
||||
this.serverSendMsg(JSON.stringify({
|
||||
messageType: 'hello',
|
||||
messageType: "hello",
|
||||
status: 200,
|
||||
uaid: '5619557c-86fe-4711-8078-d1fd6987aef7'
|
||||
uaid: "5619557c-86fe-4711-8078-d1fd6987aef7",
|
||||
}));
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
await rejects(
|
||||
await Assert.rejects(
|
||||
PushService.unregister({
|
||||
scope: '',
|
||||
scope: "",
|
||||
originAttributes: ChromeUtils.originAttributesToSuffix(
|
||||
{ appId: Ci.nsIScriptSecurityManager.NO_APP_ID, inIsolatedMozBrowser: false }),
|
||||
}),
|
||||
/Invalid page record/,
|
||||
'Expected error for empty endpoint'
|
||||
"Expected error for empty endpoint"
|
||||
);
|
||||
});
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
'use strict';
|
||||
"use strict";
|
||||
|
||||
const {PushDB, PushService, PushServiceWebSocket} = serviceExports;
|
||||
|
||||
const channelID = '00c7fa13-7b71-447d-bd27-a91abc09d1b2';
|
||||
const channelID = "00c7fa13-7b71-447d-bd27-a91abc09d1b2";
|
||||
|
||||
function run_test() {
|
||||
do_get_profile();
|
||||
|
@ -15,12 +15,12 @@ function run_test() {
|
|||
|
||||
add_task(async function test_unregister_error() {
|
||||
let db = PushServiceWebSocket.newPushDB();
|
||||
registerCleanupFunction(() => {return db.drop().then(_ => db.close());});
|
||||
registerCleanupFunction(() => { return db.drop().then(_ => db.close()); });
|
||||
await db.put({
|
||||
channelID: channelID,
|
||||
pushEndpoint: 'https://example.org/update/failure',
|
||||
scope: 'https://example.net/page/failure',
|
||||
originAttributes: '',
|
||||
channelID,
|
||||
pushEndpoint: "https://example.org/update/failure",
|
||||
scope: "https://example.net/page/failure",
|
||||
originAttributes: "",
|
||||
version: 1,
|
||||
quota: Infinity,
|
||||
});
|
||||
|
@ -34,34 +34,34 @@ add_task(async function test_unregister_error() {
|
|||
return new MockWebSocket(uri, {
|
||||
onHello(request) {
|
||||
this.serverSendMsg(JSON.stringify({
|
||||
messageType: 'hello',
|
||||
messageType: "hello",
|
||||
status: 200,
|
||||
uaid: '083e6c17-1063-4677-8638-ab705aebebc2'
|
||||
uaid: "083e6c17-1063-4677-8638-ab705aebebc2",
|
||||
}));
|
||||
},
|
||||
onUnregister(request) {
|
||||
// The server is notified out-of-band. Since channels may be pruned,
|
||||
// any failures are swallowed.
|
||||
equal(request.channelID, channelID, 'Unregister: wrong channel ID');
|
||||
equal(request.channelID, channelID, "Unregister: wrong channel ID");
|
||||
this.serverSendMsg(JSON.stringify({
|
||||
messageType: 'unregister',
|
||||
messageType: "unregister",
|
||||
status: 500,
|
||||
error: 'omg, everything is exploding',
|
||||
channelID
|
||||
error: "omg, everything is exploding",
|
||||
channelID,
|
||||
}));
|
||||
unregisterDone();
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
await PushService.unregister({
|
||||
scope: 'https://example.net/page/failure',
|
||||
originAttributes: '',
|
||||
scope: "https://example.net/page/failure",
|
||||
originAttributes: "",
|
||||
});
|
||||
|
||||
let result = await db.getByKeyID(channelID);
|
||||
ok(!result, 'Deleted push record exists');
|
||||
ok(!result, "Deleted push record exists");
|
||||
|
||||
// Make sure we send a request to the server.
|
||||
await unregisterPromise;
|
||||
|
|
|
@ -1,37 +1,37 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
'use strict';
|
||||
"use strict";
|
||||
|
||||
const {PushDB, PushService, PushServiceWebSocket} = serviceExports;
|
||||
|
||||
const userAgentID = '7f0af1bb-7e1f-4fb8-8e4a-e8de434abde3';
|
||||
const userAgentID = "7f0af1bb-7e1f-4fb8-8e4a-e8de434abde3";
|
||||
|
||||
function run_test() {
|
||||
do_get_profile();
|
||||
setPrefs({
|
||||
userAgentID,
|
||||
requestTimeout: 150,
|
||||
retryBaseInterval: 150
|
||||
retryBaseInterval: 150,
|
||||
});
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
add_task(async function test_unregister_invalid_json() {
|
||||
let db = PushServiceWebSocket.newPushDB();
|
||||
registerCleanupFunction(() => {return db.drop().then(_ => db.close());});
|
||||
registerCleanupFunction(() => { return db.drop().then(_ => db.close()); });
|
||||
let records = [{
|
||||
channelID: '87902e90-c57e-4d18-8354-013f4a556559',
|
||||
pushEndpoint: 'https://example.org/update/1',
|
||||
scope: 'https://example.edu/page/1',
|
||||
originAttributes: '',
|
||||
channelID: "87902e90-c57e-4d18-8354-013f4a556559",
|
||||
pushEndpoint: "https://example.org/update/1",
|
||||
scope: "https://example.edu/page/1",
|
||||
originAttributes: "",
|
||||
version: 1,
|
||||
quota: Infinity,
|
||||
}, {
|
||||
channelID: '057caa8f-9b99-47ff-891c-adad18ce603e',
|
||||
pushEndpoint: 'https://example.com/update/2',
|
||||
scope: 'https://example.net/page/1',
|
||||
originAttributes: '',
|
||||
channelID: "057caa8f-9b99-47ff-891c-adad18ce603e",
|
||||
pushEndpoint: "https://example.com/update/2",
|
||||
scope: "https://example.net/page/1",
|
||||
originAttributes: "",
|
||||
version: 1,
|
||||
quota: Infinity,
|
||||
}];
|
||||
|
@ -48,47 +48,47 @@ add_task(async function test_unregister_invalid_json() {
|
|||
return new MockWebSocket(uri, {
|
||||
onHello(request) {
|
||||
this.serverSendMsg(JSON.stringify({
|
||||
messageType: 'hello',
|
||||
messageType: "hello",
|
||||
status: 200,
|
||||
uaid: userAgentID,
|
||||
use_webpush: true,
|
||||
}));
|
||||
},
|
||||
onUnregister(request) {
|
||||
this.serverSendMsg(');alert(1);(');
|
||||
this.serverSendMsg(");alert(1);(");
|
||||
unregisterDone();
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
await rejects(
|
||||
await Assert.rejects(
|
||||
PushService.unregister({
|
||||
scope: 'https://example.edu/page/1',
|
||||
originAttributes: '',
|
||||
scope: "https://example.edu/page/1",
|
||||
originAttributes: "",
|
||||
}),
|
||||
/Request timed out/,
|
||||
'Expected error for first invalid JSON response'
|
||||
"Expected error for first invalid JSON response"
|
||||
);
|
||||
|
||||
let record = await db.getByKeyID(
|
||||
'87902e90-c57e-4d18-8354-013f4a556559');
|
||||
ok(!record, 'Failed to delete unregistered record');
|
||||
"87902e90-c57e-4d18-8354-013f4a556559");
|
||||
ok(!record, "Failed to delete unregistered record");
|
||||
|
||||
await rejects(
|
||||
await Assert.rejects(
|
||||
PushService.unregister({
|
||||
scope: 'https://example.net/page/1',
|
||||
scope: "https://example.net/page/1",
|
||||
originAttributes: ChromeUtils.originAttributesToSuffix(
|
||||
{ appId: Ci.nsIScriptSecurityManager.NO_APP_ID, inIsolatedMozBrowser: false }),
|
||||
}),
|
||||
/Request timed out/,
|
||||
'Expected error for second invalid JSON response'
|
||||
"Expected error for second invalid JSON response"
|
||||
);
|
||||
|
||||
record = await db.getByKeyID(
|
||||
'057caa8f-9b99-47ff-891c-adad18ce603e');
|
||||
"057caa8f-9b99-47ff-891c-adad18ce603e");
|
||||
ok(!record,
|
||||
'Failed to delete unregistered record after receiving invalid JSON');
|
||||
"Failed to delete unregistered record after receiving invalid JSON");
|
||||
|
||||
await unregisterPromise;
|
||||
});
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
'use strict';
|
||||
"use strict";
|
||||
|
||||
const {PushDB, PushService} = serviceExports;
|
||||
|
||||
|
@ -18,17 +18,17 @@ add_task(async function test_unregister_not_found() {
|
|||
return new MockWebSocket(uri, {
|
||||
onHello(request) {
|
||||
this.serverSendMsg(JSON.stringify({
|
||||
messageType: 'hello',
|
||||
messageType: "hello",
|
||||
status: 200,
|
||||
uaid: 'f074ed80-d479-44fa-ba65-792104a79ea9'
|
||||
uaid: "f074ed80-d479-44fa-ba65-792104a79ea9",
|
||||
}));
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
let result = await PushService.unregister({
|
||||
scope: 'https://example.net/nonexistent',
|
||||
scope: "https://example.net/nonexistent",
|
||||
originAttributes: ChromeUtils.originAttributesToSuffix(
|
||||
{ appId: Ci.nsIScriptSecurityManager.NO_APP_ID, inIsolatedMozBrowser: false }),
|
||||
});
|
||||
|
|
|
@ -1,29 +1,29 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
'use strict';
|
||||
"use strict";
|
||||
|
||||
const {PushDB, PushService, PushServiceWebSocket} = serviceExports;
|
||||
|
||||
const userAgentID = 'fbe865a6-aeb8-446f-873c-aeebdb8d493c';
|
||||
const channelID = 'db0a7021-ec2d-4bd3-8802-7a6966f10ed8';
|
||||
const userAgentID = "fbe865a6-aeb8-446f-873c-aeebdb8d493c";
|
||||
const channelID = "db0a7021-ec2d-4bd3-8802-7a6966f10ed8";
|
||||
|
||||
function run_test() {
|
||||
do_get_profile();
|
||||
setPrefs({
|
||||
userAgentID: userAgentID,
|
||||
userAgentID,
|
||||
});
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
add_task(async function test_unregister_success() {
|
||||
let db = PushServiceWebSocket.newPushDB();
|
||||
registerCleanupFunction(() => {return db.drop().then(_ => db.close());});
|
||||
registerCleanupFunction(() => { return db.drop().then(_ => db.close()); });
|
||||
await db.put({
|
||||
channelID,
|
||||
pushEndpoint: 'https://example.org/update/unregister-success',
|
||||
scope: 'https://example.com/page/unregister-success',
|
||||
originAttributes: '',
|
||||
pushEndpoint: "https://example.org/update/unregister-success",
|
||||
scope: "https://example.com/page/unregister-success",
|
||||
originAttributes: "",
|
||||
version: 1,
|
||||
quota: Infinity,
|
||||
});
|
||||
|
@ -37,40 +37,40 @@ add_task(async function test_unregister_success() {
|
|||
return new MockWebSocket(uri, {
|
||||
onHello(request) {
|
||||
this.serverSendMsg(JSON.stringify({
|
||||
messageType: 'hello',
|
||||
messageType: "hello",
|
||||
status: 200,
|
||||
uaid: userAgentID,
|
||||
use_webpush: true,
|
||||
}));
|
||||
},
|
||||
onUnregister(request) {
|
||||
equal(request.channelID, channelID, 'Should include the channel ID');
|
||||
equal(request.code, 200, 'Expected manual unregister reason');
|
||||
equal(request.channelID, channelID, "Should include the channel ID");
|
||||
equal(request.code, 200, "Expected manual unregister reason");
|
||||
this.serverSendMsg(JSON.stringify({
|
||||
messageType: 'unregister',
|
||||
messageType: "unregister",
|
||||
status: 200,
|
||||
channelID
|
||||
channelID,
|
||||
}));
|
||||
unregisterDone();
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
let subModifiedPromise = promiseObserverNotification(
|
||||
PushServiceComponent.subscriptionModifiedTopic);
|
||||
|
||||
await PushService.unregister({
|
||||
scope: 'https://example.com/page/unregister-success',
|
||||
originAttributes: '',
|
||||
scope: "https://example.com/page/unregister-success",
|
||||
originAttributes: "",
|
||||
});
|
||||
|
||||
let {data: subModifiedScope} = await subModifiedPromise;
|
||||
equal(subModifiedScope, 'https://example.com/page/unregister-success',
|
||||
'Should fire a subscription modified event after unsubscribing');
|
||||
equal(subModifiedScope, "https://example.com/page/unregister-success",
|
||||
"Should fire a subscription modified event after unsubscribing");
|
||||
|
||||
let record = await db.getByKeyID(channelID);
|
||||
ok(!record, 'Unregister did not remove record');
|
||||
ok(!record, "Unregister did not remove record");
|
||||
|
||||
await unregisterPromise;
|
||||
});
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
'use strict';
|
||||
"use strict";
|
||||
|
||||
const {PushDB, PushService, PushServiceHttp2} = serviceExports;
|
||||
|
||||
var prefs;
|
||||
var pushEnabled;
|
||||
var pushConnectionEnabled;
|
||||
|
||||
|
@ -15,20 +14,18 @@ function run_test() {
|
|||
serverPort = getTestServerPort();
|
||||
|
||||
do_get_profile();
|
||||
prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
|
||||
|
||||
pushEnabled = prefs.getBoolPref("dom.push.enabled");
|
||||
pushConnectionEnabled = prefs.getBoolPref("dom.push.connection.enabled");
|
||||
pushEnabled = Services.prefs.getBoolPref("dom.push.enabled");
|
||||
pushConnectionEnabled = Services.prefs.getBoolPref("dom.push.connection.enabled");
|
||||
|
||||
// Set to allow the cert presented by our H2 server
|
||||
var oldPref = prefs.getIntPref("network.http.speculative-parallel-limit");
|
||||
prefs.setIntPref("network.http.speculative-parallel-limit", 0);
|
||||
prefs.setBoolPref("dom.push.enabled", true);
|
||||
prefs.setBoolPref("dom.push.connection.enabled", true);
|
||||
var oldPref = Services.prefs.getIntPref("network.http.speculative-parallel-limit");
|
||||
Services.prefs.setIntPref("network.http.speculative-parallel-limit", 0);
|
||||
Services.prefs.setBoolPref("dom.push.enabled", true);
|
||||
Services.prefs.setBoolPref("dom.push.connection.enabled", true);
|
||||
|
||||
trustHttp2CA();
|
||||
|
||||
prefs.setIntPref("network.http.speculative-parallel-limit", oldPref);
|
||||
Services.prefs.setIntPref("network.http.speculative-parallel-limit", oldPref);
|
||||
|
||||
run_next_test();
|
||||
}
|
||||
|
@ -42,10 +39,10 @@ add_task(async function test_pushUnsubscriptionSuccess() {
|
|||
var serverURL = "https://localhost:" + serverPort;
|
||||
|
||||
await db.put({
|
||||
subscriptionUri: serverURL + '/subscriptionUnsubscriptionSuccess',
|
||||
pushEndpoint: serverURL + '/pushEndpointUnsubscriptionSuccess',
|
||||
pushReceiptEndpoint: serverURL + '/receiptPushEndpointUnsubscriptionSuccess',
|
||||
scope: 'https://example.com/page/unregister-success',
|
||||
subscriptionUri: serverURL + "/subscriptionUnsubscriptionSuccess",
|
||||
pushEndpoint: serverURL + "/pushEndpointUnsubscriptionSuccess",
|
||||
pushReceiptEndpoint: serverURL + "/receiptPushEndpointUnsubscriptionSuccess",
|
||||
scope: "https://example.com/page/unregister-success",
|
||||
originAttributes: ChromeUtils.originAttributesToSuffix(
|
||||
{ appId: Ci.nsIScriptSecurityManager.NO_APP_ID, inIsolatedMozBrowser: false }),
|
||||
quota: Infinity,
|
||||
|
@ -53,20 +50,19 @@ add_task(async function test_pushUnsubscriptionSuccess() {
|
|||
|
||||
PushService.init({
|
||||
serverURI: serverURL,
|
||||
db
|
||||
db,
|
||||
});
|
||||
|
||||
await PushService.unregister({
|
||||
scope: 'https://example.com/page/unregister-success',
|
||||
scope: "https://example.com/page/unregister-success",
|
||||
originAttributes: ChromeUtils.originAttributesToSuffix(
|
||||
{ appId: Ci.nsIScriptSecurityManager.NO_APP_ID, inIsolatedMozBrowser: false }),
|
||||
});
|
||||
let record = await db.getByKeyID(serverURL + '/subscriptionUnsubscriptionSuccess');
|
||||
ok(!record, 'Unregister did not remove record');
|
||||
|
||||
let record = await db.getByKeyID(serverURL + "/subscriptionUnsubscriptionSuccess");
|
||||
ok(!record, "Unregister did not remove record");
|
||||
});
|
||||
|
||||
add_task(async function test_complete() {
|
||||
prefs.setBoolPref("dom.push.enabled", pushEnabled);
|
||||
prefs.setBoolPref("dom.push.connection.enabled", pushConnectionEnabled);
|
||||
Services.prefs.setBoolPref("dom.push.enabled", pushEnabled);
|
||||
Services.prefs.setBoolPref("dom.push.connection.enabled", pushConnectionEnabled);
|
||||
});
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
'use strict';
|
||||
"use strict";
|
||||
|
||||
const {HttpServer} = ChromeUtils.import("resource://testing-common/httpd.js");
|
||||
|
||||
|
@ -25,22 +25,20 @@ httpServer.registerPathHandler("/subscriptionNoKey", listenHandler);
|
|||
httpServer.start(-1);
|
||||
|
||||
function run_test() {
|
||||
|
||||
do_get_profile();
|
||||
setPrefs({
|
||||
'testing.allowInsecureServerURL': true,
|
||||
'http2.retryInterval': 1000,
|
||||
'http2.maxRetries': 2
|
||||
"testing.allowInsecureServerURL": true,
|
||||
"http2.retryInterval": 1000,
|
||||
"http2.maxRetries": 2,
|
||||
});
|
||||
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
add_task(async function test1() {
|
||||
|
||||
let db = PushServiceHttp2.newPushDB();
|
||||
registerCleanupFunction(_ => {
|
||||
return db.drop().then(_ => db.close());
|
||||
registerCleanupFunction(() => {
|
||||
return db.drop().then(() => db.close());
|
||||
});
|
||||
|
||||
do_test_pending();
|
||||
|
@ -48,11 +46,11 @@ add_task(async function test1() {
|
|||
var serverURL = "http://localhost:" + httpServer.identity.primaryPort;
|
||||
|
||||
let record = {
|
||||
subscriptionUri: serverURL + '/subscriptionNoKey',
|
||||
pushEndpoint: serverURL + '/pushEndpoint',
|
||||
pushReceiptEndpoint: serverURL + '/pushReceiptEndpoint',
|
||||
scope: 'https://example.com/page',
|
||||
originAttributes: '',
|
||||
subscriptionUri: serverURL + "/subscriptionNoKey",
|
||||
pushEndpoint: serverURL + "/pushEndpoint",
|
||||
pushReceiptEndpoint: serverURL + "/pushReceiptEndpoint",
|
||||
scope: "https://example.com/page",
|
||||
originAttributes: "",
|
||||
quota: Infinity,
|
||||
systemRecord: true,
|
||||
};
|
||||
|
@ -64,13 +62,13 @@ add_task(async function test1() {
|
|||
|
||||
PushService.init({
|
||||
serverURI: serverURL + "/subscribe",
|
||||
db
|
||||
db,
|
||||
});
|
||||
|
||||
await notifyPromise;
|
||||
|
||||
let aRecord = await db.getByKeyID(serverURL + '/subscriptionNoKey');
|
||||
ok(aRecord, 'The record should still be there');
|
||||
ok(aRecord.p256dhPublicKey, 'There should be a public key');
|
||||
ok(aRecord.p256dhPrivateKey, 'There should be a private key');
|
||||
let aRecord = await db.getByKeyID(serverURL + "/subscriptionNoKey");
|
||||
ok(aRecord, "The record should still be there");
|
||||
ok(aRecord.p256dhPublicKey, "There should be a public key");
|
||||
ok(aRecord.p256dhPrivateKey, "There should be a private key");
|
||||
});
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
'use strict';
|
||||
"use strict";
|
||||
|
||||
const {PushDB, PushService, PushServiceWebSocket, PushCrypto} = serviceExports;
|
||||
|
||||
const userAgentID = '4dffd396-6582-471d-8c0c-84f394e9f7db';
|
||||
const userAgentID = "4dffd396-6582-471d-8c0c-84f394e9f7db";
|
||||
|
||||
function run_test() {
|
||||
do_get_profile();
|
||||
|
@ -17,20 +17,20 @@ function run_test() {
|
|||
|
||||
add_task(async function test_with_data_enabled() {
|
||||
let db = PushServiceWebSocket.newPushDB();
|
||||
registerCleanupFunction(() => {return db.drop().then(_ => db.close());});
|
||||
registerCleanupFunction(() => { return db.drop().then(_ => db.close()); });
|
||||
|
||||
let [publicKey, privateKey] = await PushCrypto.generateKeys();
|
||||
let records = [{
|
||||
channelID: 'eb18f12a-cc42-4f14-accb-3bfc1227f1aa',
|
||||
pushEndpoint: 'https://example.org/push/no-key/1',
|
||||
scope: 'https://example.com/page/1',
|
||||
originAttributes: '',
|
||||
channelID: "eb18f12a-cc42-4f14-accb-3bfc1227f1aa",
|
||||
pushEndpoint: "https://example.org/push/no-key/1",
|
||||
scope: "https://example.com/page/1",
|
||||
originAttributes: "",
|
||||
quota: Infinity,
|
||||
}, {
|
||||
channelID: '0d8886b9-8da1-4778-8f5d-1cf93a877ed6',
|
||||
pushEndpoint: 'https://example.org/push/key',
|
||||
scope: 'https://example.com/page/2',
|
||||
originAttributes: '',
|
||||
channelID: "0d8886b9-8da1-4778-8f5d-1cf93a877ed6",
|
||||
pushEndpoint: "https://example.org/push/key",
|
||||
scope: "https://example.com/page/2",
|
||||
originAttributes: "",
|
||||
p256dhPublicKey: publicKey,
|
||||
p256dhPrivateKey: privateKey,
|
||||
quota: Infinity,
|
||||
|
@ -46,9 +46,9 @@ add_task(async function test_with_data_enabled() {
|
|||
return new MockWebSocket(uri, {
|
||||
onHello(request) {
|
||||
ok(request.use_webpush,
|
||||
'Should use Web Push if data delivery is enabled');
|
||||
"Should use Web Push if data delivery is enabled");
|
||||
this.serverSendMsg(JSON.stringify({
|
||||
messageType: 'hello',
|
||||
messageType: "hello",
|
||||
status: 200,
|
||||
uaid: request.uaid,
|
||||
use_webpush: true,
|
||||
|
@ -56,31 +56,31 @@ add_task(async function test_with_data_enabled() {
|
|||
},
|
||||
onRegister(request) {
|
||||
this.serverSendMsg(JSON.stringify({
|
||||
messageType: 'register',
|
||||
messageType: "register",
|
||||
status: 200,
|
||||
uaid: userAgentID,
|
||||
channelID: request.channelID,
|
||||
pushEndpoint: 'https://example.org/push/new',
|
||||
pushEndpoint: "https://example.org/push/new",
|
||||
}));
|
||||
}
|
||||
},
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
let newRecord = await PushService.register({
|
||||
scope: 'https://example.com/page/3',
|
||||
scope: "https://example.com/page/3",
|
||||
originAttributes: ChromeUtils.originAttributesToSuffix(
|
||||
{ appId: Ci.nsIScriptSecurityManager.NO_APP_ID, inIsolatedMozBrowser: false }),
|
||||
});
|
||||
ok(newRecord.p256dhKey, 'Should generate public keys for new records');
|
||||
ok(newRecord.p256dhKey, "Should generate public keys for new records");
|
||||
|
||||
let record = await db.getByKeyID('eb18f12a-cc42-4f14-accb-3bfc1227f1aa');
|
||||
ok(record.p256dhPublicKey, 'Should add public key to partial record');
|
||||
ok(record.p256dhPrivateKey, 'Should add private key to partial record');
|
||||
let record = await db.getByKeyID("eb18f12a-cc42-4f14-accb-3bfc1227f1aa");
|
||||
ok(record.p256dhPublicKey, "Should add public key to partial record");
|
||||
ok(record.p256dhPrivateKey, "Should add private key to partial record");
|
||||
|
||||
record = await db.getByKeyID('0d8886b9-8da1-4778-8f5d-1cf93a877ed6');
|
||||
record = await db.getByKeyID("0d8886b9-8da1-4778-8f5d-1cf93a877ed6");
|
||||
deepEqual(record.p256dhPublicKey, publicKey,
|
||||
'Should leave existing public key');
|
||||
"Should leave existing public key");
|
||||
deepEqual(record.p256dhPrivateKey, privateKey,
|
||||
'Should leave existing private key');
|
||||
"Should leave existing private key");
|
||||
});
|
||||
|
|
Загрузка…
Ссылка в новой задаче