mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 962299 - Bundle account data into a single userdata field and add profile tracking. r=nalexander
This commit is contained in:
parent
2546e3f69f
commit
a8b7a9e312
@ -17,6 +17,7 @@ import org.mozilla.gecko.fxa.activities.FxAccountSetupTask.FxAccountCreateAccoun
|
|||||||
import org.mozilla.gecko.fxa.authenticator.AndroidFxAccount;
|
import org.mozilla.gecko.fxa.authenticator.AndroidFxAccount;
|
||||||
import org.mozilla.gecko.sync.HTTPFailureException;
|
import org.mozilla.gecko.sync.HTTPFailureException;
|
||||||
import org.mozilla.gecko.sync.net.SyncStorageResponse;
|
import org.mozilla.gecko.sync.net.SyncStorageResponse;
|
||||||
|
import org.mozilla.gecko.sync.setup.Constants;
|
||||||
|
|
||||||
import android.accounts.Account;
|
import android.accounts.Account;
|
||||||
import android.accounts.AccountManager;
|
import android.accounts.AccountManager;
|
||||||
@ -160,8 +161,9 @@ public class FxAccountCreateAccountActivity extends FxAccountAbstractSetupActivi
|
|||||||
// We're on the UI thread, but it's okay to create the account here.
|
// We're on the UI thread, but it's okay to create the account here.
|
||||||
Account account;
|
Account account;
|
||||||
try {
|
try {
|
||||||
|
final String profile = Constants.DEFAULT_PROFILE;
|
||||||
account = AndroidFxAccount.addAndroidAccount(activity, email, password,
|
account = AndroidFxAccount.addAndroidAccount(activity, email, password,
|
||||||
serverURI, null, null, false);
|
profile, serverURI, null, null, false);
|
||||||
if (account == null) {
|
if (account == null) {
|
||||||
throw new RuntimeException("XXX what?");
|
throw new RuntimeException("XXX what?");
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@ import org.mozilla.gecko.fxa.activities.FxAccountSetupTask.FxAccountSignInTask;
|
|||||||
import org.mozilla.gecko.fxa.authenticator.AndroidFxAccount;
|
import org.mozilla.gecko.fxa.authenticator.AndroidFxAccount;
|
||||||
import org.mozilla.gecko.sync.HTTPFailureException;
|
import org.mozilla.gecko.sync.HTTPFailureException;
|
||||||
import org.mozilla.gecko.sync.net.SyncStorageResponse;
|
import org.mozilla.gecko.sync.net.SyncStorageResponse;
|
||||||
|
import org.mozilla.gecko.sync.setup.Constants;
|
||||||
|
|
||||||
import android.accounts.Account;
|
import android.accounts.Account;
|
||||||
import android.accounts.AccountManager;
|
import android.accounts.AccountManager;
|
||||||
@ -129,8 +130,9 @@ public class FxAccountSignInActivity extends FxAccountAbstractSetupActivity {
|
|||||||
// We're on the UI thread, but it's okay to create the account here.
|
// We're on the UI thread, but it's okay to create the account here.
|
||||||
Account account;
|
Account account;
|
||||||
try {
|
try {
|
||||||
|
final String profile = Constants.DEFAULT_PROFILE;
|
||||||
account = AndroidFxAccount.addAndroidAccount(activity, email, password,
|
account = AndroidFxAccount.addAndroidAccount(activity, email, password,
|
||||||
serverURI, result.sessionToken, result.keyFetchToken, result.verified);
|
serverURI, profile, result.sessionToken, result.keyFetchToken, result.verified);
|
||||||
if (account == null) {
|
if (account == null) {
|
||||||
throw new RuntimeException("XXX what?");
|
throw new RuntimeException("XXX what?");
|
||||||
}
|
}
|
||||||
|
@ -40,6 +40,11 @@ public interface AbstractFxAccount {
|
|||||||
*/
|
*/
|
||||||
public String getServerURI();
|
public String getServerURI();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the profile name associated with the account, such as "default".
|
||||||
|
*/
|
||||||
|
public String getProfile();
|
||||||
|
|
||||||
public boolean isValid();
|
public boolean isValid();
|
||||||
public void setInvalid();
|
public void setInvalid();
|
||||||
|
|
||||||
|
@ -33,17 +33,24 @@ import android.os.Bundle;
|
|||||||
public class AndroidFxAccount implements AbstractFxAccount {
|
public class AndroidFxAccount implements AbstractFxAccount {
|
||||||
protected static final String LOG_TAG = AndroidFxAccount.class.getSimpleName();
|
protected static final String LOG_TAG = AndroidFxAccount.class.getSimpleName();
|
||||||
|
|
||||||
public static final String ACCOUNT_KEY_ASSERTION = "assertion";
|
public static final int CURRENT_ACCOUNT_VERSION = 2;
|
||||||
public static final String ACCOUNT_KEY_CERTIFICATE = "certificate";
|
public static final String ACCOUNT_KEY_ACCOUNT_VERSION = "version";
|
||||||
public static final String ACCOUNT_KEY_INVALID = "invalid";
|
public static final String ACCOUNT_KEY_PROFILE = "profile";
|
||||||
public static final String ACCOUNT_KEY_SERVERURI = "serverURI";
|
public static final String ACCOUNT_KEY_DESCRIPTOR = "descriptor";
|
||||||
public static final String ACCOUNT_KEY_SESSION_TOKEN = "sessionToken";
|
|
||||||
public static final String ACCOUNT_KEY_KEY_FETCH_TOKEN = "keyFetchToken";
|
public static final int CURRENT_BUNDLE_VERSION = 1;
|
||||||
public static final String ACCOUNT_KEY_VERIFIED = "verified";
|
public static final String BUNDLE_KEY_BUNDLE_VERSION = "version";
|
||||||
public static final String ACCOUNT_KEY_KA = "kA";
|
public static final String BUNDLE_KEY_ASSERTION = "assertion";
|
||||||
public static final String ACCOUNT_KEY_KB = "kB";
|
public static final String BUNDLE_KEY_CERTIFICATE = "certificate";
|
||||||
public static final String ACCOUNT_KEY_UNWRAPKB = "unwrapkB";
|
public static final String BUNDLE_KEY_INVALID = "invalid";
|
||||||
public static final String ACCOUNT_KEY_ASSERTION_KEY_PAIR = "assertionKeyPair";
|
public static final String BUNDLE_KEY_SERVERURI = "serverURI";
|
||||||
|
public static final String BUNDLE_KEY_SESSION_TOKEN = "sessionToken";
|
||||||
|
public static final String BUNDLE_KEY_KEY_FETCH_TOKEN = "keyFetchToken";
|
||||||
|
public static final String BUNDLE_KEY_VERIFIED = "verified";
|
||||||
|
public static final String BUNDLE_KEY_KA = "kA";
|
||||||
|
public static final String BUNDLE_KEY_KB = "kB";
|
||||||
|
public static final String BUNDLE_KEY_UNWRAPKB = "unwrapkB";
|
||||||
|
public static final String BUNDLE_KEY_ASSERTION_KEY_PAIR = "assertionKeyPair";
|
||||||
|
|
||||||
protected final Context context;
|
protected final Context context;
|
||||||
protected final AccountManager accountManager;
|
protected final AccountManager accountManager;
|
||||||
@ -71,6 +78,105 @@ public class AndroidFxAccount implements AbstractFxAccount {
|
|||||||
this.accountManager = AccountManager.get(this.context);
|
this.accountManager = AccountManager.get(this.context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected int getAccountVersion() {
|
||||||
|
String v = accountManager.getUserData(account, ACCOUNT_KEY_ACCOUNT_VERSION);
|
||||||
|
if (v == null) {
|
||||||
|
return 0; // Implicit.
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
return Integer.parseInt(v, 10);
|
||||||
|
} catch (NumberFormatException ex) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void persistBundle(ExtendedJSONObject bundle) {
|
||||||
|
accountManager.setUserData(account, ACCOUNT_KEY_DESCRIPTOR, bundle.toJSONString());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ExtendedJSONObject unbundle() {
|
||||||
|
final int version = getAccountVersion();
|
||||||
|
if (version < CURRENT_ACCOUNT_VERSION) {
|
||||||
|
// Needs upgrade. For now, do nothing.
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (version > CURRENT_ACCOUNT_VERSION) {
|
||||||
|
// Oh dear.
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
String bundle = accountManager.getUserData(account, ACCOUNT_KEY_DESCRIPTOR);
|
||||||
|
if (bundle == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return unbundleAccountV1(bundle);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getBundleData(String key) {
|
||||||
|
ExtendedJSONObject o = unbundle();
|
||||||
|
if (o == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return o.getString(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean getBundleDataBoolean(String key, boolean def) {
|
||||||
|
ExtendedJSONObject o = unbundle();
|
||||||
|
if (o == null) {
|
||||||
|
return def;
|
||||||
|
}
|
||||||
|
Boolean b = o.getBoolean(key);
|
||||||
|
if (b == null) {
|
||||||
|
return def;
|
||||||
|
}
|
||||||
|
return b.booleanValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected byte[] getBundleDataBytes(String key) {
|
||||||
|
ExtendedJSONObject o = unbundle();
|
||||||
|
if (o == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return o.getByteArrayHex(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void updateBundleDataBytes(String key, byte[] value) {
|
||||||
|
updateBundleValue(key, value == null ? null : Utils.byte2Hex(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void updateBundleValue(String key, boolean value) {
|
||||||
|
ExtendedJSONObject descriptor = unbundle();
|
||||||
|
if (descriptor == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
descriptor.put(key, value);
|
||||||
|
persistBundle(descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void updateBundleValue(String key, String value) {
|
||||||
|
ExtendedJSONObject descriptor = unbundle();
|
||||||
|
if (descriptor == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
descriptor.put(key, value);
|
||||||
|
persistBundle(descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ExtendedJSONObject unbundleAccountV1(String bundle) {
|
||||||
|
ExtendedJSONObject o;
|
||||||
|
try {
|
||||||
|
o = new ExtendedJSONObject(bundle);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (CURRENT_BUNDLE_VERSION == o.getIntegerSafely(BUNDLE_KEY_BUNDLE_VERSION)) {
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public byte[] getEmailUTF8() {
|
public byte[] getEmailUTF8() {
|
||||||
try {
|
try {
|
||||||
@ -81,6 +187,15 @@ public class AndroidFxAccount implements AbstractFxAccount {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Note that if the user clears data, an account will be left pointing to a
|
||||||
|
* deleted profile. Such is life.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String getProfile() {
|
||||||
|
return accountManager.getUserData(account, ACCOUNT_KEY_PROFILE);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setQuickStretchedPW(byte[] quickStretchedPW) {
|
public void setQuickStretchedPW(byte[] quickStretchedPW) {
|
||||||
accountManager.setPassword(account, quickStretchedPW == null ? null : Utils.byte2Hex(quickStretchedPW));
|
accountManager.setPassword(account, quickStretchedPW == null ? null : Utils.byte2Hex(quickStretchedPW));
|
||||||
@ -95,7 +210,7 @@ public class AndroidFxAccount implements AbstractFxAccount {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getServerURI() {
|
public String getServerURI() {
|
||||||
return accountManager.getUserData(account, ACCOUNT_KEY_SERVERURI);
|
return getBundleData(BUNDLE_KEY_SERVERURI);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected byte[] getUserDataBytes(String key) {
|
protected byte[] getUserDataBytes(String key) {
|
||||||
@ -108,58 +223,57 @@ public class AndroidFxAccount implements AbstractFxAccount {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public byte[] getSessionToken() {
|
public byte[] getSessionToken() {
|
||||||
return getUserDataBytes(ACCOUNT_KEY_SESSION_TOKEN);
|
return getBundleDataBytes(BUNDLE_KEY_SESSION_TOKEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public byte[] getKeyFetchToken() {
|
public byte[] getKeyFetchToken() {
|
||||||
return getUserDataBytes(ACCOUNT_KEY_KEY_FETCH_TOKEN);
|
return getBundleDataBytes(BUNDLE_KEY_KEY_FETCH_TOKEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setSessionToken(byte[] sessionToken) {
|
public void setSessionToken(byte[] sessionToken) {
|
||||||
accountManager.setUserData(account, ACCOUNT_KEY_SESSION_TOKEN, sessionToken == null ? null : Utils.byte2Hex(sessionToken));
|
updateBundleDataBytes(BUNDLE_KEY_SESSION_TOKEN, sessionToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setKeyFetchToken(byte[] keyFetchToken) {
|
public void setKeyFetchToken(byte[] keyFetchToken) {
|
||||||
accountManager.setUserData(account, ACCOUNT_KEY_KEY_FETCH_TOKEN, keyFetchToken == null ? null : Utils.byte2Hex(keyFetchToken));
|
updateBundleDataBytes(BUNDLE_KEY_KEY_FETCH_TOKEN, keyFetchToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isVerified() {
|
public boolean isVerified() {
|
||||||
String data = accountManager.getUserData(account, ACCOUNT_KEY_VERIFIED);
|
return getBundleDataBoolean(BUNDLE_KEY_VERIFIED, false);
|
||||||
return Boolean.valueOf(data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setVerified() {
|
public void setVerified() {
|
||||||
accountManager.setUserData(account, ACCOUNT_KEY_VERIFIED, Boolean.valueOf(true).toString());
|
updateBundleValue(BUNDLE_KEY_VERIFIED, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public byte[] getKa() {
|
public byte[] getKa() {
|
||||||
return getUserDataBytes(ACCOUNT_KEY_KA);
|
return getUserDataBytes(BUNDLE_KEY_KA);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setKa(byte[] kA) {
|
public void setKa(byte[] kA) {
|
||||||
accountManager.setUserData(account, ACCOUNT_KEY_KA, Utils.byte2Hex(kA));
|
updateBundleValue(BUNDLE_KEY_KA, Utils.byte2Hex(kA));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setWrappedKb(byte[] wrappedKb) {
|
public void setWrappedKb(byte[] wrappedKb) {
|
||||||
byte[] unwrapKb = getUserDataBytes(ACCOUNT_KEY_UNWRAPKB);
|
byte[] unwrapKb = getUserDataBytes(BUNDLE_KEY_UNWRAPKB);
|
||||||
byte[] kB = new byte[wrappedKb.length]; // We could hard-code this to be 32.
|
byte[] kB = new byte[wrappedKb.length]; // We could hard-code this to be 32.
|
||||||
for (int i = 0; i < wrappedKb.length; i++) {
|
for (int i = 0; i < wrappedKb.length; i++) {
|
||||||
kB[i] = (byte) (wrappedKb[i] ^ unwrapKb[i]);
|
kB[i] = (byte) (wrappedKb[i] ^ unwrapKb[i]);
|
||||||
}
|
}
|
||||||
accountManager.setUserData(account, ACCOUNT_KEY_KB, Utils.byte2Hex(kB));
|
updateBundleValue(BUNDLE_KEY_KB, Utils.byte2Hex(kB));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public byte[] getKb() {
|
public byte[] getKb() {
|
||||||
return getUserDataBytes(ACCOUNT_KEY_KB);
|
return getUserDataBytes(BUNDLE_KEY_KB);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected BrowserIDKeyPair generateNewAssertionKeyPair() throws GeneralSecurityException {
|
protected BrowserIDKeyPair generateNewAssertionKeyPair() throws GeneralSecurityException {
|
||||||
@ -171,35 +285,41 @@ public class AndroidFxAccount implements AbstractFxAccount {
|
|||||||
@Override
|
@Override
|
||||||
public BrowserIDKeyPair getAssertionKeyPair() throws GeneralSecurityException {
|
public BrowserIDKeyPair getAssertionKeyPair() throws GeneralSecurityException {
|
||||||
try {
|
try {
|
||||||
String data = accountManager.getUserData(account, ACCOUNT_KEY_ASSERTION_KEY_PAIR);
|
String data = getBundleData(BUNDLE_KEY_ASSERTION_KEY_PAIR);
|
||||||
return RSACryptoImplementation.fromJSONObject(new ExtendedJSONObject(data));
|
return RSACryptoImplementation.fromJSONObject(new ExtendedJSONObject(data));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
// Fall through to generating a new key pair.
|
// Fall through to generating a new key pair.
|
||||||
}
|
}
|
||||||
|
|
||||||
BrowserIDKeyPair keyPair = generateNewAssertionKeyPair();
|
BrowserIDKeyPair keyPair = generateNewAssertionKeyPair();
|
||||||
accountManager.setUserData(account, ACCOUNT_KEY_ASSERTION_KEY_PAIR, keyPair.toJSONObject().toJSONString());
|
|
||||||
|
ExtendedJSONObject descriptor = unbundle();
|
||||||
|
if (descriptor == null) {
|
||||||
|
descriptor = new ExtendedJSONObject();
|
||||||
|
}
|
||||||
|
descriptor.put(BUNDLE_KEY_ASSERTION_KEY_PAIR, keyPair.toJSONObject().toJSONString());
|
||||||
|
persistBundle(descriptor);
|
||||||
return keyPair;
|
return keyPair;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getCertificate() {
|
public String getCertificate() {
|
||||||
return accountManager.getUserData(account, ACCOUNT_KEY_CERTIFICATE);
|
return getBundleData(BUNDLE_KEY_CERTIFICATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setCertificate(String certificate) {
|
public void setCertificate(String certificate) {
|
||||||
accountManager.setUserData(account, ACCOUNT_KEY_CERTIFICATE, certificate);
|
updateBundleValue(BUNDLE_KEY_CERTIFICATE, certificate);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getAssertion() {
|
public String getAssertion() {
|
||||||
return accountManager.getUserData(account, ACCOUNT_KEY_ASSERTION);
|
return getBundleData(BUNDLE_KEY_ASSERTION);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setAssertion(String assertion) {
|
public void setAssertion(String assertion) {
|
||||||
accountManager.setUserData(account, ACCOUNT_KEY_ASSERTION, assertion);
|
updateBundleValue(BUNDLE_KEY_ASSERTION, assertion);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -212,22 +332,7 @@ public class AndroidFxAccount implements AbstractFxAccount {
|
|||||||
* @return JSON-object of Strings.
|
* @return JSON-object of Strings.
|
||||||
*/
|
*/
|
||||||
public ExtendedJSONObject toJSONObject() {
|
public ExtendedJSONObject toJSONObject() {
|
||||||
ExtendedJSONObject o = new ExtendedJSONObject();
|
ExtendedJSONObject o = unbundle();
|
||||||
for (String key : new String[] {
|
|
||||||
ACCOUNT_KEY_ASSERTION,
|
|
||||||
ACCOUNT_KEY_CERTIFICATE,
|
|
||||||
ACCOUNT_KEY_SERVERURI,
|
|
||||||
ACCOUNT_KEY_SESSION_TOKEN,
|
|
||||||
ACCOUNT_KEY_INVALID,
|
|
||||||
ACCOUNT_KEY_KEY_FETCH_TOKEN,
|
|
||||||
ACCOUNT_KEY_VERIFIED,
|
|
||||||
ACCOUNT_KEY_KA,
|
|
||||||
ACCOUNT_KEY_KB,
|
|
||||||
ACCOUNT_KEY_UNWRAPKB,
|
|
||||||
ACCOUNT_KEY_ASSERTION_KEY_PAIR,
|
|
||||||
}) {
|
|
||||||
o.put(key, accountManager.getUserData(account, key));
|
|
||||||
}
|
|
||||||
o.put("email", account.name);
|
o.put("email", account.name);
|
||||||
try {
|
try {
|
||||||
o.put("emailUTF8", Utils.byte2Hex(account.name.getBytes("UTF-8")));
|
o.put("emailUTF8", Utils.byte2Hex(account.name.getBytes("UTF-8")));
|
||||||
@ -238,7 +343,7 @@ public class AndroidFxAccount implements AbstractFxAccount {
|
|||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Account addAndroidAccount(Context context, String email, String password,
|
public static Account addAndroidAccount(Context context, String email, String password, String profile,
|
||||||
String serverURI, byte[] sessionToken, byte[] keyFetchToken, boolean verified)
|
String serverURI, byte[] sessionToken, byte[] keyFetchToken, boolean verified)
|
||||||
throws UnsupportedEncodingException, GeneralSecurityException {
|
throws UnsupportedEncodingException, GeneralSecurityException {
|
||||||
if (email == null) {
|
if (email == null) {
|
||||||
@ -265,11 +370,17 @@ public class AndroidFxAccount implements AbstractFxAccount {
|
|||||||
byte[] unwrapBkey = FxAccountUtils.generateUnwrapBKey(quickStretchedPW);
|
byte[] unwrapBkey = FxAccountUtils.generateUnwrapBKey(quickStretchedPW);
|
||||||
|
|
||||||
Bundle userdata = new Bundle();
|
Bundle userdata = new Bundle();
|
||||||
userdata.putString(AndroidFxAccount.ACCOUNT_KEY_SERVERURI, serverURI);
|
userdata.putInt(ACCOUNT_KEY_ACCOUNT_VERSION, CURRENT_ACCOUNT_VERSION);
|
||||||
userdata.putString(AndroidFxAccount.ACCOUNT_KEY_SESSION_TOKEN, sessionToken == null ? null : Utils.byte2Hex(sessionToken));
|
|
||||||
userdata.putString(AndroidFxAccount.ACCOUNT_KEY_KEY_FETCH_TOKEN, keyFetchToken == null ? null : Utils.byte2Hex(keyFetchToken));
|
ExtendedJSONObject descriptor = new ExtendedJSONObject();
|
||||||
userdata.putString(AndroidFxAccount.ACCOUNT_KEY_VERIFIED, Boolean.valueOf(verified).toString());
|
descriptor.put(BUNDLE_KEY_BUNDLE_VERSION, CURRENT_BUNDLE_VERSION);
|
||||||
userdata.putString(AndroidFxAccount.ACCOUNT_KEY_UNWRAPKB, Utils.byte2Hex(unwrapBkey));
|
descriptor.put(BUNDLE_KEY_SERVERURI, serverURI);
|
||||||
|
descriptor.put(BUNDLE_KEY_SESSION_TOKEN, sessionToken == null ? null : Utils.byte2Hex(sessionToken));
|
||||||
|
descriptor.put(BUNDLE_KEY_KEY_FETCH_TOKEN, keyFetchToken == null ? null : Utils.byte2Hex(keyFetchToken));
|
||||||
|
descriptor.put(BUNDLE_KEY_VERIFIED, Boolean.valueOf(verified).toString());
|
||||||
|
descriptor.put(BUNDLE_KEY_UNWRAPKB, Utils.byte2Hex(unwrapBkey));
|
||||||
|
|
||||||
|
userdata.putString(ACCOUNT_KEY_DESCRIPTOR, descriptor.toJSONString());
|
||||||
|
|
||||||
Account account = new Account(email, FxAccountConstants.ACCOUNT_TYPE);
|
Account account = new Account(email, FxAccountConstants.ACCOUNT_TYPE);
|
||||||
AccountManager accountManager = AccountManager.get(context);
|
AccountManager accountManager = AccountManager.get(context);
|
||||||
@ -285,13 +396,12 @@ public class AndroidFxAccount implements AbstractFxAccount {
|
|||||||
public boolean isValid() {
|
public boolean isValid() {
|
||||||
// Boolean.valueOf only returns true for the string "true"; this errors in
|
// Boolean.valueOf only returns true for the string "true"; this errors in
|
||||||
// the direction of marking accounts valid.
|
// the direction of marking accounts valid.
|
||||||
boolean invalid = Boolean.valueOf(accountManager.getUserData(account, ACCOUNT_KEY_INVALID)).booleanValue();
|
return !getBundleDataBoolean(BUNDLE_KEY_INVALID, false);
|
||||||
return !invalid;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setInvalid() {
|
public void setInvalid() {
|
||||||
accountManager.setUserData(account, ACCOUNT_KEY_INVALID, Boolean.valueOf(true).toString());
|
updateBundleValue(BUNDLE_KEY_INVALID, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -313,8 +423,13 @@ public class AndroidFxAccount implements AbstractFxAccount {
|
|||||||
* <b>For debugging only!</b>
|
* <b>For debugging only!</b>
|
||||||
*/
|
*/
|
||||||
public void forgetAccountTokens() {
|
public void forgetAccountTokens() {
|
||||||
accountManager.setUserData(account, ACCOUNT_KEY_SESSION_TOKEN, null);
|
ExtendedJSONObject descriptor = unbundle();
|
||||||
accountManager.setUserData(account, ACCOUNT_KEY_KEY_FETCH_TOKEN, null);
|
if (descriptor == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
descriptor.remove(BUNDLE_KEY_SESSION_TOKEN);
|
||||||
|
descriptor.remove(BUNDLE_KEY_KEY_FETCH_TOKEN);
|
||||||
|
persistBundle(descriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -15,6 +15,7 @@ import org.json.simple.JSONArray;
|
|||||||
import org.json.simple.JSONObject;
|
import org.json.simple.JSONObject;
|
||||||
import org.json.simple.parser.JSONParser;
|
import org.json.simple.parser.JSONParser;
|
||||||
import org.json.simple.parser.ParseException;
|
import org.json.simple.parser.ParseException;
|
||||||
|
import org.mozilla.apache.commons.codec.binary.Base64;
|
||||||
import org.mozilla.gecko.sync.UnexpectedJSONException.BadRequiredFieldJSONException;
|
import org.mozilla.gecko.sync.UnexpectedJSONException.BadRequiredFieldJSONException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -363,4 +364,26 @@ public class ExtendedJSONObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a base64-encoded string value as a byte array.
|
||||||
|
*/
|
||||||
|
public byte[] getByteArrayBase64(String key) {
|
||||||
|
String s = (String) this.object.get(key);
|
||||||
|
if (s == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return Base64.decodeBase64(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a hex-encoded string value as a byte array.
|
||||||
|
*/
|
||||||
|
public byte[] getByteArrayHex(String key) {
|
||||||
|
String s = (String) this.object.get(key);
|
||||||
|
if (s == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return Utils.hex2Byte(s);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user