14e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 24e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 34e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// found in the LICENSE file. 44e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 54e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)package org.chromium.chrome.browser.signin; 64e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 74e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)import android.accounts.Account; 84e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)import android.app.Activity; 94e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)import android.content.Context; 105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuimport android.preference.PreferenceManager; 114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)import android.util.Log; 124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)import org.chromium.base.CalledByNative; 144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)import org.chromium.base.ObserverList; 154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)import org.chromium.base.ThreadUtils; 161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport org.chromium.base.VisibleForTesting; 174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)import org.chromium.chrome.browser.profiles.Profile; 184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)import org.chromium.sync.signin.AccountManagerHelper; 194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)import org.chromium.sync.signin.ChromeSigninController; 204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuimport java.util.Arrays; 22f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)import java.util.HashSet; 23f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)import java.util.Set; 244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)import java.util.concurrent.Semaphore; 254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)import java.util.concurrent.TimeUnit; 264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)import java.util.concurrent.atomic.AtomicReference; 274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)import javax.annotation.Nullable; 294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)/** 314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * Java instance for the native OAuth2TokenService. 324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * <p/> 334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * This class forwards calls to request or invalidate access tokens made by native code to 344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * AccountManagerHelper and forwards callbacks to native code. 354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * <p/> 364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) */ 374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)public final class OAuth2TokenService { 384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) private static final String TAG = "OAuth2TokenService"; 404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu @VisibleForTesting 425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu public static final String STORED_ACCOUNTS_KEY = "google.services.stored_accounts"; 435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 44f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) /** 45f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * Classes that want to listen for refresh token availability should 46f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * implement this interface and register with {@link #addObserver}. 47f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) public interface OAuth2TokenServiceObserver { 494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) void onRefreshTokenAvailable(Account account); 504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) void onRefreshTokenRevoked(Account account); 514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) void onRefreshTokensLoaded(); 524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) private static final String OAUTH2_SCOPE_PREFIX = "oauth2:"; 554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 56f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private final long mNativeProfileOAuth2TokenService; 574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) private final ObserverList<OAuth2TokenServiceObserver> mObservers; 584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 59f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private OAuth2TokenService(long nativeOAuth2Service) { 604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) mNativeProfileOAuth2TokenService = nativeOAuth2Service; 614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) mObservers = new ObserverList<OAuth2TokenServiceObserver>(); 624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) public static OAuth2TokenService getForProfile(Profile profile) { 654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) ThreadUtils.assertOnUiThread(); 664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return (OAuth2TokenService) nativeGetForProfile(profile); 674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) @CalledByNative 70f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private static OAuth2TokenService create(long nativeOAuth2Service) { 714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) ThreadUtils.assertOnUiThread(); 724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return new OAuth2TokenService(nativeOAuth2Service); 734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) public void addObserver(OAuth2TokenServiceObserver observer) { 764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) ThreadUtils.assertOnUiThread(); 774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) mObservers.addObserver(observer); 784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) public void removeObserver(OAuth2TokenServiceObserver observer) { 814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) ThreadUtils.assertOnUiThread(); 824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) mObservers.removeObserver(observer); 834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) private static Account getAccountOrNullFromUsername(Context context, String username) { 864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (username == null) { 874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) Log.e(TAG, "Username is null"); 884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return null; 894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) AccountManagerHelper accountManagerHelper = AccountManagerHelper.get(context); 924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) Account account = accountManagerHelper.getAccountFromName(username); 934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (account == null) { 944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) Log.e(TAG, "Account not found for provided username."); 954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return null; 964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return account; 984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) /** 1015c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * Called by native to list the activite accounts in the OS. 1024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) */ 1035c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu @VisibleForTesting 1044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) @CalledByNative 1055c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu public static String[] getSystemAccounts(Context context) { 1064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) AccountManagerHelper accountManagerHelper = AccountManagerHelper.get(context); 1074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) java.util.List<String> accountNames = accountManagerHelper.getGoogleAccountNames(); 1084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return accountNames.toArray(new String[accountNames.size()]); 1094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 1104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) /** 1125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * Called by native to list the accounts with OAuth2 refresh tokens. 1135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * This can differ from getSystemAccounts as the user add/remove accounts 1145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * from the OS. validateAccounts should be called to keep these two 1155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * in sync. 1165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu */ 1175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu @CalledByNative 1185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu public static String[] getAccounts(Context context) { 1195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return getStoredAccounts(context); 1205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 1215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 1225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu /** 1234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * Called by native to retrieve OAuth2 tokens. 1244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * 1254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * @param username The native username (full address). 1264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * @param scope The scope to get an auth token for (without Android-style 'oauth2:' prefix). 1274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * @param nativeCallback The pointer to the native callback that should be run upon completion. 1284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) */ 1294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) @CalledByNative 1304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) public static void getOAuth2AuthToken( 131f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) Context context, String username, String scope, final long nativeCallback) { 1324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) Account account = getAccountOrNullFromUsername(context, username); 1334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (account == null) { 1344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) nativeOAuth2TokenFetched(null, false, nativeCallback); 1354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return; 1364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 1374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) String oauth2Scope = OAUTH2_SCOPE_PREFIX + scope; 1384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) AccountManagerHelper accountManagerHelper = AccountManagerHelper.get(context); 1404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) accountManagerHelper.getAuthTokenFromForeground( 1414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) null, account, oauth2Scope, new AccountManagerHelper.GetAuthTokenCallback() { 1424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) @Override 1434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) public void tokenAvailable(String token) { 1444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) nativeOAuth2TokenFetched( 1454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) token, token != null, nativeCallback); 1464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 1474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) }); 1484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 1494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) /** 1514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * Call this method to retrieve an OAuth2 access token for the given account and scope. 1524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * 1534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * @param activity the current activity. May be null. 1544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * @param account the account to get the access token for. 1554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * @param scope The scope to get an auth token for (without Android-style 'oauth2:' prefix). 1564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * @param callback called on successful and unsuccessful fetching of auth token. 1574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) */ 1584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) public static void getOAuth2AccessToken(Context context, @Nullable Activity activity, 1594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) Account account, String scope, 1604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) AccountManagerHelper.GetAuthTokenCallback callback) { 1614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) String oauth2Scope = OAUTH2_SCOPE_PREFIX + scope; 1624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) AccountManagerHelper.get(context).getAuthTokenFromForeground( 1634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) activity, account, oauth2Scope, callback); 1644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 1654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) /** 1674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * Call this method to retrieve an OAuth2 access token for the given account and scope. This 1684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * method times out after the specified timeout, and will return null if that happens. 1694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * 1704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * Given that this is a blocking method call, this should never be called from the UI thread. 1714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * 1724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * @param activity the current activity. May be null. 1734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * @param account the account to get the access token for. 1744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * @param scope The scope to get an auth token for (without Android-style 'oauth2:' prefix). 1754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * @param timeout the timeout. 1764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * @param unit the unit for |timeout|. 1774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) */ 1784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) public static String getOAuth2AccessTokenWithTimeout( 1794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) Context context, @Nullable Activity activity, Account account, String scope, 1804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) long timeout, TimeUnit unit) { 1814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) assert !ThreadUtils.runningOnUiThread(); 1824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) final AtomicReference<String> result = new AtomicReference<String>(); 1834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) final Semaphore semaphore = new Semaphore(0); 1844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) getOAuth2AccessToken( 1854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) context, activity, account, scope, 1864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) new AccountManagerHelper.GetAuthTokenCallback() { 1874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) @Override 1884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) public void tokenAvailable(String token) { 1894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) result.set(token); 1904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) semaphore.release(); 1914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 1924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) }); 1934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) try { 1944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (semaphore.tryAcquire(timeout, unit)) { 1954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return result.get(); 1964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } else { 1974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) Log.d(TAG, "Failed to retrieve auth token within timeout (" + 1984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) timeout + " + " + unit.name() + ")"); 1994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return null; 2004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 2014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } catch (InterruptedException e) { 2024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) Log.w(TAG, "Got interrupted while waiting for auth token"); 2034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return null; 2044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 2054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 2064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 2074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) /** 2084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * Called by native to check wether the account has an OAuth2 refresh token. 2094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) */ 2104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) @CalledByNative 2114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) public static boolean hasOAuth2RefreshToken(Context context, String accountName) { 2124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return AccountManagerHelper.get(context).hasAccountForName(accountName); 2134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 2144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 2154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) /** 2164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * Called by native to invalidate an OAuth2 token. 2174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) */ 2184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) @CalledByNative 2194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) public static void invalidateOAuth2AuthToken(Context context, String accessToken) { 2204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (accessToken != null) { 2214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) AccountManagerHelper.get(context).invalidateAuthToken(accessToken); 2224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 2234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 2244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 225f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) @CalledByNative 226f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) public void validateAccounts(Context context, boolean forceNotifications) { 2274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) ThreadUtils.assertOnUiThread(); 2284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) String currentlySignedInAccount = 2294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) ChromeSigninController.get(context).getSignedInAccountName(); 230f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) nativeValidateAccounts(mNativeProfileOAuth2TokenService, currentlySignedInAccount, 231f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) forceNotifications); 2324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 2334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 2344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) /** 2354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * Triggers a notification to all observers of the native and Java instance of the 2364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * OAuth2TokenService that a refresh token is now available. This may cause observers to retry 2374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * operations that require authentication. 2384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) */ 2394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) public void fireRefreshTokenAvailable(Account account) { 2404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) ThreadUtils.assertOnUiThread(); 2414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) assert account != null; 2424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) nativeFireRefreshTokenAvailableFromJava(mNativeProfileOAuth2TokenService, account.name); 2434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 2444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 2454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) @CalledByNative 2464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) public void notifyRefreshTokenAvailable(String accountName) { 2474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) assert accountName != null; 2484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) Account account = AccountManagerHelper.createAccountFromName(accountName); 2494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) for (OAuth2TokenServiceObserver observer : mObservers) { 2504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) observer.onRefreshTokenAvailable(account); 2514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 2524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 2534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 2544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) /** 2554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * Triggers a notification to all observers of the native and Java instance of the 2564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * OAuth2TokenService that a refresh token is now revoked. 2574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) */ 2584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) public void fireRefreshTokenRevoked(Account account) { 2594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) ThreadUtils.assertOnUiThread(); 2604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) assert account != null; 2614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) nativeFireRefreshTokenRevokedFromJava(mNativeProfileOAuth2TokenService, account.name); 2624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 2634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 2644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) @CalledByNative 2654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) public void notifyRefreshTokenRevoked(String accountName) { 2664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) assert accountName != null; 2674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) Account account = AccountManagerHelper.createAccountFromName(accountName); 2684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) for (OAuth2TokenServiceObserver observer : mObservers) { 2694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) observer.onRefreshTokenRevoked(account); 2704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 2714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 2724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 2734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) /** 2744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * Triggers a notification to all observers of the native and Java instance of the 2754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * OAuth2TokenService that all refresh tokens now have been loaded. 2764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) */ 2774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) public void fireRefreshTokensLoaded() { 2784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) ThreadUtils.assertOnUiThread(); 2794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) nativeFireRefreshTokensLoadedFromJava(mNativeProfileOAuth2TokenService); 2804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 2814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 2824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) @CalledByNative 2834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) public void notifyRefreshTokensLoaded() { 2844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) for (OAuth2TokenServiceObserver observer : mObservers) { 2854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) observer.onRefreshTokensLoaded(); 2864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 2874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 2884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 2895c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu private static String[] getStoredAccounts(Context context) { 2905c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu Set<String> accounts = 2915c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu PreferenceManager.getDefaultSharedPreferences(context) 2925c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu .getStringSet(STORED_ACCOUNTS_KEY, null); 2935c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return accounts == null ? new String[]{} : accounts.toArray(new String[accounts.size()]); 2945c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 2955c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 2965c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu @CalledByNative 2975c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu private static void saveStoredAccounts(Context context, String[] accounts) { 2985c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu Set<String> set = new HashSet<String>(Arrays.asList(accounts)); 2995c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu PreferenceManager.getDefaultSharedPreferences(context).edit(). 3005c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu putStringSet(STORED_ACCOUNTS_KEY, set).apply(); 3015c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 3025c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 3034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) private static native Object nativeGetForProfile(Profile profile); 3044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) private static native void nativeOAuth2TokenFetched( 305f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) String authToken, boolean result, long nativeCallback); 306f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private native void nativeValidateAccounts( 307f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) long nativeAndroidProfileOAuth2TokenService, 308f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) String currentlySignedInAccount, 309f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) boolean forceNotifications); 3104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) private native void nativeFireRefreshTokenAvailableFromJava( 311f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) long nativeAndroidProfileOAuth2TokenService, String accountName); 3124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) private native void nativeFireRefreshTokenRevokedFromJava( 313f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) long nativeAndroidProfileOAuth2TokenService, String accountName); 3144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) private native void nativeFireRefreshTokensLoadedFromJava( 315f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) long nativeAndroidProfileOAuth2TokenService); 3164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 317