Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3752)

Unified Diff: chrome/android/java/src/org/chromium/chrome/browser/child_accounts/ChildAccountService.java

Issue 789853002: Add support for child accounts on Android. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: x Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/android/java/src/org/chromium/chrome/browser/child_accounts/ChildAccountService.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/child_accounts/ChildAccountService.java b/chrome/android/java/src/org/chromium/chrome/browser/child_accounts/ChildAccountService.java
new file mode 100644
index 0000000000000000000000000000000000000000..15066cc7da8e9c86c9a72aaad4928558d760aca9
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/child_accounts/ChildAccountService.java
@@ -0,0 +1,214 @@
+// Copyright 2014 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.child_accounts;
+
+import android.accounts.Account;
+import android.accounts.AccountManager;
+import android.accounts.AccountManagerCallback;
+import android.accounts.AccountManagerFuture;
+import android.accounts.AuthenticatorException;
+import android.accounts.OperationCanceledException;
+import android.content.Context;
+import android.os.AsyncTask;
+import android.util.Log;
+
+import org.chromium.base.CommandLine;
+import org.chromium.chrome.ChromeSwitches;
+import org.chromium.sync.signin.AccountManagerHelper;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Timer;
+import java.util.TimerTask;
+import java.util.concurrent.ExecutionException;
+
+/**
+ * This class detects child accounts and enables special treatment for them.
+ */
+public class ChildAccountService {
+
+ private static final String TAG = "ChildAccountService";
+
+ /**
+ * An account feature (corresponding to a Gaia service flag) that specifies whether the account
+ * is a child account.
+ */
+ private static final String FEATURE_IS_CHILD_ACCOUNT_KEY = "service_uca";
+
+ /**
+ * The maximum amount of time to wait for the child account check, in milliseconds.
+ */
+ private static final int CHILD_ACCOUNT_TIMEOUT_MS = 1000;
+
+ private static final Object sLock = new Object();
+
+ private static ChildAccountService sChildAccountService;
+
+ private final Context mContext;
+
+ // This is null if we haven't determined the child account status yet.
+ private Boolean mHasChildAccount;
+
+ private AccountManagerFuture<Boolean> mAccountManagerFuture;
+
+ private final List<HasChildAccountCallback> mCallbacks = new ArrayList<>();
+
+ private ChildAccountService(Context context) {
+ mContext = context;
+ }
+
+ /**
+ * Returns the shared ChildAccountService instance, creating one if necessary.
+ * @param context The context to initialize the ChildAccountService with.
+ * @return The shared instance.
+ */
+ public static ChildAccountService getInstance(Context context) {
+ synchronized (sLock) {
+ if (sChildAccountService == null) {
+ sChildAccountService = new ChildAccountService(context.getApplicationContext());
+ }
+ }
+ return sChildAccountService;
+ }
+
+ /**
+ * A callback to return the result of {@link #checkHasChildAccount}.
+ */
+ public static interface HasChildAccountCallback {
+
+ /**
+ * @param hasChildAccount Whether there is exactly one child account on the device.
+ */
+ public void onChildAccountChecked(boolean hasChildAccount);
+
+ }
+
+ /**
+ * Checks for the presence of child accounts on the device.
+ * @param callback Will be called with the result (see
+ * {@link HasChildAccountCallback#onChildAccountChecked}).
+ */
+ public void checkHasChildAccount(final HasChildAccountCallback callback) {
+ if (mHasChildAccount != null) {
+ callback.onChildAccountChecked(mHasChildAccount);
+ return;
+ }
+
+ Account[] googleAccounts =
+ AccountManagerHelper.get(mContext).getGoogleAccounts();
+ if (googleAccounts.length != 1) {
+ mHasChildAccount = false;
+ callback.onChildAccountChecked(false);
+ if (CommandLine.getInstance().hasSwitch(ChromeSwitches.CHILD_ACCOUNT)) {
+ Log.w(TAG, "Ignoring --" + ChromeSwitches.CHILD_ACCOUNT + " command line flag "
+ + "because there are " + googleAccounts.length + " Google accounts on the "
+ + "device");
+ }
+ return;
+ }
+ Account account = googleAccounts[0];
+
+ if (shouldForceChildAccount(account)) {
+ mHasChildAccount = true;
+ callback.onChildAccountChecked(true);
+ return;
+ }
+
+ mCallbacks.add(callback);
+
+ if (mAccountManagerFuture != null) return;
+
+ final Timer timer = new Timer();
+
+ String[] features = {FEATURE_IS_CHILD_ACCOUNT_KEY};
+ mAccountManagerFuture = AccountManager.get(mContext).hasFeatures(account, features,
+ new AccountManagerCallback<Boolean>() {
+ @Override
+ public void run(AccountManagerFuture<Boolean> future) {
+ assert future == mAccountManagerFuture;
+ assert future.isDone();
+
+ timer.cancel();
+
+ boolean hasChildAccount = hasChildAccount();
+ for (HasChildAccountCallback callback : mCallbacks) {
+ callback.onChildAccountChecked(hasChildAccount);
+ }
+ }
+ }, null /* handler */);
+
+ timer.schedule(new TimerTask() {
+ @Override
+ public void run() {
+ if (!mAccountManagerFuture.isDone()) mAccountManagerFuture.cancel(true);
+ }}, CHILD_ACCOUNT_TIMEOUT_MS);
+ }
+
+ private boolean shouldForceChildAccount(Account account) {
+ String childAccountName = CommandLine.getInstance().getSwitchValue(
+ ChromeSwitches.CHILD_ACCOUNT);
+ return childAccountName != null && account.name.equals(childAccountName);
+ }
+
+ private boolean getFutureResult() {
+ try {
+ return mAccountManagerFuture.getResult();
+ } catch (OperationCanceledException e) {
+ Log.e(TAG, "Timed out fetching child account flag: ", e);
+ } catch (AuthenticatorException e) {
+ Log.e(TAG, "Error while fetching child account flag: ", e);
+ } catch (IOException e) {
+ Log.e(TAG, "Error while fetching child account flag: ", e);
+ }
+ return false;
+ }
+
+ /**
+ * Synchronously checks for the presence of child accounts on the device. This method should
+ * only be called after the result has been determined (usually using
+ * {@link #checkHasChildAccount} or {@link #waitUntilFinished} to block).
+ * @return Whether there is a child account on the device.
+ */
+ public boolean hasChildAccount() {
+ // Lazily get the result from the future, so this can be called both from the
+ // AccountManagerCallback and after waiting for the future to be resolved.
+ if (mHasChildAccount == null) {
+ // If the future is not resolved yet, this will assert.
+ mHasChildAccount = getFutureResult();
+ }
+ return mHasChildAccount;
+ }
+
+ /**
+ * Waits until we have determined the child account status. Usually you should use callbacks
+ * instead of this method, see {@link #checkHasChildAccount}.
+ */
+ public void waitUntilFinished() {
+ if (mAccountManagerFuture == null) return;
+ if (mAccountManagerFuture.isDone()) return;
+
+ // This will block in getFutureResult(), but that may only happen on a background thread.
+ try {
+ new AsyncTask<Void, Void, Void>() {
+ @Override
+ protected Void doInBackground(Void... params) {
+ getFutureResult();
+ return null;
+ }
+ }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR).get();
+ } catch (ExecutionException e) {
+ Log.w(TAG, "Error while fetching child account flag: ", e);
+ } catch (InterruptedException e) {
+ Log.w(TAG, "Interrupted while fetching child account flag: ", e);
+ }
+ }
+
+ public void onChildAccountSigninComplete() {
+ nativeOnChildAccountSigninComplete();
+ }
+
+ private native void nativeOnChildAccountSigninComplete();
+}
« no previous file with comments | « chrome/android/java/src/org/chromium/chrome/ChromeSwitches.java ('k') | chrome/browser/android/chrome_jni_registrar.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698