Bug 1204937 - Part 3: Add Accounts:UpdateAccountFromJSON message. r=sebastian

This commit does a few things.  First, it fixes a typo
(s/ForResponse/ForResult/).  It's not clear how this /ever/ worked,
but it did.

Second, it adds an UpdateAccountFromJSON sibling to
CreateAccountFromJSON.  It would have been reasonable to have the
create message do double-duty and update an existing account (we have
the latitude to change the meaning since this API is not yet public)
but I generally prefer each consumer to perform the conditional state
check and to act appropriately.

Third, it generalizes the existing Accounts:Exist message to provide
some details (including email and UID) of any existing Firefox
Account.  The Accounts.exist() API /is/ public, so I introduce a new
(not yet public) API for this richer information.

--HG--
extra : commitid : 5OcLn2ejQzZ
extra : rebase_source : dca7f1ab0cb101948e9d67db4595b91127f0bfd6
This commit is contained in:
Nick Alexander 2015-08-21 11:27:54 -07:00
Родитель 83fab33f78
Коммит 803a8d2abf
2 изменённых файлов: 110 добавлений и 6 удалений

Просмотреть файл

@ -5,6 +5,7 @@
package org.mozilla.gecko;
import android.accounts.Account;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
@ -46,6 +47,7 @@ public class AccountsHelper implements NativeEventListener {
}
dispatcher.registerGeckoThreadListener(this,
"Accounts:CreateFirefoxAccountFromJSON",
"Accounts:UpdateFirefoxAccountFromJSON",
"Accounts:Create",
"Accounts:Exist");
}
@ -58,6 +60,7 @@ public class AccountsHelper implements NativeEventListener {
}
dispatcher.unregisterGeckoThreadListener(this,
"Accounts:CreateFirefoxAccountFromJSON",
"Accounts:UpdateFirefoxAccountFromJSON",
"Accounts:Create",
"Accounts:Exist");
}
@ -101,6 +104,39 @@ public class AccountsHelper implements NativeEventListener {
callback.sendSuccess(fxAccount != null);
}
} else if ("Accounts:UpdateFirefoxAccountFromJSON".equals(event)) {
try {
final Account account = FirefoxAccounts.getFirefoxAccount(mContext);
if (account == null) {
if (callback != null) {
callback.sendError("Could not update Firefox Account since non exists");
}
return;
}
final NativeJSObject json = message.getObject("json");
final String email = json.getString("email");
final String uid = json.getString("uid");
final boolean verified = json.optBoolean("verified", false);
final byte[] unwrapkB = Utils.hex2Byte(json.getString("unwrapBKey"));
final byte[] sessionToken = Utils.hex2Byte(json.getString("sessionToken"));
final byte[] keyFetchToken = Utils.hex2Byte(json.getString("keyFetchToken"));
final State state = new Engaged(email, uid, verified, unwrapkB, sessionToken, keyFetchToken);
final AndroidFxAccount fxAccount = new AndroidFxAccount(mContext, account);
fxAccount.setState(state);
if (callback != null) {
callback.sendSuccess(true);
}
} catch (Exception e) {
Log.w(LOGTAG, "Got exception updating Firefox Account from JSON; ignoring.", e);
if (callback != null) {
callback.sendError("Could not update Firefox Account from JSON: " + e.toString());
return;
}
}
} else if ("Accounts:Create".equals(event)) {
// Do exactly the same thing as if you tapped 'Sync' in Settings.
final Intent intent = new Intent(FxAccountConstants.ACTION_FXA_GET_STARTED);
@ -126,7 +162,26 @@ public class AccountsHelper implements NativeEventListener {
FirefoxAccounts.firefoxAccountsExist(mContext));
callback.sendSuccess(response);
} else if ("fxa".equals(kind)) {
response.put("exists", FirefoxAccounts.firefoxAccountsExist(mContext));
final Account account = FirefoxAccounts.getFirefoxAccount(mContext);
response.put("exists", account != null);
if (account != null) {
response.put("email", account.name);
// We should always be able to extract the server endpoints.
final AndroidFxAccount fxAccount = new AndroidFxAccount(mContext, account);
response.put("authServerEndpoint", fxAccount.getAccountServerURI());
response.put("profileServerEndpoint", fxAccount.getProfileServerURI());
response.put("tokenServerEndpoint", fxAccount.getTokenServerURI());
try {
// It is possible for the state fetch to fail and us to not be able to provide a UID.
// Long term, the UID (and verification flag) will be attached to the Android account
// user data and not the internal state representation.
final State state = fxAccount.getState();
response.put("uid", state.uid);
} catch (Exception e) {
Log.w(LOGTAG, "Got exception extracting account UID; ignoring.", e);
}
}
callback.sendSuccess(response);
} else if ("sync11".equals(kind)) {
response.put("exists", SyncAccounts.syncAccountsExist(mContext));

Просмотреть файл

@ -8,9 +8,9 @@ this.EXPORTED_SYMBOLS = ["Accounts"];
const { utils: Cu } = Components;
Cu.import("resource://gre/modules/Messaging.jsm");
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/Promise.jsm");
Cu.import("resource://gre/modules/Messaging.jsm"); /*global Messaging */
Cu.import("resource://gre/modules/Promise.jsm"); /*global Promise */
Cu.import("resource://gre/modules/Services.jsm"); /*global Services */
/**
* A promise-based API for querying the existence of Sync accounts,
@ -68,6 +68,19 @@ let Accounts = Object.freeze({
});
},
_addDefaultEndpoints: function (json) {
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
@ -78,9 +91,45 @@ let Accounts = Object.freeze({
* Returns a Promise that resolves to a boolean indicating success.
*/
createFirefoxAccountFromJSON: function (json) {
return Messaging.sendRequestForResponse({
return Messaging.sendRequestForResult({
type: "Accounts:CreateFirefoxAccountFromJSON",
json: json
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)
});
},
/**
* 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;
});
}
});