Chromium Code Reviews| 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 |
| 73 && nativeAreAllAccountsSeeded()) { | |
|
gogerald1
2015/10/13 16:34:53
seedSystemAccounts is called on UI thread and Seed
| |
| 75 return true; | 74 return true; |
| 76 } | 75 } |
| 77 | |
| 78 if (mSystemAccountsSeedingStatus == SystemAccountsSeedingStatus.SEEDING_ NOT_STARTED) { | 76 if (mSystemAccountsSeedingStatus == SystemAccountsSeedingStatus.SEEDING_ NOT_STARTED) { |
| 79 seedSystemAccounts(); | 77 seedSystemAccounts(); |
| 80 } | 78 } |
| 81 | |
| 82 return false; | 79 return false; |
| 83 } | 80 } |
| 84 | 81 |
| 85 /** | 82 /** |
| 86 * Register an |observer| to observe system accounts seeding status. | 83 * Register an |observer| to observe system accounts seeding status. |
| 87 */ | 84 */ |
| 88 public void addSystemAccountsSeededListener(OnSystemAccountsSeededListener o bserver) { | 85 public void addSystemAccountsSeededListener(OnSystemAccountsSeededListener o bserver) { |
| 89 ThreadUtils.assertOnUiThread(); | 86 ThreadUtils.assertOnUiThread(); |
| 90 mSystemAccountsSeedingObservers.addObserver(observer); | 87 mSystemAccountsSeedingObservers.addObserver(observer); |
| 91 if (mSystemAccountsSeedingStatus == SystemAccountsSeedingStatus.SEEDING_ DONE) { | 88 if (mSystemAccountsSeedingStatus == SystemAccountsSeedingStatus.SEEDING_ DONE) { |
| 92 observer.onSystemAccountsSeedingComplete(); | 89 observer.onSystemAccountsSeedingComplete(); |
| 93 } | 90 } |
| 94 } | 91 } |
| 95 | 92 |
| 96 private void seedSystemAccounts() { | 93 private void seedSystemAccounts() { |
| 97 ThreadUtils.assertOnUiThread(); | 94 ThreadUtils.assertOnUiThread(); |
| 98 mSystemAccountsSeedingStatus = SystemAccountsSeedingStatus.SEEDING_IN_PR OGRESS; | |
| 99 mForceRefresh = false; | 95 mForceRefresh = false; |
| 100 mSyncForceRefreshedForTest = false; | 96 mSyncForceRefreshedForTest = false; |
| 101 AccountManagerHelper accountManagerHelper = AccountManagerHelper.get(mCo ntext); | 97 final AccountIdProvider accountIdProvider = AccountIdProvider.getInstanc e(); |
| 102 List<String> accountNamesList = accountManagerHelper.getGoogleAccountNam es(); | 98 if (accountIdProvider.canBeUsed(mContext, null)) { |
| 103 final String[] accountNames = accountNamesList.toArray(new String[accoun tNamesList.size()]); | 99 mSystemAccountsSeedingStatus = SystemAccountsSeedingStatus.SEEDING_I N_PROGRESS; |
| 104 new AsyncTask<Void, Void, String[]>() { | 100 } else { |
| 101 mSystemAccountsSeedingStatus = SystemAccountsSeedingStatus.SEEDING_N OT_STARTED; | |
| 102 notifyObserversOnForceRefreshed(); | |
| 103 return; | |
| 104 } | |
| 105 AccountManagerHelper.get(mContext).getGoogleAccounts(new Callback<Accoun t[]>() { | |
| 105 @Override | 106 @Override |
| 106 public String[] doInBackground(Void... params) { | 107 public void gotResult(final Account[] accounts) { |
| 107 Log.d(TAG, "Getting id/email mapping"); | 108 new AsyncTask<Void, Void, String[][]>() { |
| 108 String[] accountIds = new String[accountNames.length]; | 109 @Override |
| 109 for (int i = 0; i < accountIds.length; ++i) { | 110 public String[][] doInBackground(Void... params) { |
| 110 accountIds[i] = sAccountIdProvider.getAccountId(mContext, ac countNames[i]); | 111 Log.d(TAG, "Getting id/email mapping"); |
| 111 } | 112 String[][] accountIdNameMap = new String[2][accounts.len gth]; |
| 112 return accountIds; | 113 for (int i = 0; i < accounts.length; ++i) { |
| 114 accountIdNameMap[0][i] = | |
| 115 accountIdProvider.getAccountId(mContext, acc ounts[i].name); | |
| 116 accountIdNameMap[1][i] = accounts[i].name; | |
| 117 } | |
| 118 return accountIdNameMap; | |
| 119 } | |
| 120 @Override | |
| 121 public void onPostExecute(String[][] accountIdNameMap) { | |
| 122 if (mSyncForceRefreshedForTest) return; | |
| 123 if (mForceRefresh) { | |
| 124 seedSystemAccounts(); | |
| 125 return; | |
| 126 } | |
| 127 if (areAccountIdsValid(accountIdNameMap[0])) { | |
| 128 nativeSeedAccountsInfo(accountIdNameMap[0], accountI dNameMap[1]); | |
| 129 mSystemAccountsSeedingStatus = SystemAccountsSeeding Status.SEEDING_DONE; | |
| 130 notifyObserversOnSeedingComplete(); | |
| 131 } else { | |
| 132 Log.w(TAG, "Invalid mapping of id/email"); | |
| 133 seedSystemAccounts(); | |
| 134 } | |
| 135 } | |
| 136 }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); | |
| 113 } | 137 } |
| 114 @Override | 138 }); |
| 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 } | 139 } |
| 137 | 140 |
| 138 private boolean areAccountIdsValid(String[] accountIds) { | 141 private boolean areAccountIdsValid(String[] accountIds) { |
| 139 for (int i = 0; i < accountIds.length; ++i) { | 142 for (int i = 0; i < accountIds.length; ++i) { |
| 140 if (accountIds[i] == null) return false; | 143 if (accountIds[i] == null) return false; |
| 141 } | 144 } |
| 142 return true; | 145 return true; |
| 143 } | 146 } |
| 144 | 147 |
| 145 private void notifyObserversOnSeedingComplete() { | 148 private void notifyObserversOnSeedingComplete() { |
| 146 for (OnSystemAccountsSeededListener observer : mSystemAccountsSeedingObs ervers) { | 149 for (OnSystemAccountsSeededListener observer : mSystemAccountsSeedingObs ervers) { |
| 147 observer.onSystemAccountsSeedingComplete(); | 150 observer.onSystemAccountsSeedingComplete(); |
| 148 } | 151 } |
| 149 } | 152 } |
| 150 | 153 |
| 151 /** | 154 /** |
| 152 * Seed system accounts into AccountTrackerService synchronously for test pur pose. | 155 * Seed system accounts into AccountTrackerService synchronously for test pur pose. |
| 153 */ | 156 */ |
| 154 @VisibleForTesting | 157 @VisibleForTesting |
| 155 public void syncForceRefreshForTest(String[] accountIds, String[] accountNam es) { | 158 public void syncForceRefreshForTest(String[] accountIds, String[] accountNam es) { |
| 156 ThreadUtils.assertOnUiThread(); | 159 ThreadUtils.assertOnUiThread(); |
| 157 mSystemAccountsSeedingStatus = SystemAccountsSeedingStatus.SEEDING_IN_PR OGRESS; | 160 mSystemAccountsSeedingStatus = SystemAccountsSeedingStatus.SEEDING_IN_PR OGRESS; |
| 158 mForceRefresh = false; | 161 mForceRefresh = false; |
| 159 mSyncForceRefreshedForTest = true; | 162 mSyncForceRefreshedForTest = true; |
| 160 nativeSeedAccountsInfo(mNativeAccountTrackerService, accountIds, account Names); | 163 nativeSeedAccountsInfo(accountIds, accountNames); |
| 161 mSystemAccountsSeedingStatus = SystemAccountsSeedingStatus.SEEDING_DONE; | 164 mSystemAccountsSeedingStatus = SystemAccountsSeedingStatus.SEEDING_DONE; |
| 162 } | 165 } |
| 163 | 166 |
| 164 /** | 167 /** |
| 165 * Force AccountTrackerService refresh/update systems accounts. | 168 * Force AccountTrackerService refresh/update systems accounts. |
| 166 */ | 169 */ |
| 167 public void forceRefresh() { | 170 public void forceRefresh() { |
| 168 ThreadUtils.assertOnUiThread(); | 171 ThreadUtils.assertOnUiThread(); |
| 169 mForceRefresh = true; | 172 mForceRefresh = true; |
| 170 notifyObserversOnForceRefreshed(); | 173 notifyObserversOnForceRefreshed(); |
| 171 if (mSystemAccountsSeedingStatus != SystemAccountsSeedingStatus.SEEDING_ IN_PROGRESS) { | 174 if (mSystemAccountsSeedingStatus != SystemAccountsSeedingStatus.SEEDING_ IN_PROGRESS) { |
| 172 seedSystemAccounts(); | 175 seedSystemAccounts(); |
| 173 } | 176 } |
| 174 } | 177 } |
| 175 | 178 |
| 176 private void notifyObserversOnForceRefreshed() { | 179 private void notifyObserversOnForceRefreshed() { |
| 177 for (OnSystemAccountsSeededListener observer : mSystemAccountsSeedingObs ervers) { | 180 for (OnSystemAccountsSeededListener observer : mSystemAccountsSeedingObs ervers) { |
| 178 observer.onSystemAccountsForceRefreshed(); | 181 observer.onSystemAccountsForceRefreshed(); |
| 179 } | 182 } |
| 180 } | 183 } |
| 181 | 184 |
| 182 // Native methods. | 185 private static native boolean nativeAreAllAccountsSeeded(); |
| 183 private native long nativeInit(); | 186 private static native void nativeSeedAccountsInfo(String[] gaiaIds, String[] accountNames); |
| 184 private native void nativeSeedAccountsInfo( | |
| 185 long nativeAccountTrackerServiceAndroid, String[] gaiaIds, String[] accountNames); | |
| 186 } | 187 } |
| OLD | NEW |