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

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

Issue 2014833002: Show dialogs for syncing to managed accounts. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 7 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/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.
+ }
+}
+

Powered by Google App Engine
This is Rietveld 408576698