mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-08 00:38:39 +09:00
Remove Firefox Accounts service and tie-ins.
See previous commit for removal of browser identity module.
This commit is contained in:
parent
ccf32a6b79
commit
c64dc935f9
420 changed files with 9 additions and 51958 deletions
|
|
@ -40,14 +40,8 @@ var Accounts = Object.freeze({
|
|||
}).then(data => data.exists);
|
||||
},
|
||||
|
||||
firefoxAccountsExist: function () {
|
||||
return this._accountsExist("fxa");
|
||||
},
|
||||
|
||||
syncAccountsExist: function () {
|
||||
Deprecated.warning("The legacy Sync account type has been removed from Firefox for Android. " +
|
||||
"Please use `firefoxAccountsExist` instead.",
|
||||
"https://developer.mozilla.org/en-US/Add-ons/Firefox_for_Android/API/Accounts.jsm");
|
||||
Deprecated.warning("The legacy Sync account type has been removed from Firefox for Android.");
|
||||
return Promise.resolve(false);
|
||||
},
|
||||
|
||||
|
|
@ -73,106 +67,13 @@ var Accounts = Object.freeze({
|
|||
},
|
||||
|
||||
_addDefaultEndpoints: function (json) {
|
||||
// Empty without FxA
|
||||
let newData = Cu.cloneInto(json, {}, { cloneFunctions: false });
|
||||
let associations = {
|
||||
authServerEndpoint: 'identity.fxaccounts.auth.uri',
|
||||
profileServerEndpoint: 'identity.fxaccounts.remote.profile.uri',
|
||||
tokenServerEndpoint: 'identity.sync.tokenserver.uri'
|
||||
};
|
||||
for (let key in associations) {
|
||||
newData[key] = newData[key] || Services.urlFormatter.formatURLPref(associations[key]);
|
||||
}
|
||||
return newData;
|
||||
},
|
||||
|
||||
/**
|
||||
* Create a new Android Account corresponding to the given
|
||||
* fxa-content-server "login" JSON datum. The new account will be
|
||||
* in the "Engaged" state, and will start syncing immediately.
|
||||
*
|
||||
* It is an error if an Android Account already exists.
|
||||
*
|
||||
* Returns a Promise that resolves to a boolean indicating success.
|
||||
*/
|
||||
createFirefoxAccountFromJSON: function (json) {
|
||||
return Messaging.sendRequestForResult({
|
||||
type: "Accounts:CreateFirefoxAccountFromJSON",
|
||||
json: this._addDefaultEndpoints(json)
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Move an existing Android Account to the "Engaged" state with the given
|
||||
* fxa-content-server "login" JSON datum. The account will (re)start
|
||||
* syncing immediately, unless the user has manually configured the account
|
||||
* to not Sync.
|
||||
*
|
||||
* It is an error if no Android Account exists.
|
||||
*
|
||||
* Returns a Promise that resolves to a boolean indicating success.
|
||||
*/
|
||||
updateFirefoxAccountFromJSON: function (json) {
|
||||
return Messaging.sendRequestForResult({
|
||||
type: "Accounts:UpdateFirefoxAccountFromJSON",
|
||||
json: this._addDefaultEndpoints(json)
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Notify that profile for Android Account has updated.
|
||||
* The account will re-fetch the profile image.
|
||||
*
|
||||
* It is an error if no Android Account exists.
|
||||
*
|
||||
* There is no return value from this method.
|
||||
*/
|
||||
notifyFirefoxAccountProfileChanged: function () {
|
||||
Messaging.sendRequest({
|
||||
type: "Accounts:ProfileUpdated",
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Fetch information about an existing Android Firefox Account.
|
||||
*
|
||||
* Returns a Promise that resolves to null if no Android Firefox Account
|
||||
* exists, or an object including at least a string-valued 'email' key.
|
||||
*/
|
||||
getFirefoxAccount: function () {
|
||||
return Messaging.sendRequestForResult({
|
||||
type: "Accounts:Exist",
|
||||
kind: "fxa",
|
||||
}).then(data => {
|
||||
if (!data || !data.exists) {
|
||||
return null;
|
||||
}
|
||||
delete data.exists;
|
||||
return data;
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Delete an existing Android Firefox Account.
|
||||
*
|
||||
* It is an error if no Android Account exists.
|
||||
*
|
||||
* Returns a Promise that resolves to a boolean indicating success.
|
||||
*/
|
||||
deleteFirefoxAccount: function () {
|
||||
return Messaging.sendRequestForResult({
|
||||
type: "Accounts:DeleteFirefoxAccount",
|
||||
});
|
||||
},
|
||||
|
||||
showSyncPreferences: function () {
|
||||
// Only show Sync preferences of an existing Android Account.
|
||||
return Accounts.getFirefoxAccount().then(account => {
|
||||
if (!account) {
|
||||
throw new Error("Can't show Sync preferences of non-existent Firefox Account!");
|
||||
}
|
||||
return Messaging.sendRequestForResult({
|
||||
type: "Accounts:ShowSyncPreferences"
|
||||
});
|
||||
});
|
||||
throw new Error("Can't show Sync preferences without accounts!");
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,394 +0,0 @@
|
|||
// -*- Mode: js2; tab-width: 2; indent-tabs-mode: nil; js2-basic-offset: 2; js2-skip-preprocessor-directives: t; -*-
|
||||
/* 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/. */
|
||||
|
||||
/**
|
||||
* Firefox Accounts Web Channel.
|
||||
*
|
||||
* Use the WebChannel component to receive messages about account
|
||||
* state changes.
|
||||
*/
|
||||
this.EXPORTED_SYMBOLS = ["EnsureFxAccountsWebChannel"];
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components; /*global Components */
|
||||
|
||||
Cu.import("resource://gre/modules/Accounts.jsm"); /*global Accounts */
|
||||
Cu.import("resource://gre/modules/Services.jsm"); /*global Services */
|
||||
Cu.import("resource://gre/modules/WebChannel.jsm"); /*global WebChannel */
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm"); /*global XPCOMUtils */
|
||||
|
||||
const log = Cu.import("resource://gre/modules/AndroidLog.jsm", {}).AndroidLog.bind("FxAccounts");
|
||||
|
||||
const WEBCHANNEL_ID = "account_updates";
|
||||
|
||||
const COMMAND_LOADED = "fxaccounts:loaded";
|
||||
const COMMAND_CAN_LINK_ACCOUNT = "fxaccounts:can_link_account";
|
||||
const COMMAND_LOGIN = "fxaccounts:login";
|
||||
const COMMAND_CHANGE_PASSWORD = "fxaccounts:change_password";
|
||||
const COMMAND_DELETE_ACCOUNT = "fxaccounts:delete_account";
|
||||
const COMMAND_PROFILE_CHANGE = "profile:change";
|
||||
const COMMAND_SYNC_PREFERENCES = "fxaccounts:sync_preferences";
|
||||
|
||||
const PREF_LAST_FXA_USER = "identity.fxaccounts.lastSignedInUserHash";
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "strings",
|
||||
() => Services.strings.createBundle("chrome://browser/locale/aboutAccounts.properties")); /*global strings */
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Snackbars", "resource://gre/modules/Snackbars.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Prompt", "resource://gre/modules/Prompt.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "UITelemetry", "resource://gre/modules/UITelemetry.jsm");
|
||||
|
||||
this.FxAccountsWebChannelHelpers = function() {
|
||||
};
|
||||
|
||||
this.FxAccountsWebChannelHelpers.prototype = {
|
||||
/**
|
||||
* Get the hash of account name of the previously signed in account.
|
||||
*/
|
||||
getPreviousAccountNameHashPref() {
|
||||
try {
|
||||
return Services.prefs.getComplexValue(PREF_LAST_FXA_USER, Ci.nsISupportsString).data;
|
||||
} catch (_) {
|
||||
return "";
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Given an account name, set the hash of the previously signed in account.
|
||||
*
|
||||
* @param acctName the account name of the user's account.
|
||||
*/
|
||||
setPreviousAccountNameHashPref(acctName) {
|
||||
let string = Cc["@mozilla.org/supports-string;1"]
|
||||
.createInstance(Ci.nsISupportsString);
|
||||
string.data = this.sha256(acctName);
|
||||
Services.prefs.setComplexValue(PREF_LAST_FXA_USER, Ci.nsISupportsString, string);
|
||||
},
|
||||
|
||||
/**
|
||||
* Given a string, returns the SHA265 hash in base64.
|
||||
*/
|
||||
sha256(str) {
|
||||
let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"]
|
||||
.createInstance(Ci.nsIScriptableUnicodeConverter);
|
||||
converter.charset = "UTF-8";
|
||||
// Data is an array of bytes.
|
||||
let data = converter.convertToByteArray(str, {});
|
||||
let hasher = Cc["@mozilla.org/security/hash;1"]
|
||||
.createInstance(Ci.nsICryptoHash);
|
||||
hasher.init(hasher.SHA256);
|
||||
hasher.update(data, data.length);
|
||||
|
||||
return hasher.finish(true);
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a new FxAccountsWebChannel to listen for account updates.
|
||||
*
|
||||
* @param {Object} options Options
|
||||
* @param {Object} options
|
||||
* @param {String} options.content_uri
|
||||
* The FxA Content server uri
|
||||
* @param {String} options.channel_id
|
||||
* The ID of the WebChannel
|
||||
* @param {String} options.helpers
|
||||
* Helpers functions. Should only be passed in for testing.
|
||||
* @constructor
|
||||
*/
|
||||
this.FxAccountsWebChannel = function(options) {
|
||||
if (!options) {
|
||||
throw new Error("Missing configuration options");
|
||||
}
|
||||
if (!options["content_uri"]) {
|
||||
throw new Error("Missing 'content_uri' option");
|
||||
}
|
||||
this._contentUri = options.content_uri;
|
||||
|
||||
if (!options["channel_id"]) {
|
||||
throw new Error("Missing 'channel_id' option");
|
||||
}
|
||||
this._webChannelId = options.channel_id;
|
||||
|
||||
// options.helpers is only specified by tests.
|
||||
this._helpers = options.helpers || new FxAccountsWebChannelHelpers(options);
|
||||
|
||||
this._setupChannel();
|
||||
};
|
||||
|
||||
this.FxAccountsWebChannel.prototype = {
|
||||
/**
|
||||
* WebChannel that is used to communicate with content page
|
||||
*/
|
||||
_channel: null,
|
||||
|
||||
/**
|
||||
* WebChannel ID.
|
||||
*/
|
||||
_webChannelId: null,
|
||||
/**
|
||||
* WebChannel origin, used to validate origin of messages
|
||||
*/
|
||||
_webChannelOrigin: null,
|
||||
|
||||
/**
|
||||
* Release all resources that are in use.
|
||||
*/
|
||||
tearDown() {
|
||||
this._channel.stopListening();
|
||||
this._channel = null;
|
||||
this._channelCallback = null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Configures and registers a new WebChannel
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_setupChannel() {
|
||||
// if this.contentUri is present but not a valid URI, then this will throw an error.
|
||||
try {
|
||||
this._webChannelOrigin = Services.io.newURI(this._contentUri, null, null);
|
||||
this._registerChannel();
|
||||
} catch (e) {
|
||||
log.e(e.toString());
|
||||
throw e;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Create a new channel with the WebChannelBroker, setup a callback listener
|
||||
* @private
|
||||
*/
|
||||
_registerChannel() {
|
||||
/**
|
||||
* Processes messages that are called back from the FxAccountsChannel
|
||||
*
|
||||
* @param webChannelId {String}
|
||||
* Command webChannelId
|
||||
* @param message {Object}
|
||||
* Command message
|
||||
* @param sendingContext {Object}
|
||||
* Message sending context.
|
||||
* @param sendingContext.browser {browser}
|
||||
* The <browser> object that captured the
|
||||
* WebChannelMessageToChrome.
|
||||
* @param sendingContext.eventTarget {EventTarget}
|
||||
* The <EventTarget> where the message was sent.
|
||||
* @param sendingContext.principal {Principal}
|
||||
* The <Principal> of the EventTarget where the message was sent.
|
||||
* @private
|
||||
*
|
||||
*/
|
||||
let listener = (webChannelId, message, sendingContext) => {
|
||||
if (message) {
|
||||
let command = message.command;
|
||||
let data = message.data;
|
||||
log.d("FxAccountsWebChannel message received, command: " + command);
|
||||
|
||||
// Respond to the message with true or false.
|
||||
let respond = (data) => {
|
||||
let response = {
|
||||
command: command,
|
||||
messageId: message.messageId,
|
||||
data: data
|
||||
};
|
||||
log.d("Sending response to command: " + command);
|
||||
this._channel.send(response, sendingContext);
|
||||
};
|
||||
|
||||
switch (command) {
|
||||
case COMMAND_LOADED:
|
||||
let mm = sendingContext.browser.docShell
|
||||
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIContentFrameMessageManager);
|
||||
mm.sendAsyncMessage(COMMAND_LOADED);
|
||||
break;
|
||||
|
||||
case COMMAND_CAN_LINK_ACCOUNT:
|
||||
Accounts.getFirefoxAccount().then(account => {
|
||||
if (account) {
|
||||
// If we /have/ an Android Account, we never allow the user to
|
||||
// login to a different account. They need to manually delete
|
||||
// the first Android Account and then create a new one.
|
||||
if (account.email == data.email) {
|
||||
// In future, we should use a UID for this comparison.
|
||||
log.d("Relinking existing Android Account: email addresses agree.");
|
||||
respond({ok: true});
|
||||
} else {
|
||||
log.w("Not relinking existing Android Account: email addresses disagree!");
|
||||
let message = strings.GetStringFromName("relinkDenied.message");
|
||||
let buttonLabel = strings.GetStringFromName("relinkDenied.openPrefs");
|
||||
Snackbars.show(message, Snackbars.LENGTH_LONG, {
|
||||
action: {
|
||||
label: buttonLabel,
|
||||
callback: () => {
|
||||
// We have an account, so this opens Sync native preferences.
|
||||
Accounts.launchSetup();
|
||||
},
|
||||
}
|
||||
});
|
||||
respond({ok: false});
|
||||
}
|
||||
} else {
|
||||
// If we /don't have/ an Android Account, we warn if we're
|
||||
// connecting to a new Account. This is to minimize surprise;
|
||||
// we never did this when changing accounts via the native UI.
|
||||
let prevAcctHash = this._helpers.getPreviousAccountNameHashPref();
|
||||
let shouldShowWarning = prevAcctHash && (prevAcctHash != this._helpers.sha256(data.email));
|
||||
|
||||
if (shouldShowWarning) {
|
||||
log.w("Warning about creating a new Android Account: previously linked to different email address!");
|
||||
let message = strings.formatStringFromName("relinkVerify.message", [data.email], 1);
|
||||
new Prompt({
|
||||
title: strings.GetStringFromName("relinkVerify.title"),
|
||||
message: message,
|
||||
buttons: [
|
||||
// This puts Cancel on the right.
|
||||
strings.GetStringFromName("relinkVerify.cancel"),
|
||||
strings.GetStringFromName("relinkVerify.continue"),
|
||||
],
|
||||
}).show(result => respond({ok: result && result.button == 1}));
|
||||
} else {
|
||||
log.d("Not warning about creating a new Android Account: no previously linked email address.");
|
||||
respond({ok: true});
|
||||
}
|
||||
}
|
||||
}).catch(e => {
|
||||
log.e(e.toString());
|
||||
respond({ok: false});
|
||||
});
|
||||
break;
|
||||
|
||||
case COMMAND_LOGIN:
|
||||
// Either create a new Android Account or re-connect an existing
|
||||
// Android Account here. There's not much to be done if we don't
|
||||
// succeed or get an error.
|
||||
Accounts.getFirefoxAccount().then(account => {
|
||||
if (!account) {
|
||||
return Accounts.createFirefoxAccountFromJSON(data).then(success => {
|
||||
if (!success) {
|
||||
throw new Error("Could not create Firefox Account!");
|
||||
}
|
||||
UITelemetry.addEvent("action.1", "content", null, "fxaccount-create");
|
||||
return success;
|
||||
});
|
||||
} else {
|
||||
return Accounts.updateFirefoxAccountFromJSON(data).then(success => {
|
||||
if (!success) {
|
||||
throw new Error("Could not update Firefox Account!");
|
||||
}
|
||||
UITelemetry.addEvent("action.1", "content", null, "fxaccount-login");
|
||||
return success;
|
||||
});
|
||||
}
|
||||
})
|
||||
.then(success => {
|
||||
if (!success) {
|
||||
throw new Error("Could not create or update Firefox Account!");
|
||||
}
|
||||
|
||||
// Remember who it is so we can show a relink warning when appropriate.
|
||||
this._helpers.setPreviousAccountNameHashPref(data.email);
|
||||
|
||||
log.i("Created or updated Firefox Account.");
|
||||
})
|
||||
.catch(e => {
|
||||
log.e(e.toString());
|
||||
});
|
||||
break;
|
||||
|
||||
case COMMAND_CHANGE_PASSWORD:
|
||||
// Only update an existing Android Account.
|
||||
Accounts.getFirefoxAccount().then(account => {
|
||||
if (!account) {
|
||||
throw new Error("Can't change password of non-existent Firefox Account!");
|
||||
}
|
||||
return Accounts.updateFirefoxAccountFromJSON(data);
|
||||
})
|
||||
.then(success => {
|
||||
if (!success) {
|
||||
throw new Error("Could not change Firefox Account password!");
|
||||
}
|
||||
UITelemetry.addEvent("action.1", "content", null, "fxaccount-changepassword");
|
||||
log.i("Changed Firefox Account password.");
|
||||
})
|
||||
.catch(e => {
|
||||
log.e(e.toString());
|
||||
});
|
||||
break;
|
||||
|
||||
case COMMAND_DELETE_ACCOUNT:
|
||||
// The fxa-content-server has already confirmed the user's intent.
|
||||
// Bombs away. There's no recovery from failure, and not even a
|
||||
// real need to check an account exists (although we do, for error
|
||||
// messaging only).
|
||||
Accounts.getFirefoxAccount().then(account => {
|
||||
if (!account) {
|
||||
throw new Error("Can't delete non-existent Firefox Account!");
|
||||
}
|
||||
return Accounts.deleteFirefoxAccount().then(success => {
|
||||
if (!success) {
|
||||
throw new Error("Could not delete Firefox Account!");
|
||||
}
|
||||
UITelemetry.addEvent("action.1", "content", null, "fxaccount-delete");
|
||||
log.i("Firefox Account deleted.");
|
||||
});
|
||||
}).catch(e => {
|
||||
log.e(e.toString());
|
||||
});
|
||||
break;
|
||||
|
||||
case COMMAND_PROFILE_CHANGE:
|
||||
// Only update an existing Android Account.
|
||||
Accounts.getFirefoxAccount().then(account => {
|
||||
if (!account) {
|
||||
throw new Error("Can't change profile of non-existent Firefox Account!");
|
||||
}
|
||||
UITelemetry.addEvent("action.1", "content", null, "fxaccount-changeprofile");
|
||||
return Accounts.notifyFirefoxAccountProfileChanged();
|
||||
})
|
||||
.catch(e => {
|
||||
log.e(e.toString());
|
||||
});
|
||||
break;
|
||||
|
||||
case COMMAND_SYNC_PREFERENCES:
|
||||
UITelemetry.addEvent("action.1", "content", null, "fxaccount-syncprefs");
|
||||
Accounts.showSyncPreferences()
|
||||
.catch(e => {
|
||||
log.e(e.toString());
|
||||
});
|
||||
break;
|
||||
|
||||
default:
|
||||
log.w("Ignoring unrecognized FxAccountsWebChannel command: " + JSON.stringify(command));
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this._channelCallback = listener;
|
||||
this._channel = new WebChannel(this._webChannelId, this._webChannelOrigin);
|
||||
this._channel.listen(listener);
|
||||
|
||||
log.d("FxAccountsWebChannel registered: " + this._webChannelId + " with origin " + this._webChannelOrigin.prePath);
|
||||
}
|
||||
};
|
||||
|
||||
var singleton;
|
||||
// The entry-point for this module, which ensures only one of our channels is
|
||||
// ever created - we require this because the WebChannel is global in scope and
|
||||
// allowing multiple channels would cause such notifications to be sent multiple
|
||||
// times.
|
||||
this.EnsureFxAccountsWebChannel = function() {
|
||||
if (!singleton) {
|
||||
let contentUri = Services.urlFormatter.formatURLPref("identity.fxaccounts.remote.webchannel.uri");
|
||||
// The FxAccountsWebChannel listens for events and updates the Java layer.
|
||||
singleton = new this.FxAccountsWebChannel({
|
||||
content_uri: contentUri,
|
||||
channel_id: WEBCHANNEL_ID,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
@ -10,7 +10,6 @@ EXTRA_JS_MODULES += [
|
|||
'dbg-browser-actors.js',
|
||||
'DelayedInit.jsm',
|
||||
'DownloadNotifications.jsm',
|
||||
'FxAccountsWebChannel.jsm',
|
||||
'HelperApps.jsm',
|
||||
'Home.jsm',
|
||||
'HomeProvider.jsm',
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue