From 73101f3a7bc1e735199a7c2c18358e9db9af0bca Mon Sep 17 00:00:00 2001 From: Tony Mantler Date: Mon, 9 Jun 2014 15:28:11 -0700 Subject: [PATCH] Fix OAuth when changing credentials from settings b/15521401 Change-Id: I7909389943c8e3eefbef0699f1c7c9c338282ca5 (cherry picked from commit 994c282d804a635f783681ae314a6b4b244b476e) --- .../android/emailcommon/provider/Account.java | 14 ++++- .../activity/setup/SetupDataFragment.java | 9 +-- src/com/android/email/mail/Store.java | 57 ++++++++++++------- .../mail/internet/AuthenticationCache.java | 5 +- 4 files changed, 58 insertions(+), 27 deletions(-) diff --git a/emailcommon/src/com/android/emailcommon/provider/Account.java b/emailcommon/src/com/android/emailcommon/provider/Account.java index c35009d34..d9062b37c 100755 --- a/emailcommon/src/com/android/emailcommon/provider/Account.java +++ b/emailcommon/src/com/android/emailcommon/provider/Account.java @@ -147,6 +147,10 @@ public final class Account extends EmailContent implements AccountColumns, Parce public transient HostAuth mHostAuthSend; public transient Policy mPolicy; + // Marks this account as being a temporary entry, so we know to use it directly and not go + // through the database or any caches + private transient boolean mTemporary; + public static final int CONTENT_ID_COLUMN = 0; public static final int CONTENT_DISPLAY_NAME_COLUMN = 1; public static final int CONTENT_EMAIL_ADDRESS_COLUMN = 2; @@ -282,6 +286,14 @@ public final class Account extends EmailContent implements AccountColumns, Parce mPingDuration = cursor.getLong(CONTENT_PING_DURATION_COLUMN); } + public boolean isTemporary() { + return mTemporary; + } + + public void setTemporary(boolean temporary) { + mTemporary = temporary; + } + private static long getId(Uri u) { return Long.parseLong(u.getPathSegments().get(1)); } @@ -978,4 +990,4 @@ public final class Account extends EmailContent implements AccountColumns, Parce sb.append(']'); return sb.toString(); } -} \ No newline at end of file +} diff --git a/src/com/android/email/activity/setup/SetupDataFragment.java b/src/com/android/email/activity/setup/SetupDataFragment.java index d9e069c33..df9714cdb 100644 --- a/src/com/android/email/activity/setup/SetupDataFragment.java +++ b/src/com/android/email/activity/setup/SetupDataFragment.java @@ -71,7 +71,7 @@ public class SetupDataFragment extends Fragment implements Parcelable { public SetupDataFragment() { mPolicy = null; - mAccount = new Account(); + setAccount(new Account()); mEmail = null; mCredentialResults = null; } @@ -83,7 +83,7 @@ public class SetupDataFragment extends Fragment implements Parcelable { public SetupDataFragment(int flowMode, Account account) { this(flowMode); - mAccount = account; + setAccount(account); } @Override @@ -105,7 +105,7 @@ public class SetupDataFragment extends Fragment implements Parcelable { super.onCreate(savedInstanceState); if (savedInstanceState != null) { mFlowMode = savedInstanceState.getInt(SAVESTATE_FLOWMODE); - mAccount = savedInstanceState.getParcelable(SAVESTATE_ACCOUNT); + setAccount((Account) savedInstanceState.getParcelable(SAVESTATE_ACCOUNT)); mEmail = savedInstanceState.getString(SAVESTATE_EMAIL); mCredentialResults = savedInstanceState.getParcelable(SAVESTATE_CREDENTIAL); mIncomingCredLoaded = savedInstanceState.getBoolean(SAVESTATE_INCOMING_LOADED); @@ -132,6 +132,7 @@ public class SetupDataFragment extends Fragment implements Parcelable { public void setAccount(Account account) { mAccount = account; + mAccount.setTemporary(true); } public String getEmail() { @@ -269,7 +270,7 @@ public class SetupDataFragment extends Fragment implements Parcelable { public SetupDataFragment(Parcel in) { final ClassLoader loader = getClass().getClassLoader(); mFlowMode = in.readInt(); - mAccount = in.readParcelable(loader); + setAccount((Account) in.readParcelable(loader)); mEmail = in.readString(); mCredentialResults = in.readParcelable(loader); final boolean[] credsLoaded = in.createBooleanArray(); diff --git a/src/com/android/email/mail/Store.java b/src/com/android/email/mail/Store.java index 1a98543ed..377b59448 100644 --- a/src/com/android/email/mail/Store.java +++ b/src/com/android/email/mail/Store.java @@ -77,6 +77,7 @@ public abstract class Store { * a critical problem. However, it is something we should consider fixing. * * @param account The account of the store. + * @param context For all the usual context-y stuff * @return an initialized store of the appropriate class * @throws MessagingException If the store cannot be obtained or if the account is invalid. */ @@ -89,27 +90,43 @@ public abstract class Store { HostAuth hostAuth = account.getOrCreateHostAuthRecv(context); // An existing account might have been deleted if (hostAuth == null) return null; - Store store = sStores.get(hostAuth); - if (store == null) { - Context appContext = context.getApplicationContext(); - Class klass = sStoreClasses.get(hostAuth.mProtocol); - if (klass == null) { - klass = ServiceStore.class; - } - try { - // invoke "newInstance" class method - Method m = klass.getMethod("newInstance", Account.class, Context.class); - store = (Store)m.invoke(null, account, appContext); - } catch (Exception e) { - LogUtils.d(Logging.LOG_TAG, String.format( - "exception %s invoking method %s#newInstance(Account, Context) for %s", - e.toString(), klass.getName(), account.mDisplayName)); - throw new MessagingException("Can't instantiate Store for " + account.mDisplayName); - } - // Don't cache this unless it's we've got a saved HostAuth - if (hostAuth.mId != EmailContent.NOT_SAVED) { - sStores.put(hostAuth, store); + if (!account.isTemporary()) { + Store store = sStores.get(hostAuth); + if (store == null) { + store = createInstanceInternal(account, context, true); + } else { + // Make sure the account object is up to date (according to the caller, at least) + store.mAccount = account; } + return store; + } else { + return createInstanceInternal(account, context, false); + } + } + + private synchronized static Store createInstanceInternal(final Account account, + final Context context, final boolean cacheInstance) + throws MessagingException { + Context appContext = context.getApplicationContext(); + final HostAuth hostAuth = account.getOrCreateHostAuthRecv(context); + Class klass = sStoreClasses.get(hostAuth.mProtocol); + if (klass == null) { + klass = ServiceStore.class; + } + final Store store; + try { + // invoke "newInstance" class method + Method m = klass.getMethod("newInstance", Account.class, Context.class); + store = (Store)m.invoke(null, account, appContext); + } catch (Exception e) { + LogUtils.d(Logging.LOG_TAG, String.format( + "exception %s invoking method %s#newInstance(Account, Context) for %s", + e.toString(), klass.getName(), account.mDisplayName)); + throw new MessagingException("Can't instantiate Store for " + account.mDisplayName); + } + // Don't cache this unless it's we've got a saved HostAuth + if (hostAuth.mId != EmailContent.NOT_SAVED && cacheInstance) { + sStores.put(hostAuth, store); } return store; } diff --git a/src/com/android/email/mail/internet/AuthenticationCache.java b/src/com/android/email/mail/internet/AuthenticationCache.java index 51e281da9..21508af35 100644 --- a/src/com/android/email/mail/internet/AuthenticationCache.java +++ b/src/com/android/email/mail/internet/AuthenticationCache.java @@ -91,7 +91,7 @@ public class AuthenticationCache { private CacheEntry getEntry(Context context, Account account) { CacheEntry entry; - if (account.isSaved()) { + if (account.isSaved() && !account.isTemporary()) { entry = mCache.get(account.mId); if (entry == null) { LogUtils.d(Logging.LOG_TAG, "initializing entry from database"); @@ -102,7 +102,7 @@ public class AuthenticationCache { mCache.put(account.mId, entry); } } else { - // This account is not yet saved, just create a temporary entry. Don't store + // This account is temporary, just create a temporary entry. Don't store // it in the cache, it won't be findable because we don't yet have an account Id. final HostAuth hostAuth = account.getOrCreateHostAuthRecv(context); final Credential credential = hostAuth.getCredential(context); @@ -157,5 +157,6 @@ public class AuthenticationCache { entry.mRefreshToken = ""; entry.mExpirationTime = 0; saveEntry(context, entry); + mCache.remove(entry.mAccountId); } }