private CacheEntry getEntry(Context context, Account account) { CacheEntry entry; if (account.isSaved() && !account.isTemporary()) { entry = mCache.get(account.mId); if (entry == null) { LogUtils.d(Logging.LOG_TAG, "initializing entry from database"); final HostAuth hostAuth = account.getOrCreateHostAuthRecv(context); final Credential credential = hostAuth.getOrCreateCredential(context); entry = new CacheEntry( account.mId, credential.mProviderId, credential.mAccessToken, credential.mRefreshToken, credential.mExpiration); mCache.put(account.mId, entry); } } else { // 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); entry = new CacheEntry( account.mId, credential.mProviderId, credential.mAccessToken, credential.mRefreshToken, credential.mExpiration); } return entry; }
@Override public Bundle autoDiscover(String userName, String password) throws RemoteException { HostAuth hostAuth = new HostAuth(); hostAuth.mLogin = userName; hostAuth.mPassword = password; hostAuth.mFlags = HostAuth.FLAG_AUTHENTICATE | HostAuth.FLAG_SSL; hostAuth.mPort = 443; return new EasSyncService().tryAutodiscover(ExchangeService.this, hostAuth); }
private void saveEntry(Context context, CacheEntry entry) { LogUtils.d(Logging.LOG_TAG, "saveEntry"); final Account account = Account.restoreAccountWithId(context, entry.mAccountId); final HostAuth hostAuth = account.getOrCreateHostAuthRecv(context); final Credential cred = hostAuth.getOrCreateCredential(context); cred.mProviderId = entry.mProviderId; cred.mAccessToken = entry.mAccessToken; cred.mRefreshToken = entry.mRefreshToken; cred.mExpiration = entry.mExpirationTime; cred.update(context, cred.toContentValues()); }
/** * Legacy URI parser. Used in parsing template from provider.xml Example string: * "eas+ssl+trustallcerts://user:password@server/domain:123" * * <p>Note that the use of client certificate is specified in the URI, a secure connection type * must be used. */ public static void setHostAuthFromString(HostAuth auth, String uriString) throws URISyntaxException { URI uri = new URI(uriString); String path = uri.getPath(); String domain = null; if (!TextUtils.isEmpty(path)) { // Strip off the leading slash that begins the path. domain = path.substring(1); } auth.mDomain = domain; auth.setLogin(uri.getUserInfo()); String scheme = uri.getScheme(); auth.setConnection(scheme, uri.getHost(), uri.getPort()); }
/** * Return a list of all Accounts in EmailProvider. Because the result of this call may be used in * account reconciliation, an exception is thrown if the result cannot be guaranteed accurate * * @param context the caller's context * @param accounts a list that Accounts will be added into * @return the list of Accounts * @throws ProviderUnavailableException if the list of Accounts cannot be guaranteed valid */ @Override public AccountList collectAccounts(Context context, AccountList accounts) { ContentResolver resolver = context.getContentResolver(); Cursor c = resolver.query(Account.CONTENT_URI, Account.CONTENT_PROJECTION, null, null, null); // We must throw here; callers might use the information we provide for reconciliation, etc. if (c == null) throw new ProviderUnavailableException(); try { ContentValues cv = new ContentValues(); while (c.moveToNext()) { long hostAuthId = c.getLong(Account.CONTENT_HOST_AUTH_KEY_RECV_COLUMN); if (hostAuthId > 0) { HostAuth ha = HostAuth.restoreHostAuthWithId(context, hostAuthId); if (ha != null && ha.mProtocol.equals(Eas.PROTOCOL)) { Account account = new Account(); account.restore(c); // Cache the HostAuth account.mHostAuthRecv = ha; accounts.add(account); // Fixup flags for inbox (should accept moved mail) Mailbox inbox = Mailbox.restoreMailboxOfType(context, account.mId, Mailbox.TYPE_INBOX); if (inbox != null && ((inbox.mFlags & Mailbox.FLAG_ACCEPTS_MOVED_MAIL) == 0)) { cv.put(MailboxColumns.FLAGS, inbox.mFlags | Mailbox.FLAG_ACCEPTS_MOVED_MAIL); resolver.update( ContentUris.withAppendedId(Mailbox.CONTENT_URI, inbox.mId), cv, null, null); } } } } } finally { c.close(); } return accounts; }
public void testValidateAccount() throws Exception { setupAccountMailboxAndMessages(0); HostAuth auth = new HostAuth(); auth.mAddress = mAccount.mEmailAddress; auth.mProtocol = "eas"; auth.mLogin = mAccount.mDisplayName; auth.mPassword = "******"; auth.mPort = 80; EasSyncService eas = getTestService(mAccount, mMailbox); Bundle bundle = eas.validateAccount(auth, mProviderContext); assertEquals("14.1", bundle.get(EmailServiceProxy.VALIDATE_BUNDLE_PROTOCOL_VERSION)); assertEquals( MessagingException.NO_ERROR, bundle.get(EmailServiceProxy.VALIDATE_BUNDLE_RESULT_CODE)); }
public void testTryAutodiscover() throws RemoteException, IOException { String userName = "******"; String password = "******"; EasSyncService service = new EasSyncService(); Bundle bundle1 = service.tryAutodiscover(userName, password); Bundle bundle2 = new Bundle(); bundle2.putInt(EmailServiceProxy.AUTO_DISCOVER_BUNDLE_ERROR_CODE, MessagingException.NO_ERROR); HostAuth hostAuth = new HostAuth(); hostAuth.mAddress = "google.com"; hostAuth.mLogin = userName; hostAuth.mPassword = password; hostAuth.mPort = 443; hostAuth.mProtocol = "eas"; hostAuth.mFlags = HostAuth.FLAG_SSL | HostAuth.FLAG_AUTHENTICATE; bundle2.putParcelable(EmailServiceProxy.AUTO_DISCOVER_BUNDLE_HOST_AUTH, hostAuth); assertEquals(bundle2.toString(), bundle1.toString()); }
/** * Add an account to the AccountManager. * * @param context Our {@link Context}. * @param account The {@link Account} we're adding. * @param email Whether the user wants to sync email on this account. * @param calendar Whether the user wants to sync calendar on this account. * @param contacts Whether the user wants to sync contacts on this account. * @param callback A callback for when the AccountManager is done. * @return The result of {@link AccountManager#addAccount}. */ public static AccountManagerFuture<Bundle> setupAccountManagerAccount( final Context context, final Account account, final boolean email, final boolean calendar, final boolean contacts, final AccountManagerCallback<Bundle> callback) { final Bundle options = new Bundle(5); final HostAuth hostAuthRecv = HostAuth.restoreHostAuthWithId(context, account.mHostAuthKeyRecv); if (hostAuthRecv == null) { return null; } // Set up username/password options.putString(EasAuthenticatorService.OPTIONS_USERNAME, account.mEmailAddress); options.putString(EasAuthenticatorService.OPTIONS_PASSWORD, hostAuthRecv.mPassword); options.putBoolean(EasAuthenticatorService.OPTIONS_CONTACTS_SYNC_ENABLED, contacts); options.putBoolean(EasAuthenticatorService.OPTIONS_CALENDAR_SYNC_ENABLED, calendar); options.putBoolean(EasAuthenticatorService.OPTIONS_EMAIL_SYNC_ENABLED, email); final EmailServiceInfo info = getServiceInfo(context, hostAuthRecv.mProtocol); return AccountManager.get(context) .addAccount(info.accountType, null, null, options, null, callback, null); }
public static void updateAccountManagerType( Context context, android.accounts.Account amAccount, final Map<String, String> protocolMap) { final ContentResolver resolver = context.getContentResolver(); final Cursor c = resolver.query( Account.CONTENT_URI, Account.CONTENT_PROJECTION, AccountColumns.EMAIL_ADDRESS + "=?", new String[] {amAccount.name}, null); // That's odd, isn't it? if (c == null) return; try { if (c.moveToNext()) { // Get the EmailProvider Account/HostAuth final Account account = new Account(); account.restore(c); final HostAuth hostAuth = HostAuth.restoreHostAuthWithId(context, account.mHostAuthKeyRecv); if (hostAuth == null) { return; } final String newProtocol = protocolMap.get(hostAuth.mProtocol); if (newProtocol == null) { // This account doesn't need updating. return; } LogUtils.w(Logging.LOG_TAG, "Converting " + amAccount.name + " to " + newProtocol); final ContentValues accountValues = new ContentValues(); int oldFlags = account.mFlags; // Mark the provider account incomplete so it can't get reconciled away account.mFlags |= Account.FLAGS_INCOMPLETE; accountValues.put(AccountColumns.FLAGS, account.mFlags); final Uri accountUri = ContentUris.withAppendedId(Account.CONTENT_URI, account.mId); resolver.update(accountUri, accountValues, null, null); // Change the HostAuth to reference the new protocol; this has to be done before // trying to create the AccountManager account (below) final ContentValues hostValues = new ContentValues(); hostValues.put(HostAuth.PROTOCOL, newProtocol); resolver.update( ContentUris.withAppendedId(HostAuth.CONTENT_URI, hostAuth.mId), hostValues, null, null); LogUtils.w(Logging.LOG_TAG, "Updated HostAuths"); try { // Get current settings for the existing AccountManager account boolean email = ContentResolver.getSyncAutomatically(amAccount, EmailContent.AUTHORITY); if (!email) { // Try our old provider name email = ContentResolver.getSyncAutomatically(amAccount, "com.android.email.provider"); } final boolean contacts = ContentResolver.getSyncAutomatically(amAccount, ContactsContract.AUTHORITY); final boolean calendar = ContentResolver.getSyncAutomatically(amAccount, CalendarContract.AUTHORITY); LogUtils.w( Logging.LOG_TAG, "Email: " + email + ", Contacts: " + contacts + "," + " Calendar: " + calendar); // Get sync keys for calendar/contacts final String amName = amAccount.name; final String oldType = amAccount.type; ContentProviderClient client = context .getContentResolver() .acquireContentProviderClient(CalendarContract.CONTENT_URI); byte[] calendarSyncKey = null; try { calendarSyncKey = SyncStateContract.Helpers.get( client, asCalendarSyncAdapter(SyncState.CONTENT_URI, amName, oldType), new android.accounts.Account(amName, oldType)); } catch (RemoteException e) { LogUtils.w(Logging.LOG_TAG, "Get calendar key FAILED"); } finally { client.release(); } client = context .getContentResolver() .acquireContentProviderClient(ContactsContract.AUTHORITY_URI); byte[] contactsSyncKey = null; try { contactsSyncKey = SyncStateContract.Helpers.get( client, ContactsContract.SyncState.CONTENT_URI, new android.accounts.Account(amName, oldType)); } catch (RemoteException e) { LogUtils.w(Logging.LOG_TAG, "Get contacts key FAILED"); } finally { client.release(); } if (calendarSyncKey != null) { LogUtils.w(Logging.LOG_TAG, "Got calendar key: " + new String(calendarSyncKey)); } if (contactsSyncKey != null) { LogUtils.w(Logging.LOG_TAG, "Got contacts key: " + new String(contactsSyncKey)); } // Set up a new AccountManager account with new type and old settings AccountManagerFuture<?> amFuture = setupAccountManagerAccount(context, account, email, calendar, contacts, null); finishAccountManagerBlocker(amFuture); LogUtils.w(Logging.LOG_TAG, "Created new AccountManager account"); // TODO: Clean up how we determine the type. final String accountType = protocolMap.get(hostAuth.mProtocol + "_type"); // Move calendar and contacts data from the old account to the new one. // We must do this before deleting the old account or the data is lost. moveCalendarData(context.getContentResolver(), amName, oldType, accountType); moveContactsData(context.getContentResolver(), amName, oldType, accountType); // Delete the AccountManager account amFuture = AccountManager.get(context).removeAccount(amAccount, null, null); finishAccountManagerBlocker(amFuture); LogUtils.w(Logging.LOG_TAG, "Deleted old AccountManager account"); // Restore sync keys for contacts/calendar if (accountType != null && calendarSyncKey != null && calendarSyncKey.length != 0) { client = context .getContentResolver() .acquireContentProviderClient(CalendarContract.CONTENT_URI); try { SyncStateContract.Helpers.set( client, asCalendarSyncAdapter(SyncState.CONTENT_URI, amName, accountType), new android.accounts.Account(amName, accountType), calendarSyncKey); LogUtils.w(Logging.LOG_TAG, "Set calendar key..."); } catch (RemoteException e) { LogUtils.w(Logging.LOG_TAG, "Set calendar key FAILED"); } finally { client.release(); } } if (accountType != null && contactsSyncKey != null && contactsSyncKey.length != 0) { client = context .getContentResolver() .acquireContentProviderClient(ContactsContract.AUTHORITY_URI); try { SyncStateContract.Helpers.set( client, ContactsContract.SyncState.CONTENT_URI, new android.accounts.Account(amName, accountType), contactsSyncKey); LogUtils.w(Logging.LOG_TAG, "Set contacts key..."); } catch (RemoteException e) { LogUtils.w(Logging.LOG_TAG, "Set contacts key FAILED"); } } // That's all folks! LogUtils.w(Logging.LOG_TAG, "Account update completed."); } finally { // Clear the incomplete flag on the provider account accountValues.put(AccountColumns.FLAGS, oldFlags); resolver.update(accountUri, accountValues, null, null); LogUtils.w(Logging.LOG_TAG, "[Incomplete flag cleared]"); } } } finally { c.close(); } }