Fix account matching at initial screen to match against email address

b/10210901

Change-Id: I64d60ca33a42a19e085dd98a7a61d68ac30027f9
This commit is contained in:
Tony Mantler 2013-09-25 14:47:13 -07:00
parent feb2c387b0
commit 463584d23f
6 changed files with 117 additions and 71 deletions

View File

@ -277,6 +277,46 @@ public class Utility {
return null;
}
/**
* This only actually matches against the email address. It's technically kosher to allow the
* same address across different account types, but that's a pretty rare use case and isn't well
* handled in the UI.
*
* @param context context
* @param syncAuthority the account manager type to check against or null for all types
* @param address email address to match against
* @return account name for match found or null
*/
public static String findExistingAccount(final Context context, final String syncAuthority,
final String address) {
final ContentResolver resolver = context.getContentResolver();
final Cursor c = resolver.query(Account.CONTENT_URI, Account.CONTENT_PROJECTION,
AccountColumns.EMAIL_ADDRESS + "=?", new String[] {address}, null);
try {
if (!c.moveToFirst()) {
return null;
}
return c.getString(c.getColumnIndex(Account.DISPLAY_NAME));
/*
do {
if (syncAuthority != null) {
// TODO: actually compare the sync authority to allow creating the same account
// on different protocols. Sadly this code can't directly access the service info
} else {
final Account account = new Account();
account.restore(c);
return account.mDisplayName;
}
} while (c.moveToNext());
*/
} finally {
c.close();
}
/*
return null;
*/
}
/**
* Generate a random message-id header for locally-generated messages.
*/

View File

@ -35,7 +35,6 @@ import com.android.email.R;
import com.android.email.activity.UiUtilities;
import com.android.emailcommon.provider.Account;
import com.android.emailcommon.provider.HostAuth;
import com.android.emailcommon.utility.Utility;
/**
* Common base class for server settings fragments, so they can be more easily manipulated by
@ -227,18 +226,6 @@ public abstract class AccountServerBaseFragment extends Fragment
mCallback.onEnableProceedButtons(enable);
}
/**
* Performs async operations as part of saving changes to the settings.
* Check for duplicate account
* Display dialog if necessary
* Else, proceed via mCallback.onProceedNext
*/
protected void startDuplicateTaskCheck(long accountId, String checkHost, String checkLogin,
int checkSettingsMode) {
new DuplicateCheckTask(accountId, checkHost, checkLogin, checkSettingsMode)
.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
/**
* Make the given text view uneditable. If the text view is ever focused, the specified
* error message will be displayed.
@ -304,47 +291,10 @@ public abstract class AccountServerBaseFragment extends Fragment
/**
* Clears the "next" button de-bounce flags and allows the "next" button to activate.
*/
private void clearButtonBounce() {
protected void clearButtonBounce() {
mProceedButtonPressed = false;
}
private class DuplicateCheckTask extends AsyncTask<Void, Void, Account> {
private final long mAccountId;
private final String mCheckHost;
private final String mCheckLogin;
private final int mCheckSettingsMode;
public DuplicateCheckTask(long accountId, String checkHost, String checkLogin,
int checkSettingsMode) {
mAccountId = accountId;
mCheckHost = checkHost;
mCheckLogin = checkLogin;
mCheckSettingsMode = checkSettingsMode;
}
@Override
protected Account doInBackground(Void... params) {
return Utility.findExistingAccount(mContext, mAccountId, mCheckHost, mCheckLogin);
}
@Override
protected void onPostExecute(Account duplicateAccount) {
AccountServerBaseFragment fragment = AccountServerBaseFragment.this;
if (duplicateAccount != null) {
// Show duplicate account warning
final DuplicateAccountDialogFragment dialogFragment =
DuplicateAccountDialogFragment.newInstance(duplicateAccount.mDisplayName);
dialogFragment.show(fragment.getFragmentManager(),
DuplicateAccountDialogFragment.TAG);
} else {
// Otherwise, proceed with the save/check
mCallback.onProceedNext(mCheckSettingsMode, fragment);
}
clearButtonBounce();
}
}
/**
* Implements AccountCheckSettingsFragment.Callbacks
*

View File

@ -445,7 +445,8 @@ public class AccountSetupBasics extends AccountSetupActivity
HostAuth.setHostAuthFromString(recvAuth, mProvider.incomingUri);
recvAuth.setLogin(mProvider.incomingUsername, password);
final EmailServiceInfo info = EmailServiceUtils.getServiceInfo(this, recvAuth.mProtocol);
final EmailServiceInfo info = EmailServiceUtils.getServiceInfo(this,
recvAuth.mProtocol);
recvAuth.mPort =
((recvAuth.mFlags & HostAuth.FLAG_SSL) != 0) ? info.portSsl : info.port;
@ -458,7 +459,7 @@ public class AccountSetupBasics extends AccountSetupActivity
// Stop here if the login credentials duplicate an existing account
// Launch an Async task to do the work
new DuplicateCheckTask(this, recvAuth.mAddress, mProvider.incomingUsername, true)
new DuplicateCheckTask(this, email, true)
.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
} catch (URISyntaxException e) {
/*
@ -475,36 +476,34 @@ public class AccountSetupBasics extends AccountSetupActivity
* Async task that continues the work of finishAutoSetup(). Checks for a duplicate
* account and then either alerts the user, or continues.
*/
private class DuplicateCheckTask extends AsyncTask<Void, Void, Account> {
private class DuplicateCheckTask extends AsyncTask<Void, Void, String> {
private final Context mContext;
private final String mCheckHost;
private final String mCheckLogin;
private final String mCheckAddress;
private final boolean mAutoSetup;
public DuplicateCheckTask(Context context, String checkHost, String checkLogin,
public DuplicateCheckTask(Context context, String checkAddress,
boolean autoSetup) {
mContext = context;
mCheckHost = checkHost;
mCheckLogin = checkLogin;
mCheckAddress = checkAddress;
// Prevent additional clicks on the next button during Async lookup
mNextButtonInhibit = true;
mAutoSetup = autoSetup;
}
@Override
protected Account doInBackground(Void... params) {
return Utility.findExistingAccount(mContext, -1, mCheckHost, mCheckLogin);
protected String doInBackground(Void... params) {
return Utility.findExistingAccount(mContext, null, mCheckAddress);
}
@Override
protected void onPostExecute(Account duplicateAccount) {
protected void onPostExecute(String duplicateAccountName) {
mNextButtonInhibit = false;
// Exit immediately if the user left before we finished
if (mPaused) return;
// Show duplicate account warning, or proceed
if (duplicateAccount != null) {
if (duplicateAccountName != null) {
final DuplicateAccountDialogFragment dialogFragment =
DuplicateAccountDialogFragment.newInstance(duplicateAccount.mDisplayName);
DuplicateAccountDialogFragment.newInstance(duplicateAccountName);
dialogFragment.show(getFragmentManager(), DuplicateAccountDialogFragment.TAG);
} else {
if (mAutoSetup) {
@ -520,6 +519,12 @@ public class AccountSetupBasics extends AccountSetupActivity
}
}
}
@Override
protected void onCancelled(String s) {
mNextButtonInhibit = false;
LogUtils.d(LogUtils.TAG, "DuplicateCheckTask cancelled (AccountSetupBasics)");
}
}
/**
@ -529,7 +534,6 @@ public class AccountSetupBasics extends AccountSetupActivity
// Try auto-configuration from XML providers (unless in EAS mode, we can skip it)
final String email = mEmailView.getText().toString().trim();
final String[] emailParts = email.split("@");
final String user = emailParts[0].trim();
final String domain = emailParts[1].trim();
mProvider = AccountSettingsUtils.findProviderForDomain(this, domain);
if (mProvider != null) {
@ -543,7 +547,7 @@ public class AccountSetupBasics extends AccountSetupActivity
}
} else {
// Can't use auto setup (although EAS accounts may still be able to AutoDiscover)
new DuplicateCheckTask(this, domain, user, false)
new DuplicateCheckTask(this, email, false)
.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
}

View File

@ -565,10 +565,8 @@ public class AccountSetupIncomingFragment extends AccountServerBaseFragment
recvAuth.mDomain = null;
}
// Check for a duplicate account (requires async DB work) and if OK,
// proceed with check
startDuplicateTaskCheck(
account.mId, serverAddress, mCacheLoginCredential, SetupData.CHECK_INCOMING);
mCallback.onProceedNext(SetupData.CHECK_INCOMING, this);
clearButtonBounce();
}
@Override

View File

@ -388,5 +388,6 @@ public class AccountSetupOutgoingFragment extends AccountServerBaseFragment
sendAuth.mDomain = null;
mCallback.onProceedNext(SetupData.CHECK_OUTGOING, this);
clearButtonBounce();
}
}

View File

@ -18,6 +18,7 @@ package com.android.email.activity.setup;
import android.app.Activity;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
@ -34,6 +35,8 @@ import com.android.email.service.EmailServiceUtils;
import com.android.email.service.EmailServiceUtils.EmailServiceInfo;
import com.android.emailcommon.provider.Account;
import com.android.emailcommon.provider.HostAuth;
import com.android.emailcommon.utility.Utility;
import com.android.mail.utils.LogUtils;
/**
* Prompts the user to select an account type. The account type, along with the
@ -42,6 +45,8 @@ import com.android.emailcommon.provider.HostAuth;
*/
public class AccountSetupType extends AccountSetupActivity implements OnClickListener {
private boolean mButtonPressed;
public static void actionSelectAccountType(Activity fromActivity, SetupData setupData) {
final Intent i = new ForwardingIntent(fromActivity, AccountSetupType.class);
i.putExtra(SetupData.EXTRA_SETUP_DATA, setupData);
@ -111,6 +116,15 @@ public class AccountSetupType extends AccountSetupActivity implements OnClickLis
final HostAuth recvAuth = account.getOrCreateHostAuthRecv(this);
recvAuth.setConnection(protocol, recvAuth.mAddress, recvAuth.mPort, recvAuth.mFlags);
final EmailServiceInfo info = EmailServiceUtils.getServiceInfo(this, protocol);
new DuplicateCheckTask(account.mEmailAddress, info.accountType)
.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
private void onProceedNext() {
final Account account = mSetupData.getAccount();
final HostAuth recvAuth = account.getOrCreateHostAuthRecv(this);
final EmailServiceInfo info = EmailServiceUtils.getServiceInfo(this, recvAuth.mProtocol);
if (info.usesAutodiscover) {
mSetupData.setCheckSettingsMode(SetupData.CHECK_AUTODISCOVER);
} else {
@ -131,8 +145,47 @@ public class AccountSetupType extends AccountSetupActivity implements OnClickLis
finish();
break;
default:
onSelect((String)v.getTag());
if (!mButtonPressed) {
mButtonPressed = true;
onSelect((String)v.getTag());
}
break;
}
}
private class DuplicateCheckTask extends AsyncTask<Void, Void, String> {
private final String mAddress;
private final String mAuthority;
public DuplicateCheckTask(String address, String authority) {
mAddress = address;
mAuthority = authority;
}
@Override
protected String doInBackground(Void... params) {
return Utility.findExistingAccount(AccountSetupType.this, mAuthority, mAddress);
}
@Override
protected void onPostExecute(String duplicateAccountName) {
mButtonPressed = false;
if (duplicateAccountName != null) {
// Show duplicate account warning
final DuplicateAccountDialogFragment dialogFragment =
DuplicateAccountDialogFragment.newInstance(duplicateAccountName);
dialogFragment.show(AccountSetupType.this.getFragmentManager(),
DuplicateAccountDialogFragment.TAG);
} else {
// Otherwise, proceed with the save/check
onProceedNext();
}
}
@Override
protected void onCancelled(String s) {
mButtonPressed = false;
LogUtils.d(LogUtils.TAG, "Duplicate account check cancelled (AccountSetupType)");
}
}
}