Index: chrome/android/java/src/org/chromium/chrome/browser/sync/ui/ConfirmSyncDataStateMachine.java |
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/ConfirmSyncDataStateMachine.java b/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/ConfirmSyncDataStateMachine.java |
new file mode 100644 |
index 0000000000000000000000000000000000000000..d1bba6cc8f3f79b7842c86c758e2efabb4ad6a7b |
--- /dev/null |
+++ b/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/ConfirmSyncDataStateMachine.java |
@@ -0,0 +1,196 @@ |
+// 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.sync.ui; |
+ |
+import android.app.FragmentManager; |
+import android.content.Context; |
+import android.text.TextUtils; |
+ |
+import org.chromium.base.Callback; |
+import org.chromium.chrome.browser.signin.SigninManager; |
+import org.chromium.chrome.browser.sync.ui.ConfirmImportSyncDataDialog.ImportSyncType; |
+ |
+/** |
+ * 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----\ H--\ |
+ * ^ | ^ | |
+ * | | | v |
+ * A->B->C->D-+->F->G->I |
+ * | | |
+ * \-------/ |
+ * |
+ * 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 - Action: start the asynchronous request to check if the next account is managed. |
+ * G - Decision: progress to H if we are switching to a managed account, I otherwise. |
+ * H - Action: show Switching to Managed Account Dialog. |
+ * I - 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 { |
+ private enum State { |
+ BEFORE_OLD_ACCOUNT_DIALOG, // Start of state B. |
+ AFTER_OLD_ACCOUNT_DIALOG, // Start of state F. |
+ BEFORE_NEW_ACCOUNT_DIALOG, // Start of state G. |
+ AFTER_NEW_ACCOUNT_DIALOG, // Start of state I. |
+ DONE |
+ } |
+ |
+ private boolean mWipeData; |
+ private State mState = State.BEFORE_OLD_ACCOUNT_DIALOG; |
+ |
+ private final ConfirmImportSyncDataDialog.Listener mCallback; |
+ private final String mOldAccountName; |
+ private final String mNewAccountName; |
+ private final boolean mCurrentlyManaged; |
+ private boolean mNewAccountManaged; |
+ 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; |
+ |
+ // TODO(peconn): Kick off the mNewAccountManaged check here. |
+ } |
+ |
+ private static String getDomain(String email) { |
+ // Assumes that the email is of the form user@domain.com, and returns Domain. |
Bernhard Bauer
2016/06/03 08:50:06
This should use (the native) gaia::ExtractDomainNa
PEConn
2016/06/27 09:34:32
Done.
|
+ int start = email.indexOf('@') + 1; |
+ int end = email.lastIndexOf('.'); |
Bernhard Bauer
2016/06/03 08:50:06
This is also a bit weird. For user@example.co.uk,
PEConn
2016/06/27 09:34:33
Why did you think 'Example.co' - it returns 'Examp
Bernhard Bauer
2016/06/29 10:51:26
But it's _last_ index of, and the last index in `u
|
+ return Character.toUpperCase(email.charAt(start)) + email.substring(start + 1, end); |
+ } |
+ |
+ /** |
+ * 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 |
Bernhard Bauer
2016/06/03 08:50:06
Nit: remove the command after "negatively" (or add
PEConn
2016/06/27 09:34:33
Done.
|
+ * 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 = State.AFTER_OLD_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(), |
+ getDomain(mOldAccountName), mOldAccountName, mNewAccountName); |
+ } else { |
+ // This will call back into onConfirm(boolean wipeData) on success. |
+ ConfirmImportSyncDataDialog.showNewInstance(mOldAccountName, mNewAccountName, |
+ mImportSyncType, mFragmentManager, this); |
+ } |
+ |
+ break; |
+ case AFTER_OLD_ACCOUNT_DIALOG: |
+ mState = State.BEFORE_NEW_ACCOUNT_DIALOG; |
+ |
+ // We can shortcut the account management step since we know certain domains are |
+ // not going to be managed (eg, gmail, hotmail, yahoo). |
+ if (SigninManager.couldUserBeManaged(mNewAccountName)) { |
Bernhard Bauer
2016/06/03 08:50:06
You could also move this into fetchManagementDomai
PEConn
2016/06/27 09:34:32
Done.
|
+ |
Bernhard Bauer
2016/06/03 08:50:06
Remove the empty line.
PEConn
2016/06/27 09:34:32
Done.
|
+ SigninManager.fetchManagementDomain(mNewAccountName, new Callback<String>(){ |
+ @Override |
+ public void onResult(String result) { |
+ mNewAccountManaged = !TextUtils.isEmpty(result); |
+ progress(); |
+ } |
+ }); |
+ } else { |
+ mNewAccountManaged = false; |
+ progress(); |
+ } |
+ |
+ break; |
+ case BEFORE_NEW_ACCOUNT_DIALOG: |
+ mState = State.AFTER_NEW_ACCOUNT_DIALOG; |
+ |
+ if (mNewAccountManaged) { |
+ // Show 'logging into managed account' dialog |
+ // This will call back into onConfirm on success. |
+ ConfirmManagedSyncDataDialog.showSignInToManagedAccountDialog(this, |
+ mFragmentManager, mContext.getResources(), getDomain(mNewAccountName)); |
+ } else { |
+ // Go to the next state. |
+ progress(); |
+ } |
+ |
+ break; |
+ case AFTER_NEW_ACCOUNT_DIALOG: |
+ mState = State.DONE; |
+ mCallback.onConfirm(mWipeData); |
+ break; |
+ default: |
Bernhard Bauer
2016/06/03 08:50:06
Could you just list the remaining value here?
PEConn
2016/06/27 09:34:32
Done.
|
+ assert false : "Invalid state"; |
+ } |
+ } |
+ |
+ // 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() { |
+ mCallback.onCancel(); |
Bernhard Bauer
2016/06/03 08:50:06
You could also transition to the DONE state here,
PEConn
2016/06/27 09:34:32
Done.
|
+ } |
+} |
+ |