AccountManagerHelper.java revision 7dbb3d5cf0c15f500944d211057644d6a2f37371
12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2011 The Chromium Authors. All rights reserved. 22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file. 42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)package org.chromium.sync.signin; 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import com.google.common.annotations.VisibleForTesting; 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import android.accounts.Account; 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import android.accounts.AccountManager; 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import android.accounts.AccountManagerFuture; 13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import android.accounts.AuthenticatorDescription; 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import android.accounts.AuthenticatorException; 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import android.accounts.OperationCanceledException; 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import android.app.Activity; 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import android.content.Context; 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import android.content.Intent; 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import android.os.AsyncTask; 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import android.os.Bundle; 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import android.util.Log; 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import org.chromium.net.NetworkChangeNotifier; 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import java.io.IOException; 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import java.util.ArrayList; 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import java.util.concurrent.atomic.AtomicBoolean; 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import java.util.concurrent.atomic.AtomicInteger; 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import java.util.List; 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import javax.annotation.Nullable; 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/** 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * AccountManagerHelper wraps our access of AccountManager in Android. 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Use the AccountManagerHelper.get(someContext) to instantiate it 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)public class AccountManagerHelper { 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private static final String TAG = "AccountManagerHelper"; 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public static final String GOOGLE_ACCOUNT_TYPE = "com.google"; 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private static final Object lock = new Object(); 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private static final int MAX_TRIES = 3; 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private static AccountManagerHelper sAccountManagerHelper; 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private final AccountManagerDelegate mAccountManager; 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private Context mApplicationContext; 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public interface GetAuthTokenCallback { 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) /** 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Invoked on the UI thread once a token has been provided by the AccountManager. 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @param token Auth token, or null if no token is available (bad credentials, 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * permission denied, etc). 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void tokenAvailable(String token); 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) /** 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @param context the Android context 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @param accountManager the account manager to use as a backend service 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private AccountManagerHelper(Context context, 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AccountManagerDelegate accountManager) { 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) mApplicationContext = context.getApplicationContext(); 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) mAccountManager = accountManager; 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) /** 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * A factory method for the AccountManagerHelper. 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * It is possible to override the AccountManager to use in tests for the instance of the 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * AccountManagerHelper by calling overrideAccountManagerHelperForTests(...) with 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * your MockAccountManager. 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @param context the applicationContext is retrieved from the context used as an argument. 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @return a singleton instance of the AccountManagerHelper 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public static AccountManagerHelper get(Context context) { 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) synchronized (lock) { 842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (sAccountManagerHelper == null) { 852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sAccountManagerHelper = new AccountManagerHelper(context, 862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) new SystemAccountManagerDelegate(context)); 872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return sAccountManagerHelper; 902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) @VisibleForTesting 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public static void overrideAccountManagerHelperForTests(Context context, 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AccountManagerDelegate accountManager) { 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) synchronized (lock) { 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sAccountManagerHelper = new AccountManagerHelper(context, accountManager); 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) /** 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Creates an Account object for the given name. 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public static Account createAccountFromName(String name) { 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return new Account(name, GOOGLE_ACCOUNT_TYPE); 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public List<String> getGoogleAccountNames() { 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) List<String> accountNames = new ArrayList<String>(); 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Account[] accounts = mAccountManager.getAccountsByType(GOOGLE_ACCOUNT_TYPE); 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (Account account : accounts) { 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) accountNames.add(account.name); 1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return accountNames; 1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public Account[] getGoogleAccounts() { 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return mAccountManager.getAccountsByType(GOOGLE_ACCOUNT_TYPE); 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public boolean hasGoogleAccounts() { 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return getGoogleAccounts().length > 0; 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) /** 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Returns the account if it exists, null otherwise. 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public Account getAccountFromName(String accountName) { 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Account[] accounts = mAccountManager.getAccountsByType(GOOGLE_ACCOUNT_TYPE); 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (Account account : accounts) { 1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (account.name.equals(accountName)) { 1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return account; 1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return null; 1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) /** 138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * @return Whether or not there is an account authenticator for Google accounts. 139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */ 140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public boolean hasGoogleAccountAuthenticator() { 141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) AuthenticatorDescription[] descs = mAccountManager.getAuthenticatorTypes(); 142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) for (AuthenticatorDescription desc : descs) { 143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (GOOGLE_ACCOUNT_TYPE.equals(desc.type)) return true; 144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return false; 146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) /** 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Gets the auth token synchronously. 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * 1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * - Assumes that the account is a valid account. 1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * - Should not be called on the main thread. 1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) @Deprecated 1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public String getAuthTokenFromBackground(Account account, String authTokenType) { 1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AccountManagerFuture<Bundle> future = mAccountManager.getAuthToken(account, 1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) authTokenType, false, null, null); 1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AtomicBoolean errorEncountered = new AtomicBoolean(false); 1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return getAuthTokenInner(future, errorEncountered); 1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) /** 1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Gets the auth token and returns the response asynchronously. 1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * This should be called when we have a foreground activity that needs an auth token. 1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * If encountered an IO error, it will attempt to retry when the network is back. 1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * 1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * - Assumes that the account is a valid account. 1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public void getAuthTokenFromForeground(Activity activity, Account account, String authTokenType, 1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GetAuthTokenCallback callback) { 1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AtomicInteger numTries = new AtomicInteger(0); 1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AtomicBoolean errorEncountered = new AtomicBoolean(false); 1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) getAuthTokenAsynchronously(activity, account, authTokenType, callback, numTries, 1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) errorEncountered, null); 1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private class ConnectionRetry implements NetworkChangeNotifier.ConnectionTypeObserver { 1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private final Account mAccount; 1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private final String mAuthTokenType; 1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private final GetAuthTokenCallback mCallback; 1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private final AtomicInteger mNumTries; 1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private final AtomicBoolean mErrorEncountered; 1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ConnectionRetry(Account account, String authTokenType, GetAuthTokenCallback callback, 1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AtomicInteger numTries, AtomicBoolean errorEncountered) { 1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) mAccount = account; 1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) mAuthTokenType = authTokenType; 1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) mCallback = callback; 1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) mNumTries = numTries; 1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) mErrorEncountered = errorEncountered; 1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) @Override 1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public void onConnectionTypeChanged(int connectionType) { 1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) assert mNumTries.get() <= MAX_TRIES; 1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (mNumTries.get() == MAX_TRIES) { 1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NetworkChangeNotifier.removeConnectionTypeObserver(this); 1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (NetworkChangeNotifier.isOnline()) { 2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NetworkChangeNotifier.removeConnectionTypeObserver(this); 2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) getAuthTokenAsynchronously(null, mAccount, mAuthTokenType, mCallback, mNumTries, 2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) mErrorEncountered, this); 2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Gets the auth token synchronously 2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private String getAuthTokenInner(AccountManagerFuture<Bundle> future, 2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AtomicBoolean errorEncountered) { 2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) try { 2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Bundle result = future.getResult(); 2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (result != null) { 2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (result.containsKey(AccountManager.KEY_INTENT)) { 2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Log.d(TAG, "Starting intent to get auth credentials"); 2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Need to start intent to get credentials 2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Intent intent = result.getParcelable(AccountManager.KEY_INTENT); 2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int flags = intent.getFlags(); 2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) flags |= Intent.FLAG_ACTIVITY_NEW_TASK; 2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) intent.setFlags(flags); 2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) mApplicationContext.startActivity(intent); 2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return null; 2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return result.getString(AccountManager.KEY_AUTHTOKEN); 2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Log.w(TAG, "Auth token - getAuthToken returned null"); 2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } catch (OperationCanceledException e) { 2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Log.w(TAG, "Auth token - operation cancelled", e); 2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } catch (AuthenticatorException e) { 2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Log.w(TAG, "Auth token - authenticator exception", e); 2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } catch (IOException e) { 2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Log.w(TAG, "Auth token - IO exception", e); 2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) errorEncountered.set(true); 2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return null; 2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private void getAuthTokenAsynchronously(@Nullable Activity activity, final Account account, 2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) final String authTokenType, final GetAuthTokenCallback callback, 2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) final AtomicInteger numTries, final AtomicBoolean errorEncountered, 2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) final ConnectionRetry retry) { 2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AccountManagerFuture<Bundle> future; 2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (numTries.get() == 0 && activity != null) { 2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) future = mAccountManager.getAuthToken( 2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) account, authTokenType, null, activity, null, null); 2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) future = mAccountManager.getAuthToken( 2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) account, authTokenType, false, null, null); 2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) final AccountManagerFuture<Bundle> finalFuture = future; 2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) errorEncountered.set(false); 2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) new AsyncTask<Void, Void, String>() { 2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) @Override 2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public String doInBackground(Void... params) { 2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return getAuthTokenInner(finalFuture, errorEncountered); 2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) @Override 2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public void onPostExecute(String authToken) { 2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (authToken != null || !errorEncountered.get() || 261c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) numTries.incrementAndGet() == MAX_TRIES || 262c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) !NetworkChangeNotifier.isInitialized()) { 2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) callback.tokenAvailable(authToken); 2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (retry == null) { 2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ConnectionRetry newRetry = new ConnectionRetry(account, authTokenType, callback, 2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) numTries, errorEncountered); 2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NetworkChangeNotifier.addConnectionTypeObserver(newRetry); 2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) else { 2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NetworkChangeNotifier.addConnectionTypeObserver(retry); 2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) }.execute(); 2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) /** 2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Invalidates the old token (if non-null/non-empty) and synchronously generates a new one. 2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Also notifies the user (via status bar) if any user action is required. The method will 2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * return null if any user action is required to generate the new token. 2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * 2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * - Assumes that the account is a valid account. 2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * - Should not be called on the main thread. 2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) @Deprecated 2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public String getNewAuthToken(Account account, String authToken, String authTokenType) { 2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(dsmyers): consider reimplementing using an AccountManager function with an 2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // explicit timeout. 2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Bug: https://code.google.com/p/chromium/issues/detail?id=172394. 2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (authToken != null && !authToken.isEmpty()) { 2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) mAccountManager.invalidateAuthToken(GOOGLE_ACCOUNT_TYPE, authToken); 2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) try { 2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return mAccountManager.blockingGetAuthToken(account, authTokenType, true); 2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } catch (OperationCanceledException e) { 2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Log.w(TAG, "Auth token - operation cancelled", e); 2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } catch (AuthenticatorException e) { 3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Log.w(TAG, "Auth token - authenticator exception", e); 3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } catch (IOException e) { 3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Log.w(TAG, "Auth token - IO exception", e); 3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return null; 3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) /** 3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Invalidates the old token (if non-null/non-empty) and asynchronously generates a new one. 3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * 3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * - Assumes that the account is a valid account. 3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public void getNewAuthTokenFromForeground(Account account, String authToken, 3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) String authTokenType, GetAuthTokenCallback callback) { 3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (authToken != null && !authToken.isEmpty()) { 3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) mAccountManager.invalidateAuthToken(GOOGLE_ACCOUNT_TYPE, authToken); 3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AtomicInteger numTries = new AtomicInteger(0); 3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AtomicBoolean errorEncountered = new AtomicBoolean(false); 3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) getAuthTokenAsynchronously( 3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) null, account, authTokenType, callback, numTries, errorEncountered, null); 3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 322c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 323c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) /** 324c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * Removes an auth token from the AccountManager's cache. 325c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */ 3267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch public void invalidateAuthToken(String authToken) { 3277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch mAccountManager.invalidateAuthToken(GOOGLE_ACCOUNT_TYPE, authToken); 328c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 330