diff options
Diffstat (limited to 'mobile/android/modules')
-rw-r--r-- | mobile/android/modules/Accounts.jsm | 105 | ||||
-rw-r--r-- | mobile/android/modules/FxAccountsWebChannel.jsm | 394 | ||||
-rw-r--r-- | mobile/android/modules/moz.build | 1 |
3 files changed, 3 insertions, 497 deletions
diff --git a/mobile/android/modules/Accounts.jsm b/mobile/android/modules/Accounts.jsm index a611f3c58..ee0fc0c5b 100644 --- a/mobile/android/modules/Accounts.jsm +++ b/mobile/android/modules/Accounts.jsm @@ -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!"); } }); diff --git a/mobile/android/modules/FxAccountsWebChannel.jsm b/mobile/android/modules/FxAccountsWebChannel.jsm deleted file mode 100644 index 6ee8fd07f..000000000 --- a/mobile/android/modules/FxAccountsWebChannel.jsm +++ /dev/null @@ -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, - }); - } -}; diff --git a/mobile/android/modules/moz.build b/mobile/android/modules/moz.build index 479ff1f3f..dd62e484a 100644 --- a/mobile/android/modules/moz.build +++ b/mobile/android/modules/moz.build @@ -10,7 +10,6 @@ EXTRA_JS_MODULES += [ 'dbg-browser-actors.js', 'DelayedInit.jsm', 'DownloadNotifications.jsm', - 'FxAccountsWebChannel.jsm', 'HelperApps.jsm', 'Home.jsm', 'HomeProvider.jsm', |