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

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

Issue 2772203004: Add progress and timeout dialogs for getting account management policy (Closed)
Patch Set: Updated strings and addressed comments Created 3 years, 8 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 unified diff | Download patch
OLDNEW
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.os.Handler;
11 import android.support.annotation.IntDef; 12 import android.support.annotation.IntDef;
12 import android.text.TextUtils; 13 import android.text.TextUtils;
13 14
14 import org.chromium.base.Callback; 15 import org.chromium.base.Callback;
15 import org.chromium.base.Promise; 16 import org.chromium.base.ThreadUtils;
16 import org.chromium.chrome.browser.signin.ConfirmImportSyncDataDialog.ImportSync Type; 17 import org.chromium.chrome.browser.signin.ConfirmImportSyncDataDialog.ImportSync Type;
17 18
18 import java.lang.annotation.Retention; 19 import java.lang.annotation.Retention;
19 import java.lang.annotation.RetentionPolicy; 20 import java.lang.annotation.RetentionPolicy;
20 21
21 /** 22 /**
22 * This class takes care of the various dialogs that must be shown when the user changes the 23 * 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 24 * 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 . 25 * complexity is due to many of the decisions getting answered through callbacks .
25 * 26 *
26 * This class progresses along the following state machine: 27 * This class progresses along the following state machine:
27 * 28 *
28 * E----\ G--\ 29 * E-----\ G--\
29 * ^ | ^ | 30 * ^ | ^ |
30 * | | | v 31 * | v | v
31 * A->B->C->D-+->F->H 32 * A->B->C->D->+->F->H
32 * | | 33 * | ^
33 * \-------/ 34 * v |
35 * \--------/
34 * 36 *
35 * Where: 37 * Where:
36 * A - Start 38 * A - Start
37 * B - Decision: progress to C if the user signed in previously to a different a ccount, F otherwise. 39 * 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. 40 * C - Decision: progress to E if we are switching from a managed account, D oth erwise.
39 * D - Action: show Import Data Dialog. 41 * D - Action: show Import Data Dialog.
40 * E - Action: show Switching from Managed Account Dialog. 42 * 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. 43 * 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. 44 * G - Action: show Switching to Managed Account Dialog.
43 * H - End: perform {@link ConfirmImportSyncDataDialog.Listener#onConfirm} with the result of the 45 * 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. 46 * Import Data Dialog, if displayed or true if switching from a managed acco unt.
45 * 47 *
46 * At any dialog, the user can cancel the dialog and end the whole process (resu lting in 48 * At any dialog, the user can cancel the dialog and end the whole process (resu lting in
47 * {@link ConfirmImportSyncDataDialog.Listener#onCancel}). 49 * {@link ConfirmImportSyncDataDialog.Listener#onCancel}).
48 */ 50 */
49 public class ConfirmSyncDataStateMachine 51 public class ConfirmSyncDataStateMachine
50 implements ConfirmImportSyncDataDialog.Listener, ConfirmManagedSyncDataD ialog.Listener { 52 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) 53 @Retention(RetentionPolicy.SOURCE)
54 @IntDef({BEFORE_OLD_ACCOUNT_DIALOG, BEFORE_NEW_ACCOUNT_DIALOG, AFTER_NEW_ACC OUNT_DIALOG, DONE})
57 private @interface State {} 55 private @interface State {}
58 private static final int BEFORE_OLD_ACCOUNT_DIALOG = 0; // Start of state B . 56 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 . 57 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 . 58 private static final int AFTER_NEW_ACCOUNT_DIALOG = 2; // Start of state H .
61 private static final int DONE = 4; 59 private static final int DONE = 4;
62 60
63 private boolean mWipeData;
64 @State private int mState = BEFORE_OLD_ACCOUNT_DIALOG; 61 @State private int mState = BEFORE_OLD_ACCOUNT_DIALOG;
65 62
63 private static final int ACCOUNT_CHECK_TIMEOUT_MS = 30000;
64
66 private final ConfirmImportSyncDataDialog.Listener mCallback; 65 private final ConfirmImportSyncDataDialog.Listener mCallback;
67 private final String mOldAccountName; 66 private final String mOldAccountName;
68 private final String mNewAccountName; 67 private final String mNewAccountName;
69 private final boolean mCurrentlyManaged; 68 private final boolean mCurrentlyManaged;
70 private final Promise<Boolean> mNewAccountManaged = new Promise<>();
71 private final FragmentManager mFragmentManager; 69 private final FragmentManager mFragmentManager;
72 private final Context mContext; 70 private final Context mContext;
73 private final ImportSyncType mImportSyncType; 71 private final ImportSyncType mImportSyncType;
72 private final ConfirmSyncDataStateMachineDelegate mDelegate;
73 private final Handler mHandler = new Handler();
74
75 private boolean mWipeData;
76 private Boolean mNewAccountManaged;
77 private Runnable mCheckTimeoutRunnable;
74 78
75 /** 79 /**
76 * Run this state machine, displaying the appropriate dialogs. 80 * Run this state machine, displaying the appropriate dialogs.
77 * @param callback One of the two functions of the {@link ConfirmImportSyncD ataDialog.Listener} 81 * @param callback One of the two functions of the {@link ConfirmImportSyncD ataDialog.Listener}
78 * are guaranteed to be called. 82 * are guaranteed to be called.
79 */ 83 */
80 public static void run(String oldAccountName, String newAccountName, 84 public static void run(String oldAccountName, String newAccountName,
81 ImportSyncType importSyncType, FragmentManager fragmentManager, Cont ext context, 85 ImportSyncType importSyncType, FragmentManager fragmentManager, Cont ext context,
82 ConfirmImportSyncDataDialog.Listener callback) { 86 ConfirmImportSyncDataDialog.Listener callback) {
83 // Includes implicit not-null assertion. 87 // Includes implicit not-null assertion.
(...skipping 22 matching lines...) Expand all
106 if (fragment == null) return; 110 if (fragment == null) return;
107 DialogFragment dialogFragment = (DialogFragment) fragment; 111 DialogFragment dialogFragment = (DialogFragment) fragment;
108 112
109 if (dialogFragment.getDialog() == null) return; 113 if (dialogFragment.getDialog() == null) return;
110 dialogFragment.getDialog().cancel(); 114 dialogFragment.getDialog().cancel();
111 } 115 }
112 116
113 private ConfirmSyncDataStateMachine(String oldAccountName, String newAccount Name, 117 private ConfirmSyncDataStateMachine(String oldAccountName, String newAccount Name,
114 ImportSyncType importSyncType, FragmentManager fragmentManager, Cont ext context, 118 ImportSyncType importSyncType, FragmentManager fragmentManager, Cont ext context,
115 ConfirmImportSyncDataDialog.Listener callback) { 119 ConfirmImportSyncDataDialog.Listener callback) {
120 ThreadUtils.assertOnUiThread();
121
116 mOldAccountName = oldAccountName; 122 mOldAccountName = oldAccountName;
117 mNewAccountName = newAccountName; 123 mNewAccountName = newAccountName;
118 mImportSyncType = importSyncType; 124 mImportSyncType = importSyncType;
119 mFragmentManager = fragmentManager; 125 mFragmentManager = fragmentManager;
120 mContext = context; 126 mContext = context;
121 mCallback = callback; 127 mCallback = callback;
122 128
123 mCurrentlyManaged = SigninManager.get(context).getManagementDomain() != null; 129 mCurrentlyManaged = SigninManager.get(context).getManagementDomain() != null;
124 130
125 // This check isn't needed right now, but can take a few seconds, so we kick it off early. 131 mDelegate = new ConfirmSyncDataStateMachineDelegate(mContext);
126 SigninManager.isUserManaged(mNewAccountName, mNewAccountManaged.fulfillm entCallback()); 132
133 // New account management status isn't needed right now, but fetching it
134 // can take a few seconds, so we kick it off early.
135 requestNewAccountManagementStatus();
127 } 136 }
128 137
129 /** 138 /**
130 * This will progress the state machine, by moving the state along and then by either calling 139 * 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 140 * 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 141 * entire flow is over, if it is answered positively one of the onConfirm fu nctions is called
133 * and this function is called again. 142 * and this function is called again.
134 */ 143 */
135 private void progress() { 144 private void progress() {
136 switch (mState) { 145 switch (mState) {
(...skipping 18 matching lines...) Expand all
155 mOldAccountName, mNewAccountName); 164 mOldAccountName, mNewAccountName);
156 } else { 165 } else {
157 // This will call back into onConfirm(boolean wipeData) on s uccess. 166 // This will call back into onConfirm(boolean wipeData) on s uccess.
158 ConfirmImportSyncDataDialog.showNewInstance(mOldAccountName, mNewAccountName, 167 ConfirmImportSyncDataDialog.showNewInstance(mOldAccountName, mNewAccountName,
159 mImportSyncType, mFragmentManager, this); 168 mImportSyncType, mFragmentManager, this);
160 } 169 }
161 170
162 break; 171 break;
163 case BEFORE_NEW_ACCOUNT_DIALOG: 172 case BEFORE_NEW_ACCOUNT_DIALOG:
164 mState = AFTER_NEW_ACCOUNT_DIALOG; 173 mState = AFTER_NEW_ACCOUNT_DIALOG;
165 174 if (mNewAccountManaged != null) {
166 mNewAccountManaged.then(new Callback<Boolean>() { 175 // No need to show dialog if account management status is al ready known
167 @Override 176 handleNewAccountManagementStatus();
168 public void onResult(Boolean newAccountManaged) { 177 } else {
169 if (newAccountManaged) { 178 showProgressDialog();
170 // Show 'logging into managed account' dialog 179 scheduleTimeout();
171 // This will call back into onConfirm on success. 180 }
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; 181 break;
183 case AFTER_NEW_ACCOUNT_DIALOG: 182 case AFTER_NEW_ACCOUNT_DIALOG:
184 mState = DONE; 183 mState = DONE;
185 mCallback.onConfirm(mWipeData); 184 mCallback.onConfirm(mWipeData);
186 break; 185 break;
187 case DONE: 186 case DONE:
188 throw new IllegalStateException("Can't progress from DONE state! "); 187 throw new IllegalStateException("Can't progress from DONE state! ");
189 } 188 }
190 } 189 }
191 190
191 private void requestNewAccountManagementStatus() {
192 SigninManager.isUserManaged(mNewAccountName, new Callback<Boolean>() {
193 @Override
194 public void onResult(Boolean result) {
195 setIsNewAccountManaged(result);
196 }
197 });
198 }
199
200 private void setIsNewAccountManaged(Boolean isManaged) {
201 assert isManaged != null;
202 mNewAccountManaged = isManaged;
203 if (mState == AFTER_NEW_ACCOUNT_DIALOG) {
204 cancelTimeout();
205 handleNewAccountManagementStatus();
206 }
207 }
208
209 private void handleNewAccountManagementStatus() {
210 assert mNewAccountManaged != null;
211 assert mState == AFTER_NEW_ACCOUNT_DIALOG;
212
213 mDelegate.dismissAllDialogs();
214
215 if (mNewAccountManaged) {
216 // Show 'logging into managed account' dialog
217 // This will call back into onConfirm on success.
218 ConfirmManagedSyncDataDialog.showSignInToManagedAccountDialog(
219 ConfirmSyncDataStateMachine.this, mFragmentManager, mContext .getResources(),
220 SigninManager.extractDomainName(mNewAccountName));
221 } else {
222 progress();
223 }
224 }
225
226 private void showProgressDialog() {
227 mDelegate.showFetchManagementPolicyProgressDialog(
228 new ConfirmSyncDataStateMachineDelegate.ProgressDialogListener() {
229 @Override
230 public void onCancel() {
231 ConfirmSyncDataStateMachine.this.onCancel();
232 }
233 });
234 }
235
236 private void scheduleTimeout() {
237 if (mCheckTimeoutRunnable == null) {
238 mCheckTimeoutRunnable = new Runnable() {
239 @Override
240 public void run() {
241 checkTimeout();
242 }
243 };
244 }
245 mHandler.postDelayed(mCheckTimeoutRunnable, ACCOUNT_CHECK_TIMEOUT_MS);
246 }
247
248 private void cancelTimeout() {
249 if (mCheckTimeoutRunnable == null) {
250 return;
251 }
252 mHandler.removeCallbacks(mCheckTimeoutRunnable);
253 mCheckTimeoutRunnable = null;
254 }
255
256 private void checkTimeout() {
257 assert mState == AFTER_NEW_ACCOUNT_DIALOG;
258 assert mNewAccountManaged == null;
259
260 mDelegate.showFetchManagementPolicyTimeoutDialog(
261 new ConfirmSyncDataStateMachineDelegate.TimeoutDialogListener() {
262 @Override
263 public void onCancel() {
264 ConfirmSyncDataStateMachine.this.onCancel();
265 }
266
267 @Override
268 public void onRetry() {
269 requestNewAccountManagementStatus();
270 scheduleTimeout();
271 }
272 });
273 }
274
192 // ConfirmImportSyncDataDialog.Listener implementation. 275 // ConfirmImportSyncDataDialog.Listener implementation.
193 @Override 276 @Override
194 public void onConfirm(boolean wipeData) { 277 public void onConfirm(boolean wipeData) {
195 mWipeData = wipeData; 278 mWipeData = wipeData;
196 progress(); 279 progress();
197 } 280 }
198 281
199 // ConfirmManagedSyncDataDialog.Listener implementation. 282 // ConfirmManagedSyncDataDialog.Listener implementation.
200 @Override 283 @Override
201 public void onConfirm() { 284 public void onConfirm() {
202 progress(); 285 progress();
203 } 286 }
204 287
205 // ConfirmImportSyncDataDialog.Listener & ConfirmManagedSyncDataDialog.Liste ner implementation. 288 // ConfirmImportSyncDataDialog.Listener & ConfirmManagedSyncDataDialog.Liste ner implementation.
206 @Override 289 @Override
207 public void onCancel() { 290 public void onCancel() {
291 cancelTimeout();
292 mDelegate.dismissAllDialogs();
293
208 mState = DONE; 294 mState = DONE;
209 mCallback.onCancel(); 295 mCallback.onCancel();
210 } 296 }
211 } 297 }
212 298
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698