--- a/mobile/android/services/src/main/java/org/mozilla/gecko/fxa/authenticator/AccountPickler.java
+++ b/mobile/android/services/src/main/java/org/mozilla/gecko/fxa/authenticator/AccountPickler.java
@@ -70,18 +70,21 @@ public class AccountPickler {
public static final String KEY_EMAIL = "email";
public static final String KEY_PROFILE = "profile";
public static final String KEY_IDP_SERVER_URI = "idpServerURI";
public static final String KEY_TOKEN_SERVER_URI = "tokenServerURI";
public static final String KEY_PROFILE_SERVER_URI = "profileServerURI";
public static final String KEY_AUTHORITIES_TO_SYNC_AUTOMATICALLY_MAP = "authoritiesToSyncAutomaticallyMap";
- // Deprecated, but maintained for migration purposes.
+ // All deprecated, but maintained for migration purposes.
public static final String KEY_IS_SYNCING_ENABLED = "isSyncingEnabled";
+ public static final String KEY_STATE_LABEL = "stateLabel";
+ public static final String KEY_STATE = "state";
+ public static final String KEY_PROFILE_JSON = "profileJSON";
public static final String KEY_BUNDLE = "bundle";
/**
* Remove Firefox account persisted to disk.
* This operation is synchronized to avoid race condition while deleting the account.
*
* @param context Android context.
@@ -99,43 +102,39 @@ public class AccountPickler {
o.put(KEY_ACCOUNT_VERSION, AndroidFxAccount.CURRENT_ACCOUNT_VERSION);
o.put(KEY_ACCOUNT_TYPE, FxAccountConstants.ACCOUNT_TYPE);
o.put(KEY_EMAIL, account.getEmail());
o.put(KEY_PROFILE, account.getProfile());
o.put(KEY_IDP_SERVER_URI, account.getAccountServerURI());
o.put(KEY_TOKEN_SERVER_URI, account.getTokenServerURI());
o.put(KEY_PROFILE_SERVER_URI, account.getProfileServerURI());
+ final ExtendedJSONObject profileJSON = account.getProfileJSON();
+ if (profileJSON != null) {
+ o.put(KEY_PROFILE_JSON, profileJSON.toJSONString());
+ }
+ final State state = account.getState();
+ o.put(KEY_STATE_LABEL, state.getStateLabel().name());
+ o.put(KEY_STATE, state.toJSONObject().toJSONString());
final ExtendedJSONObject p = new ExtendedJSONObject();
for (Entry<String, Boolean> pair : account.getAuthoritiesToSyncAutomaticallyMap().entrySet()) {
p.put(pair.getKey(), pair.getValue());
}
o.put(KEY_AUTHORITIES_TO_SYNC_AUTOMATICALLY_MAP, p);
// TODO: If prefs version changes under us, SyncPrefsPath will change, "clearing" prefs.
- final ExtendedJSONObject bundle = account.unbundle();
- if (bundle == null) {
- Logger.warn(LOG_TAG, "Unable to obtain account bundle; aborting.");
- return null;
- }
- o.put(KEY_BUNDLE, bundle);
-
return o;
}
/**
* Persist Firefox account to disk as a JSON object.
* This operation is synchronized to avoid race condition while deleting the account.
*
- * Note that pickling is different from bundling, which involves operations on a
- * {@link android.os.Bundle Bundle} object of miscellaneous data associated with the account.
- * See {@link AndroidFxAccount#persistBundle} and {@link AndroidFxAccount#unbundle} for more.
- *
* @param account the AndroidFxAccount to persist to disk
* @param filename name of file to persist to; must not contain path separators.
* @deprecated Pickling/Un-pickling logic will be removed entirely in the future. This method is
* still present to make sure un-pickling tests pass.
*/
public synchronized static void pickle(final AndroidFxAccount account, final String filename) {
final ExtendedJSONObject o = toJSON(account, System.currentTimeMillis());
writeToDisk(account.context, filename, o);
@@ -196,17 +195,17 @@ public class AccountPickler {
}
final AndroidFxAccount account;
try {
account = AndroidFxAccount.addAndroidAccount(context, params.state.uid, params.email, params.profile,
params.authServerURI, params.tokenServerURI, params.profileServerURI, params.state,
params.authoritiesToSyncAutomaticallyMap,
params.accountVersion,
- true, params.bundle);
+ true, params.profileJSON);
} catch (Exception e) {
Logger.warn(LOG_TAG, "Exception when adding Android Account; aborting.", e);
return null;
}
if (account == null) {
Logger.warn(LOG_TAG, "Failed to add Android Account; aborting.");
return null;
@@ -224,18 +223,18 @@ public class AccountPickler {
private int accountVersion;
private String email;
private String profile;
private String authServerURI;
private String tokenServerURI;
private String profileServerURI;
private final Map<String, Boolean> authoritiesToSyncAutomaticallyMap = new HashMap<>();
- private ExtendedJSONObject bundle;
private State state;
+ private String profileJSON;
private UnpickleParams() {
}
private static UnpickleParams fromJSON(final ExtendedJSONObject json)
throws InvalidKeySpecException, NoSuchAlgorithmException, NonObjectJSONException {
final UnpickleParams params = new UnpickleParams();
params.pickleVersion = json.getLong(KEY_PICKLE_VERSION);
@@ -309,21 +308,29 @@ public class AccountPickler {
this.profileServerURI = FxAccountConstants.DEFAULT_AUTH_SERVER_ENDPOINT.equals(this.authServerURI)
? FxAccountConstants.DEFAULT_PROFILE_SERVER_ENDPOINT
: FxAccountConstants.STAGE_PROFILE_SERVER_ENDPOINT;
}
// We get the default value for everything except syncing browser data.
this.authoritiesToSyncAutomaticallyMap.put(BrowserContract.AUTHORITY, json.getBoolean(KEY_IS_SYNCING_ENABLED));
- this.bundle = json.getObject(KEY_BUNDLE);
- if (bundle == null) {
- throw new IllegalStateException("Pickle bundle is null.");
+ final ExtendedJSONObject bundle = json.getObject(KEY_BUNDLE);
+ if (bundle != null) {
+ this.state = getState(bundle);
+ this.profileJSON = bundle.getString(AndroidFxAccount.BUNDLE_KEY_PROFILE_JSON);
+ return;
}
- this.state = getState(bundle);
+ final String stateLabelString = json.getString(KEY_STATE_LABEL);
+ final String stateString = json.getString(KEY_STATE);
+ if (stateLabelString == null || stateString == null) {
+ throw new IllegalStateException("Unable to get pickled state.");
+ }
+ this.state = getState(stateLabelString, stateString);
+ this.profileJSON = json.getString(KEY_PROFILE_JSON);
}
private void unpickleV3(final ExtendedJSONObject json)
throws NonObjectJSONException, NoSuchAlgorithmException, InvalidKeySpecException {
// We'll overwrite the extracted sync automatically map.
unpickleV1(json);
// Extract the map of authorities to sync automatically.
@@ -339,27 +346,31 @@ public class AccountPickler {
}
}
}
private State getState(final ExtendedJSONObject bundle) throws InvalidKeySpecException,
NonObjectJSONException, NoSuchAlgorithmException {
// TODO: Should copy-pasta BUNDLE_KEY_STATE & LABEL to this file to ensure we maintain
// old versions?
- final StateLabel stateLabelString = StateLabel.valueOf(
- bundle.getString(AndroidFxAccount.BUNDLE_KEY_STATE_LABEL));
+ final String stateLabelString = bundle.getString(AndroidFxAccount.BUNDLE_KEY_STATE_LABEL);
final String stateString = bundle.getString(AndroidFxAccount.BUNDLE_KEY_STATE);
- if (stateLabelString == null || stateString == null) {
+ return getState(stateLabelString, stateString);
+ }
+
+ private State getState(String stateLabelString, String stateString) {
+ final StateLabel stateLabel = StateLabel.valueOf(stateLabelString);
+ if (stateLabel == null || stateString == null) {
throw new IllegalStateException("stateLabel and stateString must not be null, but: " +
- "(stateLabel == null) = " + (stateLabelString == null) +
- " and (stateString == null) = " + (stateString == null));
+ "(stateLabel == null) = " + (stateLabel == null) +
+ " and (stateString == null) = " + (stateString == null));
}
try {
- return StateFactory.fromJSONObject(stateLabelString, new ExtendedJSONObject(stateString));
+ return StateFactory.fromJSONObject(stateLabel, new ExtendedJSONObject(stateString));
} catch (Exception e) {
throw new IllegalStateException("could not get state", e);
}
}
@Nullable
/* package-private */ String getUID() {
return this.state.uid;
--- a/mobile/android/services/src/main/java/org/mozilla/gecko/fxa/authenticator/AndroidFxAccount.java
+++ b/mobile/android/services/src/main/java/org/mozilla/gecko/fxa/authenticator/AndroidFxAccount.java
@@ -91,21 +91,24 @@ public class AndroidFxAccount {
// It's important that when renaming is complete - or fails - that this flag is reset, otherwise
// normal account deletion will not function correctly.
/* package-private */ static final String ACCOUNT_KEY_RENAME_IN_PROGRESS = "accountBeingRenamed";
/* package-private */ static final String ACCOUNT_VALUE_RENAME_IN_PROGRESS = "true";
private static final String ACCOUNT_KEY_TOKEN_SERVER = "tokenServerURI"; // Sync-specific.
private static final String ACCOUNT_KEY_DESCRIPTOR = "descriptor";
- private static final int CURRENT_BUNDLE_VERSION = 2;
- private static final String BUNDLE_KEY_BUNDLE_VERSION = "version";
- /* package-private */static final String BUNDLE_KEY_STATE_LABEL = "stateLabel";
+ // Deprecated, but maintained for migration purposes.
+ /* package-private */ static final String BUNDLE_KEY_STATE_LABEL = "stateLabel";
/* package-private */ static final String BUNDLE_KEY_STATE = "state";
- private static final String BUNDLE_KEY_PROFILE_JSON = "profile";
+ /* package-private */ static final String BUNDLE_KEY_PROFILE_JSON = "profile";
+
+ private static final String ACCOUNT_KEY_STATE_LABEL = "stateLabel";
+ private static final String ACCOUNT_KEY_STATE = "state";
+ private static final String ACCOUNT_KEY_PROFILE_JSON = "profile";
private static final String ACCOUNT_KEY_DEVICE_ID = "deviceId";
private static final String ACCOUNT_KEY_DEVICE_REGISTRATION_VERSION = "deviceRegistrationVersion";
private static final String ACCOUNT_KEY_DEVICE_REGISTRATION_TIMESTAMP = "deviceRegistrationTimestamp";
private static final String ACCOUNT_KEY_DEVICE_PUSH_REGISTRATION_ERROR = "devicePushRegistrationError";
private static final String ACCOUNT_KEY_DEVICE_PUSH_REGISTRATION_ERROR_TIME = "devicePushRegistrationErrorTime";
// Account authentication token type for fetching account profile.
@@ -135,17 +138,18 @@ public class AndroidFxAccount {
private static final List<String> ACCOUNT_KEY_TO_CARRY_OVER_ON_RENAME_SET;
static {
ArrayList<String> keysToCarryOver = new ArrayList<>(6);
keysToCarryOver.add(ACCOUNT_KEY_ACCOUNT_VERSION);
keysToCarryOver.add(ACCOUNT_KEY_IDP_SERVER);
keysToCarryOver.add(ACCOUNT_KEY_TOKEN_SERVER);
keysToCarryOver.add(ACCOUNT_KEY_PROFILE_SERVER);
keysToCarryOver.add(ACCOUNT_KEY_PROFILE);
- keysToCarryOver.add(ACCOUNT_KEY_DESCRIPTOR);
+ keysToCarryOver.add(ACCOUNT_KEY_STATE_LABEL);
+ keysToCarryOver.add(ACCOUNT_KEY_STATE);
ACCOUNT_KEY_TO_CARRY_OVER_ON_RENAME_SET = Collections.unmodifiableList(keysToCarryOver);
}
private static final String PREF_KEY_LAST_SYNCED_TIMESTAMP = "lastSyncedTimestamp";
protected final Context context;
private final AccountManager accountManager;
private final long neverSynced = -1;
@@ -169,16 +173,17 @@ public class AndroidFxAccount {
* to use as long-lived ambient Android context.
* @param account
* Android account to use for storage.
*/
public AndroidFxAccount(Context applicationContext, Account account) {
this.context = applicationContext;
this.account = account;
this.accountManager = AccountManager.get(this.context);
+ maybeMigrateBundle();
}
public static AndroidFxAccount fromContext(Context context) {
context = context.getApplicationContext();
Account account = FirefoxAccounts.getFirefoxAccount(context);
if (account == null) {
return null;
}
@@ -230,90 +235,16 @@ public class AndroidFxAccount {
// Persist our UID into userData, so that we never have to do this dance again.
accountManager.setUserData(account, ACCOUNT_KEY_UID, unpickledAccountUID);
return unpickledAccountUID;
}
/**
- * Saves the given data as the internal bundle associated with this account.
- * @param bundle to write to account.
- */
- private synchronized void persistBundle(ExtendedJSONObject bundle) {
- accountManager.setUserData(account, ACCOUNT_KEY_DESCRIPTOR, bundle.toJSONString());
- }
-
- /**
- * Retrieve the internal bundle associated with this account.
- * @return bundle associated with account.
- */
- /* package-private */ synchronized ExtendedJSONObject unbundle() {
- final String bundleString = accountManager.getUserData(account, ACCOUNT_KEY_DESCRIPTOR);
-
- final int version = getAccountVersion();
- if (version < CURRENT_ACCOUNT_VERSION) {
- // Needs upgrade. For now, do nothing. We'd like to just put your account
- // into the Separated state here and have you update your credentials.
- return null;
- }
-
- if (version > CURRENT_ACCOUNT_VERSION) {
- // Oh dear.
- throw new IllegalStateException("Invalid account bundle version. Current: " + CURRENT_ACCOUNT_VERSION + ", bundle version: " + version);
- }
-
- if (bundleString == null) {
- return null;
- }
-
- return unbundleAccountV2(bundleString);
- }
-
- private String getBundleData(String key) {
- ExtendedJSONObject o = unbundle();
- if (o == null) {
- return null;
- }
- return o.getString(key);
- }
-
- private void updateBundleValues(String key, String value, String... more) {
- if (more.length % 2 != 0) {
- throw new IllegalArgumentException("more must be a list of key, value pairs");
- }
- ExtendedJSONObject descriptor = unbundle();
- if (descriptor == null) {
- return;
- }
- descriptor.put(key, value);
- for (int i = 0; i + 1 < more.length; i += 2) {
- descriptor.put(more[i], more[i+1]);
- }
- 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;
- }
-
- private ExtendedJSONObject unbundleAccountV2(String bundle) {
- return unbundleAccountV1(bundle);
- }
-
- /**
* Note that if the user clears data, an account will be left pointing to a
* deleted profile. Such is life.
*/
public String getProfile() {
return accountManager.getUserData(account, ACCOUNT_KEY_PROFILE);
}
public String getAccountServerURI() {
@@ -384,16 +315,40 @@ public class AndroidFxAccount {
}
private String getReadingListPrefsPath(final String accountKey) throws GeneralSecurityException, UnsupportedEncodingException {
final String product = GlobalConstants.BROWSER_INTENT_PACKAGE + ".reading";
final long version = CURRENT_RL_PREFS_VERSION;
return constructPrefsPath(accountKey, product, version, "");
}
+ private void maybeMigrateBundle() {
+ final String bundleString = accountManager.getUserData(account, ACCOUNT_KEY_DESCRIPTOR);
+ if (TextUtils.isEmpty(bundleString)) {
+ return;
+ }
+ try {
+ final ExtendedJSONObject o = new ExtendedJSONObject(bundleString);
+
+ final String stateLabel = o.getString(BUNDLE_KEY_STATE_LABEL);
+ final String state = o.getString(BUNDLE_KEY_STATE);
+ final String profileJSON = o.getString(BUNDLE_KEY_PROFILE_JSON);
+
+ // Unwrap bundle values and save them individually.
+ accountManager.setUserData(account, ACCOUNT_KEY_STATE_LABEL, stateLabel);
+ accountManager.setUserData(account, ACCOUNT_KEY_STATE, state);
+ accountManager.setUserData(account, ACCOUNT_KEY_PROFILE_JSON, profileJSON);
+ } catch (Exception e) {
+ Log.e(LOG_TAG, "Error in maybeMigrateBundle", e);
+ } finally {
+ // Delete the old bundle.
+ accountManager.setUserData(account, ACCOUNT_KEY_DESCRIPTOR, null);
+ }
+ }
+
@SuppressWarnings("unchecked")
private static void migrateSharedPreferencesValues(SharedPreferences sharedPreferences, Map<String, ?> values) {
final SharedPreferences.Editor editor = sharedPreferences.edit();
for (String key : values.keySet()) {
final Object value = values.get(key);
if (value instanceof String) {
editor.putString(key, (String) value);
} else if (value instanceof Integer) {
@@ -474,26 +429,30 @@ public class AndroidFxAccount {
* <p>
* <b>For debugging use only!</b> The contents of this JSON object completely
* determine the user's Firefox Account status and yield access to whatever
* user data the device has access to.
*
* @return JSON-object of Strings.
*/
public ExtendedJSONObject toJSONObject() {
- ExtendedJSONObject o = unbundle();
+ ExtendedJSONObject o = new ExtendedJSONObject();
o.put("email", account.name);
try {
o.put("emailUTF8", Utils.byte2Hex(account.name.getBytes("UTF-8")));
} catch (UnsupportedEncodingException e) {
// Ignore.
}
o.put("fxaDeviceId", getDeviceId());
o.put("fxaDeviceRegistrationVersion", getDeviceRegistrationVersion());
o.put("fxaDeviceRegistrationTimestamp", getDeviceRegistrationTimestamp());
+ final State state = getState();
+ o.put("stateLabel", state.getStateLabel().name());
+ o.put("state", state.toJSONObject().toJSONString());
+ o.put("profile", getProfileJSON());
return o;
}
public static AndroidFxAccount addAndroidAccount(
@NonNull Context context,
@NonNull String uid,
@NonNull String email,
@NonNull String profile,
@@ -515,17 +474,17 @@ public class AndroidFxAccount {
@NonNull String profile,
@NonNull String idpServerURI,
@NonNull String tokenServerURI,
@NonNull String profileServerURI,
@NonNull State state,
final Map<String, Boolean> authoritiesToSyncAutomaticallyMap,
final int accountVersion,
final boolean fromPickle,
- ExtendedJSONObject bundle)
+ final String profileJSON /* remove this once pickling is removed */)
throws UnsupportedEncodingException, GeneralSecurityException, URISyntaxException {
if (uid == null) {
throw new IllegalArgumentException("uid must not be null");
}
if (email == null) {
throw new IllegalArgumentException("email must not be null");
}
if (profile == null) {
@@ -554,26 +513,18 @@ public class AndroidFxAccount {
// bundle to be strings. *sigh*
Bundle userdata = new Bundle();
userdata.putString(ACCOUNT_KEY_ACCOUNT_VERSION, "" + CURRENT_ACCOUNT_VERSION);
userdata.putString(ACCOUNT_KEY_IDP_SERVER, idpServerURI);
userdata.putString(ACCOUNT_KEY_TOKEN_SERVER, tokenServerURI);
userdata.putString(ACCOUNT_KEY_PROFILE_SERVER, profileServerURI);
userdata.putString(ACCOUNT_KEY_PROFILE, profile);
userdata.putString(ACCOUNT_KEY_UID, uid);
-
- if (bundle == null) {
- bundle = new ExtendedJSONObject();
- // TODO: How to upgrade?
- bundle.put(BUNDLE_KEY_BUNDLE_VERSION, CURRENT_BUNDLE_VERSION);
- }
- bundle.put(BUNDLE_KEY_STATE_LABEL, state.getStateLabel().name());
- bundle.put(BUNDLE_KEY_STATE, state.toJSONObject().toJSONString());
-
- userdata.putString(ACCOUNT_KEY_DESCRIPTOR, bundle.toJSONString());
+ userdata.putString(ACCOUNT_KEY_STATE_LABEL, state.getStateLabel().name());
+ userdata.putString(ACCOUNT_KEY_STATE, state.toJSONObject().toJSONString());
Account account = new Account(email, FxAccountConstants.ACCOUNT_TYPE);
AccountManager accountManager = AccountManager.get(context);
// We don't set an Android password, because we don't want to persist the
// password (or anything else as powerful as the password). Instead, we
// internally manage a sessionToken with a remotely owned lifecycle.
boolean added = accountManager.addAccountExplicitly(account, null, userdata);
if (!added) {
@@ -590,16 +541,20 @@ public class AndroidFxAccount {
}
final AndroidFxAccount fxAccount = new AndroidFxAccount(context, account);
if (!fromPickle) {
fxAccount.clearSyncPrefs();
}
+ if (profileJSON != null) {
+ accountManager.setUserData(account, ACCOUNT_KEY_PROFILE_JSON, profileJSON);
+ }
+
fxAccount.setAuthoritiesToSyncAutomaticallyMap(authoritiesToSyncAutomaticallyMap);
return fxAccount;
}
private void clearSyncPrefs() throws UnsupportedEncodingException, GeneralSecurityException {
getSyncPrefs().edit().clear().apply();
}
@@ -667,19 +622,18 @@ public class AndroidFxAccount {
}
public synchronized void setState(State state) {
if (state == null) {
throw new IllegalArgumentException("state must not be null");
}
Logger.info(LOG_TAG, "Moving account named like " + getObfuscatedEmail() +
" to state " + state.getStateLabel().toString());
- updateBundleValues(
- BUNDLE_KEY_STATE_LABEL, state.getStateLabel().name(),
- BUNDLE_KEY_STATE, state.toJSONObject().toJSONString());
+ accountManager.setUserData(account, ACCOUNT_KEY_STATE_LABEL, state.getStateLabel().name());
+ accountManager.setUserData(account, ACCOUNT_KEY_STATE, state.toJSONObject().toJSONString());
broadcastAccountStateChangedIntent();
}
private void broadcastAccountStateChangedIntent() {
final Intent intent = new Intent(FxAccountConstants.ACCOUNT_STATE_CHANGED_ACTION);
intent.putExtra(Constants.JSON_KEY_ACCOUNT, account.name);
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
}
@@ -687,18 +641,19 @@ public class AndroidFxAccount {
public synchronized State getState() {
// Ensure we're working with the latest 'account' state. It might have changed underneath us.
// Note that this "state refresh" is inefficient for some callers, since they might have
// created this object (and thus fetched an account from the accounts system) just moments ago.
// Other callers maintain this object for a while, and thus might be out-of-sync with the world.
// See Bug 1407316 for higher-order improvements that will make this unnecessary.
account = FirefoxAccounts.getFirefoxAccount(context);
- String stateLabelString = getBundleData(BUNDLE_KEY_STATE_LABEL);
- String stateString = getBundleData(BUNDLE_KEY_STATE);
+ final String stateLabelString = accountManager.getUserData(account, ACCOUNT_KEY_STATE_LABEL);
+ final String stateString = accountManager.getUserData(account, ACCOUNT_KEY_STATE);
+
if (stateLabelString == null || stateString == null) {
throw new IllegalStateException("stateLabelString and stateString must not be null, but: " +
"(stateLabelString == null) = " + (stateLabelString == null) +
" and (stateString == null) = " + (stateString == null));
}
try {
StateLabel stateLabel = StateLabel.valueOf(stateLabelString);
@@ -865,17 +820,17 @@ public class AndroidFxAccount {
}
/**
* Returns the current profile JSON if available, or null.
*
* @return profile JSON object.
*/
public ExtendedJSONObject getProfileJSON() {
- final String profileString = getBundleData(BUNDLE_KEY_PROFILE_JSON);
+ String profileString = accountManager.getUserData(account, ACCOUNT_KEY_PROFILE_JSON);
if (profileString == null) {
return null;
}
try {
return new ExtendedJSONObject(profileString);
} catch (Exception e) {
Logger.error(LOG_TAG, "Failed to parse profile JSON; ignoring and returning null.", e);
@@ -1005,17 +960,17 @@ public class AndroidFxAccount {
case Activity.RESULT_OK:
Logger.info(LOG_TAG, "Profile JSON fetch succeeded!");
final String resultData = bundle.getString(FxAccountProfileService.KEY_RESULT_STRING);
FxAccountUtils.pii(LOG_TAG, "Profile JSON fetch returned: " + resultData);
renameAccountIfNecessary(resultData, new Runnable() {
@Override
public void run() {
- updateBundleValues(BUNDLE_KEY_PROFILE_JSON, resultData);
+ accountManager.setUserData(account, ACCOUNT_KEY_PROFILE_JSON, resultData);
LocalBroadcastManager.getInstance(context).sendBroadcast(makeProfileJSONUpdatedIntent());
}
});
break;
case Activity.RESULT_CANCELED:
Logger.warn(LOG_TAG, "Failed to fetch profile JSON; ignoring.");
break;
default: