mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-22 17:55:50 +00:00
e930b89c34
*** Bug 1514594: Part 3a - Change ChromeUtils.import to return an exports object; not pollute global. r=mccr8 This changes the behavior of ChromeUtils.import() to return an exports object, rather than a module global, in all cases except when `null` is passed as a second argument, and changes the default behavior not to pollute the global scope with the module's exports. Thus, the following code written for the old model: ChromeUtils.import("resource://gre/modules/Services.jsm"); is approximately the same as the following, in the new model: var {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm"); Since the two behaviors are mutually incompatible, this patch will land with a scripted rewrite to update all existing callers to use the new model rather than the old. *** Bug 1514594: Part 3b - Mass rewrite all JS code to use the new ChromeUtils.import API. rs=Gijs This was done using the followng script: https://bitbucket.org/kmaglione/m-c-rewrites/src/tip/processors/cu-import-exports.jsm *** Bug 1514594: Part 3c - Update ESLint plugin for ChromeUtils.import API changes. r=Standard8 Differential Revision: https://phabricator.services.mozilla.com/D16747 *** Bug 1514594: Part 3d - Remove/fix hundreds of duplicate imports from sync tests. r=Gijs Differential Revision: https://phabricator.services.mozilla.com/D16748 *** Bug 1514594: Part 3e - Remove no-op ChromeUtils.import() calls. r=Gijs Differential Revision: https://phabricator.services.mozilla.com/D16749 *** Bug 1514594: Part 3f.1 - Cleanup various test corner cases after mass rewrite. r=Gijs *** Bug 1514594: Part 3f.2 - Cleanup various non-test corner cases after mass rewrite. r=Gijs Differential Revision: https://phabricator.services.mozilla.com/D16750 --HG-- extra : rebase_source : 359574ee3064c90f33bf36c2ebe3159a24cc8895 extra : histedit_source : b93c8f42808b1599f9122d7842d2c0b3e656a594%2C64a3a4e3359dc889e2ab2b49461bab9e27fc10a7
177 lines
6.1 KiB
JavaScript
177 lines
6.1 KiB
JavaScript
/* 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/. */
|
|
|
|
const {XPCOMUtils} = ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
|
|
const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
|
const {EventDispatcher} = ChromeUtils.import("resource://gre/modules/Messaging.jsm");
|
|
const {
|
|
PushCrypto,
|
|
getCryptoParams,
|
|
} = ChromeUtils.import("resource://gre/modules/PushCrypto.jsm", null);
|
|
|
|
XPCOMUtils.defineLazyServiceGetter(this, "PushService",
|
|
"@mozilla.org/push/Service;1", "nsIPushService");
|
|
XPCOMUtils.defineLazyGetter(this, "_decoder", () => new TextDecoder());
|
|
|
|
const FXA_PUSH_SCOPE = "chrome://fxa-push";
|
|
const Log = ChromeUtils.import("resource://gre/modules/AndroidLog.jsm", {}).AndroidLog.bind("FxAccountsPush");
|
|
|
|
function FxAccountsPush() {
|
|
Services.obs.addObserver(this, "FxAccountsPush:ReceivedPushMessageToDecode");
|
|
|
|
EventDispatcher.instance.sendRequestForResult({
|
|
type: "FxAccountsPush:Initialized",
|
|
});
|
|
}
|
|
|
|
FxAccountsPush.prototype = {
|
|
observe: function(subject, topic, data) {
|
|
switch (topic) {
|
|
case "android-push-service":
|
|
if (data === "android-fxa-subscribe") {
|
|
this._subscribe();
|
|
} else if (data === "android-fxa-unsubscribe") {
|
|
this._unsubscribe();
|
|
} else if (data === "android-fxa-resubscribe") {
|
|
// If unsubscription fails, we still want to try to subscribe.
|
|
this._unsubscribe().then(this._subscribe, this._subscribe);
|
|
}
|
|
break;
|
|
case "FxAccountsPush:ReceivedPushMessageToDecode":
|
|
this._decodePushMessage(data);
|
|
break;
|
|
}
|
|
},
|
|
|
|
_subscribe() {
|
|
Log.i("FxAccountsPush _subscribe");
|
|
return new Promise((resolve, reject) => {
|
|
PushService.subscribe(FXA_PUSH_SCOPE,
|
|
Services.scriptSecurityManager.getSystemPrincipal(),
|
|
(result, subscription) => {
|
|
if (Components.isSuccessCode(result)) {
|
|
Log.d("FxAccountsPush got subscription");
|
|
resolve(subscription);
|
|
} else {
|
|
Log.w("FxAccountsPush failed to subscribe", result);
|
|
const err = new Error("FxAccountsPush failed to subscribe");
|
|
err.result = result;
|
|
reject(err);
|
|
}
|
|
});
|
|
})
|
|
.then(subscription => {
|
|
EventDispatcher.instance.sendRequest({
|
|
type: "FxAccountsPush:Subscribe:Response",
|
|
subscription: {
|
|
pushCallback: subscription.endpoint,
|
|
pushPublicKey: urlsafeBase64Encode(subscription.getKey("p256dh")),
|
|
pushAuthKey: urlsafeBase64Encode(subscription.getKey("auth")),
|
|
},
|
|
});
|
|
})
|
|
.catch(err => {
|
|
Log.i("Error when registering FxA push endpoint " + err);
|
|
EventDispatcher.instance.sendRequest({
|
|
type: "FxAccountsPush:Subscribe:Response",
|
|
error: err.result.toString(), // Convert to string because the GeckoBundle can't getLong();
|
|
});
|
|
});
|
|
},
|
|
|
|
_unsubscribe() {
|
|
Log.i("FxAccountsPush _unsubscribe");
|
|
return new Promise((resolve) => {
|
|
PushService.unsubscribe(FXA_PUSH_SCOPE,
|
|
Services.scriptSecurityManager.getSystemPrincipal(),
|
|
(result, ok) => {
|
|
if (Components.isSuccessCode(result)) {
|
|
if (ok === true) {
|
|
Log.d("FxAccountsPush unsubscribed");
|
|
} else {
|
|
Log.d("FxAccountsPush had no subscription to unsubscribe");
|
|
}
|
|
} else {
|
|
Log.w("FxAccountsPush failed to unsubscribe", result);
|
|
}
|
|
return resolve(ok);
|
|
});
|
|
}).catch(err => {
|
|
Log.e("Error during unsubscribe", err);
|
|
});
|
|
},
|
|
|
|
_decodePushMessage(data) {
|
|
Log.i("FxAccountsPush _decodePushMessage");
|
|
data = JSON.parse(data);
|
|
let { headers, message } = this._messageAndHeaders(data);
|
|
return new Promise((resolve, reject) => {
|
|
PushService.getSubscription(FXA_PUSH_SCOPE,
|
|
Services.scriptSecurityManager.getSystemPrincipal(),
|
|
(result, subscription) => {
|
|
if (!Components.isSuccessCode(result)) {
|
|
return reject(new Error(`Error getting subscription (${result})`));
|
|
}
|
|
if (!subscription) {
|
|
return reject(new Error("No subscription found"));
|
|
}
|
|
return resolve(subscription);
|
|
});
|
|
}).then(subscription => {
|
|
return PushCrypto.decrypt(subscription.p256dhPrivateKey,
|
|
new Uint8Array(subscription.getKey("p256dh")),
|
|
new Uint8Array(subscription.getKey("auth")),
|
|
headers, message);
|
|
})
|
|
.then(plaintext => {
|
|
let decryptedMessage = plaintext ? _decoder.decode(plaintext) : "";
|
|
EventDispatcher.instance.sendRequestForResult({
|
|
type: "FxAccountsPush:ReceivedPushMessageToDecode:Response",
|
|
message: decryptedMessage,
|
|
});
|
|
})
|
|
.catch(err => {
|
|
Log.d("Error while decoding incoming message : " + err);
|
|
EventDispatcher.instance.sendRequestForResult({
|
|
type: "FxAccountsPush:ReceivedPushMessageToDecode:Response",
|
|
error: err.message || "",
|
|
});
|
|
});
|
|
},
|
|
|
|
// Copied from PushServiceAndroidGCM
|
|
_messageAndHeaders(data) {
|
|
// Default is no data (and no encryption).
|
|
let message = null;
|
|
let headers = null;
|
|
|
|
if (data.message && data.enc && (data.enckey || data.cryptokey)) {
|
|
headers = {
|
|
encryption_key: data.enckey,
|
|
crypto_key: data.cryptokey,
|
|
encryption: data.enc,
|
|
encoding: data.con,
|
|
};
|
|
// Ciphertext is (urlsafe) Base 64 encoded.
|
|
message = ChromeUtils.base64URLDecode(data.message, {
|
|
// The Push server may append padding.
|
|
padding: "ignore",
|
|
});
|
|
}
|
|
return { headers, message };
|
|
},
|
|
|
|
QueryInterface: ChromeUtils.generateQI([Ci.nsIObserver]),
|
|
|
|
classID: Components.ID("{d1bbb0fd-1d47-4134-9c12-d7b1be20b721}"),
|
|
};
|
|
|
|
function urlsafeBase64Encode(key) {
|
|
return ChromeUtils.base64URLEncode(new Uint8Array(key), { pad: false });
|
|
}
|
|
|
|
var components = [ FxAccountsPush ];
|
|
this.NSGetFactory = XPCOMUtils.generateNSGetFactory(components);
|