Index: components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountManagerHelper.java |
diff --git a/components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountManagerHelper.java b/components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountManagerHelper.java |
index 761a7286a6f89a379e34daaf3ae9e8980950a86b..e5f42bfd9eb1d50221a69596130492d09231090e 100644 |
--- a/components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountManagerHelper.java |
+++ b/components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountManagerHelper.java |
@@ -7,7 +7,6 @@ package org.chromium.components.signin; |
import android.accounts.Account; |
import android.accounts.AuthenticatorDescription; |
import android.app.Activity; |
-import android.content.Context; |
import android.os.AsyncTask; |
import android.support.annotation.Nullable; |
@@ -44,7 +43,12 @@ public class AccountManagerHelper { |
@VisibleForTesting |
public static final String FEATURE_IS_CHILD_ACCOUNT_KEY = "service_uca"; |
- private static final AtomicReference<AccountManagerHelper> sInstance = new AtomicReference<>(); |
+ private static final AtomicReference<AccountManagerHelper> sAtomicInstance = |
+ new AtomicReference<>(); |
+ |
+ private static final Object sLock = new Object(); |
+ private static Throwable sInstanceInitializedBy; |
+ private static Throwable sTestingInstanceInitializedBy; |
private final AccountManagerDelegate mDelegate; |
@@ -76,51 +80,61 @@ public class AccountManagerHelper { |
} |
/** |
- * Initialize AccountManagerHelper with a custom AccountManagerDelegate. |
- * Ensures that the singleton AccountManagerHelper hasn't been created yet. |
- * This can be overriden in tests using the overrideAccountManagerHelperForTests method. |
+ * Initialize AccountManagerHelper with a custom AccountManagerDelegate. Ensures that it wasn't |
+ * already initialized. |
+ * Tests can override this, see {@link #overrideAccountManagerHelperForTests}. |
* |
* @param delegate the custom AccountManagerDelegate to use. |
+ * |
+ * @see #overrideAccountManagerHelperForTests |
*/ |
public static void initializeAccountManagerHelper(AccountManagerDelegate delegate) { |
- if (!sInstance.compareAndSet(null, new AccountManagerHelper(delegate))) { |
- throw new IllegalStateException("AccountManagerHelper is already initialized!"); |
+ assert delegate != null; |
+ synchronized (sLock) { |
+ if (sInstanceInitializedBy != null) { |
+ throw new IllegalStateException( |
+ "AccountManagerHelper is already initialized.", sInstanceInitializedBy); |
+ } |
+ sInstanceInitializedBy = new Throwable(); |
+ if (sTestingInstanceInitializedBy != null) return; |
+ sAtomicInstance.set(new AccountManagerHelper(delegate)); |
} |
} |
/** |
- * Singleton instance getter. Singleton must be initialized before calling this |
- * (by initializeAccountManagerHelper or overrideAccountManagerHelperForTests). |
- * |
- * @return a singleton instance |
- */ |
- public static AccountManagerHelper get() { |
- AccountManagerHelper instance = sInstance.get(); |
- assert instance != null : "AccountManagerHelper is not initialized!"; |
- return instance; |
- } |
- |
- /** |
- * Override AccountManagerHelper with a custom AccountManagerDelegate in tests. |
- * Unlike initializeAccountManagerHelper, this will override the existing instance of |
- * AccountManagerHelper if any. Only for use in Tests. |
+ * Override AccountManagerHelper with a custom AccountManagerDelegate for tests. Only for use |
+ * in tests. This should be called before call to {@link #initializeAccountManagerHelper} |
+ * to make sure instance returned by {@link #get} doesn't change on the fly. |
* |
- * @param context the applicationContext is retrieved from the context used as an argument. |
* @param delegate the custom AccountManagerDelegate to use. |
*/ |
@VisibleForTesting |
- public static void overrideAccountManagerHelperForTests( |
- Context context, AccountManagerDelegate delegate) { |
- sInstance.set(new AccountManagerHelper(delegate)); |
+ public static void overrideAccountManagerHelperForTests(AccountManagerDelegate delegate) { |
+ assert delegate != null; |
+ synchronized (sLock) { |
+ Throwable initializedBy = sInstanceInitializedBy != null |
+ ? sInstanceInitializedBy |
+ : sTestingInstanceInitializedBy; |
+ if (initializedBy != null) { |
+ throw new IllegalStateException( |
+ "AccountManagerHelper is already initialized.", initializedBy); |
+ } |
+ sTestingInstanceInitializedBy = new Throwable(); |
+ sAtomicInstance.set(new AccountManagerHelper(delegate)); |
+ } |
} |
/** |
- * Resets custom AccountManagerHelper set with {@link #overrideAccountManagerHelperForTests}. |
- * Only for use in Tests. |
+ * Singleton instance getter. Singleton must be initialized before calling this |
+ * (by initializeAccountManagerHelper or overrideAccountManagerHelperForTests). |
+ * It is guaranteed that this method always returns the same instance during app lifetime. |
+ * |
+ * @return a singleton instance |
*/ |
- @VisibleForTesting |
- public static void resetAccountManagerHelperForTests() { |
- sInstance.set(null); |
+ public static AccountManagerHelper get() { |
+ AccountManagerHelper instance = sAtomicInstance.get(); |
+ assert instance != null : "AccountManagerHelper is not initialized!"; |
+ return instance; |
} |
/** |