Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 package org.chromium.chrome.browser.signin; | 5 package org.chromium.chrome.browser.signin; |
| 6 | 6 |
| 7 import android.app.DialogFragment; | 7 import android.app.DialogFragment; |
| 8 import android.app.Fragment; | 8 import android.app.Fragment; |
| 9 import android.app.FragmentManager; | 9 import android.app.FragmentManager; |
| 10 import android.content.Context; | 10 import android.content.Context; |
| 11 import android.support.annotation.IntDef; | 11 import android.support.annotation.IntDef; |
| 12 import android.text.TextUtils; | 12 import android.text.TextUtils; |
| 13 | 13 |
| 14 import org.chromium.base.Callback; | 14 import org.chromium.base.Callback; |
| 15 import org.chromium.base.Promise; | 15 import org.chromium.base.ThreadUtils; |
| 16 import org.chromium.chrome.browser.signin.ConfirmImportSyncDataDialog.ImportSync Type; | 16 import org.chromium.chrome.browser.signin.ConfirmImportSyncDataDialog.ImportSync Type; |
| 17 | 17 |
| 18 import java.lang.annotation.Retention; | 18 import java.lang.annotation.Retention; |
| 19 import java.lang.annotation.RetentionPolicy; | 19 import java.lang.annotation.RetentionPolicy; |
| 20 | 20 |
| 21 /** | 21 /** |
| 22 * This class takes care of the various dialogs that must be shown when the user changes the | 22 * This class takes care of the various dialogs that must be shown when the user changes the |
| 23 * account they are syncing to (either directly, or by signing in to a new accou nt). Most of the | 23 * account they are syncing to (either directly, or by signing in to a new accou nt). Most of the |
| 24 * complexity is due to many of the decisions getting answered through callbacks . | 24 * complexity is due to many of the decisions getting answered through callbacks . |
| 25 * | 25 * |
| 26 * This class progresses along the following state machine: | 26 * This class progresses along the following state machine: |
| 27 * | 27 * |
| 28 * E----\ G--\ | 28 * E-----\ G--\ |
| 29 * ^ | ^ | | 29 * ^ | ^ | |
| 30 * | | | v | 30 * | v | v |
| 31 * A->B->C->D-+->F->H | 31 * A->B->C->D->+->F->H |
| 32 * | | | 32 * | ^ |
| 33 * \-------/ | 33 * v | |
| 34 * \--------/ | |
| 34 * | 35 * |
| 35 * Where: | 36 * Where: |
| 36 * A - Start | 37 * A - Start |
| 37 * B - Decision: progress to C if the user signed in previously to a different a ccount, F otherwise. | 38 * B - Decision: progress to C if the user signed in previously to a different a ccount, F otherwise. |
| 38 * C - Decision: progress to E if we are switching from a managed account, D oth erwise. | 39 * C - Decision: progress to E if we are switching from a managed account, D oth erwise. |
| 39 * D - Action: show Import Data Dialog. | 40 * D - Action: show Import Data Dialog. |
| 40 * E - Action: show Switching from Managed Account Dialog. | 41 * E - Action: show Switching from Managed Account Dialog. |
| 41 * F - Decision: progress to G if we are switching to a managed account, H other wise. | 42 * F - Decision: progress to G if we are switching to a managed account, H other wise. |
| 42 * G - Action: show Switching to Managed Account Dialog. | 43 * G - Action: show Switching to Managed Account Dialog. |
| 43 * H - End: perform {@link ConfirmImportSyncDataDialog.Listener#onConfirm} with the result of the | 44 * H - End: perform {@link ConfirmImportSyncDataDialog.Listener#onConfirm} with the result of the |
| 44 * Import Data Dialog, if displayed or true if switching from a managed acco unt. | 45 * Import Data Dialog, if displayed or true if switching from a managed acco unt. |
| 45 * | 46 * |
| 46 * At any dialog, the user can cancel the dialog and end the whole process (resu lting in | 47 * At any dialog, the user can cancel the dialog and end the whole process (resu lting in |
| 47 * {@link ConfirmImportSyncDataDialog.Listener#onCancel}). | 48 * {@link ConfirmImportSyncDataDialog.Listener#onCancel}). |
| 48 */ | 49 */ |
| 49 public class ConfirmSyncDataStateMachine | 50 public class ConfirmSyncDataStateMachine |
| 50 implements ConfirmImportSyncDataDialog.Listener, ConfirmManagedSyncDataD ialog.Listener { | 51 implements ConfirmImportSyncDataDialog.Listener, ConfirmManagedSyncDataD ialog.Listener { |
| 51 | |
| 52 @IntDef({ | |
| 53 BEFORE_OLD_ACCOUNT_DIALOG, BEFORE_NEW_ACCOUNT_DIALOG, | |
| 54 AFTER_NEW_ACCOUNT_DIALOG, DONE | |
| 55 }) | |
| 56 @Retention(RetentionPolicy.SOURCE) | 52 @Retention(RetentionPolicy.SOURCE) |
| 53 @IntDef({BEFORE_OLD_ACCOUNT_DIALOG, BEFORE_NEW_ACCOUNT_DIALOG, AFTER_NEW_ACC OUNT_DIALOG, DONE}) | |
| 57 private @interface State {} | 54 private @interface State {} |
| 58 private static final int BEFORE_OLD_ACCOUNT_DIALOG = 0; // Start of state B . | 55 private static final int BEFORE_OLD_ACCOUNT_DIALOG = 0; // Start of state B . |
| 59 private static final int BEFORE_NEW_ACCOUNT_DIALOG = 1; // Start of state F . | 56 private static final int BEFORE_NEW_ACCOUNT_DIALOG = 1; // Start of state F . |
| 60 private static final int AFTER_NEW_ACCOUNT_DIALOG = 2; // Start of state H . | 57 private static final int AFTER_NEW_ACCOUNT_DIALOG = 2; // Start of state H . |
| 61 private static final int DONE = 4; | 58 private static final int DONE = 4; |
| 62 | 59 |
| 63 private boolean mWipeData; | |
| 64 @State private int mState = BEFORE_OLD_ACCOUNT_DIALOG; | 60 @State private int mState = BEFORE_OLD_ACCOUNT_DIALOG; |
| 65 | 61 |
| 62 private static final int ACCOUNT_CHECK_TIMEOUT_MS = 30000; | |
| 63 | |
| 66 private final ConfirmImportSyncDataDialog.Listener mCallback; | 64 private final ConfirmImportSyncDataDialog.Listener mCallback; |
| 67 private final String mOldAccountName; | 65 private final String mOldAccountName; |
| 68 private final String mNewAccountName; | 66 private final String mNewAccountName; |
| 69 private final boolean mCurrentlyManaged; | 67 private final boolean mCurrentlyManaged; |
| 70 private final Promise<Boolean> mNewAccountManaged = new Promise<>(); | |
| 71 private final FragmentManager mFragmentManager; | 68 private final FragmentManager mFragmentManager; |
| 72 private final Context mContext; | 69 private final Context mContext; |
| 73 private final ImportSyncType mImportSyncType; | 70 private final ImportSyncType mImportSyncType; |
| 71 private final ConfirmSyncDataStateMachineDelegate mDelegate; | |
| 72 | |
| 73 private boolean mWipeData; | |
| 74 private Boolean mNewAccountManaged; | |
| 74 | 75 |
| 75 /** | 76 /** |
| 76 * Run this state machine, displaying the appropriate dialogs. | 77 * Run this state machine, displaying the appropriate dialogs. |
| 77 * @param callback One of the two functions of the {@link ConfirmImportSyncD ataDialog.Listener} | 78 * @param callback One of the two functions of the {@link ConfirmImportSyncD ataDialog.Listener} |
| 78 * are guaranteed to be called. | 79 * are guaranteed to be called. |
| 79 */ | 80 */ |
| 80 public static void run(String oldAccountName, String newAccountName, | 81 public static void run(String oldAccountName, String newAccountName, |
| 81 ImportSyncType importSyncType, FragmentManager fragmentManager, Cont ext context, | 82 ImportSyncType importSyncType, FragmentManager fragmentManager, Cont ext context, |
| 82 ConfirmImportSyncDataDialog.Listener callback) { | 83 ConfirmImportSyncDataDialog.Listener callback) { |
| 83 // Includes implicit not-null assertion. | 84 // Includes implicit not-null assertion. |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 115 ConfirmImportSyncDataDialog.Listener callback) { | 116 ConfirmImportSyncDataDialog.Listener callback) { |
| 116 mOldAccountName = oldAccountName; | 117 mOldAccountName = oldAccountName; |
| 117 mNewAccountName = newAccountName; | 118 mNewAccountName = newAccountName; |
| 118 mImportSyncType = importSyncType; | 119 mImportSyncType = importSyncType; |
| 119 mFragmentManager = fragmentManager; | 120 mFragmentManager = fragmentManager; |
| 120 mContext = context; | 121 mContext = context; |
| 121 mCallback = callback; | 122 mCallback = callback; |
| 122 | 123 |
| 123 mCurrentlyManaged = SigninManager.get(context).getManagementDomain() != null; | 124 mCurrentlyManaged = SigninManager.get(context).getManagementDomain() != null; |
| 124 | 125 |
| 126 mDelegate = new ConfirmSyncDataStateMachineDelegate(mContext); | |
| 127 | |
| 125 // This check isn't needed right now, but can take a few seconds, so we kick it off early. | 128 // This check isn't needed right now, but can take a few seconds, so we kick it off early. |
|
gogerald1
2017/03/28 20:22:52
nit: might change this comment accordingly for the
bsazonov
2017/03/29 13:05:05
Fixed the comment. Thanks for pointing it out.
| |
| 126 SigninManager.isUserManaged(mNewAccountName, mNewAccountManaged.fulfillm entCallback()); | 129 requestNewAccountManagementStatus(); |
| 127 } | 130 } |
| 128 | 131 |
| 129 /** | 132 /** |
| 130 * This will progress the state machine, by moving the state along and then by either calling | 133 * This will progress the state machine, by moving the state along and then by either calling |
| 131 * itself directly or creating a dialog. If the dialog is dismissed or answe red negatively the | 134 * itself directly or creating a dialog. If the dialog is dismissed or answe red negatively the |
| 132 * entire flow is over, if it is answered positively one of the onConfirm fu nctions is called | 135 * entire flow is over, if it is answered positively one of the onConfirm fu nctions is called |
| 133 * and this function is called again. | 136 * and this function is called again. |
| 134 */ | 137 */ |
| 135 private void progress() { | 138 private void progress() { |
| 136 switch (mState) { | 139 switch (mState) { |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 155 mOldAccountName, mNewAccountName); | 158 mOldAccountName, mNewAccountName); |
| 156 } else { | 159 } else { |
| 157 // This will call back into onConfirm(boolean wipeData) on s uccess. | 160 // This will call back into onConfirm(boolean wipeData) on s uccess. |
| 158 ConfirmImportSyncDataDialog.showNewInstance(mOldAccountName, mNewAccountName, | 161 ConfirmImportSyncDataDialog.showNewInstance(mOldAccountName, mNewAccountName, |
| 159 mImportSyncType, mFragmentManager, this); | 162 mImportSyncType, mFragmentManager, this); |
| 160 } | 163 } |
| 161 | 164 |
| 162 break; | 165 break; |
| 163 case BEFORE_NEW_ACCOUNT_DIALOG: | 166 case BEFORE_NEW_ACCOUNT_DIALOG: |
| 164 mState = AFTER_NEW_ACCOUNT_DIALOG; | 167 mState = AFTER_NEW_ACCOUNT_DIALOG; |
| 165 | 168 if (mNewAccountManaged != null) { |
| 166 mNewAccountManaged.then(new Callback<Boolean>() { | 169 // No need to show dialog if account management status is al ready known |
| 167 @Override | 170 handleNewAccountManagementStatus(); |
| 168 public void onResult(Boolean newAccountManaged) { | 171 } else { |
| 169 if (newAccountManaged) { | 172 showProgressDialog(); |
| 170 // Show 'logging into managed account' dialog | 173 scheduleTimeout(); |
| 171 // This will call back into onConfirm on success. | 174 } |
| 172 ConfirmManagedSyncDataDialog.showSignInToManagedAcco untDialog( | |
| 173 ConfirmSyncDataStateMachine.this, | |
| 174 mFragmentManager, mContext.getResources(), | |
| 175 SigninManager.extractDomainName(mNewAccountN ame)); | |
| 176 } else { | |
| 177 progress(); | |
| 178 } | |
| 179 } | |
| 180 }); | |
| 181 | |
| 182 break; | 175 break; |
| 183 case AFTER_NEW_ACCOUNT_DIALOG: | 176 case AFTER_NEW_ACCOUNT_DIALOG: |
| 184 mState = DONE; | 177 mState = DONE; |
| 185 mCallback.onConfirm(mWipeData); | 178 mCallback.onConfirm(mWipeData); |
| 186 break; | 179 break; |
| 187 case DONE: | 180 case DONE: |
| 188 throw new IllegalStateException("Can't progress from DONE state! "); | 181 throw new IllegalStateException("Can't progress from DONE state! "); |
| 189 } | 182 } |
| 190 } | 183 } |
| 191 | 184 |
| 185 private void requestNewAccountManagementStatus() { | |
| 186 SigninManager.isUserManaged(mNewAccountName, new Callback<Boolean>() { | |
| 187 @Override | |
| 188 public void onResult(Boolean result) { | |
| 189 setIsNewAccountManaged(result); | |
| 190 } | |
| 191 }); | |
| 192 } | |
| 193 | |
| 194 private void setIsNewAccountManaged(Boolean isManaged) { | |
| 195 assert isManaged != null; | |
| 196 mNewAccountManaged = isManaged; | |
| 197 if (mState == AFTER_NEW_ACCOUNT_DIALOG) { | |
| 198 handleNewAccountManagementStatus(); | |
| 199 } | |
| 200 } | |
| 201 | |
| 202 private void handleNewAccountManagementStatus() { | |
| 203 assert mNewAccountManaged != null; | |
| 204 assert mState == AFTER_NEW_ACCOUNT_DIALOG; | |
| 205 | |
| 206 mDelegate.dismissFetchManagementPolicyProgressDialog(); | |
| 207 mDelegate.dismissFetchManagementPolicyTimeoutDialog(); | |
| 208 | |
| 209 if (mNewAccountManaged) { | |
| 210 // Show 'logging into managed account' dialog | |
| 211 // This will call back into onConfirm on success. | |
| 212 ConfirmManagedSyncDataDialog.showSignInToManagedAccountDialog( | |
| 213 ConfirmSyncDataStateMachine.this, mFragmentManager, mContext .getResources(), | |
| 214 SigninManager.extractDomainName(mNewAccountName)); | |
| 215 } else { | |
| 216 progress(); | |
| 217 } | |
| 218 } | |
| 219 | |
| 220 private void showProgressDialog() { | |
| 221 mDelegate.showFetchManagementPolicyProgressDialog( | |
| 222 new ConfirmSyncDataStateMachineDelegate.ProgressDialogListener() { | |
| 223 @Override | |
| 224 public void onCancel() { | |
| 225 ConfirmSyncDataStateMachine.this.onCancel(); | |
| 226 } | |
| 227 }); | |
| 228 } | |
| 229 | |
| 230 private void scheduleTimeout() { | |
| 231 ThreadUtils.postOnUiThreadDelayed(new Runnable() { | |
| 232 @Override | |
| 233 public void run() { | |
| 234 checkTimeout(); | |
| 235 } | |
| 236 }, ACCOUNT_CHECK_TIMEOUT_MS); | |
| 237 } | |
| 238 | |
| 239 private void checkTimeout() { | |
| 240 if (mState != AFTER_NEW_ACCOUNT_DIALOG || mNewAccountManaged != null) { | |
| 241 return; | |
| 242 } | |
| 243 | |
| 244 mDelegate.showFetchManagementPolicyTimeoutDialog( | |
| 245 new ConfirmSyncDataStateMachineDelegate.TimeoutDialogListener() { | |
| 246 @Override | |
| 247 public void onCancel() { | |
| 248 ConfirmSyncDataStateMachine.this.onCancel(); | |
| 249 } | |
| 250 | |
| 251 @Override | |
| 252 public void onRetry() { | |
| 253 requestNewAccountManagementStatus(); | |
| 254 scheduleTimeout(); | |
| 255 } | |
| 256 }); | |
| 257 } | |
| 258 | |
| 192 // ConfirmImportSyncDataDialog.Listener implementation. | 259 // ConfirmImportSyncDataDialog.Listener implementation. |
| 193 @Override | 260 @Override |
| 194 public void onConfirm(boolean wipeData) { | 261 public void onConfirm(boolean wipeData) { |
| 195 mWipeData = wipeData; | 262 mWipeData = wipeData; |
| 196 progress(); | 263 progress(); |
| 197 } | 264 } |
| 198 | 265 |
| 199 // ConfirmManagedSyncDataDialog.Listener implementation. | 266 // ConfirmManagedSyncDataDialog.Listener implementation. |
| 200 @Override | 267 @Override |
| 201 public void onConfirm() { | 268 public void onConfirm() { |
| 202 progress(); | 269 progress(); |
| 203 } | 270 } |
| 204 | 271 |
| 205 // ConfirmImportSyncDataDialog.Listener & ConfirmManagedSyncDataDialog.Liste ner implementation. | 272 // ConfirmImportSyncDataDialog.Listener & ConfirmManagedSyncDataDialog.Liste ner implementation. |
| 206 @Override | 273 @Override |
| 207 public void onCancel() { | 274 public void onCancel() { |
| 208 mState = DONE; | 275 mState = DONE; |
| 209 mCallback.onCancel(); | 276 mCallback.onCancel(); |
| 277 mDelegate.dismissFetchManagementPolicyProgressDialog(); | |
| 278 mDelegate.dismissFetchManagementPolicyTimeoutDialog(); | |
| 210 } | 279 } |
| 211 } | 280 } |
| 212 | 281 |
| OLD | NEW |