Commit 03f33b29 authored by peconn's avatar peconn Committed by Commit bot

Show dialogs for syncing to managed accounts earlier in the signin flow,...

Show dialogs for syncing to managed accounts earlier in the signin flow, moving them forward to be alongside the dialog for importing/wiping sync data.

BUG=595411, 612165

Review-Url: https://codereview.chromium.org/2014833002
Cr-Commit-Position: refs/heads/master@{#403195}
parent 8329ebd3
......@@ -126,6 +126,18 @@ public class Promise<T> {
exceptInner(onReject);
}
/**
* A convenience method that returns a Callback that fulfills this Promise with its result.
*/
public Callback<T> fulfillmentCallback() {
return new Callback<T>() {
@Override
public void onResult(T result) {
fulfill(result);
}
};
}
private void thenInner(Callback<T> onFulfill) {
if (mState == FULFILLED) {
postCallbackToLooper(onFulfill, mResult);
......
......@@ -70,7 +70,8 @@ import java.util.HashMap;
*/
public class AccountManagementFragment extends PreferenceFragment
implements SignOutDialogListener, ProfileDownloader.Observer,
SyncStateChangedListener, SignInStateObserver {
SyncStateChangedListener, SignInStateObserver,
ConfirmManagedSyncDataDialog.Listener {
public static final String SIGN_OUT_DIALOG_TAG = "sign_out_dialog_tag";
private static final String CLEAR_DATA_PROGRESS_DIALOG_TAG = "clear_data_progress";
......@@ -250,13 +251,24 @@ public class AccountManagementFragment extends PreferenceFragment
ProfileAccountManagementMetrics.TOGGLE_SIGNOUT,
mGaiaServiceType);
SignOutDialogFragment signOutFragment = new SignOutDialogFragment();
Bundle args = new Bundle();
args.putInt(SHOW_GAIA_SERVICE_TYPE_EXTRA, mGaiaServiceType);
signOutFragment.setArguments(args);
String managementDomain =
SigninManager.get(getActivity()).getManagementDomain();
if (managementDomain != null) {
// Show the 'You are signing out of a managed account' dialog.
ConfirmManagedSyncDataDialog.showSignOutFromManagedAccountDialog(
AccountManagementFragment.this, getFragmentManager(),
getResources(), managementDomain);
} else {
// Show the 'You are signing out' dialog.
SignOutDialogFragment signOutFragment = new SignOutDialogFragment();
Bundle args = new Bundle();
args.putInt(SHOW_GAIA_SERVICE_TYPE_EXTRA, mGaiaServiceType);
signOutFragment.setArguments(args);
signOutFragment.setTargetFragment(AccountManagementFragment.this, 0);
signOutFragment.show(getFragmentManager(), SIGN_OUT_DIALOG_TAG);
}
signOutFragment.setTargetFragment(AccountManagementFragment.this, 0);
signOutFragment.show(getFragmentManager(), SIGN_OUT_DIALOG_TAG);
return true;
}
......@@ -502,6 +514,17 @@ public class AccountManagementFragment extends PreferenceFragment
}
}
// ConfirmManagedSyncDataDialog.Listener implementation
@Override
public void onConfirm() {
onSignOutClicked();
}
@Override
public void onCancel() {
onSignOutDialogDismissed(false);
}
// ProfileSyncServiceListener implementation:
@Override
......
......@@ -24,9 +24,7 @@ import org.chromium.chrome.browser.firstrun.ProfileDataCache;
import org.chromium.chrome.browser.preferences.PrefServiceBridge;
import org.chromium.chrome.browser.profiles.ProfileDownloader;
import org.chromium.chrome.browser.signin.AccountTrackerService.OnSystemAccountsSeededListener;
import org.chromium.chrome.browser.sync.ui.ConfirmImportSyncDataDialog;
import org.chromium.chrome.browser.sync.ui.ConfirmImportSyncDataDialog.ImportSyncType;
import org.chromium.signin.InvestigatedScenario;
import org.chromium.chrome.browser.signin.ConfirmImportSyncDataDialog.ImportSyncType;
import org.chromium.sync.signin.AccountManagerHelper;
import org.chromium.ui.text.NoUnderlineClickableSpan;
import org.chromium.ui.text.SpanApplier;
......@@ -370,30 +368,25 @@ public class AccountSigninView extends FrameLayout implements ProfileDownloader.
private void showConfirmSigninPagePreviousAccountCheck() {
String accountName = getSelectedAccountName();
if (SigninInvestigator.investigate(accountName) == InvestigatedScenario.DIFFERENT_ACCOUNT) {
ConfirmImportSyncDataDialog.showNewInstance(
PrefServiceBridge.getInstance().getSyncLastAccountName(), accountName,
ImportSyncType.PREVIOUS_DATA_FOUND, mDelegate.getFragmentManager(),
new ConfirmImportSyncDataDialog.Listener() {
@Override
public void onConfirm(boolean wipeData) {
SigninManager.wipeSyncUserDataIfRequired(wipeData)
.then(new Callback<Void>() {
@Override
public void onResult(Void v) {
showConfirmSigninPage();
}
});
}
ConfirmSyncDataStateMachine.run(PrefServiceBridge.getInstance().getSyncLastAccountName(),
accountName, ImportSyncType.PREVIOUS_DATA_FOUND, mDelegate.getFragmentManager(),
getContext(), new ConfirmImportSyncDataDialog.Listener() {
@Override
public void onConfirm(boolean wipeData) {
SigninManager.wipeSyncUserDataIfRequired(wipeData)
.then(new Callback<Void>() {
@Override
public void onResult(Void v) {
showConfirmSigninPage();
}
});
}
@Override
public void onCancel() {
setButtonsEnabled(true);
}
});
} else {
showConfirmSigninPage();
}
@Override
public void onCancel() {
setButtonsEnabled(true);
}
});
}
private void setUpCancelButton() {
......
......@@ -2,7 +2,7 @@
// 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;
package org.chromium.chrome.browser.signin;
import android.app.Dialog;
import android.app.DialogFragment;
......@@ -19,7 +19,6 @@ import org.chromium.base.VisibleForTesting;
import org.chromium.base.metrics.RecordUserAction;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.preferences.ManagedPreferencesUtils;
import org.chromium.chrome.browser.signin.SigninManager;
import org.chromium.chrome.browser.widget.RadioButtonWithDescription;
import java.util.Arrays;
......
// Copyright 2014 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.Activity;
import android.app.Dialog;
import android.app.DialogFragment;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.os.Bundle;
import android.support.v7.app.AlertDialog;
import org.chromium.base.Log;
import org.chromium.chrome.R;
/**
* This is a dialog asking the user to confirm that they want to sign in to a managed account.
*/
public class ConfirmManagedSigninFragment extends DialogFragment implements OnClickListener {
private static final String TAG = "ConfirmManagedSignin";
private static final String KEY_MANAGEMENT_DOMAIN = "managementDomain";
// Tracks whether to abort signin in onDismiss.
private boolean mAbortSignin = true;
public static ConfirmManagedSigninFragment newInstance(String managementDomain) {
ConfirmManagedSigninFragment dialogFragment = new ConfirmManagedSigninFragment();
Bundle args = new Bundle();
args.putString(KEY_MANAGEMENT_DOMAIN, managementDomain);
dialogFragment.setArguments(args);
return dialogFragment;
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
setCancelable(false);
Activity activity = getActivity();
String managementDomain = getArguments().getString(KEY_MANAGEMENT_DOMAIN);
AlertDialog.Builder builder = new AlertDialog.Builder(activity, R.style.AlertDialogTheme);
builder.setTitle(R.string.policy_dialog_title);
builder.setMessage(activity.getResources().getString(
R.string.policy_dialog_message, managementDomain));
builder.setPositiveButton(R.string.policy_dialog_proceed, this);
builder.setNegativeButton(R.string.policy_dialog_cancel, this);
return builder.create();
}
@Override
public void onClick(DialogInterface dialog, int which) {
if (which == AlertDialog.BUTTON_POSITIVE) {
Log.d(TAG, "Accepted policy management, proceeding with sign-in.");
SigninManager.get(getActivity()).progressInteractiveSignInFlowManagedConfirmed();
mAbortSignin = false;
}
}
@Override
public void onDismiss(DialogInterface dialogInterface) {
super.onDismiss(dialogInterface);
if (mAbortSignin) {
Log.d(TAG, "Policy confirmation rejected; abort sign-in.");
SigninManager.get(getActivity()).abortSignIn();
}
}
}
// 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.Dialog;
import android.app.DialogFragment;
import android.app.FragmentManager;
import android.content.DialogInterface;
import android.content.res.Resources;
import android.os.Bundle;
import android.support.v7.app.AlertDialog;
import org.chromium.base.VisibleForTesting;
import org.chromium.chrome.R;
/**
* A class to display the dialogs the user may encounter when switching to/from or signing into/out
* of a managed account.
*/
public class ConfirmManagedSyncDataDialog extends DialogFragment
implements DialogInterface.OnClickListener {
/**
* A listener to allow the Dialog to report on the action taken. Either
* {@link Listener#onConfirm} or {@link Listener#onCancel} will be called once.
*/
public interface Listener {
/**
* The user has accepted the dialog.
*/
public void onConfirm();
/**
* The user has cancelled the dialog either through a negative response or by dismissing it.
*/
public void onCancel();
}
@VisibleForTesting
public static final String CONFIRM_IMPORT_SYNC_DATA_DIALOG_TAG =
"sync_managed_data_tag";
private static final String KEY_TITLE = "title";
private static final String KEY_DESCRIPTION = "description";
private static final String KEY_POSITIVE_BUTTON = "positiveButton";
private static final String KEY_NEGATIVE_BUTTON = "negativeButton";
private Listener mListener;
private boolean mListenerCalled;
/**
* Create the dialog to show when signing in to a managed account (either through sign in or
* when switching accounts).
* @param callback Callback for result.
* @param fragmentManager FragmentManaged to display the dialog.
* @param resources Resources to load the strings.
* @param domain The domain of the managed account.
*/
public static void showSignInToManagedAccountDialog(Listener callback,
FragmentManager fragmentManager, Resources resources, String domain) {
String title = resources.getString(R.string.sign_in_managed_account);
String positive = resources.getString(R.string.policy_dialog_proceed);
String negative = resources.getString(R.string.cancel);
String desc = resources.getString(R.string.sign_in_managed_account_description, domain);
showNewInstance(title, desc, positive, negative, fragmentManager, callback);
}
/**
* Create the dialog to show when signing out of a managed account (but not switching from a
* managed account).
* @param callback Callback for result.
* @param fragmentManager FragmentManaged to display the dialog.
* @param resources Resources to load the strings.
* @param domain The domain of the managed account.
*/
public static void showSignOutFromManagedAccountDialog(Listener callback,
FragmentManager fragmentManager, Resources resources, String domain) {
String title = resources.getString(R.string.sign_out_managed_account);
String positive = resources.getString(R.string.accept_and_sign_out);
String negative = resources.getString(R.string.cancel);
String desc = resources.getString(R.string.sign_out_managed_account_description, domain);
showNewInstance(title, desc, positive, negative, fragmentManager, callback);
}
/**
* Create the dialog to show when switching from a managed account.
* @param callback Callback for result.
* @param fragmentManager FragmentManaged to display the dialog.
* @param resources Resources to load the strings.
* @param domain The domain of the managed account.
* @param oldAccount The old account email address.
* @param newAccount The new account email address.
*/
public static void showSwitchFromManagedAccountDialog(Listener callback,
FragmentManager fragmentManager, Resources resources, String domain, String oldAccount,
String newAccount) {
String title = resources.getString(R.string.sign_out_managed_account);
String positive = resources.getString(R.string.accept_and_switch_accounts);
String negative = resources.getString(R.string.cancel);
String desc = resources.getString(R.string.switch_from_managed_account_description,
oldAccount, newAccount, domain);
showNewInstance(title, desc, positive, negative, fragmentManager, callback);
}
private static void showNewInstance(String title, String description, String positiveButton,
String negativeButton, FragmentManager fragmentManager, Listener callback) {
ConfirmManagedSyncDataDialog confirmSync =
newInstance(title, description, positiveButton, negativeButton);
confirmSync.setListener(callback);
confirmSync.show(fragmentManager, CONFIRM_IMPORT_SYNC_DATA_DIALOG_TAG);
}
private static ConfirmManagedSyncDataDialog newInstance(String title, String description,
String positiveButton, String negativeButton) {
ConfirmManagedSyncDataDialog fragment = new ConfirmManagedSyncDataDialog();
Bundle args = new Bundle();
args.putString(KEY_TITLE, title);
args.putString(KEY_DESCRIPTION, description);
args.putString(KEY_POSITIVE_BUTTON, positiveButton);
args.putString(KEY_NEGATIVE_BUTTON, negativeButton);
fragment.setArguments(args);
return fragment;
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
String title = getArguments().getString(KEY_TITLE);
String description = getArguments().getString(KEY_DESCRIPTION);
String positiveButton = getArguments().getString(KEY_POSITIVE_BUTTON);
String negativeButton = getArguments().getString(KEY_NEGATIVE_BUTTON);
return new AlertDialog.Builder(getActivity(), R.style.AlertDialogTheme)
.setTitle(title)
.setMessage(description)
.setPositiveButton(positiveButton, this)
.setNegativeButton(negativeButton, this)
.create();
}
private void setListener(Listener listener) {
assert mListener == null;
mListener = listener;
}
@Override
public void onClick(DialogInterface dialog, int which) {
if (which == AlertDialog.BUTTON_POSITIVE) {
mListener.onConfirm();
} else {
assert which == AlertDialog.BUTTON_NEGATIVE;
mListener.onCancel();
}
mListenerCalled = true;
}
@Override
public void onDismiss(DialogInterface dialog) {
super.onDismiss(dialog);
if (!mListenerCalled) {
mListener.onCancel();
}
}
}
// 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();
}
}
......@@ -6,7 +6,6 @@ package org.chromium.chrome.browser.signin;
import android.accounts.Account;
import android.app.Activity;
import android.app.DialogFragment;
import android.content.Context;
import android.os.Handler;
......@@ -18,7 +17,6 @@ import org.chromium.base.Log;
import org.chromium.base.ObserverList;
import org.chromium.base.Promise;
import org.chromium.base.ThreadUtils;
import org.chromium.base.VisibleForTesting;
import org.chromium.base.annotations.CalledByNative;
import org.chromium.base.metrics.RecordHistogram;
import org.chromium.base.metrics.RecordUserAction;
......@@ -43,12 +41,6 @@ import javax.annotation.Nullable;
public class SigninManager implements AccountTrackerService.OnSystemAccountsSeededListener {
private static final String TAG = "SigninManager";
private static final String CONFIRM_ACCOUNT_CHANGED_DIALOG_TAG =
"confirm_account_changed_dialog_tag";
@VisibleForTesting
public static final String CONFIRM_MANAGED_SIGNIN_DIALOG_TAG =
"confirm_managed_signin_dialog_tag";
private static SigninManager sSigninManager;
private static int sSignInAccessPoint = SigninAccessPoint.UNKNOWN;
......@@ -145,11 +137,6 @@ public class SigninManager implements AccountTrackerService.OnSystemAccountsSeed
public final Activity activity;
public final SignInCallback callback;
/**
* The dialog currently being displayed to the user, if any.
*/
public DialogFragment displayedDialog = null;
/**
* If the system accounts need to be seeded, the sign in flow will block for that to occur.
* This boolean should be set to true during that time and then reset back to false
......@@ -426,30 +413,7 @@ public class SigninManager implements AccountTrackerService.OnSystemAccountsSeed
return;
}
if (!mSignInState.isInteractive()) {
// If this is a forced sign-in then don't show the confirmation dialog.
// This will call back to onPolicyFetchedBeforeSignIn.
nativeFetchPolicyBeforeSignIn(mNativeSigninManagerAndroid);
return;
}
// TODO(peconn): Move this and other UI interactions into AccountSigninView.
Log.d(TAG, "Account has policy management");
mSignInState.displayedDialog = ConfirmManagedSigninFragment.newInstance(managementDomain);
mSignInState.displayedDialog.show(
mSignInState.activity.getFragmentManager(), CONFIRM_MANAGED_SIGNIN_DIALOG_TAG);
}
/**
* Called from ConfirmManagedSigninFragment if the managed account was confirmed.
*/
void progressInteractiveSignInFlowManagedConfirmed() {
if (mSignInState == null || mSignInState.displayedDialog == null) {
// Stop if sign-in was cancelled or this is a duplicate click event.
return;
}
mSignInState.displayedDialog = null;
// The user has already been notified that they are signing into a managed account.
// This will call back to onPolicyFetchedBeforeSignIn.
nativeFetchPolicyBeforeSignIn(mNativeSigninManagerAndroid);
}
......@@ -586,10 +550,6 @@ public class SigninManager implements AccountTrackerService.OnSystemAccountsSeed
assert signInState != null;
mSignInState = null;
if (signInState.displayedDialog != null) {
signInState.displayedDialog.dismiss();
}
if (signInState.callback != null) {
signInState.callback.onSignInAborted();
}
......@@ -671,10 +631,37 @@ public class SigninManager implements AccountTrackerService.OnSystemAccountsSeed
notifySignInAllowedChanged();
}
/**
* Performs an asynchronous check to see if the user is a managed user.
* @param callback A callback to be called with true if the user is a managed user and false
* otherwise.
*/
public static void isUserManaged(String email, final Callback<Boolean> callback) {
if (nativeShouldLoadPolicyForUser(email)) {
nativeIsUserManaged(email, callback);
} else {
// Although we know the result immediately, the caller may not be able to handle the
// callback being executed during this method call. So we post the callback on the
// looper.
ThreadUtils.postOnUiThread(new Runnable() {
@Override
public void run() {
callback.onResult(false);
}
});
}
}
public static String extractDomainName(String email) {
return nativeExtractDomainName(email);
}
// Native methods.
private static native String nativeExtractDomainName(String email);
private static native boolean nativeShouldLoadPolicyForUser(String username);
private static native void nativeIsUserManaged(String username, Callback<Boolean> callback);
private native long nativeInit();
private native boolean nativeIsSigninAllowedByPolicy(long nativeSigninManagerAndroid);
private native boolean nativeShouldLoadPolicyForUser(String username);
private native void nativeCheckPolicyBeforeSignIn(
long nativeSigninManagerAndroid, String username);
private native void nativeFetchPolicyBeforeSignIn(long nativeSigninManagerAndroid);
......
......@@ -12,10 +12,11 @@ import android.text.TextUtils;
import org.chromium.base.Callback;
import org.chromium.base.Promise;
import org.chromium.chrome.browser.preferences.SyncedAccountPreference;
import org.chromium.chrome.browser.signin.ConfirmImportSyncDataDialog;
import org.chromium.chrome.browser.signin.ConfirmImportSyncDataDialog.ImportSyncType;
import org.chromium.chrome.browser.signin.ConfirmSyncDataStateMachine;
import org.chromium.chrome.browser.signin.SigninManager;
import org.chromium.chrome.browser.signin.SigninManager.SignInCallback;
import org.chromium.chrome.browser.sync.ui.ConfirmImportSyncDataDialog;
import org.chromium.chrome.browser.sync.ui.ConfirmImportSyncDataDialog.ImportSyncType;
/**
* A class that encapsulates the control flow of listeners and callbacks when switching sync
......@@ -56,8 +57,10 @@ public class SyncAccountSwitcher
if (TextUtils.equals(mNewAccountName, currentAccount)) return false;
ConfirmImportSyncDataDialog.showNewInstance(currentAccount, mNewAccountName,
ImportSyncType.SWITCHING_SYNC_ACCOUNTS, mActivity.getFragmentManager(), this);
ConfirmSyncDataStateMachine.run(currentAccount, mNewAccountName,
ImportSyncType.SWITCHING_SYNC_ACCOUNTS, mActivity.getFragmentManager(),
mActivity, this);
// Don't update the selected account in the preference. It will be updated by
// the call to mSyncAccountListPreference.update() if everything succeeds.
......
......@@ -1054,6 +1054,27 @@ To obtain new licenses, connect to the internet and play your downloaded content
</message>
<!-- Sync strings -->
<message name="IDS_SIGN_OUT_MANAGED_ACCOUNT" desc="Title for prompts to sign out of managed accounts">
Sign out of managed account
</message>
<message name="IDS_SIGN_IN_MANAGED_ACCOUNT" desc="Title for prompts to sign in to managed accounts">
Sign in to managed account
</message>
<message name="IDS_SIGN_IN_MANAGED_ACCOUNT_DESCRIPTION" desc="Description for signing in to managed accounts">
You are signing in with an account managed by <ph name="MANAGED_DOMAIN">%1$s<ex>Google</ex></ph> and giving its administrator control over your Chrome data. Your data will become permanently tied to this account. Signing out of Chrome will delete your data from this device, but it will remain stored in your Google Account.
</message>
<message name="IDS_SIGN_OUT_MANAGED_ACCOUNT_DESCRIPTION" desc="Description for signing out of a managed account">
You are signing out of an account managed by <ph name="MANAGED_DOMAIN">%1$s<ex>Google</ex></ph>. This will delete your Chrome data from this device, but your data will remain in your Google Account.
</message>
<message name="IDS_SWITCH_FROM_MANAGED_ACCOUNT_DESCRIPTION" desc="Description for switching from a managed account">
You are switching sync accounts from <ph name="ACCOUNT_EMAIL_OLD">%1$s<ex>user@example.com</ex></ph> to <ph name="ACCOUNT_EMAIL_NEW">%2$s<ex>user@example.com</ex></ph>. Your existing Chrome data is managed by <ph name="MANAGED_DOMAIN">%3$s<ex>Google</ex></ph>. This will delete your data from this device, but your data will remain in <ph name="ACCOUNT_EMAIL_OLD">%1$s<ex>user@example.com</ex></ph>.
</message>
<message name="IDS_ACCEPT_AND_SIGN_OUT" desc="Button displayed for user to confirm and sign out of a managed account">
Accept and sign out
</message>
<message name="IDS_ACCEPT_AND_SWITCH_ACCOUNTS" desc="Button displayed for user to confirm and switch from a managed account">
Accept and switch accounts
</message>
<message name="IDS_SYNC_YOUR_BOOKMARKS" desc="Title for the prompt to signin and enable sync to sync their bookmarks">
Sync your bookmarks
</message>
......
......@@ -769,7 +769,9 @@ chrome_java_sources = [
"java/src/org/chromium/chrome/browser/signin/AccountSigninConfirmationView.java",
"java/src/org/chromium/chrome/browser/signin/AccountSigninView.java",
"java/src/org/chromium/chrome/browser/signin/AccountTrackerService.java",
"java/src/org/chromium/chrome/browser/signin/ConfirmManagedSigninFragment.java",
"java/src/org/chromium/chrome/browser/signin/ConfirmImportSyncDataDialog.java",
"java/src/org/chromium/chrome/browser/signin/ConfirmManagedSyncDataDialog.java",
"java/src/org/chromium/chrome/browser/signin/ConfirmSyncDataStateMachine.java",
"java/src/org/chromium/chrome/browser/signin/GoogleActivityController.java",
"java/src/org/chromium/chrome/browser/signin/OAuth2TokenService.java",
"java/src/org/chromium/chrome/browser/signin/SignOutDialogFragment.java",
......@@ -798,7 +800,6 @@ chrome_java_sources = [
"java/src/org/chromium/chrome/browser/sync/SyncNotificationController.java",
"java/src/org/chromium/chrome/browser/sync/SyncSessionsMetrics.java",
"java/src/org/chromium/chrome/browser/sync/SyncUserDataWiper.java",
"java/src/org/chromium/chrome/browser/sync/ui/ConfirmImportSyncDataDialog.java",
"java/src/org/chromium/chrome/browser/sync/ui/PassphraseActivity.java",
"java/src/org/chromium/chrome/browser/sync/ui/PassphraseCreationDialogFragment.java",
"java/src/org/chromium/chrome/browser/sync/ui/PassphraseDialogFragment.java",
......
......@@ -4,7 +4,6 @@
package org.chromium.chrome.browser.signin;
import android.accounts.Account;
import android.app.Activity;
import android.app.DialogFragment;
import android.app.Fragment;
......@@ -286,11 +285,8 @@ public class SigninTest extends ChromeTabbedActivityTestBase {
@MediumTest
public void testConsumerSignin() throws InterruptedException {
Account testAccount = SigninTestUtil.addTestAccount();
// Sign in to that account.
boolean isManaged = false;
signInToSingleAccount(testAccount.name, isManaged);
SigninTestUtil.addTestAccount();
signInToSingleAccount();
ThreadUtils.runOnUiThreadBlocking(new Runnable() {
@Override
......@@ -328,8 +324,7 @@ public class SigninTest extends ChromeTabbedActivityTestBase {
});
}
private void signInToSingleAccount(String accountName, boolean isManaged)
throws InterruptedException {
private void signInToSingleAccount() {
// Verify that we aren't signed in yet.
assertFalse(ChromeSigninController.get(mContext).isSignedIn());
......@@ -355,15 +350,10 @@ public class SigninTest extends ChromeTabbedActivityTestBase {
Button positiveButton = (Button) signinActivity.findViewById(R.id.positive_button);
// Press 'sign in'.
TestTouchUtils.performClickOnMainSync(getInstrumentation(), positiveButton);
getInstrumentation().waitForIdleSync();
// Press 'ok, got it' (the same button is reused).
TestTouchUtils.performClickOnMainSync(getInstrumentation(), positiveButton);
if (isManaged) {
// If the account is managed then there is going to be a second dialog.
assertFalse(ChromeSigninController.get(mContext).isSignedIn());
acceptAlertDialogWithTag(prefActivity, SigninManager.CONFIRM_MANAGED_SIGNIN_DIALOG_TAG);
}
// Sync doesn't actually start up until we finish the sync setup. This usually happens
// in the resume of the Main activity, but we forcefully do this here.
getInstrumentation().waitForIdleSync();
......
......@@ -6,6 +6,7 @@
#include "chrome/browser/android/signin/signin_manager_android.h"
#include "base/android/callback_android.h"
#include "base/android/jni_android.h"
#include "base/android/jni_array.h"
#include "base/android/jni_string.h"
......@@ -78,6 +79,12 @@ class ProfileDataRemover : public BrowsingDataRemover::Observer {
DISALLOW_COPY_AND_ASSIGN(ProfileDataRemover);
};
void UserManagementDomainFetched(
base::android::ScopedJavaGlobalRef<jobject> callback,
const std::string& dm_token, const std::string& client_id) {
base::android::RunCallbackAndroid(callback, !dm_token.empty());
}
} // namespace
SigninManagerAndroid::SigninManagerAndroid(JNIEnv* env, jobject obj)
......@@ -298,13 +305,42 @@ static jlong Init(JNIEnv* env, const JavaParamRef<jobject>& obj) {
static jboolean ShouldLoadPolicyForUser(
JNIEnv* env,
const JavaParamRef<jobject>& obj,
const JavaParamRef<jclass>& clazz,
const JavaParamRef<jstring>& j_username) {
std::string username =
base::android::ConvertJavaStringToUTF8(env, j_username);
return !policy::BrowserPolicyConnector::IsNonEnterpriseUser(username);
}
static void IsUserManaged(
JNIEnv* env,
const JavaParamRef<jclass>& clazz,
const JavaParamRef<jstring>& j_username,
const JavaParamRef<jobject>& j_callback) {
base::android::ScopedJavaGlobalRef<jobject> callback(env, j_callback);
Profile* profile = ProfileManager::GetActiveUserProfile();
std::string username =
base::android::ConvertJavaStringToUTF8(env, j_username);
policy::UserPolicySigninService* service =
policy::UserPolicySigninServiceFactory::GetForProfile(profile);
service->RegisterForPolicy(
username, AccountTrackerServiceFactory::GetForProfile(profile)
->FindAccountInfoByEmail(username)
.account_id,
base::Bind(&UserManagementDomainFetched, callback));
}
base::android::ScopedJavaLocalRef<jstring>
ExtractDomainName(
JNIEnv *env,
const JavaParamRef<jclass>& clazz,
const JavaParamRef<jstring>& j_email) {
std::string email = base::android::ConvertJavaStringToUTF8(env, j_email);
std::string domain = gaia::ExtractDomainName(email);
return base::android::ConvertUTF8ToJavaString(env, domain);
}
// static
bool SigninManagerAndroid::Register(JNIEnv* env) {
return RegisterNativesImpl(env);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment