| Index: sync/test/android/javatests/src/org/chromium/sync/test/util/MockAccountManager.java
|
| diff --git a/sync/test/android/javatests/src/org/chromium/sync/test/util/MockAccountManager.java b/sync/test/android/javatests/src/org/chromium/sync/test/util/MockAccountManager.java
|
| index 8c3efc9055aaf48d523040e2767f40f6d48a1358..f28f21d7c94b612ad581555cfabc6ec99ace2fe3 100644
|
| --- a/sync/test/android/javatests/src/org/chromium/sync/test/util/MockAccountManager.java
|
| +++ b/sync/test/android/javatests/src/org/chromium/sync/test/util/MockAccountManager.java
|
| @@ -8,23 +8,11 @@ import static org.chromium.base.test.util.ScalableTimeout.scaleTimeout;
|
|
|
| import android.accounts.Account;
|
| import android.accounts.AccountManager;
|
| -import android.accounts.AccountManagerCallback;
|
| -import android.accounts.AccountManagerFuture;
|
| import android.accounts.AuthenticatorDescription;
|
| -import android.accounts.AuthenticatorException;
|
| -import android.accounts.OperationCanceledException;
|
| -import android.app.Activity;
|
| -import android.content.BroadcastReceiver;
|
| -import android.content.ComponentName;
|
| import android.content.Context;
|
| import android.content.Intent;
|
| -import android.content.IntentFilter;
|
| -import android.content.pm.ActivityInfo;
|
| -import android.content.pm.PackageManager;
|
| import android.os.AsyncTask;
|
| -import android.os.Bundle;
|
| import android.os.Handler;
|
| -import android.text.TextUtils;
|
|
|
| import org.chromium.base.Callback;
|
| import org.chromium.base.Log;
|
| @@ -32,24 +20,13 @@ import org.chromium.base.VisibleForTesting;
|
| import org.chromium.sync.signin.AccountManagerDelegate;
|
| import org.chromium.sync.signin.AccountManagerHelper;
|
|
|
| -import java.io.IOException;
|
| import java.util.ArrayList;
|
| import java.util.HashSet;
|
| -import java.util.LinkedList;
|
| -import java.util.List;
|
| import java.util.Set;
|
| import java.util.UUID;
|
| -import java.util.concurrent.Callable;
|
| -import java.util.concurrent.CancellationException;
|
| -import java.util.concurrent.ExecutionException;
|
| -import java.util.concurrent.Executor;
|
| -import java.util.concurrent.FutureTask;
|
| import java.util.concurrent.LinkedBlockingDeque;
|
| import java.util.concurrent.ThreadPoolExecutor;
|
| import java.util.concurrent.TimeUnit;
|
| -import java.util.concurrent.TimeoutException;
|
| -
|
| -import javax.annotation.Nullable;
|
|
|
| /**
|
| * The MockAccountManager helps out if you want to mock out all calls to the Android AccountManager.
|
| @@ -84,8 +61,6 @@ public class MockAccountManager implements AccountManagerDelegate {
|
|
|
| private final Set<AccountHolder> mAccounts;
|
|
|
| - private final List<AccountAuthTokenPreparation> mAccountPermissionPreparations;
|
| -
|
| private final Handler mMainHandler;
|
|
|
| private final SingleThreadedExecutor mExecutor;
|
| @@ -104,7 +79,6 @@ public class MockAccountManager implements AccountManagerDelegate {
|
| mExecutor = new SingleThreadedExecutor();
|
| mGetAccountsTaskCounter = new ZeroCounter();
|
| mAccounts = new HashSet<AccountHolder>();
|
| - mAccountPermissionPreparations = new LinkedList<AccountAuthTokenPreparation>();
|
| if (accounts != null) {
|
| for (Account account : accounts) {
|
| mAccounts.add(AccountHolder.create().account(account).alwaysAccept(true).build());
|
| @@ -119,7 +93,7 @@ public class MockAccountManager implements AccountManagerDelegate {
|
| }
|
|
|
| @Override
|
| - public Account[] getAccountsByType(@Nullable String type) {
|
| + public Account[] getAccountsByType(String type) {
|
| if (!AccountManagerHelper.GOOGLE_ACCOUNT_TYPE.equals(type)) {
|
| throw new IllegalArgumentException("Invalid account type: " + type);
|
| }
|
| @@ -128,7 +102,7 @@ public class MockAccountManager implements AccountManagerDelegate {
|
| } else {
|
| ArrayList<Account> validAccounts = new ArrayList<Account>();
|
| for (AccountHolder ah : mAccounts) {
|
| - if (TextUtils.equals(ah.getAccount().type, type)) {
|
| + if (type.equals(ah.getAccount().type)) {
|
| validAccounts.add(ah.getAccount());
|
| }
|
| }
|
| @@ -208,72 +182,28 @@ public class MockAccountManager implements AccountManagerDelegate {
|
| }
|
|
|
| @Override
|
| - public AccountManagerFuture<Bundle> getAuthToken(Account account, String authTokenType,
|
| - boolean notifyAuthFailure, AccountManagerCallback<Bundle> callback, Handler handler) {
|
| - return getAuthTokenFuture(account, authTokenType, null, callback, handler);
|
| - }
|
| -
|
| - private AccountManagerFuture<Bundle> getAuthTokenFuture(Account account, String authTokenType,
|
| - Activity activity, AccountManagerCallback<Bundle> callback, Handler handler) {
|
| - final AccountHolder ah = getAccountHolder(account);
|
| - if (ah.hasBeenAccepted(authTokenType)) {
|
| - final String authToken = internalGenerateAndStoreAuthToken(ah, authTokenType);
|
| - return runTask(mExecutor,
|
| - new AccountManagerAuthTokenTask(activity, handler, callback,
|
| - account, authTokenType,
|
| - new Callable<Bundle>() {
|
| - @Override
|
| - public Bundle call() throws Exception {
|
| - return getAuthTokenBundle(ah.getAccount(), authToken);
|
| - }
|
| - }));
|
| - } else {
|
| - Log.d(TAG, "getAuthTokenFuture: Account " + ah.getAccount()
|
| - + " is asking for permission for " + authTokenType);
|
| - final Intent intent = newGrantCredentialsPermissionIntent(
|
| - activity != null, account, authTokenType);
|
| - return runTask(mExecutor,
|
| - new AccountManagerAuthTokenTask(activity, handler, callback,
|
| - account, authTokenType,
|
| - new Callable<Bundle>() {
|
| - @Override
|
| - public Bundle call() throws Exception {
|
| - Bundle result = new Bundle();
|
| - result.putParcelable(AccountManager.KEY_INTENT, intent);
|
| - return result;
|
| - }
|
| - }));
|
| - }
|
| - }
|
| -
|
| - private static Bundle getAuthTokenBundle(Account account, String authToken) {
|
| - Bundle result = new Bundle();
|
| - result.putString(AccountManager.KEY_AUTHTOKEN, authToken);
|
| - result.putString(AccountManager.KEY_ACCOUNT_NAME, account.name);
|
| - result.putString(AccountManager.KEY_ACCOUNT_TYPE, account.type);
|
| - return result;
|
| - }
|
| -
|
| - private String internalGenerateAndStoreAuthToken(AccountHolder ah, String authTokenType) {
|
| + public String getAuthToken(Account account, String authTokenScope) {
|
| + AccountHolder ah = getAccountHolder(account);
|
| + assert ah.hasBeenAccepted(authTokenScope);
|
| synchronized (mAccounts) {
|
| // Some tests register auth tokens with value null, and those should be preserved.
|
| - if (!ah.hasAuthTokenRegistered(authTokenType)
|
| - && ah.getAuthToken(authTokenType) == null) {
|
| + if (!ah.hasAuthTokenRegistered(authTokenScope)
|
| + && ah.getAuthToken(authTokenScope) == null) {
|
| // No authtoken registered. Need to create one.
|
| String authToken = UUID.randomUUID().toString();
|
| - Log.d(TAG, "Created new auth token for " + ah.getAccount()
|
| - + ": autTokenType = " + authTokenType + ", authToken = " + authToken);
|
| - ah = ah.withAuthToken(authTokenType, authToken);
|
| + Log.d(TAG, "Created new auth token for " + ah.getAccount() + ": authTokenScope = "
|
| + + authTokenScope + ", authToken = " + authToken);
|
| + ah = ah.withAuthToken(authTokenScope, authToken);
|
| mAccounts.add(ah);
|
| }
|
| }
|
| - return ah.getAuthToken(authTokenType);
|
| + return ah.getAuthToken(authTokenScope);
|
| }
|
|
|
| @Override
|
| - public void invalidateAuthToken(String accountType, String authToken) {
|
| - if (!AccountManagerHelper.GOOGLE_ACCOUNT_TYPE.equals(accountType)) {
|
| - throw new IllegalArgumentException("Invalid account type: " + accountType);
|
| + public void invalidateAuthToken(String accountScope, String authToken) {
|
| + if (!AccountManagerHelper.GOOGLE_ACCOUNT_TYPE.equals(accountScope)) {
|
| + throw new IllegalArgumentException("Invalid account type: " + accountScope);
|
| }
|
| if (authToken == null) {
|
| throw new IllegalArgumentException("AuthToken can not be null");
|
| @@ -313,74 +243,6 @@ public class MockAccountManager implements AccountManagerDelegate {
|
| });
|
| }
|
|
|
| - public void notifyFeaturesFetched(Account account, Set<String> features) {
|
| - getAccountHolder(account).didFetchFeatures(features);
|
| - }
|
| -
|
| - public void prepareAllowAppPermission(Account account, String authTokenType) {
|
| - addPreparedAppPermission(new AccountAuthTokenPreparation(account, authTokenType, true));
|
| - }
|
| -
|
| - public void prepareDenyAppPermission(Account account, String authTokenType) {
|
| - addPreparedAppPermission(new AccountAuthTokenPreparation(account, authTokenType, false));
|
| - }
|
| -
|
| - private void addPreparedAppPermission(AccountAuthTokenPreparation accountAuthTokenPreparation) {
|
| - Log.d(TAG, "Adding " + accountAuthTokenPreparation);
|
| - mAccountPermissionPreparations.add(accountAuthTokenPreparation);
|
| - }
|
| -
|
| - private AccountAuthTokenPreparation getPreparedPermission(Account account,
|
| - String authTokenType) {
|
| - for (AccountAuthTokenPreparation accountPrep : mAccountPermissionPreparations) {
|
| - if (accountPrep.getAccount().equals(account)
|
| - && accountPrep.getAuthTokenType().equals(authTokenType)) {
|
| - return accountPrep;
|
| - }
|
| - }
|
| - return null;
|
| - }
|
| -
|
| - private void applyPreparedPermission(AccountAuthTokenPreparation prep) {
|
| - if (prep != null) {
|
| - Log.d(TAG, "Applying " + prep);
|
| - mAccountPermissionPreparations.remove(prep);
|
| - mAccounts.add(getAccountHolder(prep.getAccount()).withHasBeenAccepted(
|
| - prep.getAuthTokenType(), prep.isAllowed()));
|
| - }
|
| - }
|
| -
|
| - private Intent newGrantCredentialsPermissionIntent(boolean hasActivity, Account account,
|
| - String authTokenType) {
|
| - ComponentName component = new ComponentName(mTestContext,
|
| - MockGrantCredentialsPermissionActivity.class.getCanonicalName());
|
| -
|
| - // Make sure we can start the activity.
|
| - ActivityInfo ai = null;
|
| - try {
|
| - ai = mContext.getPackageManager().getActivityInfo(component, 0);
|
| - } catch (PackageManager.NameNotFoundException e) {
|
| - throw new IllegalStateException(
|
| - "Unable to find " + component.getClassName());
|
| - }
|
| - if (ai.applicationInfo != mContext.getApplicationInfo() && !ai.exported) {
|
| - throw new IllegalStateException(
|
| - "Unable to start " + ai.name + ". "
|
| - + "The accounts you added to MockAccountManager may not be "
|
| - + "configured correctly.");
|
| - }
|
| -
|
| - Intent intent = new Intent();
|
| - intent.setComponent(component);
|
| - intent.putExtra(MockGrantCredentialsPermissionActivity.ACCOUNT, account);
|
| - intent.putExtra(MockGrantCredentialsPermissionActivity.AUTH_TOKEN_TYPE, authTokenType);
|
| - if (!hasActivity) {
|
| - // No activity provided, so we help the caller by adding the new task flag
|
| - intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
| - }
|
| - return intent;
|
| - }
|
| -
|
| private AccountHolder getAccountHolder(Account account) {
|
| if (account == null) {
|
| throw new IllegalArgumentException("Account can not be null");
|
| @@ -393,216 +255,6 @@ public class MockAccountManager implements AccountManagerDelegate {
|
| throw new IllegalArgumentException("Can not find AccountHolder for account " + account);
|
| }
|
|
|
| - private static <T> AccountManagerFuture<T> runTask(Executor executorService,
|
| - AccountManagerTask<T> accountManagerBundleTask) {
|
| - executorService.execute(accountManagerBundleTask);
|
| - return accountManagerBundleTask;
|
| - }
|
| -
|
| - private class AccountManagerTask<T> extends FutureTask<T> implements AccountManagerFuture<T> {
|
| -
|
| - protected final Handler mHandler;
|
| -
|
| - protected final AccountManagerCallback<T> mCallback;
|
| -
|
| - protected final Callable<T> mCallable;
|
| -
|
| - public AccountManagerTask(Handler handler,
|
| - AccountManagerCallback<T> callback, Callable<T> callable) {
|
| - super(new Callable<T>() {
|
| - @Override
|
| - public T call() throws Exception {
|
| - throw new IllegalStateException("this should never be called, "
|
| - + "but call must be overridden.");
|
| - }
|
| - });
|
| - mHandler = handler;
|
| - mCallback = callback;
|
| - mCallable = callable;
|
| - }
|
| -
|
| - private T internalGetResult(long timeout, TimeUnit unit)
|
| - throws OperationCanceledException, IOException, AuthenticatorException {
|
| - try {
|
| - if (timeout == -1) {
|
| - return get();
|
| - } else {
|
| - return get(timeout, unit);
|
| - }
|
| - } catch (CancellationException e) {
|
| - throw new OperationCanceledException();
|
| - } catch (TimeoutException e) {
|
| - // Fall through and cancel.
|
| - } catch (InterruptedException e) {
|
| - // Fall through and cancel.
|
| - } catch (ExecutionException e) {
|
| - final Throwable cause = e.getCause();
|
| - if (cause instanceof IOException) {
|
| - throw (IOException) cause;
|
| - } else if (cause instanceof UnsupportedOperationException) {
|
| - throw new AuthenticatorException(cause);
|
| - } else if (cause instanceof AuthenticatorException) {
|
| - throw (AuthenticatorException) cause;
|
| - } else if (cause instanceof RuntimeException) {
|
| - throw (RuntimeException) cause;
|
| - } else if (cause instanceof Error) {
|
| - throw (Error) cause;
|
| - } else {
|
| - throw new IllegalStateException(cause);
|
| - }
|
| - } finally {
|
| - cancel(true /* Interrupt if running. */);
|
| - }
|
| - throw new OperationCanceledException();
|
| - }
|
| -
|
| - @Override
|
| - public T getResult()
|
| - throws OperationCanceledException, IOException, AuthenticatorException {
|
| - return internalGetResult(-1, null);
|
| - }
|
| -
|
| - @Override
|
| - public T getResult(long timeout, TimeUnit unit)
|
| - throws OperationCanceledException, IOException, AuthenticatorException {
|
| - return internalGetResult(timeout, unit);
|
| - }
|
| -
|
| - @Override
|
| - public void run() {
|
| - try {
|
| - set(mCallable.call());
|
| - } catch (Exception e) {
|
| - setException(e);
|
| - }
|
| - }
|
| -
|
| - @Override
|
| - protected void done() {
|
| - if (mCallback != null) {
|
| - postToHandler(getHandler(), mCallback, this);
|
| - }
|
| - }
|
| -
|
| - private Handler getHandler() {
|
| - return mHandler == null ? mMainHandler : mHandler;
|
| - }
|
| -
|
| - }
|
| -
|
| - private static <T> void postToHandler(Handler handler, final AccountManagerCallback<T> callback,
|
| - final AccountManagerFuture<T> future) {
|
| - handler.post(new Runnable() {
|
| - @Override
|
| - public void run() {
|
| - callback.run(future);
|
| - }
|
| - });
|
| - }
|
| -
|
| - private class AccountManagerAuthTokenTask extends AccountManagerTask<Bundle> {
|
| -
|
| - private final Activity mActivity;
|
| -
|
| - private final AccountAuthTokenPreparation mAccountAuthTokenPreparation;
|
| -
|
| - private final Account mAccount;
|
| -
|
| - private final String mAuthTokenType;
|
| -
|
| - public AccountManagerAuthTokenTask(Activity activity, Handler handler,
|
| - AccountManagerCallback<Bundle> callback,
|
| - Account account, String authTokenType,
|
| - Callable<Bundle> callable) {
|
| - super(handler, callback, callable);
|
| - mActivity = activity;
|
| - mAccountAuthTokenPreparation = getPreparedPermission(account, authTokenType);
|
| - mAccount = account;
|
| - mAuthTokenType = authTokenType;
|
| - }
|
| -
|
| - @Override
|
| - public void run() {
|
| - try {
|
| - Bundle bundle = mCallable.call();
|
| - Intent intent = bundle.getParcelable(AccountManager.KEY_INTENT);
|
| - if (intent != null) {
|
| - // Start the intent activity and wait for it to finish.
|
| - if (mActivity != null) {
|
| - waitForActivity(mActivity, intent);
|
| - } else {
|
| - waitForActivity(mContext, intent);
|
| - }
|
| - if (mAccountAuthTokenPreparation == null) {
|
| - throw new IllegalStateException("No account preparation ready for "
|
| - + mAccount + ", authTokenType = " + mAuthTokenType
|
| - + ". Add a call to either prepareGrantAppPermission(...) or "
|
| - + "prepareRevokeAppPermission(...) in your test before asking for "
|
| - + "an auth token");
|
| - } else {
|
| - // We have shown the Allow/Deny activity, and it has gone away. We can now
|
| - // apply the pre-stored permission.
|
| - applyPreparedPermission(mAccountAuthTokenPreparation);
|
| - generateResult(getAccountHolder(mAccount), mAuthTokenType);
|
| - }
|
| - } else {
|
| - set(bundle);
|
| - }
|
| - } catch (Exception e) {
|
| - setException(e);
|
| - }
|
| - }
|
| -
|
| - private void generateResult(AccountHolder accountHolder, String authTokenType)
|
| - throws OperationCanceledException {
|
| - if (accountHolder.hasBeenAccepted(authTokenType)) {
|
| - String authToken = internalGenerateAndStoreAuthToken(accountHolder, authTokenType);
|
| - // Return a valid auth token.
|
| - set(getAuthTokenBundle(accountHolder.getAccount(), authToken));
|
| - } else {
|
| - // Throw same exception as when user clicks "Deny".
|
| - throw new OperationCanceledException("User denied request");
|
| - }
|
| - }
|
| - }
|
| -
|
| - /**
|
| - * This method starts {@link MockGrantCredentialsPermissionActivity} and waits for it
|
| - * to be started before it returns.
|
| - *
|
| - * @param context the context to start the intent in
|
| - * @param intent the intent to use to start MockGrantCredentialsPermissionActivity
|
| - */
|
| - @SuppressWarnings("WaitNotInLoop")
|
| - private void waitForActivity(Context context, Intent intent) {
|
| - final Object mutex = new Object();
|
| - BroadcastReceiver receiver = new BroadcastReceiver() {
|
| - @Override
|
| - public void onReceive(Context context, Intent intent) {
|
| - synchronized (mutex) {
|
| - mutex.notifyAll();
|
| - }
|
| - }
|
| - };
|
| - if (!MockGrantCredentialsPermissionActivity.class.getCanonicalName()
|
| - .equals(intent.getComponent().getClassName())) {
|
| - throw new IllegalArgumentException("Can only wait for "
|
| - + "MockGrantCredentialsPermissionActivity");
|
| - }
|
| - mContext.registerReceiver(receiver, new IntentFilter(MUTEX_WAIT_ACTION));
|
| - context.startActivity(intent);
|
| - try {
|
| - Log.d(TAG, "Waiting for broadcast of " + MUTEX_WAIT_ACTION);
|
| - synchronized (mutex) {
|
| - mutex.wait(WAIT_TIME_FOR_GRANT_BROADCAST_MS);
|
| - }
|
| - } catch (InterruptedException e) {
|
| - throw new IllegalStateException("Got unexpected InterruptedException");
|
| - }
|
| - Log.d(TAG, "Got broadcast of " + MUTEX_WAIT_ACTION);
|
| - mContext.unregisterReceiver(receiver);
|
| - }
|
| -
|
| private void postAsyncAccountChangedEvent() {
|
| // Mimic that this does not happen on the main thread.
|
| new AsyncTask<Void, Void, Void>() {
|
| @@ -615,49 +267,6 @@ public class MockAccountManager implements AccountManagerDelegate {
|
| }
|
|
|
| /**
|
| - * Internal class for storage of prepared account auth token permissions.
|
| - *
|
| - * This is used internally by {@link MockAccountManager} to mock the same behavior as clicking
|
| - * Allow/Deny in the Android {@link GrantCredentialsPermissionActivity}.
|
| - */
|
| - private static class AccountAuthTokenPreparation {
|
| -
|
| - private final Account mAccount;
|
| -
|
| - private final String mAuthTokenType;
|
| -
|
| - private final boolean mAllowed;
|
| -
|
| - private AccountAuthTokenPreparation(Account account, String authTokenType,
|
| - boolean allowed) {
|
| - mAccount = account;
|
| - mAuthTokenType = authTokenType;
|
| - mAllowed = allowed;
|
| - }
|
| -
|
| - public Account getAccount() {
|
| - return mAccount;
|
| - }
|
| -
|
| - public String getAuthTokenType() {
|
| - return mAuthTokenType;
|
| - }
|
| -
|
| - public boolean isAllowed() {
|
| - return mAllowed;
|
| - }
|
| -
|
| - @Override
|
| - public String toString() {
|
| - return "AccountAuthTokenPreparation{"
|
| - + "mAccount=" + mAccount
|
| - + ", mAuthTokenType='" + mAuthTokenType + '\''
|
| - + ", mAllowed=" + mAllowed
|
| - + '}';
|
| - }
|
| - }
|
| -
|
| - /**
|
| * Simple concurrency helper class for waiting until a resource count becomes zero.
|
| */
|
| private static class ZeroCounter {
|
|
|