Chromium Code Reviews| Index: chrome/test/android/javatests/src/org/chromium/chrome/test/util/ChromeSigninUtils.java |
| diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/ChromeSigninUtils.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/ChromeSigninUtils.java |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..5904451ebcab4d44699db5ce49063a6577b3e665 |
| --- /dev/null |
| +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/ChromeSigninUtils.java |
| @@ -0,0 +1,248 @@ |
| +// Copyright 2015 The Chromium Authors. All rights reserved. |
|
jbudorick
2015/08/04 13:42:42
I would remove references to "gaia" and just repla
|
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +package org.chromium.chrome.test.util; |
| + |
| +import android.accounts.Account; |
| +import android.accounts.AccountManager; |
| +import android.accounts.AccountManagerCallback; |
| +import android.accounts.AccountManagerFuture; |
| +import android.accounts.AuthenticatorException; |
| +import android.accounts.OperationCanceledException; |
| +import android.content.Context; |
| +import android.os.Bundle; |
| +import android.test.InstrumentationTestCase; |
| +import android.text.TextUtils; |
| + |
| +import org.chromium.sync.signin.ChromeSigninController; |
| + |
| +import java.io.IOException; |
| + |
| +/** |
| + * A tool used for running tests as signed in. |
| + */ |
| +public class ChromeSigninUtils { |
| + /** Bundle tags */ |
| + private static final String USERNAME = "username"; |
| + private static final String PASSWORD = "password"; |
| + private static final String ALLOW_SKIP = "allowSkip"; |
| + |
| + /** Information for fake OS account */ |
| + private static final String FAKE_ACCOUNT_TYPE = "com.example"; |
| + |
| + /** Information for Gaia OS account */ |
| + private static final String GOOGLE_ACCOUNT_TYPE = "com.google"; |
| + |
| + private AccountManager mAccountManager; |
| + private Context mContext; |
| + |
| + /** |
| + * The constructor for SigninUtils for a given test case. |
| + * |
| + * @param testCase the test case to perform signin operations with. |
| + */ |
| + public ChromeSigninUtils(InstrumentationTestCase testCase) { |
| + mContext = testCase.getInstrumentation().getContext(); |
| + mAccountManager = AccountManager.get(testCase.getInstrumentation().getContext()); |
|
jbudorick
2015/08/04 13:42:42
nit: AccountManager.get(mContext) as long as it st
|
| + } |
| + |
| + /** |
| + * Removes account from the app. |
| + */ |
| + public void removeAccountFromApp() { |
| + ChromeSigninController.get(mContext).clearSignedInUser(); |
|
jbudorick
2015/08/04 13:42:42
Again, I'm not sure this is the right context. I t
|
| + } |
| + |
| + /** |
| + * Checks if an existing fake account is on the app. |
| + * |
| + * @return true if fake account is signed in on app, false otherwise. |
| + */ |
| + public boolean isExistingAccountOnApp() { |
|
jbudorick
2015/08/04 13:42:42
Still not crazy about the two functions that just
|
| + return ChromeSigninController.get(mContext).isSignedIn(); |
| + } |
| + |
| + /** |
| + * Adds an account to the app. |
| + * |
| + * @param username the username for the logged in account. must be a gaia account. |
| + */ |
| + public void addAccountToApp(String username) { |
| + if (isExistingAccountOnApp()) { |
| + removeAccountFromApp(); |
| + } |
| + ChromeSigninController.get(mContext).setSignedInAccountName(username); |
| + } |
| + |
| + /** |
| + * Adds a fake account to the OS. |
| + */ |
| + public void addFakeAccountToOs(String username, String password) { |
| + addAccountToOs(username, password, FAKE_ACCOUNT_TYPE); |
| + } |
| + |
| + /** |
| + * Removes all fake accounts from the OS. |
| + */ |
| + public void removeAllFakeAccountsFromOs() { |
| + removeAllAccountsOfTypeFromOs(FAKE_ACCOUNT_TYPE); |
| + } |
| + |
| + /** |
| + * Checks if an existing fake account is on the OS. |
| + * |
| + * @return true if fake account is on OS, false otherwise. |
| + */ |
| + public boolean isExistingFakeAccountOnOs() { |
| + return mAccountManager.getAccountsByType(FAKE_ACCOUNT_TYPE).length > 0; |
| + } |
| + |
| + /** |
| + * Adds a Gaia account to the OS. |
| + * |
| + * @param username the username for the logged in account; must be a gaia account. |
| + * @param password the password for the username specified |
| + * @param gaiaAccountType the account type to log into (e.g. @gmail.com accounts use "mail") |
| + */ |
| + public void addGaiaAccountToOs(String username, String password, String gaiaAccountType) { |
| + final Bundle options = new Bundle(); |
| + options.putString(USERNAME, username); |
| + options.putString(PASSWORD, password); |
| + options.putBoolean(ALLOW_SKIP, true); |
| + |
| + AuthenticationCallback authCallback = new AuthenticationCallback(); |
| + mAccountManager.addAccount(GOOGLE_ACCOUNT_TYPE, gaiaAccountType, null, options, null, |
| + authCallback, null); |
| + |
| + Bundle authResult = authCallback.waitForAuthCompletion(); |
| + |
| + if (authResult.containsKey(AccountManager.KEY_ERROR_CODE)) { |
| + throw new IllegalStateException(String.format("AddAccount failed. Reason: %s", |
| + authResult.get(AccountManager.KEY_ERROR_MESSAGE))); |
| + } |
| + } |
| + |
| + /** |
| + * Checks to see if an existing Gaia account is on OS. |
| + * |
| + * @return {@code true} if one or more gaia accounts exists on OS, {@code false} otherwise |
| + */ |
| + public boolean isExistingGaiaAccountOnOs() { |
| + return mAccountManager.getAccountsByType(GOOGLE_ACCOUNT_TYPE).length > 0; |
| + } |
| + |
| + /** |
| + * Removes all Gaia accounts from the OS. |
| + */ |
| + public void removeAllGaiaAccountsFromOs() { |
| + removeAllAccountsOfTypeFromOs(GOOGLE_ACCOUNT_TYPE); |
| + } |
| + |
| + /** |
| + * Helper class for adding Gaia accounts to OS. |
| + * |
| + * Usage: Use this as the callback parameter when using {@link addAccount} in |
| + * {@link android.accounts.AccountManager}. |
| + */ |
| + private static class AuthenticationCallback implements AccountManagerCallback<Bundle> { |
| + private final Object mAuthenticationCompletionLock = new Object(); |
| + |
| + /** Stores the result of account authentication. Null means not finished. */ |
| + private Bundle mResultBundle = null; |
| + |
| + /** |
| + * Block and wait for the authentication callback to complete. |
| + * |
| + * @return the {@link Bundle} result from the authentication. |
| + */ |
| + public Bundle waitForAuthCompletion() { |
| + synchronized (mAuthenticationCompletionLock) { |
| + while (mResultBundle == null) { |
| + try { |
| + mAuthenticationCompletionLock.wait(); |
| + } catch (InterruptedException e) { |
| + // ignore |
| + } |
| + } |
| + return mResultBundle; |
| + } |
| + } |
| + |
| + public void run(AccountManagerFuture<Bundle> future) { |
| + Bundle resultBundle; |
| + try { |
| + resultBundle = future.getResult(); |
| + } catch (OperationCanceledException e) { |
| + resultBundle = buildExceptionBundle(e); |
| + } catch (IOException e) { |
| + resultBundle = buildExceptionBundle(e); |
| + } catch (AuthenticatorException e) { |
| + resultBundle = buildExceptionBundle(e); |
| + } |
| + synchronized (mAuthenticationCompletionLock) { |
| + mResultBundle = resultBundle; |
| + mAuthenticationCompletionLock.notify(); |
| + } |
| + } |
| + |
| + /** |
| + * Create a result bundle for a given exception. |
| + * |
| + * @param e the exception to be made into a {@link Bundle} |
| + * @return the {@link Bundle} for the given exception e. |
| + */ |
| + private Bundle buildExceptionBundle(Exception e) { |
| + Bundle bundle = new Bundle(); |
| + bundle.putInt(AccountManager.KEY_ERROR_CODE, |
| + AccountManager.ERROR_CODE_INVALID_RESPONSE); |
| + bundle.putString(AccountManager.KEY_ERROR_MESSAGE, e.toString()); |
| + return bundle; |
| + } |
| + } |
| + |
| + /** |
| + * Adds a user account. If the account already exists, we do nothing. |
| + * |
| + * @param username the username of the account. |
| + * @param password the password of the account. |
| + * @param type the type of the account. |
| + * @throws RuntimeException if the account creation fails. |
| + */ |
| + private void addAccountToOs(String username, String password, String type) { |
| + Account account = new Account(username, type); |
| + mAccountManager.addAccountExplicitly(account, password, new Bundle()); |
| + } |
| + |
| + /** |
| + * Checks if an existing account is on the OS. |
| + * |
| + * @param username the username of the account signed in (e.g. test@example.com). |
| + * @param type the type of account on the OS (e.g. com.example). |
| + * @return true if account is signed in on OS, false otherwise. |
| + * @throws IllegalArgumentException if username is empty. |
| + */ |
| + private boolean isExistingAccountOnOs(String username, String type) { |
| + if (TextUtils.isEmpty(username)) { |
|
jbudorick
2015/08/04 13:42:42
Why check here and not when adding an account? Be
|
| + throw new IllegalArgumentException("ERROR: must specify account"); |
| + } |
| + |
| + for (Account acct : mAccountManager.getAccountsByType(type)) { |
| + if (acct.name.equals(username) && acct.type.equals(type)) { |
|
jbudorick
2015/08/04 13:42:42
Does AccountManager.getAccountsByType return some
|
| + return true; |
| + } |
| + } |
| + return false; |
| + } |
| + |
| + /** |
| + * Removes all accounts of a certain type from OS. |
| + * |
| + * @param type the type of account on the OS (e.g. com.example). |
| + */ |
| + private void removeAllAccountsOfTypeFromOs(String type) { |
| + for (Account acct : mAccountManager.getAccountsByType(type)) { |
| + mAccountManager.removeAccount(acct, null, null); |
| + } |
| + } |
| +} |