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 |