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

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

Issue 1143313006: Add an activity that allows whitelisted applications to clear all data in Chrome. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: sync Created 5 years, 6 months 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
deleted file mode 100644
index 031649e82be871f0a5443c8fbe593be50897ad16..0000000000000000000000000000000000000000
--- a/chrome/android/java/src/org/chromium/chrome/browser/child_accounts/ChildAccountService.java
+++ /dev/null
@@ -1,361 +0,0 @@
-// 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.OnAccountsUpdateListener;
-import android.accounts.OperationCanceledException;
-import android.content.Context;
-import android.os.AsyncTask;
-
-import org.chromium.base.CalledByNative;
-import org.chromium.base.CommandLine;
-import org.chromium.base.Log;
-import org.chromium.base.ThreadUtils;
-import org.chromium.base.TraceEvent;
-import org.chromium.base.VisibleForTesting;
-import org.chromium.chrome.browser.ChromeSwitches;
-import org.chromium.chrome.browser.signin.SigninManager;
-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;
-
-import javax.annotation.Nullable;
-
-/**
- * This class detects child accounts and enables special treatment for them.
- */
-public class ChildAccountService {
-
- private static final String TAG = "cr.ChildAccountService";
-
- /**
- * The maximum amount of time to wait for the initial child account check, in milliseconds.
- */
- private static final int CHILD_ACCOUNT_TIMEOUT_MS = 1000;
-
- private static ChildAccountService sChildAccountService;
-
- private final Context mContext;
-
- /**
- * Non-null if the the child account status has been determined.
- */
- private Boolean mHasChildAccount;
-
- /**
- * Non-null while a child account check is in progress. Note that if the child account status
- * has been previously determined, the externally visible status only changes when the check
- * finishes. This means that before that, calls to {@link #checkHasChildAccount} and
- * {@link #hasChildAccount} will return the last value, even if it is now stale.
- */
- private AccountManagerFuture<Boolean> mAccountManagerFuture;
-
- /**
- * Non-empty while the initial child account check is in progress.
- */
- private final List<HasChildAccountCallback> mCallbacks = new ArrayList<>();
-
- protected ChildAccountService(Context context) {
- mContext = context;
- AccountManager accountManager = AccountManager.get(mContext);
- accountManager.addOnAccountsUpdatedListener(new OnAccountsUpdateListener() {
- @Override
- public void onAccountsUpdated(Account[] accounts) {
- ThreadUtils.runOnUiThread(new Runnable() {
- @Override
- public void run() {
- recheckChildAccountStatus();
- }
- });
- }
- }, null, false);
- }
-
- /**
- * 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) {
- ThreadUtils.assertOnUiThread();
- 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}). The callback is guaranteed
- * to be called on a future turn of the event loop, even if the result can be
- * determined immediately.
- */
- public void checkHasChildAccount(final HasChildAccountCallback callback) {
- if (mHasChildAccount != null || maybeUpdatePredeterminedChildAccountStatus()) {
- postCallback(callback);
- return;
- }
- mCallbacks.add(callback);
- if (mAccountManagerFuture == null) requestChildAccountStatus();
- }
-
- private void postCallback(final HasChildAccountCallback callback) {
- final boolean hasChildAccount = mHasChildAccount;
- ThreadUtils.postOnUiThread(new Runnable() {
- @Override
- public void run() {
- callback.onChildAccountChecked(hasChildAccount);
- }
- });
- }
-
- /**
- * Updates the child account status if it can be determined immediately.
- *
- * @return Whether the child account status was updated.
- */
- private boolean maybeUpdatePredeterminedChildAccountStatus() {
- Boolean predeterminedChildAccountStatus = getPredeterminedChildStatus();
- if (predeterminedChildAccountStatus == null) return false;
- setHasChildAccount(predeterminedChildAccountStatus);
- return true;
- }
-
- /**
- * @return The child account status if it can be determined immediately, or null otherwise.
- */
- @Nullable
- private Boolean getPredeterminedChildStatus() {
- if (!isChildAccountDetectionEnabled()) {
- Log.v(TAG, "Child account detection disabled");
- return false;
- }
- Account[] googleAccounts =
- AccountManagerHelper.get(mContext).getGoogleAccounts();
- if (googleAccounts.length != 1) {
- 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");
- } else {
- Log.v(TAG, googleAccounts.length + " Google accounts on the device");
- }
- return false;
- }
- String childAccountName =
- CommandLine.getInstance().getSwitchValue(ChromeSwitches.CHILD_ACCOUNT);
- String accountName = googleAccounts[0].name;
- if (childAccountName != null && accountName.equals(childAccountName)) {
- Log.v(TAG, "Child account forced via command line for " + childAccountName);
- return true;
- }
- return null;
- }
-
- private void requestChildAccountStatus() {
- assert mAccountManagerFuture == null;
-
- final Timer timer = new Timer();
- final int traceId = System.identityHashCode(this);
- TraceEvent.startAsync("ChildAccountService.checkFeatures", traceId);
- AccountManagerHelper accountManagerHelper = AccountManagerHelper.get(mContext);
- final AccountManagerFuture<Boolean> future = accountManagerHelper.checkChildAccount(
- accountManagerHelper.getSingleGoogleAccount(),
- new AccountManagerCallback<Boolean>() {
- @Override
- public void run(AccountManagerFuture<Boolean> future) {
- TraceEvent.finishAsync("ChildAccountService.checkFeatures", traceId);
-
- timer.cancel();
-
- assert future.isDone();
-
- // Ignore any future that is not the current one.
- if (future == mAccountManagerFuture) {
- setHasChildAccount(getFutureResult());
- }
- }
- });
-
- // Add a timeout during the initial check, to avoid blocking startup for too long.
- if (mHasChildAccount == null) {
- timer.schedule(new TimerTask() {
- @Override
- public void run() {
- if (!future.isDone()) {
- Log.v(TAG, "AM request timed out");
- future.cancel(true);
- }
- }
- }, CHILD_ACCOUNT_TIMEOUT_MS);
- }
- mAccountManagerFuture = future;
- }
-
- private boolean getFutureResult() {
- boolean result = false;
- try {
- result = mAccountManagerFuture.getResult();
- Log.v(TAG, "AM future result:" + result);
- } catch (OperationCanceledException e) {
- Log.e(TAG, "Timed out fetching child account flag: ", e);
- } catch (AuthenticatorException | IOException e) {
- Log.e(TAG, "Error while fetching child account flag: ", e);
- } finally {
- mAccountManagerFuture = null;
- }
- return result;
- }
-
- /**
- * Returns whether there is a child account 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() {
- ThreadUtils.assertOnUiThread();
-
- 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() {
- ThreadUtils.assertOnUiThread();
-
- if (mHasChildAccount != null) return;
- assert mAccountManagerFuture != null;
-
- TraceEvent.begin("ChildAccountService.waitUntilFinished");
- // This will block in getFutureResult(), but that may only happen on a background thread.
- try {
- AsyncTask<Void, Void, Boolean> task = new AsyncTask<Void, Void, Boolean>() {
- @Override
- protected Boolean doInBackground(Void... params) {
- return getFutureResult();
- }
- };
- setHasChildAccount(task.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);
- }
- TraceEvent.end("ChildAccountService.waitUntilFinished");
- }
-
- /**
- * If this returns false, Chrome will assume there are no child accounts on the device,
- * and no further checks will be made, which has the effect of a kill switch.
- * Can be overridden by subclasses to avoid native calls in testing.
- *
- * @return Whether child account detection is enabled.
- */
- protected boolean isChildAccountDetectionEnabled() {
- return nativeIsChildAccountDetectionEnabled();
- }
-
- private void setHasChildAccount(boolean hasChildAccount) {
- Boolean oldHasChildAccount = mHasChildAccount;
- mHasChildAccount = hasChildAccount;
- for (HasChildAccountCallback callback : mCallbacks) {
- postCallback(callback);
- }
- mCallbacks.clear();
-
- onChildAccountStatusUpdated(oldHasChildAccount);
- }
-
- /**
- * Called when the child account status has been determined or updated.
- * Can be overridden by subclasses to avoid native calls and calls into dependencies in testing.
- *
- * @param oldValue The old child account status. This is null when the child account status
- * has been determined for the first time after the browser has started.
- */
- protected void onChildAccountStatusUpdated(Boolean oldValue) {
- Log.v(TAG, "hasChildAccount: " + mHasChildAccount + " oldHasChildAccount: " + oldValue);
- if (mHasChildAccount) {
- if (oldValue == null) {
- // This is the first time we have determined the child account status,
- // which means the browser is starting up. The startup code will sign in
- // and call us back in onChildAccountSigninComplete().
- return;
- }
- if (!oldValue.booleanValue()) {
- // We have switched from no child account to child account while the browser
- // is running. Sign in (which will call us back in onChildAccountSigninComplete()).
- SigninManager signinManager = SigninManager.get(mContext);
- Account account = AccountManagerHelper.get(mContext).getSingleGoogleAccount();
- signinManager.signInToSelectedAccount(null, account,
- SigninManager.SIGNIN_TYPE_FORCED_CHILD_ACCOUNT,
- SigninManager.SIGNIN_SYNC_IMMEDIATELY, false, null);
- return;
- }
- }
- // Fallthrough for all other cases: Propagate child account status to native code.
- // This is a no-op if the child account status does not change.
- nativeSetIsChildAccount(mHasChildAccount);
- }
-
- /**
- * Called when the browser has been signed in to the child account.
- */
- public void onChildAccountSigninComplete() {
- nativeSetIsChildAccount(true);
- }
-
- @VisibleForTesting
- void recheckChildAccountStatus() {
- // Cancel the AccountManagerFuture if it is running.
- if (mAccountManagerFuture != null) {
- mAccountManagerFuture.cancel(true);
- mAccountManagerFuture = null;
- }
- if (!maybeUpdatePredeterminedChildAccountStatus()) {
- requestChildAccountStatus();
- }
- }
-
- @CalledByNative
- private static void onInvalidationReceived() {
- assert ThreadUtils.runningOnUiThread();
- if (sChildAccountService == null) return;
- sChildAccountService.recheckChildAccountStatus();
- }
-
- private native boolean nativeIsChildAccountDetectionEnabled();
-
- private native void nativeSetIsChildAccount(boolean isChild);
-}

Powered by Google App Engine
This is Rietveld 408576698