From fbaf0bb26397aa498eb9156f06d5a6fe34dd7dd8 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 03:14:29 +0200 Subject: Merging upstream version 125.0.1. Signed-off-by: Daniel Baumann --- dom/push/Push.sys.mjs | 161 +++++++++++---------- dom/push/PushComponents.sys.mjs | 12 +- dom/push/PushCrypto.sys.mjs | 4 +- dom/push/PushDB.sys.mjs | 4 +- dom/push/PushService.sys.mjs | 22 ++- dom/push/PushServiceHttp2.sys.mjs | 14 +- dom/push/PushServiceWebSocket.sys.mjs | 8 +- dom/push/test/lifetime_worker.js | 4 +- dom/push/test/mockpushserviceparent.js | 2 +- dom/push/test/test_data.html | 2 +- dom/push/test/test_has_permissions.html | 2 +- dom/push/test/test_multiple_register.html | 18 +-- .../test_multiple_register_different_scope.html | 2 +- ...ultiple_register_during_service_activation.html | 2 +- dom/push/test/test_permissions.html | 2 +- dom/push/test/test_register.html | 2 +- dom/push/test/test_register_key.html | 2 +- dom/push/test/test_serviceworker_lifetime.html | 22 +-- .../test_try_registering_offline_disabled.html | 10 +- dom/push/test/test_utils.js | 8 +- dom/push/test/worker.js | 4 +- dom/push/test/xpcshell/broadcast_handler.sys.mjs | 2 +- dom/push/test/xpcshell/head.js | 8 +- dom/push/test/xpcshell/test_broadcast_success.js | 4 +- dom/push/test/xpcshell/test_clearAll_successful.js | 4 +- .../test/xpcshell/test_clear_forgetAboutSite.js | 2 +- dom/push/test/xpcshell/test_clear_origin_data.js | 5 - dom/push/test/xpcshell/test_drop_expired.js | 2 +- .../test/xpcshell/test_notification_duplicate.js | 2 +- dom/push/test/xpcshell/test_notification_error.js | 2 +- .../test/xpcshell/test_notification_incomplete.js | 4 +- .../xpcshell/test_notification_version_string.js | 2 +- dom/push/test/xpcshell/test_permissions.js | 4 +- dom/push/test/xpcshell/test_quota_exceeded.js | 6 +- dom/push/test/xpcshell/test_quota_observer.js | 4 +- .../test/xpcshell/test_quota_with_notification.js | 12 +- dom/push/test/xpcshell/test_reconnect_retry.js | 2 +- dom/push/test/xpcshell/test_register_case.js | 2 +- dom/push/test/xpcshell/test_register_flush.js | 2 +- .../test/xpcshell/test_register_invalid_channel.js | 4 +- .../xpcshell/test_register_invalid_endpoint.js | 4 +- .../test/xpcshell/test_register_invalid_json.js | 2 +- dom/push/test/xpcshell/test_register_no_id.js | 2 +- .../test/xpcshell/test_register_request_queue.js | 2 +- dom/push/test/xpcshell/test_register_rollback.js | 2 +- dom/push/test/xpcshell/test_register_wrong_id.js | 2 +- dom/push/test/xpcshell/test_register_wrong_type.js | 4 +- dom/push/test/xpcshell/test_registration_error.js | 2 +- dom/push/test/xpcshell/test_retry_ws.js | 4 +- dom/push/test/xpcshell/test_service_child.js | 4 +- .../test/xpcshell/test_unregister_empty_scope.js | 2 +- dom/push/test/xpcshell/test_unregister_error.js | 2 +- .../test/xpcshell/test_unregister_invalid_json.js | 4 +- .../test/xpcshell/test_unregister_not_found.js | 2 +- dom/push/test/xpcshell/test_unregister_success.js | 2 +- 55 files changed, 208 insertions(+), 212 deletions(-) (limited to 'dom/push') diff --git a/dom/push/Push.sys.mjs b/dom/push/Push.sys.mjs index 07f763040f..2e55d1dc89 100644 --- a/dom/push/Push.sys.mjs +++ b/dom/push/Push.sys.mjs @@ -4,8 +4,6 @@ import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs"; -import { DOMRequestIpcHelper } from "resource://gre/modules/DOMRequestHelper.sys.mjs"; - const lazy = {}; ChromeUtils.defineLazyGetter(lazy, "console", () => { @@ -25,37 +23,37 @@ XPCOMUtils.defineLazyServiceGetter( "nsIPushService" ); -const PUSH_CID = Components.ID("{cde1d019-fad8-4044-b141-65fb4fb7a245}"); - /** * The Push component runs in the child process and exposes the Push API * to the web application. The PushService running in the parent process is the * one actually performing all operations. */ -export function Push() { - lazy.console.debug("Push()"); -} - -Push.prototype = { - __proto__: DOMRequestIpcHelper.prototype, - - contractID: "@mozilla.org/push/PushManager;1", - - classID: PUSH_CID, - - QueryInterface: ChromeUtils.generateQI([ - "nsIDOMGlobalPropertyInitializer", - "nsISupportsWeakReference", - "nsIObserver", - ]), +export class Push { + constructor() { + lazy.console.debug("Push()"); + } + + get contractID() { + return "@mozilla.org/push/PushManager;1"; + } + + get classID() { + return Components.ID("{cde1d019-fad8-4044-b141-65fb4fb7a245}"); + } + + get QueryInterface() { + return ChromeUtils.generateQI([ + "nsIDOMGlobalPropertyInitializer", + "nsISupportsWeakReference", + "nsIObserver", + ]); + } init(win) { lazy.console.debug("init()"); this._window = win; - this.initDOMRequestHelper(win); - // Get the client principal from the window. This won't be null because the // service worker should be available when accessing the push manager. this._principal = win.clientPrincipal; @@ -70,11 +68,11 @@ Push.prototype = { // Accessing the top-level document might fails if cross-origin this._topLevelPrincipal = undefined; } - }, + } __init(scope) { this._scope = scope; - }, + } askPermission() { lazy.console.debug("askPermission()"); @@ -82,7 +80,7 @@ Push.prototype = { let hasValidTransientUserGestureActivation = this._window.document.hasValidTransientUserGestureActivation; - return this.createPromise((resolve, reject) => { + return new this._window.Promise((resolve, reject) => { // Test permission before requesting to support GeckoView: // * GeckoViewPermissionChild wants to return early when requested without user activation // before doing actual permission check: @@ -90,7 +88,7 @@ Push.prototype = { // which is partly because: // * GeckoView test runner has no real permission check but just returns VALUE_ALLOW. // https://searchfox.org/mozilla-central/rev/6e5b9a5a1edab13a1b2e2e90944b6e06b4d8149c/mobile/android/test_runner/src/main/java/org/mozilla/geckoview/test_runner/TestRunnerActivity.java#108-123 - if (this._testPermission() === Ci.nsIPermissionManager.ALLOW_ACTION) { + if (this.#testPermission() === Ci.nsIPermissionManager.ALLOW_ACTION) { resolve(); return; } @@ -111,42 +109,45 @@ Push.prototype = { return; } - this._requestPermission( + this.#requestPermission( hasValidTransientUserGestureActivation, resolve, permissionDenied ); }); - }, + } subscribe(options) { lazy.console.debug("subscribe()", this._scope); - return this.askPermission().then(() => - this.createPromise((resolve, reject) => { - let callback = new PushSubscriptionCallback(this, resolve, reject); - - if (!options || options.applicationServerKey === null) { - lazy.PushService.subscribe(this._scope, this._principal, callback); - return; - } - - let keyView = this._normalizeAppServerKey(options.applicationServerKey); - if (keyView.byteLength === 0) { - callback._rejectWithError(Cr.NS_ERROR_DOM_PUSH_INVALID_KEY_ERR); - return; - } - lazy.PushService.subscribeWithKey( - this._scope, - this._principal, - keyView, - callback - ); - }) + return this.askPermission().then( + () => + new this._window.Promise((resolve, reject) => { + let callback = new PushSubscriptionCallback(this, resolve, reject); + + if (!options || options.applicationServerKey === null) { + lazy.PushService.subscribe(this._scope, this._principal, callback); + return; + } + + let keyView = this.#normalizeAppServerKey( + options.applicationServerKey + ); + if (keyView.byteLength === 0) { + callback.rejectWithError(Cr.NS_ERROR_DOM_PUSH_INVALID_KEY_ERR); + return; + } + lazy.PushService.subscribeWithKey( + this._scope, + this._principal, + keyView, + callback + ); + }) ); - }, + } - _normalizeAppServerKey(appServerKey) { + #normalizeAppServerKey(appServerKey) { let key; if (typeof appServerKey == "string") { try { @@ -169,25 +170,25 @@ Push.prototype = { key = appServerKey; } return new this._window.Uint8Array(key); - }, + } getSubscription() { lazy.console.debug("getSubscription()", this._scope); - return this.createPromise((resolve, reject) => { + return new this._window.Promise((resolve, reject) => { let callback = new PushSubscriptionCallback(this, resolve, reject); lazy.PushService.getSubscription(this._scope, this._principal, callback); }); - }, + } permissionState() { lazy.console.debug("permissionState()", this._scope); - return this.createPromise((resolve, reject) => { + return new this._window.Promise((resolve, reject) => { let permission = Ci.nsIPermissionManager.UNKNOWN_ACTION; try { - permission = this._testPermission(); + permission = this.#testPermission(); } catch (e) { reject(); return; @@ -201,9 +202,9 @@ Push.prototype = { } resolve(pushPermissionStatus); }); - }, + } - _testPermission() { + #testPermission() { let permission = Services.perms.testExactPermissionFromPrincipal( this._principal, "desktop-notification" @@ -217,9 +218,9 @@ Push.prototype = { } } catch (e) {} return permission; - }, + } - _requestPermission( + #requestPermission( hasValidTransientUserGestureActivation, allowCallback, cancelCallback @@ -251,22 +252,24 @@ Push.prototype = { // remoting if needed. let windowUtils = this._window.windowUtils; windowUtils.askPermission(request); - }, -}; - -function PushSubscriptionCallback(pushManager, resolve, reject) { - this.pushManager = pushManager; - this.resolve = resolve; - this.reject = reject; + } } -PushSubscriptionCallback.prototype = { - QueryInterface: ChromeUtils.generateQI(["nsIPushSubscriptionCallback"]), +class PushSubscriptionCallback { + constructor(pushManager, resolve, reject) { + this.pushManager = pushManager; + this.resolve = resolve; + this.reject = reject; + } + + get QueryInterface() { + return ChromeUtils.generateQI(["nsIPushSubscriptionCallback"]); + } onPushSubscription(ok, subscription) { let { pushManager } = this; if (!Components.isSuccessCode(ok)) { - this._rejectWithError(ok); + this.rejectWithError(ok); return; } @@ -275,24 +278,24 @@ PushSubscriptionCallback.prototype = { return; } - let p256dhKey = this._getKey(subscription, "p256dh"); - let authSecret = this._getKey(subscription, "auth"); + let p256dhKey = this.#getKey(subscription, "p256dh"); + let authSecret = this.#getKey(subscription, "auth"); let options = { endpoint: subscription.endpoint, scope: pushManager._scope, p256dhKey, authSecret, }; - let appServerKey = this._getKey(subscription, "appServer"); + let appServerKey = this.#getKey(subscription, "appServer"); if (appServerKey) { // Avoid passing null keys to work around bug 1256449. options.appServerKey = appServerKey; } let sub = new pushManager._window.PushSubscription(options); this.resolve(sub); - }, + } - _getKey(subscription, name) { + #getKey(subscription, name) { let rawKey = Cu.cloneInto( subscription.getKey(name), this.pushManager._window @@ -305,9 +308,9 @@ PushSubscriptionCallback.prototype = { let keyView = new this.pushManager._window.Uint8Array(key); keyView.set(rawKey); return key; - }, + } - _rejectWithError(result) { + rejectWithError(result) { let error; switch (result) { case Cr.NS_ERROR_DOM_PUSH_INVALID_KEY_ERR: @@ -331,5 +334,5 @@ PushSubscriptionCallback.prototype = { ); } this.reject(error); - }, -}; + } +} diff --git a/dom/push/PushComponents.sys.mjs b/dom/push/PushComponents.sys.mjs index 0ad0505851..4a2bfc1279 100644 --- a/dom/push/PushComponents.sys.mjs +++ b/dom/push/PushComponents.sys.mjs @@ -40,7 +40,7 @@ const OBSERVER_TOPIC_SUBSCRIPTION_MODIFIED = "push-subscription-modified"; * similar to the Push DOM API, but does not require service workers. * * Push service methods may be called from the parent or content process. The - * parent process implementation loads `PushService.jsm` at app startup, and + * parent process implementation loads `PushService.sys.mjs` at app startup, and * calls its methods directly. The content implementation forwards calls to * the parent Push service via IPC. * @@ -78,7 +78,7 @@ PushServiceBase.prototype = { return this._messages.includes(message.name); }, - observe(subject, topic, data) { + observe(subject, topic) { if (topic === "android-push-service") { // Load PushService immediately. this.ensureReady(); @@ -102,7 +102,7 @@ PushServiceBase.prototype = { /** * The parent process implementation of `nsIPushService`. This version loads - * `PushService.jsm` at startup and calls its methods directly. It also + * `PushService.sys.mjs` at startup and calls its methods directly. It also * receives and responds to requests from the content process. */ let parentInstance; @@ -165,7 +165,7 @@ Object.assign(PushServiceParent.prototype, { result => { callback.onUnsubscribe(Cr.NS_OK, result); }, - error => { + () => { callback.onUnsubscribe(Cr.NS_ERROR_FAILURE, false); } ) @@ -192,10 +192,10 @@ Object.assign(PushServiceParent.prototype, { domain, }) .then( - result => { + () => { callback.onClear(Cr.NS_OK); }, - error => { + () => { callback.onClear(Cr.NS_ERROR_FAILURE); } ) diff --git a/dom/push/PushCrypto.sys.mjs b/dom/push/PushCrypto.sys.mjs index 384901f925..fab1dc4762 100644 --- a/dom/push/PushCrypto.sys.mjs +++ b/dom/push/PushCrypto.sys.mjs @@ -377,7 +377,7 @@ class Decoder { * @param {BufferSource} ikm The ECDH shared secret. * @returns {Array} A `[gcmBits, nonce]` tuple. */ - async deriveKeyAndNonce(ikm) { + async deriveKeyAndNonce() { throw new Error("Missing `deriveKeyAndNonce` implementation"); } @@ -408,7 +408,7 @@ class Decoder { * @param {Uint8Array} chunk The decrypted block with padding. * @returns {Uint8Array} The block with padding removed. */ - unpadChunk(chunk, last) { + unpadChunk() { throw new Error("Missing `unpadChunk` implementation"); } diff --git a/dom/push/PushDB.sys.mjs b/dom/push/PushDB.sys.mjs index d6eab52040..aa35093200 100644 --- a/dom/push/PushDB.sys.mjs +++ b/dom/push/PushDB.sys.mjs @@ -46,7 +46,7 @@ PushDB.prototype = { ); }, - upgradeSchema(aTransaction, aDb, aOldVersion, aNewVersion) { + upgradeSchema(aTransaction, aDb, aOldVersion) { 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. @@ -419,7 +419,7 @@ PushDB.prototype = { } function putRecord() { let req = aStore.put(newRecord); - req.onsuccess = aEvent => { + req.onsuccess = () => { lazy.console.debug( "update: Update successful", aKeyID, diff --git a/dom/push/PushService.sys.mjs b/dom/push/PushService.sys.mjs index 7314e3df54..1add65992f 100644 --- a/dom/push/PushService.sys.mjs +++ b/dom/push/PushService.sys.mjs @@ -623,7 +623,7 @@ export var PushService = { this._db.close(); this._db = null; }, - err => { + () => { this._db.close(); this._db = null; } @@ -1162,17 +1162,15 @@ export var PushService = { let keyPromise; if (aPageRecord.appServerKey && aPageRecord.appServerKey.length) { let keyView = new Uint8Array(aPageRecord.appServerKey); - keyPromise = lazy.PushCrypto.validateAppServerKey(keyView).catch( - error => { - // Normalize Web Crypto exceptions. `nsIPushService` will forward the - // error result to the DOM API implementation in `PushManager.cpp` or - // `Push.js`, which will convert it to the correct `DOMException`. - throw errorWithResult( - "Invalid app server key", - Cr.NS_ERROR_DOM_PUSH_INVALID_KEY_ERR - ); - } - ); + keyPromise = lazy.PushCrypto.validateAppServerKey(keyView).catch(() => { + // Normalize Web Crypto exceptions. `nsIPushService` will forward the + // error result to the DOM API implementation in `PushManager.cpp` or + // `Push.js`, which will convert it to the correct `DOMException`. + throw errorWithResult( + "Invalid app server key", + Cr.NS_ERROR_DOM_PUSH_INVALID_KEY_ERR + ); + }); } else { keyPromise = Promise.resolve(null); } diff --git a/dom/push/PushServiceHttp2.sys.mjs b/dom/push/PushServiceHttp2.sys.mjs index 76ac85d7b1..838071f701 100644 --- a/dom/push/PushServiceHttp2.sys.mjs +++ b/dom/push/PushServiceHttp2.sys.mjs @@ -52,7 +52,7 @@ PushSubscriptionListener.prototype = { return this.QueryInterface(aIID); }, - onStartRequest(aRequest) { + onStartRequest() { lazy.console.debug("PushSubscriptionListener: onStartRequest()"); // We do not do anything here. }, @@ -174,7 +174,7 @@ var PushServiceDelete = function (resolve, reject) { }; PushServiceDelete.prototype = { - onStartRequest(aRequest) {}, + onStartRequest() {}, onDataAvailable(aRequest, aStream, aOffset, aCount) { // Nobody should send data, but just to be sure, otherwise necko will @@ -218,9 +218,9 @@ var SubscriptionListener = function ( }; SubscriptionListener.prototype = { - onStartRequest(aRequest) {}, + onStartRequest() {}, - onDataAvailable(aRequest, aStream, aOffset, aCount) {}, + onDataAvailable() {}, onStopRequest(aRequest, aStatus) { lazy.console.debug("SubscriptionListener: onStopRequest()"); @@ -418,12 +418,12 @@ export var PushServiceHttp2 = { return this._mainPushService !== null; }, - async connect(broadcastListeners) { + async connect() { let subscriptions = await this._mainPushService.getAllUnexpired(); this.startConnections(subscriptions); }, - async sendSubscribeBroadcast(serviceId, version) { + async sendSubscribeBroadcast() { // Not implemented yet }, @@ -737,7 +737,7 @@ export var PushServiceHttp2 = { .catch(console.error); } }, - error => { + () => { if (this._mainPushService) { this._mainPushService .dropRegistrationAndNotifyApp(aSubscriptionUri) diff --git a/dom/push/PushServiceWebSocket.sys.mjs b/dom/push/PushServiceWebSocket.sys.mjs index 72d8791a96..59e8f403f1 100644 --- a/dom/push/PushServiceWebSocket.sys.mjs +++ b/dom/push/PushServiceWebSocket.sys.mjs @@ -80,11 +80,11 @@ PushWebSocketListener.prototype = { this._pushService._wsOnStop(context, statusCode); }, - onAcknowledge(context, size) { + onAcknowledge() { // EMPTY }, - onBinaryMessageAvailable(context, message) { + onBinaryMessageAvailable() { // EMPTY }, @@ -971,7 +971,7 @@ export var PushServiceWebSocket = { // Otherwise, we're still setting up. If we don't have a request queue, // make one now. if (!this._notifyRequestQueue) { - let promise = new Promise((resolve, reject) => { + let promise = new Promise(resolve => { this._notifyRequestQueue = resolve; }); this._enqueue(_ => promise); @@ -1037,7 +1037,7 @@ export var PushServiceWebSocket = { }, // begin Push protocol handshake - _wsOnStart(context) { + _wsOnStart() { lazy.console.debug("wsOnStart()"); if (this._currentState != STATE_WAITING_FOR_WS_START) { diff --git a/dom/push/test/lifetime_worker.js b/dom/push/test/lifetime_worker.js index 02c09d966e..251a4a2bee 100644 --- a/dom/push/test/lifetime_worker.js +++ b/dom/push/test/lifetime_worker.js @@ -20,7 +20,7 @@ self.onfetch = function (event) { state = "update"; } else if (event.request.url.includes("wait")) { event.respondWith( - new Promise(function (res, rej) { + new Promise(function (res) { if (resolvePromiseCallback) { dump("ERROR: service worker was already waiting on a promise.\n"); } @@ -50,7 +50,7 @@ self.onmessage = function (event) { state = event.data; if (state === "wait") { event.waitUntil( - new Promise(function (res, rej) { + new Promise(function (res) { if (resolvePromiseCallback) { dump("ERROR: service worker was already waiting on a promise.\n"); } diff --git a/dom/push/test/mockpushserviceparent.js b/dom/push/test/mockpushserviceparent.js index 08d93f3aaf..7553b81876 100644 --- a/dom/push/test/mockpushserviceparent.js +++ b/dom/push/test/mockpushserviceparent.js @@ -85,7 +85,7 @@ addMessageListener("socket-setup", function () { }); }); -addMessageListener("socket-teardown", function (msg) { +addMessageListener("socket-teardown", function () { pushService .restoreServiceBackend() .then(_ => { diff --git a/dom/push/test/test_data.html b/dom/push/test/test_data.html index a2f043b7d9..0fad066cb7 100644 --- a/dom/push/test/test_data.html +++ b/dom/push/test/test_data.html @@ -154,7 +154,7 @@ http://creativecommons.org/licenses/publicdomain/ is(message.data.text, "Hi! \ud83d\udc40", "Wrong text for message with emoji"); var text = await new Promise((resolve, reject) => { var reader = new FileReader(); - reader.onloadend = event => { + reader.onloadend = () => { if (reader.error) { reject(reader.error); } else { diff --git a/dom/push/test/test_has_permissions.html b/dom/push/test/test_has_permissions.html index 0bef8fe19f..b66a9d4746 100644 --- a/dom/push/test/test_has_permissions.html +++ b/dom/push/test/test_has_permissions.html @@ -23,7 +23,7 @@ http://creativecommons.org/licenses/publicdomain/