Chromium Code Reviews| Index: chrome/android/java/src/org/chromium/chrome/browser/signin/AccountTrackerService.java |
| diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/AccountTrackerService.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/AccountTrackerService.java |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..370dd0409f1aebe7cf7c5668e548e7f19b2e5f4a |
| --- /dev/null |
| +++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/AccountTrackerService.java |
| @@ -0,0 +1,167 @@ |
| +// Copyright 2015 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +package org.chromium.chrome.browser.signin; |
| + |
| +import android.content.Context; |
| +import android.os.AsyncTask; |
| +import android.util.Log; |
| + |
| +import com.google.android.gms.auth.GoogleAuthException; |
| +import com.google.android.gms.auth.GoogleAuthUtil; |
| + |
| +import org.chromium.base.ObserverList; |
| +import org.chromium.sync.signin.AccountManagerHelper; |
| + |
| +import java.io.IOException; |
| +import java.util.concurrent.Semaphore; |
| + |
| +/** |
| +* Android wrapper of AccountTrackerService which provides access from the java layer. |
| +* It offers the capability of fetching and seeding system accounts into AccountTrackerService in C++ |
| +* layer, and notifys observers when it is complete. |
|
Roger Tawa OOO till Jul 10th
2015/08/14 15:01:22
notifys --> notifies
gogerald1
2015/08/18 01:14:26
Done.
|
| +*/ |
| +public class AccountTrackerService { |
| + private static final String TAG = "AccountTrackerService"; |
| + private static AccountTrackerService sAccountTrackerService; |
| + private static AccountIdProvider sAccountIdProvider; |
| + |
| + private final Context mContext; |
| + private final long mNativeAccountTrackerService; |
| + private final Semaphore mSemaphore = new Semaphore(1, true); |
| + |
| + private SystemAccountsSeedingStatus mSystemAccountsSeedingStatus = |
| + SystemAccountsSeedingStatus.SEEDING_NOT_STARTED; |
| + private boolean mForceRefresh = false; |
| + |
| + public enum SystemAccountsSeedingStatus { |
| + SEEDING_NOT_STARTED, |
| + SEEDING_IN_PROGRESS, |
| + SEEDING_DONE |
| + } |
| + |
| + /** |
| + * Classes that want to listen for system accounts fetching and seeding should implement |
| + * this interface and register with {@link #observeSystemAccountsSeeding}. |
| + */ |
| + public interface SystemAccountsSeedingObserver { void onSystemAccountsSeedingComplete(); } |
| + |
| + private final ObserverList<SystemAccountsSeedingObserver> mSystemAccountsSeedingObservers = |
| + new ObserverList<SystemAccountsSeedingObserver>(); |
| + |
| + public static AccountTrackerService get(Context context) { |
| + if (sAccountTrackerService == null) { |
| + sAccountTrackerService = new AccountTrackerService(context); |
| + sAccountIdProvider = AccountIdProvider.getInstance(); |
| + if (sAccountIdProvider == null) { |
| + // Register account Id provider. |
| + AccountIdProvider.setInstance(new AccountIdProvider() { |
| + @Override |
| + public String getAccountId(Context ctx, String accountName) { |
| + try { |
| + return GoogleAuthUtil.getAccountId(ctx, accountName); |
| + } catch (IOException | GoogleAuthException ex) { |
| + Log.e(TAG, "AccountIdProvider.getAccountId", ex); |
| + return null; |
| + } |
| + } |
| + }); |
| + sAccountIdProvider = AccountIdProvider.getInstance(); |
|
Roger Tawa OOO till Jul 10th
2015/08/14 15:01:21
Looking at this code, it seems much better for Acc
gogerald1
2015/08/18 01:14:26
Acknowledged. No need setInstance right now.
|
| + } |
| + } |
| + return sAccountTrackerService; |
| + } |
| + |
| + private AccountTrackerService(Context context) { |
| + mContext = context; |
| + mNativeAccountTrackerService = nativeInit(); |
| + } |
| + |
| + /** |
| + * Check whether systems accounts have been seeded into AccountTrackerService in C++ layer. |
| + */ |
| + public boolean isSystemAccountsSeeded() { |
| + if (mSystemAccountsSeedingStatus == SystemAccountsSeedingStatus.SEEDING_DONE |
| + && !mForceRefresh) { |
| + return true; |
| + } |
| + |
| + if (mSystemAccountsSeedingStatus == SystemAccountsSeedingStatus.SEEDING_NOT_STARTED |
| + || mForceRefresh) { |
| + seedingSystemAccounts(); |
| + } |
| + |
| + return false; |
| + } |
| + |
| + /** |
| + * Register an |observer| to observe system accounts seeding status. |
| + */ |
| + public void observeSystemAccountsSeeding(SystemAccountsSeedingObserver observer) { |
| + mSystemAccountsSeedingObservers.addObserver(observer); |
| + if (mSystemAccountsSeedingStatus == SystemAccountsSeedingStatus.SEEDING_DONE |
| + && !mForceRefresh) { |
| + observer.onSystemAccountsSeedingComplete(); |
|
Roger Tawa OOO till Jul 10th
2015/08/14 15:01:22
Should the observer be removed from list?
gogerald1
2015/08/18 01:14:26
Here, the calling of onSystemAccountsSeedingComple
|
| + } |
| + } |
| + |
| + private void seedingSystemAccounts() { |
|
Roger Tawa OOO till Jul 10th
2015/08/14 15:01:21
Nit: seedingSystemAccounts --> seedSystemAccounts
gogerald1
2015/08/18 01:14:26
Done.
|
| + AccountManagerHelper accountManagerHelper = AccountManagerHelper.get(mContext); |
| + java.util.List<String> accountNamesList = accountManagerHelper.getGoogleAccountNames(); |
| + final String[] accountNames = accountNamesList.toArray(new String[accountNamesList.size()]); |
| + new AsyncTask<Void, Void, String[]>() { |
| + @Override |
| + public String[] doInBackground(Void... params) { |
| + try { |
| + mSemaphore.acquire(); |
|
Roger Tawa OOO till Jul 10th
2015/08/14 15:01:22
I'm not sure you need a semaphore here. seedingSy
gogerald1
2015/08/18 01:14:26
I am considering a extreme case. Accounts on devic
|
| + } catch (InterruptedException e) { |
| + Log.w(TAG, "Got InterruptedException while waiting for semaphore"); |
| + return new String[0]; |
| + } |
| + if (mSystemAccountsSeedingStatus == SystemAccountsSeedingStatus.SEEDING_NOT_STARTED |
| + || mForceRefresh) { |
| + mSystemAccountsSeedingStatus = SystemAccountsSeedingStatus.SEEDING_IN_PROGRESS; |
| + Log.d(TAG, "Getting id/email mapping"); |
| + String[] accountIds = new String[accountNames.length]; |
| + for (int i = 0; i < accountIds.length; ++i) { |
| + accountIds[i] = sAccountIdProvider.getAccountId(mContext, accountNames[i]); |
| + } |
| + return accountIds; |
| + } |
| + return new String[0]; |
| + } |
| + @Override |
| + public void onPostExecute(String[] accountIds) { |
| + if (mSystemAccountsSeedingStatus |
| + == SystemAccountsSeedingStatus.SEEDING_IN_PROGRESS) { |
| + nativeSeedAccountsInfo(mNativeAccountTrackerService, accountIds, accountNames); |
| + mSystemAccountsSeedingStatus = SystemAccountsSeedingStatus.SEEDING_DONE; |
| + mForceRefresh = false; |
| + } |
| + mSemaphore.release(); |
| + notifyObserversOnSeedingComplete(); |
| + } |
| + |
| + }.execute(); |
| + } |
| + |
| + private void notifyObserversOnSeedingComplete() { |
| + for (SystemAccountsSeedingObserver observer : mSystemAccountsSeedingObservers) { |
| + observer.onSystemAccountsSeedingComplete(); |
| + } |
| + } |
| + |
| + /** |
| + * Force AccountTrackerService refresh/update systems accounts. |
| + */ |
| + public void forceRefresh() { |
| + mForceRefresh = true; |
| + seedingSystemAccounts(); |
| + } |
| + |
| + // Native methods. |
| + private native long nativeInit(); |
| + private native void nativeSeedAccountsInfo( |
| + long nativeAccountTrackerServiceAndroid, String[] gaiaIds, String[] accountNames); |
| +} |