Bug 1182270 - Pre: AccountPickler public interface synchronized to avoid race condition r=nalexander.
authorvivek <vivekb.balakrishnan@gmail.com>
Thu, 16 Jul 2015 00:24:37 +0300
changeset 286965 0a2ea3f59b1b3ee44b484cf728827706b0a9a098
parent 286892 ac1dbff4c79105fbd34f9b93b5e17b428488d26b
child 286966 110b4a6848ab577836faf87a58ebe13458b32d7f
push id5067
push userraliiev@mozilla.com
push dateMon, 21 Sep 2015 14:04:52 +0000
treeherdermozilla-beta@14221ffe5b2f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnalexander
bugs1182270
milestone42.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1182270 - Pre: AccountPickler public interface synchronized to avoid race condition r=nalexander.
mobile/android/base/fxa/FirefoxAccounts.java
mobile/android/base/fxa/authenticator/AccountPickler.java
--- a/mobile/android/base/fxa/FirefoxAccounts.java
+++ b/mobile/android/base/fxa/FirefoxAccounts.java
@@ -124,17 +124,17 @@ public class FirefoxAccounts {
             return;
           }
 
           // There is a small race window here: if the user creates a new Firefox account
           // between our checks, this could erroneously report that no Firefox accounts
           // exist.
           final AndroidFxAccount fxAccount =
               AccountPickler.unpickle(context, FxAccountConstants.ACCOUNT_PICKLE_FILENAME);
-          accounts[0] = fxAccount.getAndroidAccount();
+          accounts[0] = fxAccount != null ? fxAccount.getAndroidAccount() : null;
         } finally {
           latch.countDown();
         }
       }
     });
 
     try {
       latch.await(); // Wait for the background thread to return.
--- a/mobile/android/base/fxa/authenticator/AccountPickler.java
+++ b/mobile/android/base/fxa/authenticator/AccountPickler.java
@@ -75,22 +75,23 @@ public class AccountPickler {
 
   // Deprecated, but maintained for migration purposes.
   public static final String KEY_IS_SYNCING_ENABLED = "isSyncingEnabled";
 
   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.
    * @param filename name of persisted pickle file; must not contain path separators.
    * @return <code>true</code> if given pickle existed and was successfully deleted.
    */
-  public static boolean deletePickle(final Context context, final String filename) {
+  public synchronized static boolean deletePickle(final Context context, final String filename) {
     return context.deleteFile(filename);
   }
 
   public static ExtendedJSONObject toJSON(final AndroidFxAccount account, final long now) {
     final ExtendedJSONObject o = new ExtendedJSONObject();
     o.put(KEY_PICKLE_VERSION, PICKLE_VERSION);
     o.put(KEY_PICKLE_TIMESTAMP, now);
 
@@ -117,21 +118,22 @@ public class AccountPickler {
     }
     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.
    *
-   * @param AndroidFxAccount the account to persist to disk
+   * @param account the AndroidFxAccount to persist to disk
    * @param filename name of file to persist to; must not contain path separators.
    */
-  public static void pickle(final AndroidFxAccount account, final String filename) {
+  public synchronized static void pickle(final AndroidFxAccount account, final String filename) {
     final ExtendedJSONObject o = toJSON(account, System.currentTimeMillis());
     writeToDisk(account.context, filename, o);
   }
 
   private static void writeToDisk(final Context context, final String filename,
       final ExtendedJSONObject pickle) {
     try {
       final FileOutputStream fos = context.openFileOutput(filename, Context.MODE_PRIVATE);
@@ -150,24 +152,25 @@ public class AccountPickler {
     } catch (Exception e) {
       Logger.warn(LOG_TAG, "Caught exception persisting account settings to " + filename +
           "; ignoring.", e);
     }
   }
 
   /**
    * Create Android account from saved JSON object. Assumes that an account does not exist.
+   * This operation is synchronized to avoid race condition while deleting the account.
    *
    * @param context
    *          Android context.
    * @param filename
    *          name of file to read from; must not contain path separators.
    * @return created Android account, or null on error.
    */
-  public static AndroidFxAccount unpickle(final Context context, final String filename) {
+  public synchronized static AndroidFxAccount unpickle(final Context context, final String filename) {
     final String jsonString = Utils.readFile(context, filename);
     if (jsonString == null) {
       Logger.info(LOG_TAG, "Pickle file '" + filename + "' not found; aborting.");
       return null;
     }
 
     ExtendedJSONObject json = null;
     try {