AndroidProfileOAuth2TokenServiceHelper.java revision 68043e1e95eeb07d5cae7aca370b26518b0867d6
17dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// Copyright 2013 The Chromium Authors. All rights reserved. 27dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// Use of this source code is governed by a BSD-style license that can be 37dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// found in the LICENSE file. 47dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 57dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochpackage org.chromium.chrome.browser.signin; 67dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 77dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochimport android.accounts.Account; 87dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochimport android.app.Activity; 97dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochimport android.content.Context; 107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochimport android.util.Log; 117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochimport org.chromium.base.CalledByNative; 137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochimport org.chromium.base.ThreadUtils; 147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochimport org.chromium.sync.signin.AccountManagerHelper; 157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 16a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)import java.util.concurrent.Semaphore; 177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochimport java.util.concurrent.TimeUnit; 18a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)import java.util.concurrent.atomic.AtomicReference; 19a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochimport javax.annotation.Nullable; 217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch/** 237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * Helper class for working with access tokens from native code. 247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * <p/> 257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * This class forwards calls to request or invalidate access tokens made by native code to 267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * AccountManagerHelper and forwards callbacks to native code. 277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * <p/> 287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch */ 29a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)public final class AndroidProfileOAuth2TokenServiceHelper { 307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch private static final String TAG = "AndroidProfileOAuth2TokenServiceHelper"; 327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch private static final String OAUTH2_SCOPE_PREFIX = "oauth2:"; 347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 35a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) private AndroidProfileOAuth2TokenServiceHelper() { 36a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 37a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch private static Account getAccountOrNullFromUsername(Context context, String username) { 397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (username == null) { 407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch Log.e(TAG, "Username is null"); 417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return null; 427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch AccountManagerHelper accountManagerHelper = AccountManagerHelper.get(context); 457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch Account account = accountManagerHelper.getAccountFromName(username); 467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (account == null) { 477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch Log.e(TAG, "Account not found for provided username."); 487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return null; 497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return account; 517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch /** 5468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) * Called by native to list the accounts with OAuth2 refresh tokens. 5568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) */ 5668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) @CalledByNative 5768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) public static String[] getAccounts(Context context) { 5868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) AccountManagerHelper accountManagerHelper = AccountManagerHelper.get(context); 5968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) java.util.List<String> accountNames = accountManagerHelper.getGoogleAccountNames(); 6068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return accountNames.toArray(new String[accountNames.size()]); 6168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 6268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 6368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) /** 647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * Called by native to retrieve OAuth2 tokens. 657dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * 667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * @param username The native username (full address). 677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * @param scope The scope to get an auth token for (without Android-style 'oauth2:' prefix). 687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * @param nativeCallback The pointer to the native callback that should be run upon completion. 697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch */ 707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch @CalledByNative 717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch public static void getOAuth2AuthToken( 727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch Context context, String username, String scope, final int nativeCallback) { 737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch Account account = getAccountOrNullFromUsername(context, username); 747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (account == null) { 757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch nativeOAuth2TokenFetched(null, false, nativeCallback); 767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return; 777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch String oauth2Scope = OAUTH2_SCOPE_PREFIX + scope; 797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch AccountManagerHelper accountManagerHelper = AccountManagerHelper.get(context); 817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch accountManagerHelper.getAuthTokenFromForeground( 827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch null, account, oauth2Scope, new AccountManagerHelper.GetAuthTokenCallback() { 837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch @Override 847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch public void tokenAvailable(String token) { 857dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch nativeOAuth2TokenFetched( 867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch token, token != null, nativeCallback); 877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch }); 897dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 907dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 917dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch /** 927dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * Call this method to retrieve an OAuth2 access token for the given account and scope. 937dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * 947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * @param activity the current activity. May be null. 957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * @param account the account to get the access token for. 967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * @param scope The scope to get an auth token for (without Android-style 'oauth2:' prefix). 977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * @param callback called on successful and unsuccessful fetching of auth token. 987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch */ 997dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch public static void getOAuth2AccessToken(Context context, @Nullable Activity activity, 1007dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch Account account, String scope, 1017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch AccountManagerHelper.GetAuthTokenCallback callback) { 1027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch String oauth2Scope = OAUTH2_SCOPE_PREFIX + scope; 1037dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch AccountManagerHelper.get(context).getAuthTokenFromForeground( 1047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch activity, account, oauth2Scope, callback); 1057dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 1067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 1077dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch /** 1087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * Call this method to retrieve an OAuth2 access token for the given account and scope. This 1097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * method times out after the specified timeout, and will return null if that happens. 1107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * 1117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * Given that this is a blocking method call, this should never be called from the UI thread. 1127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * 1137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * @param activity the current activity. May be null. 1147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * @param account the account to get the access token for. 1157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * @param scope The scope to get an auth token for (without Android-style 'oauth2:' prefix). 1167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * @param timeout the timeout. 1177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * @param unit the unit for |timeout|. 1187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch */ 1197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch public static String getOAuth2AccessTokenWithTimeout( 1207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch Context context, @Nullable Activity activity, Account account, String scope, 1217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch long timeout, TimeUnit unit) { 1227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch assert !ThreadUtils.runningOnUiThread(); 123a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) final AtomicReference<String> result = new AtomicReference<String>(); 124a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) final Semaphore semaphore = new Semaphore(0); 1257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch getOAuth2AccessToken( 1267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch context, activity, account, scope, 1277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch new AccountManagerHelper.GetAuthTokenCallback() { 1287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch @Override 1297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch public void tokenAvailable(String token) { 130a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) result.set(token); 131a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) semaphore.release(); 1327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 1337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch }); 1347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch try { 135a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (semaphore.tryAcquire(timeout, unit)) { 136a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return result.get(); 137a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } else { 138a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) Log.d(TAG, "Failed to retrieve auth token within timeout (" + 139a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) timeout + " + " + unit.name() + ")"); 140a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return null; 141a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 1427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } catch (InterruptedException e) { 1437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch Log.w(TAG, "Got interrupted while waiting for auth token"); 1447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return null; 1457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 1467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 1477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 1487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch /** 14968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) * Called by native to check wether the account has an OAuth2 refresh token. 15068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) */ 15168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) @CalledByNative 15268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) public static boolean hasOAuth2RefreshToken(Context context, String accountName) { 15368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return AccountManagerHelper.get(context).hasAccountForName(accountName); 15468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 15568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 15668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) /** 1577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * Called by native to invalidate an OAuth2 token. 1587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch */ 1597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch @CalledByNative 1607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch public static void invalidateOAuth2AuthToken(Context context, String accessToken) { 1617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (accessToken != null) { 1627dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch AccountManagerHelper.get(context).invalidateAuthToken(accessToken); 1637dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 1647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 1657dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 1667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch private static native void nativeOAuth2TokenFetched( 1677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch String authToken, boolean result, int nativeCallback); 1687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 1697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 170