| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 package org.chromium.chrome.browser.signin; | 5 package org.chromium.chrome.browser.signin; |
| 6 | 6 |
| 7 import android.accounts.Account; |
| 7 import android.content.Context; | 8 import android.content.Context; |
| 8 import android.os.AsyncTask; | 9 import android.os.AsyncTask; |
| 9 | 10 |
| 10 import org.chromium.base.Log; | 11 import org.chromium.base.Log; |
| 11 import org.chromium.base.ObserverList; | 12 import org.chromium.base.ObserverList; |
| 12 import org.chromium.base.ThreadUtils; | 13 import org.chromium.base.ThreadUtils; |
| 13 import org.chromium.base.VisibleForTesting; | 14 import org.chromium.base.VisibleForTesting; |
| 15 import org.chromium.base.annotations.JNINamespace; |
| 16 import org.chromium.sync.signin.AccountManagerDelegate.Callback; |
| 14 import org.chromium.sync.signin.AccountManagerHelper; | 17 import org.chromium.sync.signin.AccountManagerHelper; |
| 15 | 18 |
| 16 import java.util.List; | |
| 17 | |
| 18 /** | 19 /** |
| 19 * Android wrapper of AccountTrackerService which provides access from the java l
ayer. | 20 * Android wrapper of AccountTrackerService which provides access from the java l
ayer. |
| 20 * It offers the capability of fetching and seeding system accounts into AccountT
rackerService in C++ | 21 * It offers the capability of fetching and seeding system accounts into AccountT
rackerService in C++ |
| 21 * layer, and notifies observers when it is complete. | 22 * layer, and notifies observers when it is complete. |
| 22 */ | 23 */ |
| 24 @JNINamespace("signin::android") |
| 23 public class AccountTrackerService { | 25 public class AccountTrackerService { |
| 24 private static final String TAG = "cr.AccountService"; | 26 private static final String TAG = "AccountService"; |
| 25 private static AccountTrackerService sAccountTrackerService; | 27 private static AccountTrackerService sAccountTrackerService; |
| 26 private static AccountIdProvider sAccountIdProvider; | |
| 27 private SystemAccountsSeedingStatus mSystemAccountsSeedingStatus = | 28 private SystemAccountsSeedingStatus mSystemAccountsSeedingStatus = |
| 28 SystemAccountsSeedingStatus.SEEDING_NOT_STARTED; | 29 SystemAccountsSeedingStatus.SEEDING_NOT_STARTED; |
| 29 private boolean mForceRefresh; | 30 private boolean mForceRefresh; |
| 30 private boolean mSyncForceRefreshedForTest; | 31 private boolean mSyncForceRefreshedForTest; |
| 31 | 32 |
| 32 private final Context mContext; | 33 private final Context mContext; |
| 33 private final long mNativeAccountTrackerService; | |
| 34 | 34 |
| 35 private enum SystemAccountsSeedingStatus { | 35 private enum SystemAccountsSeedingStatus { |
| 36 SEEDING_NOT_STARTED, | 36 SEEDING_NOT_STARTED, |
| 37 SEEDING_IN_PROGRESS, | 37 SEEDING_IN_PROGRESS, |
| 38 SEEDING_DONE | 38 SEEDING_DONE |
| 39 } | 39 } |
| 40 | 40 |
| 41 /** | 41 /** |
| 42 * Classes that want to listen for system accounts fetching and seeding shoul
d implement | 42 * Classes that want to listen for system accounts fetching and seeding shoul
d implement |
| 43 * this interface and register with {@link #addSystemAccountsSeededListener}. | 43 * this interface and register with {@link #addSystemAccountsSeededListener}. |
| 44 */ | 44 */ |
| 45 public interface OnSystemAccountsSeededListener { | 45 public interface OnSystemAccountsSeededListener { |
| 46 // Called at the end of seedSystemAccounts(). | 46 // Called at the end of seedSystemAccounts(). |
| 47 void onSystemAccountsSeedingComplete(); | 47 void onSystemAccountsSeedingComplete(); |
| 48 // Called at the beginning of system accounts being force refreshed. | 48 // Called at the beginning of system accounts being force refreshed. |
| 49 void onSystemAccountsForceRefreshed(); | 49 void onSystemAccountsForceRefreshed(); |
| 50 } | 50 } |
| 51 | 51 |
| 52 private final ObserverList<OnSystemAccountsSeededListener> mSystemAccountsSe
edingObservers = | 52 private final ObserverList<OnSystemAccountsSeededListener> mSystemAccountsSe
edingObservers = |
| 53 new ObserverList<>(); | 53 new ObserverList<>(); |
| 54 | 54 |
| 55 public static AccountTrackerService get(Context context) { | 55 public static AccountTrackerService get(Context context) { |
| 56 ThreadUtils.assertOnUiThread(); | 56 ThreadUtils.assertOnUiThread(); |
| 57 if (sAccountTrackerService == null) { | 57 if (sAccountTrackerService == null) { |
| 58 sAccountTrackerService = new AccountTrackerService(context); | 58 sAccountTrackerService = new AccountTrackerService(context); |
| 59 sAccountIdProvider = AccountIdProvider.getInstance(); | |
| 60 } | 59 } |
| 61 return sAccountTrackerService; | 60 return sAccountTrackerService; |
| 62 } | 61 } |
| 63 | 62 |
| 64 private AccountTrackerService(Context context) { | 63 private AccountTrackerService(Context context) { |
| 65 mContext = context; | 64 mContext = context; |
| 66 mNativeAccountTrackerService = nativeInit(); | |
| 67 } | 65 } |
| 68 | 66 |
| 69 /** | 67 /** |
| 70 * Check whether system accounts have been seeded into AccountTrackerService
in C++ layer. | 68 * Check whether system accounts have been seeded into AccountTrackerService
in C++ layer. |
| 71 */ | 69 */ |
| 72 public boolean isSystemAccountsSeeded() { | 70 public boolean isSystemAccountsSeeded() { |
| 73 ThreadUtils.assertOnUiThread(); | 71 ThreadUtils.assertOnUiThread(); |
| 74 if (mSystemAccountsSeedingStatus == SystemAccountsSeedingStatus.SEEDING_
DONE) { | 72 if (mSystemAccountsSeedingStatus == SystemAccountsSeedingStatus.SEEDING_
DONE) { |
| 75 return true; | 73 return true; |
| 76 } | 74 } |
| 77 | |
| 78 if (mSystemAccountsSeedingStatus == SystemAccountsSeedingStatus.SEEDING_
NOT_STARTED) { | 75 if (mSystemAccountsSeedingStatus == SystemAccountsSeedingStatus.SEEDING_
NOT_STARTED) { |
| 79 seedSystemAccounts(); | 76 seedSystemAccounts(); |
| 80 } | 77 } |
| 81 | |
| 82 return false; | 78 return false; |
| 83 } | 79 } |
| 84 | 80 |
| 85 /** | 81 /** |
| 86 * Register an |observer| to observe system accounts seeding status. | 82 * Register an |observer| to observe system accounts seeding status. |
| 87 */ | 83 */ |
| 88 public void addSystemAccountsSeededListener(OnSystemAccountsSeededListener o
bserver) { | 84 public void addSystemAccountsSeededListener(OnSystemAccountsSeededListener o
bserver) { |
| 89 ThreadUtils.assertOnUiThread(); | 85 ThreadUtils.assertOnUiThread(); |
| 90 mSystemAccountsSeedingObservers.addObserver(observer); | 86 mSystemAccountsSeedingObservers.addObserver(observer); |
| 91 if (mSystemAccountsSeedingStatus == SystemAccountsSeedingStatus.SEEDING_
DONE) { | 87 if (mSystemAccountsSeedingStatus == SystemAccountsSeedingStatus.SEEDING_
DONE) { |
| 92 observer.onSystemAccountsSeedingComplete(); | 88 observer.onSystemAccountsSeedingComplete(); |
| 93 } | 89 } |
| 94 } | 90 } |
| 95 | 91 |
| 96 private void seedSystemAccounts() { | 92 private void seedSystemAccounts() { |
| 97 ThreadUtils.assertOnUiThread(); | 93 ThreadUtils.assertOnUiThread(); |
| 98 mSystemAccountsSeedingStatus = SystemAccountsSeedingStatus.SEEDING_IN_PR
OGRESS; | |
| 99 mForceRefresh = false; | 94 mForceRefresh = false; |
| 100 mSyncForceRefreshedForTest = false; | 95 mSyncForceRefreshedForTest = false; |
| 101 AccountManagerHelper accountManagerHelper = AccountManagerHelper.get(mCo
ntext); | 96 final AccountIdProvider accountIdProvider = AccountIdProvider.getInstanc
e(); |
| 102 List<String> accountNamesList = accountManagerHelper.getGoogleAccountNam
es(); | 97 if (accountIdProvider.canBeUsed(mContext, null)) { |
| 103 final String[] accountNames = accountNamesList.toArray(new String[accoun
tNamesList.size()]); | 98 mSystemAccountsSeedingStatus = SystemAccountsSeedingStatus.SEEDING_I
N_PROGRESS; |
| 104 new AsyncTask<Void, Void, String[]>() { | 99 } else { |
| 100 mSystemAccountsSeedingStatus = SystemAccountsSeedingStatus.SEEDING_N
OT_STARTED; |
| 101 notifyObserversOnForceRefreshed(); |
| 102 return; |
| 103 } |
| 104 AccountManagerHelper.get(mContext).getGoogleAccounts(new Callback<Accoun
t[]>() { |
| 105 @Override | 105 @Override |
| 106 public String[] doInBackground(Void... params) { | 106 public void gotResult(final Account[] accounts) { |
| 107 Log.d(TAG, "Getting id/email mapping"); | 107 new AsyncTask<Void, Void, String[][]>() { |
| 108 String[] accountIds = new String[accountNames.length]; | 108 @Override |
| 109 for (int i = 0; i < accountIds.length; ++i) { | 109 public String[][] doInBackground(Void... params) { |
| 110 accountIds[i] = sAccountIdProvider.getAccountId(mContext, ac
countNames[i]); | 110 Log.d(TAG, "Getting id/email mapping"); |
| 111 } | 111 String[][] accountIdNameMap = new String[2][accounts.len
gth]; |
| 112 return accountIds; | 112 for (int i = 0; i < accounts.length; ++i) { |
| 113 accountIdNameMap[0][i] = |
| 114 accountIdProvider.getAccountId(mContext, acc
ounts[i].name); |
| 115 accountIdNameMap[1][i] = accounts[i].name; |
| 116 } |
| 117 return accountIdNameMap; |
| 118 } |
| 119 @Override |
| 120 public void onPostExecute(String[][] accountIdNameMap) { |
| 121 if (mSyncForceRefreshedForTest) return; |
| 122 if (mForceRefresh) { |
| 123 seedSystemAccounts(); |
| 124 return; |
| 125 } |
| 126 if (areAccountIdsValid(accountIdNameMap[0])) { |
| 127 nativeSeedAccountsInfo(accountIdNameMap[0], accountI
dNameMap[1]); |
| 128 mSystemAccountsSeedingStatus = SystemAccountsSeeding
Status.SEEDING_DONE; |
| 129 notifyObserversOnSeedingComplete(); |
| 130 } else { |
| 131 Log.w(TAG, "Invalid mapping of id/email"); |
| 132 seedSystemAccounts(); |
| 133 } |
| 134 } |
| 135 }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); |
| 113 } | 136 } |
| 114 @Override | 137 }); |
| 115 public void onPostExecute(String[] accountIds) { | |
| 116 if (mSyncForceRefreshedForTest) return; | |
| 117 if (mForceRefresh) { | |
| 118 seedSystemAccounts(); | |
| 119 return; | |
| 120 } | |
| 121 if (areAccountIdsValid(accountIds)) { | |
| 122 nativeSeedAccountsInfo(mNativeAccountTrackerService, account
Ids, accountNames); | |
| 123 mSystemAccountsSeedingStatus = SystemAccountsSeedingStatus.S
EEDING_DONE; | |
| 124 notifyObserversOnSeedingComplete(); | |
| 125 } else { | |
| 126 Log.w(TAG, "Invalid mapping of id/email"); | |
| 127 if (sAccountIdProvider.canBeUsed(mContext, null)) { | |
| 128 seedSystemAccounts(); | |
| 129 return; | |
| 130 } | |
| 131 mSystemAccountsSeedingStatus = SystemAccountsSeedingStatus.S
EEDING_NOT_STARTED; | |
| 132 notifyObserversOnForceRefreshed(); | |
| 133 } | |
| 134 } | |
| 135 }.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR); | |
| 136 } | 138 } |
| 137 | 139 |
| 138 private boolean areAccountIdsValid(String[] accountIds) { | 140 private boolean areAccountIdsValid(String[] accountIds) { |
| 139 for (int i = 0; i < accountIds.length; ++i) { | 141 for (int i = 0; i < accountIds.length; ++i) { |
| 140 if (accountIds[i] == null) return false; | 142 if (accountIds[i] == null) return false; |
| 141 } | 143 } |
| 142 return true; | 144 return true; |
| 143 } | 145 } |
| 144 | 146 |
| 145 private void notifyObserversOnSeedingComplete() { | 147 private void notifyObserversOnSeedingComplete() { |
| 146 for (OnSystemAccountsSeededListener observer : mSystemAccountsSeedingObs
ervers) { | 148 for (OnSystemAccountsSeededListener observer : mSystemAccountsSeedingObs
ervers) { |
| 147 observer.onSystemAccountsSeedingComplete(); | 149 observer.onSystemAccountsSeedingComplete(); |
| 148 } | 150 } |
| 149 } | 151 } |
| 150 | 152 |
| 151 /** | 153 /** |
| 152 * Seed system accounts into AccountTrackerService synchronously for test pur
pose. | 154 * Seed system accounts into AccountTrackerService synchronously for test pur
pose. |
| 153 */ | 155 */ |
| 154 @VisibleForTesting | 156 @VisibleForTesting |
| 155 public void syncForceRefreshForTest(String[] accountIds, String[] accountNam
es) { | 157 public void syncForceRefreshForTest(String[] accountIds, String[] accountNam
es) { |
| 156 ThreadUtils.assertOnUiThread(); | 158 ThreadUtils.assertOnUiThread(); |
| 157 mSystemAccountsSeedingStatus = SystemAccountsSeedingStatus.SEEDING_IN_PR
OGRESS; | 159 mSystemAccountsSeedingStatus = SystemAccountsSeedingStatus.SEEDING_IN_PR
OGRESS; |
| 158 mForceRefresh = false; | 160 mForceRefresh = false; |
| 159 mSyncForceRefreshedForTest = true; | 161 mSyncForceRefreshedForTest = true; |
| 160 nativeSeedAccountsInfo(mNativeAccountTrackerService, accountIds, account
Names); | 162 nativeSeedAccountsInfo(accountIds, accountNames); |
| 161 mSystemAccountsSeedingStatus = SystemAccountsSeedingStatus.SEEDING_DONE; | 163 mSystemAccountsSeedingStatus = SystemAccountsSeedingStatus.SEEDING_DONE; |
| 162 } | 164 } |
| 163 | 165 |
| 164 /** | 166 /** |
| 165 * Force AccountTrackerService refresh/update systems accounts. | 167 * Force AccountTrackerService refresh/update systems accounts. |
| 166 */ | 168 */ |
| 167 public void forceRefresh() { | 169 public void forceRefresh() { |
| 168 ThreadUtils.assertOnUiThread(); | 170 ThreadUtils.assertOnUiThread(); |
| 169 mForceRefresh = true; | 171 mForceRefresh = true; |
| 170 notifyObserversOnForceRefreshed(); | 172 notifyObserversOnForceRefreshed(); |
| 171 if (mSystemAccountsSeedingStatus != SystemAccountsSeedingStatus.SEEDING_
IN_PROGRESS) { | 173 if (mSystemAccountsSeedingStatus != SystemAccountsSeedingStatus.SEEDING_
IN_PROGRESS) { |
| 172 seedSystemAccounts(); | 174 seedSystemAccounts(); |
| 173 } | 175 } |
| 174 } | 176 } |
| 175 | 177 |
| 176 private void notifyObserversOnForceRefreshed() { | 178 private void notifyObserversOnForceRefreshed() { |
| 177 for (OnSystemAccountsSeededListener observer : mSystemAccountsSeedingObs
ervers) { | 179 for (OnSystemAccountsSeededListener observer : mSystemAccountsSeedingObs
ervers) { |
| 178 observer.onSystemAccountsForceRefreshed(); | 180 observer.onSystemAccountsForceRefreshed(); |
| 179 } | 181 } |
| 180 } | 182 } |
| 181 | 183 |
| 182 // Native methods. | 184 private static native void nativeSeedAccountsInfo(String[] gaiaIds, String[]
accountNames); |
| 183 private native long nativeInit(); | |
| 184 private native void nativeSeedAccountsInfo( | |
| 185 long nativeAccountTrackerServiceAndroid, String[] gaiaIds, String[]
accountNames); | |
| 186 } | 185 } |
| OLD | NEW |