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

Unified Diff: chrome/android/java/src/org/chromium/chrome/browser/signin/ConfirmSyncDataStateMachine.java

Issue 2014833002: Show dialogs for syncing to managed accounts. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Replace getContext with getActivity in AccountManagementFragment. Created 4 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/signin/ConfirmSyncDataStateMachine.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/ConfirmSyncDataStateMachine.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/ConfirmSyncDataStateMachine.java
new file mode 100644
index 0000000000000000000000000000000000000000..7a05387c2b03b67ff0be639f1bf9bee4543cb996
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/ConfirmSyncDataStateMachine.java
@@ -0,0 +1,185 @@
+// Copyright 2016 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.app.FragmentManager;
+import android.content.Context;
+import android.support.annotation.IntDef;
+import android.text.TextUtils;
+
+import org.chromium.base.Callback;
+import org.chromium.base.Promise;
+import org.chromium.chrome.browser.signin.ConfirmImportSyncDataDialog.ImportSyncType;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * This class takes care of the various dialogs that must be shown when the user changes the
+ * account they are syncing to (either directly, or by signing in to a new account). Most of the
+ * complexity is due to many of the decisions getting answered through callbacks.
+ *
+ * This class progresses along the following state machine:
+ *
+ * E----\ G--\
+ * ^ | ^ |
+ * | | | v
+ * A->B->C->D-+->F->H
+ * | |
+ * \-------/
+ *
+ * Where:
+ * A - Start
+ * B - Decision: progress to C if the user signed in previously to a different account, F otherwise.
+ * C - Decision: progress to E if we are switching from a managed account, D otherwise.
+ * D - Action: show Import Data Dialog.
+ * E - Action: show Switching from Managed Account Dialog.
+ * F - Decision: progress to G if we are switching to a managed account, H otherwise.
+ * G - Action: show Switching to Managed Account Dialog.
+ * H - End: perform {@link ConfirmImportSyncDataDialog.Listener#onConfirm} with the result of the
+ * Import Data Dialog, if displayed or true if switching from a managed account.
+ *
+ * At any dialog, the user can cancel the dialog and end the whole process (resulting in
+ * {@link ConfirmImportSyncDataDialog.Listener#onCancel}).
+ */
+public class ConfirmSyncDataStateMachine
+ implements ConfirmImportSyncDataDialog.Listener, ConfirmManagedSyncDataDialog.Listener {
+
+ @IntDef({
+ BEFORE_OLD_ACCOUNT_DIALOG, BEFORE_NEW_ACCOUNT_DIALOG,
+ AFTER_NEW_ACCOUNT_DIALOG, DONE
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ private @interface State {}
+ private static final int BEFORE_OLD_ACCOUNT_DIALOG = 0; // Start of state B.
+ private static final int BEFORE_NEW_ACCOUNT_DIALOG = 1; // Start of state F.
+ private static final int AFTER_NEW_ACCOUNT_DIALOG = 2; // Start of state H.
+ private static final int DONE = 4;
+
+ private boolean mWipeData;
+ @State private int mState = BEFORE_OLD_ACCOUNT_DIALOG;
+
+ private final ConfirmImportSyncDataDialog.Listener mCallback;
+ private final String mOldAccountName;
+ private final String mNewAccountName;
+ private final boolean mCurrentlyManaged;
+ private final Promise<Boolean> mNewAccountManaged = new Promise<Boolean>();
+ private final FragmentManager mFragmentManager;
+ private final Context mContext;
+ private final ImportSyncType mImportSyncType;
+
+ /**
+ * Run this state machine, displaying the appropriate dialogs.
+ * @param callback One of the two functions of the {@link ConfirmImportSyncDataDialog.Listener}
+ * are guaranteed to be called.
+ */
+ public static void run(String oldAccountName, String newAccountName,
+ ImportSyncType importSyncType, FragmentManager fragmentManager, Context context,
+ ConfirmImportSyncDataDialog.Listener callback) {
+ ConfirmSyncDataStateMachine stateMachine = new ConfirmSyncDataStateMachine(oldAccountName,
+ newAccountName, importSyncType, fragmentManager, context, callback);
+ stateMachine.progress();
+ }
+
+ private ConfirmSyncDataStateMachine(String oldAccountName, String newAccountName,
+ ImportSyncType importSyncType, FragmentManager fragmentManager, Context context,
+ ConfirmImportSyncDataDialog.Listener callback) {
+ mOldAccountName = oldAccountName;
+ mNewAccountName = newAccountName;
+ mImportSyncType = importSyncType;
+ mFragmentManager = fragmentManager;
+ mContext = context;
+ mCallback = callback;
+
+ mCurrentlyManaged = SigninManager.get(context).getManagementDomain() != null;
+
+ // This check isn't needed right now, but can take a few seconds, so we kick it off early.
+ SigninManager.isUserManaged(mNewAccountName, mNewAccountManaged.fulfillmentCallback());
+ }
+
+ /**
+ * This will progress the state machine, by moving the state along and then by either calling
+ * itself directly or creating a dialog. If the dialog is dismissed or answered negatively the
+ * entire flow is over, if it is answered positively one of the onConfirm functions is called
+ * and this function is called again.
+ */
+ private void progress() {
+ switch (mState) {
+ case BEFORE_OLD_ACCOUNT_DIALOG:
+ mState = BEFORE_NEW_ACCOUNT_DIALOG;
+
+ if (TextUtils.isEmpty(mOldAccountName) || mOldAccountName == mNewAccountName) {
+ // If there is no old account or the user is just logging back into whatever
+ // they were previously logged in as, progress past the old account checks.
+ progress();
+ } else if (mCurrentlyManaged
+ && mImportSyncType == ImportSyncType.SWITCHING_SYNC_ACCOUNTS) {
+ // We only care about the user's previous account being managed if they are
+ // switching accounts.
+
+ mWipeData = true;
+
+ // This will call back into onConfirm() on success.
+ ConfirmManagedSyncDataDialog.showSwitchFromManagedAccountDialog(this,
+ mFragmentManager, mContext.getResources(),
+ SigninManager.extractDomainName(mOldAccountName),
+ mOldAccountName, mNewAccountName);
+ } else {
+ // This will call back into onConfirm(boolean wipeData) on success.
+ ConfirmImportSyncDataDialog.showNewInstance(mOldAccountName, mNewAccountName,
+ mImportSyncType, mFragmentManager, this);
+ }
+
+ break;
+ case BEFORE_NEW_ACCOUNT_DIALOG:
+ mState = AFTER_NEW_ACCOUNT_DIALOG;
+
+ mNewAccountManaged.then(new Callback<Boolean>() {
+ @Override
+ public void onResult(Boolean newAccountManaged) {
+ if (newAccountManaged) {
+ // Show 'logging into managed account' dialog
+ // This will call back into onConfirm on success.
+ ConfirmManagedSyncDataDialog.showSignInToManagedAccountDialog(
+ ConfirmSyncDataStateMachine.this,
+ mFragmentManager, mContext.getResources(),
+ SigninManager.extractDomainName(mNewAccountName));
+ } else {
+ progress();
+ }
+ }
+ });
+
+ break;
+ case AFTER_NEW_ACCOUNT_DIALOG:
+ mState = DONE;
+ mCallback.onConfirm(mWipeData);
+ break;
+ default:
+ assert false : "Invalid state: " + mState;
+ }
+ }
+
+ // ConfirmImportSyncDataDialog.Listener implementation.
+ @Override
+ public void onConfirm(boolean wipeData) {
+ mWipeData = wipeData;
+ progress();
+ }
+
+ // ConfirmManagedSyncDataDialog.Listener implementation.
+ @Override
+ public void onConfirm() {
+ progress();
+ }
+
+ // ConfirmImportSyncDataDialog.Listener & ConfirmManagedSyncDataDialog.Listener implementation.
+ @Override
+ public void onCancel() {
+ mState = DONE;
+ mCallback.onCancel();
+ }
+}
+

Powered by Google App Engine
This is Rietveld 408576698