diff options
Diffstat (limited to 'sync/test/android/javatests/src/org/chromium/sync/test/util/MockAccountManager.java')
-rw-r--r-- | sync/test/android/javatests/src/org/chromium/sync/test/util/MockAccountManager.java | 419 |
1 files changed, 14 insertions, 405 deletions
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 8c3efc9..f28f21d 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 { |