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(); |
+ } |
+} |
+ |