Index: chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunSignInProcessor.java |
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunSignInProcessor.java b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunSignInProcessor.java |
new file mode 100644 |
index 0000000000000000000000000000000000000000..96a4915a5de38c466542631ed266446e7a456aa4 |
--- /dev/null |
+++ b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunSignInProcessor.java |
@@ -0,0 +1,290 @@ |
+// 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.firstrun; |
+ |
+import android.accounts.Account; |
+import android.app.Activity; |
+import android.content.Context; |
+import android.os.Bundle; |
+import android.preference.PreferenceManager; |
+import android.text.TextUtils; |
+import android.util.Log; |
+ |
+import org.chromium.base.CommandLine; |
+import org.chromium.chrome.ChromeSwitches; |
+import org.chromium.chrome.browser.ChromiumApplication; |
+import org.chromium.chrome.browser.services.AndroidEduAndChildAccountHelper; |
+import org.chromium.chrome.browser.signin.SigninManager; |
+import org.chromium.chrome.browser.signin.SigninManager.SignInFlowObserver; |
+import org.chromium.chrome.browser.util.FeatureUtilities; |
+import org.chromium.sync.signin.AccountManagerHelper; |
+import org.chromium.sync.signin.ChromeSigninController; |
+ |
+/** |
+ * A helper to perform all necessary steps for the automatic FRE sign in. |
+ * The helper performs: |
+ * - necessary Android EDU and child account checks; |
+ * - automatic non-interactive forced sign in for Android EDU and child accounts; and |
+ * - any pending automatic non-interactive request to sign in from the First Run Experience. |
+ * The helper calls the observer's onSignInComplete() if |
+ * - nothing needs to be done, or when |
+ * - the sign in is complete. |
+ * If the sign in process fails or if an interactive FRE sequence is necessary, |
+ * the helper starts the FRE activity, finishes the current activity and calls |
+ * OnSignInCancelled. |
+ * |
+ * Usage: |
+ * new FirstRunSignInProcessor(activity, shouldShowNotification){ |
+ * override OnSignInComplete and OnSignInCancelled |
+ * }.start(). |
+ */ |
+public class FirstRunSignInProcessor { |
+ /** |
+ * SharedPreferences preference names to keep the state of the First Run Experience. |
+ */ |
+ private static final String FIRST_RUN_FLOW_SIGNIN_COMPLETE = "first_run_signin_complete"; |
+ private static final String FIRST_RUN_FLOW_SIGNIN_ACCOUNT_NAME = |
+ "first_run_signin_account_name"; |
+ private static final String FIRST_RUN_FLOW_SIGNIN_SETUP_SYNC = "first_run_signin_setup_sync"; |
+ |
+ private final Activity mActivity; |
+ private final SigninManager mSignInManager; |
+ private final SignInFlowObserver mObserver; |
+ private final boolean mShowSignInNotification; |
+ |
+ private boolean mIsAndroidEduDevice; |
+ private boolean mHasChildAccount; |
+ private int mSignInType; |
+ |
+ /** |
+ * Initiates the automatic sign-in process in background. |
+ * |
+ * @param activity The context for the FRE parameters processor. |
+ */ |
+ public static void start(Activity activity) { |
+ new FirstRunSignInProcessor(activity, false, null); |
+ } |
+ |
+ private FirstRunSignInProcessor(Activity activity, boolean showSignInNotification, |
+ SignInFlowObserver observer) { |
+ mActivity = activity; |
+ mSignInManager = SigninManager.get(activity); |
+ mObserver = observer; |
+ mShowSignInNotification = showSignInNotification; |
+ |
+ new AndroidEduAndChildAccountHelper() { |
+ @Override |
+ public void onParametersReady() { |
+ mIsAndroidEduDevice = isAndroidEduDevice(); |
+ mHasChildAccount = hasChildAccount(); |
+ mSignInManager.onFirstRunCheckDone(); |
+ mSignInType = mHasChildAccount |
+ ? FirstRunUtil.SIGNIN_TYPE_FORCED_CHILD_ACCOUNT |
+ : (mIsAndroidEduDevice |
+ ? FirstRunUtil.SIGNIN_TYPE_FORCED_EDU |
+ : FirstRunUtil.SIGNIN_TYPE_INTERACTIVE); |
+ |
+ // We allow to pass-through without FRE being complete only if |
+ // - FRE is disabled, or |
+ // - FRE hasn't been completed, but the user has already seen the ToS in |
+ // the Setup Wizard. |
+ boolean firstRunFlowComplete = FirstRunStatus.getFirstRunFlowComplete(mActivity); |
+ if (CommandLine.getInstance().hasSwitch(ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE) |
+ || (!firstRunFlowComplete |
+ && ToSAckedReceiver.checkAnyUserHasSeenToS(mActivity))) { |
+ mSignInManager.onFirstRunCheckDone(); |
+ if (mObserver != null) mObserver.onSigninComplete(); |
+ return; |
+ } |
+ |
+ // Otherwise, the FRE must have been completed, so let's force it. |
+ if (!firstRunFlowComplete) { |
+ requestToFireIntentAndFinish(); |
+ return; |
+ } |
+ |
+ if (!getFirstRunFlowSignInComplete(mActivity)) { |
+ // Check if we need to complete any outstanding sign-in requests from FRE. |
+ // It setFirstRunFlowSignInComplete() once the sign-in is complete or if |
+ // it's unnecessary. |
+ completeFreSignInRequest(); |
+ } else { |
+ processAutomaticSignIn(); |
+ } |
+ } |
+ }.start(mActivity); |
+ } |
+ |
+ /** |
+ * Processes the fully automatic non-FRE-related forced sign-in. |
+ * This is used to enforce the environment for Android EDU and child accounts. |
+ */ |
+ private void processAutomaticSignIn() { |
+ // This is only for non-interactive forced sign-ins. |
+ assert getFirstRunFlowSignInComplete(mActivity); |
+ assert !mHasChildAccount || !mIsAndroidEduDevice; |
+ if (!mIsAndroidEduDevice && !mHasChildAccount) return; |
+ |
+ final Account[] googleAccounts = |
+ AccountManagerHelper.get(mActivity).getGoogleAccounts(); |
+ if (!FeatureUtilities.canAllowSync(mActivity) |
+ || !SigninManager.get(mActivity.getApplicationContext()).isSignInAllowed() |
+ || googleAccounts.length != 1) return; |
+ |
+ FirstRunUtil.signInToSelectedAccount(mActivity, googleAccounts[0], |
+ mSignInType, FirstRunUtil.SIGNIN_SYNC_IMMEDIATELY, mShowSignInNotification, |
+ mObserver); |
+ } |
+ |
+ /** |
+ * Processes an outstanding FRE sign-in request if any. |
+ */ |
+ private void completeFreSignInRequest() { |
+ // This is only for completion of the FRE sign-in process. |
+ assert !getFirstRunFlowSignInComplete(mActivity); |
+ |
+ final String accountName = getFirstRunFlowSignInAccountName(mActivity); |
+ if (!FeatureUtilities.canAllowSync(mActivity) |
+ || !SigninManager.get(mActivity.getApplicationContext()).isSignInAllowed() |
+ || TextUtils.isEmpty(accountName)) { |
+ setFirstRunFlowSignInComplete(mActivity, true); |
+ if (mObserver != null) mObserver.onSigninComplete(); |
+ return; |
+ } |
+ |
+ final Account account = |
+ AccountManagerHelper.get(mActivity).getAccountFromName(accountName); |
+ if (account == null) { |
+ // TODO(aruslan): handle the account being removed during the FRE. |
+ requestToFireIntentAndFinish(); |
+ return; |
+ } |
+ |
+ FirstRunUtil.signInToSelectedAccount(mActivity, account, |
+ mSignInType, FirstRunUtil.SIGNIN_SYNC_IMMEDIATELY, mShowSignInNotification, |
+ new SignInFlowObserver() { |
+ private void completeSignIn() { |
+ // Show sync settings if user pressed the "Settings" button. |
+ if (getFirstRunFlowSignInSetupSync(mActivity)) { |
+ openSyncSettings( |
+ ChromeSigninController.get(mActivity).getSignedInAccountName()); |
+ } |
+ setFirstRunFlowSignInComplete(mActivity, true); |
+ } |
+ |
+ @Override |
+ public void onSigninComplete() { |
+ completeSignIn(); |
+ if (mObserver != null) mObserver.onSigninComplete(); |
+ } |
+ |
+ @Override |
+ public void onSigninCancelled() { |
+ completeSignIn(); |
+ if (mObserver != null) mObserver.onSigninCancelled(); |
+ } |
+ }); |
+ } |
+ |
+ /** |
+ * Opens Sync settings as requested in the FRE sign-in dialog. |
+ * @param accountName The account to show the sync settings for. |
+ */ |
+ private void openSyncSettings(final String accountName) { |
+ ((ChromiumApplication) mActivity.getApplication()).openSyncSettings(accountName); |
+ } |
+ |
+ /** |
+ * Starts the full FRE and finishes the current activity. |
+ */ |
+ private void requestToFireIntentAndFinish() { |
+ Log.e("FirstRunSignInProcessor", "Attempt to pass-through without completed FRE"); |
+ if (mObserver != null) mObserver.onSigninCancelled(); |
+ |
+ // Things went wrong -- we want the user to go through the full FRE. |
+ FirstRunStatus.setFirstRunFlowComplete(mActivity, false); |
+ setFirstRunFlowSignInComplete(mActivity, false); |
+ setFirstRunFlowSignInAccountName(mActivity, null); |
+ setFirstRunFlowSignInSetupSync(mActivity, false); |
+ mActivity.startActivity(FirstRunFlowSequencer.createGenericFirstRunIntent( |
+ mActivity, mActivity.getIntent(), true)); |
+ } |
+ |
+ /** |
+ * @return Whether there is no pending sign-in requests from the First Run Experience. |
+ * @param context A context |
+ */ |
+ private static boolean getFirstRunFlowSignInComplete(Context context) { |
+ return PreferenceManager.getDefaultSharedPreferences(context) |
+ .getBoolean(FIRST_RUN_FLOW_SIGNIN_COMPLETE, false); |
+ } |
+ |
+ /** |
+ * Sets the "pending First Run Experience sign-in requests" preference. |
+ * @param context A context |
+ * @param isComplete Whether there is no pending sign-in requests from the First Run Experience. |
+ */ |
+ private static void setFirstRunFlowSignInComplete(Context context, boolean isComplete) { |
+ PreferenceManager.getDefaultSharedPreferences(context) |
+ .edit() |
+ .putBoolean(FIRST_RUN_FLOW_SIGNIN_COMPLETE, isComplete) |
+ .apply(); |
+ } |
+ |
+ /** |
+ * @return The account name selected during the First Run Experience, or null if none. |
+ * @param context A context |
+ */ |
+ private static String getFirstRunFlowSignInAccountName(Context context) { |
+ return PreferenceManager.getDefaultSharedPreferences(context) |
+ .getString(FIRST_RUN_FLOW_SIGNIN_ACCOUNT_NAME, null); |
+ } |
+ |
+ /** |
+ * Sets the account name for the pending sign-in First Run Experience request. |
+ * @param context A context |
+ * @param accountName The account name, or null. |
+ */ |
+ private static void setFirstRunFlowSignInAccountName(Context context, String accountName) { |
+ PreferenceManager.getDefaultSharedPreferences(context) |
+ .edit() |
+ .putString(FIRST_RUN_FLOW_SIGNIN_ACCOUNT_NAME, accountName) |
+ .apply(); |
+ } |
+ |
+ /** |
+ * @return Whether the user selected to see the Sync settings once signed in after FRE. |
+ * @param context A context |
+ */ |
+ private static boolean getFirstRunFlowSignInSetupSync(Context context) { |
+ return PreferenceManager.getDefaultSharedPreferences(context) |
+ .getBoolean(FIRST_RUN_FLOW_SIGNIN_SETUP_SYNC, false); |
+ } |
+ |
+ /** |
+ * Sets the preference to see the Sync settings once signed in after FRE. |
+ * @param context A context |
+ * @param isComplete Whether the user selected to see the Sync settings once signed in. |
+ */ |
+ private static void setFirstRunFlowSignInSetupSync(Context context, boolean isComplete) { |
+ PreferenceManager.getDefaultSharedPreferences(context) |
+ .edit() |
+ .putBoolean(FIRST_RUN_FLOW_SIGNIN_SETUP_SYNC, isComplete) |
+ .apply(); |
+ } |
+ |
+ /** |
+ * Finalize the state of the FRE flow (mark is as "complete" and finalize parameters). |
+ * @param context A context |
+ * @param data Resulting FRE properties bundle |
+ */ |
+ public static void finalizeFirstRunFlowState(Context context, Bundle data) { |
+ FirstRunStatus.setFirstRunFlowComplete(context, true); |
+ setFirstRunFlowSignInAccountName(context, |
+ data.getString(FirstRunActivity.RESULT_SIGNIN_ACCOUNT_NAME)); |
+ setFirstRunFlowSignInSetupSync(context, |
+ data.getBoolean(FirstRunActivity.RESULT_SHOW_SYNC_SETTINGS)); |
+ } |
+} |