Skip to content

Commit

Permalink
Reimplement AccountManagerHelper singleton instance creation
Browse files Browse the repository at this point in the history
Current implementation of AccountManagerHelper can instantiate wrong delegate
type if get() is called in too early. This CL fixes it. AtomicReference is used
to avoid relying on external synchronization, because get() can be called
from different threads. This CL also adds
AccountManagerHelper.resetAccountManagerHelperForTests method that makes sure
there's no interference between tests.

BUG=698258

Review-Url: https://codereview.chromium.org/2747293005
Cr-Commit-Position: refs/heads/master@{#463963}
  • Loading branch information
bsazonov authored and Commit bot committed Apr 12, 2017
1 parent a6290b2 commit 1305003
Show file tree
Hide file tree
Showing 23 changed files with 119 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -561,5 +561,6 @@ public void run() {
SigninManager.get(getActivity()).removeSignInStateObserver(mTestObserver);
}
});
SigninTestUtil.tearDownAuthForTest();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;

import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
Expand Down Expand Up @@ -76,6 +77,11 @@ private void setupTestAccount(Context context) {
mAccountManager.addAccountHolderExplicitly(accountHolder.build());
}

@After
public void tearDown() {
AccountManagerHelper.resetAccountManagerHelperForTests();
}

/**
* Launches the main preferences.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ protected void setUp() throws Exception {
@Override
protected void tearDown() throws Exception {
mTestServer.stopAndDestroyServer();
SigninTestUtil.tearDownAuthForTest();
super.tearDown();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,15 +65,17 @@ public void setUp() throws Exception {
mapAccountNamesToIds();
ApplicationData.clearAppData(
InstrumentationRegistry.getInstrumentation().getTargetContext());
mActivityTestRule.loadNativeLibraryAndInitBrowserProcess();

// Set up AccountManager.
// loadNativeLibraryAndInitBrowserProcess will access AccountManagerHelper, so it should
// be initialized beforehand.
mContext = new AdvancedMockContext(
InstrumentationRegistry.getInstrumentation().getTargetContext());
mAccountManager = new MockAccountManager(
mContext, InstrumentationRegistry.getInstrumentation().getContext());
AccountManagerHelper.overrideAccountManagerHelperForTests(mContext, mAccountManager);

mActivityTestRule.loadNativeLibraryAndInitBrowserProcess();

// Make sure there is no account signed in yet.
mChromeSigninController = ChromeSigninController.get();
mChromeSigninController.setSignedInAccountName(null);
Expand All @@ -98,6 +100,7 @@ public void run() {
mOAuth2TokenService.validateAccounts(false);
}
});
AccountManagerHelper.resetAccountManagerHelperForTests();
}

private void mapAccountNamesToIds() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;

import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
Expand Down Expand Up @@ -40,6 +41,11 @@ public void setUp() throws Exception {
AccountManagerHelper.overrideAccountManagerHelperForTests(mContext, mAccountManager);
}

@After
public void tearDown() {
AccountManagerHelper.resetAccountManagerHelperForTests();
}

/*
* @SmallTest
* @Feature({"Sync"})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;

import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
Expand Down Expand Up @@ -44,6 +45,11 @@ public void setUp() {
AccountManagerHelper.overrideAccountManagerHelperForTests(mContext, mAccountManager);
}

@After
public void tearDown() {
AccountManagerHelper.resetAccountManagerHelperForTests();
}

@Test
@SmallTest
@RetryOnFailure
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,9 @@ public void run() {
mBookmarks.destroy();
}
});

SigninTestUtil.tearDownAuthForTest();

super.tearDown();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ public void setUp() throws Exception {
@Override
public void tearDown() throws Exception {
SigninTestUtil.resetSigninState();
SigninTestUtil.tearDownAuthForTest();
super.tearDown();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ public void tearDown() throws Exception {
// Clear ProfileSyncService in case it was mocked.
ProfileSyncService.overrideForTests(null);
SigninTestUtil.resetSigninState();
SigninTestUtil.tearDownAuthForTest();
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import android.test.mock.MockContext;
import android.test.mock.MockPackageManager;

import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
Expand Down Expand Up @@ -60,6 +61,11 @@ public void setUp() {
InstrumentationRegistry.getInstrumentation().getTargetContext());
}

@After
public void tearDown() {
AccountManagerHelper.resetAccountManagerHelperForTests();
}

private static class IntentTestPackageManager extends MockPackageManager {

private final String mAction;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import android.content.pm.PackageInfo;
import android.os.Bundle;

import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
Expand All @@ -30,7 +31,9 @@
import org.chromium.base.ContextUtils;
import org.chromium.base.test.util.Feature;
import org.chromium.chrome.browser.sync.ProfileSyncService;
import org.chromium.components.signin.AccountManagerHelper;
import org.chromium.components.signin.ChromeSigninController;
import org.chromium.components.signin.SystemAccountManagerDelegate;
import org.chromium.components.sync.AndroidSyncSettings;
import org.chromium.components.sync.ModelType;
import org.chromium.components.sync.ModelTypeHelper;
Expand Down Expand Up @@ -111,6 +114,9 @@ public void setUp() throws Exception {

ContextUtils.initApplicationContextForTests(mContext.getApplicationContext());

AccountManagerHelper.overrideAccountManagerHelperForTests(
mContext, new SystemAccountManagerDelegate());

ModelTypeHelper.setTestDelegate(new ModelTypeHelper.TestDelegate() {
@Override
public String toNotificationType(int modelType) {
Expand Down Expand Up @@ -139,6 +145,11 @@ public String toNotificationType(int modelType) {
AndroidSyncSettings.enableChromeSync(mContext);
}

@After
public void tearDown() {
AccountManagerHelper.resetAccountManagerHelperForTests();
}

/**
* Verify the intent sent by InvalidationController#stop().
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,8 @@ public void testShouldProceed_notSignedIn() throws ProcessInitException {
.nativeShouldProceed(eq(5678L),
any(SupervisedUserContentProvider.SupervisedUserQueryReply.class),
eq("url"));

AccountManagerHelper.resetAccountManagerHelperForTests();
}

@Test
Expand Down Expand Up @@ -266,6 +268,8 @@ public Void answer(InvocationOnMock invocation) throws Throwable {

assertThat(result.shouldProceed(), is(false));
assertThat(result.getErrorInt(0), is(5));

AccountManagerHelper.resetAccountManagerHelperForTests();
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ public void run() {
}
});
SigninTestUtil.resetSigninState();
SigninTestUtil.tearDownAuthForTest();

super.tearDown();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,14 @@ public void run() {
resetSigninState();
}

/**
* Tears down the test authentication environment.
*/
public static void tearDownAuthForTest() {
AccountManagerHelper.resetAccountManagerHelperForTests();
sContext = null;
}

/**
* Returns the currently signed in account.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "components/signin/core/browser/account_fetcher_service.h"
#include "components/signin/core/browser/account_info.h"
#include "components/signin/core/browser/account_tracker_service.h"
#include "components/signin/core/browser/child_account_info_fetcher.h"
#include "components/signin/core/browser/fake_account_fetcher_service.h"
#include "components/signin/core/browser/test_signin_client.h"
#include "components/signin/core/common/signin_pref_names.h"
Expand Down Expand Up @@ -255,6 +256,8 @@ class AccountTrackerServiceTest : public testing::Test {
~AccountTrackerServiceTest() override {}

void SetUp() override {
ChildAccountInfoFetcher::InitializeForTests();

fake_oauth2_token_service_.reset(new FakeOAuth2TokenService());

pref_service_.registry()->RegisterListPref(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,14 @@
import java.util.Locale;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.regex.Pattern;

/**
* AccountManagerHelper wraps our access of AccountManager in Android.
*
* Use the AccountManagerHelper.get(someContext) to instantiate it
* Use the {@link #initializeAccountManagerHelper} to instantiate it.
* After initialization, instance get be acquired by calling {@link #get}.
*/
public class AccountManagerHelper {
private static final String TAG = "Sync_Signin";
Expand All @@ -46,9 +48,7 @@ public class AccountManagerHelper {
@VisibleForTesting
public static final String FEATURE_IS_CHILD_ACCOUNT_KEY = "service_uca";

private static final Object sLock = new Object();

private static AccountManagerHelper sAccountManagerHelper;
private static final AtomicReference<AccountManagerHelper> sInstance = new AtomicReference<>();

private final AccountManagerDelegate mAccountManager;

Expand Down Expand Up @@ -87,26 +87,21 @@ private AccountManagerHelper(AccountManagerDelegate accountManager) {
* @param delegate the custom AccountManagerDelegate to use.
*/
public static void initializeAccountManagerHelper(AccountManagerDelegate delegate) {
synchronized (sLock) {
assert sAccountManagerHelper == null;
sAccountManagerHelper = new AccountManagerHelper(delegate);
if (!sInstance.compareAndSet(null, new AccountManagerHelper(delegate))) {
throw new IllegalStateException("AccountManagerHelper is already initialized!");
}
}

/**
* A getter method for AccountManagerHelper singleton which also initializes it if not wasn't
* already initialized.
* Singleton instance getter. Singleton must be initialized before calling this
* (by initializeAccountManagerHelper or overrideAccountManagerHelperForTests).
*
* @return a singleton instance of the AccountManagerHelper
* @return a singleton instance
*/
public static AccountManagerHelper get() {
synchronized (sLock) {
if (sAccountManagerHelper == null) {
sAccountManagerHelper =
new AccountManagerHelper(new SystemAccountManagerDelegate());
}
}
return sAccountManagerHelper;
AccountManagerHelper instance = sInstance.get();
assert instance != null : "AccountManagerHelper is not initialized!";
return instance;
}

/**
Expand All @@ -120,9 +115,16 @@ public static AccountManagerHelper get() {
@VisibleForTesting
public static void overrideAccountManagerHelperForTests(
Context context, AccountManagerDelegate delegate) {
synchronized (sLock) {
sAccountManagerHelper = new AccountManagerHelper(delegate);
}
sInstance.set(new AccountManagerHelper(delegate));
}

/**
* Resets custom AccountManagerHelper set with {@link #overrideAccountManagerHelperForTests}.
* Only for use in Tests.
*/
@VisibleForTesting
public static void resetAccountManagerHelperForTests() {
sInstance.set(null);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,13 @@ private void setIsChildAccount(boolean isChildAccount) {
nativeSetIsChildAccount(mNativeAccountFetcherService, mAccountId, isChildAccount);
}

@CalledByNative
private static void initializeForTests() {
Context context = ContextUtils.getApplicationContext();
AccountManagerDelegate delegate = new SystemAccountManagerDelegate();
AccountManagerHelper.overrideAccountManagerHelperForTests(context, delegate);
}

private static native void nativeSetIsChildAccount(
long accountFetcherServicePtr, String accountId, boolean isChildAccount);
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@ protected void setUp() throws Exception {
mHelper = AccountManagerHelper.get();
}

@Override
protected void tearDown() throws Exception {
AccountManagerHelper.resetAccountManagerHelperForTests();
super.tearDown();
}

@SmallTest
public void testCanonicalAccount() throws InterruptedException {
addTestAccount("test@gmail.com", "password");
Expand Down
6 changes: 6 additions & 0 deletions components/signin/core/browser/child_account_info_fetcher.cc
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,9 @@ std::unique_ptr<ChildAccountInfoFetcher> ChildAccountInfoFetcher::CreateFrom(

ChildAccountInfoFetcher::~ChildAccountInfoFetcher() {
}

void ChildAccountInfoFetcher::InitializeForTests() {
#if defined(OS_ANDROID)
ChildAccountInfoFetcherAndroid::InitializeForTests();
#endif
}
2 changes: 2 additions & 0 deletions components/signin/core/browser/child_account_info_fetcher.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ class ChildAccountInfoFetcher {
net::URLRequestContextGetter* request_context_getter,
invalidation::InvalidationService* invalidation_service);
virtual ~ChildAccountInfoFetcher();

static void InitializeForTests();
};

#endif // COMPONENTS_SIGNIN_CORE_BROWSER_CHILD_ACCOUNT_INFO_FETCHER_H_
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ std::unique_ptr<ChildAccountInfoFetcher> ChildAccountInfoFetcherAndroid::Create(
new ChildAccountInfoFetcherAndroid(service, account_id, account_name));
}

void ChildAccountInfoFetcherAndroid::InitializeForTests() {
Java_ChildAccountInfoFetcher_initializeForTests(
base::android::AttachCurrentThread());
}

ChildAccountInfoFetcherAndroid::ChildAccountInfoFetcherAndroid(
AccountFetcherService* service,
const std::string& account_id,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ class ChildAccountInfoFetcherAndroid : public ChildAccountInfoFetcher {
AccountFetcherService* service,
const std::string& account_id);

static void InitializeForTests();

// Register JNI methods.
static bool Register(JNIEnv* env);

Expand Down
Loading

0 comments on commit 1305003

Please sign in to comment.