Implement password expiration for EAS

* Hoist wipe() method from AbstractSyncParser to AbstractSyncAdapter
* Add deleteAccountPIMData(accountId) to the EmailService API
* Implement deleteAccountPIMData for EAS

Change-Id: I1037cde25fc2b24419f399446cfa0906dc0174d1
This commit is contained in:
Marc Blank 2010-11-16 11:01:20 -08:00
parent b0f90e9c51
commit cf3fb71bc6
16 changed files with 125 additions and 84 deletions

View File

@ -17,9 +17,9 @@
package com.android.email;
import com.android.email.mail.AuthenticationFailedException;
import com.android.email.mail.Folder.MessageRetrievalListener;
import com.android.email.mail.MessagingException;
import com.android.email.mail.Store;
import com.android.email.mail.Folder.MessageRetrievalListener;
import com.android.email.mail.store.Pop3Store.Pop3Message;
import com.android.email.provider.AttachmentProvider;
import com.android.email.provider.EmailContent;
@ -1607,6 +1607,9 @@ public class Controller {
public void moveMessage(long messageId, long mailboxId) throws RemoteException {
}
public void deleteAccountPIMData(long accountId) throws RemoteException {
}
};
@Override

View File

@ -135,6 +135,9 @@ public class ExchangeUtils {
public void moveMessage(long messageId, long mailboxId) throws RemoteException {
}
public void deleteAccountPIMData(long accountId) throws RemoteException {
}
public IBinder asBinder() {
return null;
}

View File

@ -328,6 +328,17 @@ public class EmailServiceProxy implements IEmailService {
});
}
public void deleteAccountPIMData(final long accountId) throws RemoteException {
setTask(new Runnable () {
public void run() {
try {
mService.deleteAccountPIMData(accountId);
} catch (RemoteException e) {
}
}
});
}
public IBinder asBinder() {
return null;
}

View File

@ -46,4 +46,6 @@ interface IEmailService {
void sendMeetingResponse(long messageId, int response);
void moveMessage(long messageId, long mailboxId);
void deleteAccountPIMData(long accountId);
}

View File

@ -18,8 +18,8 @@
package com.android.exchange;
import com.android.email.SecurityPolicy;
import com.android.email.Utility;
import com.android.email.SecurityPolicy.PolicySet;
import com.android.email.Utility;
import com.android.email.mail.Address;
import com.android.email.mail.MeetingInfo;
import com.android.email.mail.MessagingException;
@ -46,11 +46,11 @@ import com.android.exchange.adapter.FolderSyncParser;
import com.android.exchange.adapter.GalParser;
import com.android.exchange.adapter.MeetingResponseParser;
import com.android.exchange.adapter.MoveItemsParser;
import com.android.exchange.adapter.Parser.EasParserException;
import com.android.exchange.adapter.PingParser;
import com.android.exchange.adapter.ProvisionParser;
import com.android.exchange.adapter.Serializer;
import com.android.exchange.adapter.Tags;
import com.android.exchange.adapter.Parser.EasParserException;
import com.android.exchange.provider.GalResult;
import com.android.exchange.utility.CalendarUtilities;
@ -1644,8 +1644,7 @@ public class EasSyncService extends AbstractSyncService {
if (len != 0) {
InputStream is = entity.getContent();
// Returns true if we need to sync again
if (new FolderSyncParser(is, new AccountSyncAdapter(mMailbox, this))
.parse()) {
if (new FolderSyncParser(is, new AccountSyncAdapter(this)).parse()) {
continue;
}
}
@ -2303,11 +2302,11 @@ public class EasSyncService extends AbstractSyncService {
} else {
AbstractSyncAdapter target;
if (mMailbox.mType == Mailbox.TYPE_CONTACTS) {
target = new ContactsSyncAdapter(mMailbox, this);
target = new ContactsSyncAdapter( this);
} else if (mMailbox.mType == Mailbox.TYPE_CALENDAR) {
target = new CalendarSyncAdapter(mMailbox, this);
target = new CalendarSyncAdapter(this);
} else {
target = new EmailSyncAdapter(mMailbox, this);
target = new EmailSyncAdapter(this);
}
// We loop here because someone might have put a request in while we were syncing
// and we've missed that opportunity...

View File

@ -36,6 +36,7 @@ import com.android.email.service.IEmailService;
import com.android.email.service.IEmailServiceCallback;
import com.android.email.service.MailService;
import com.android.exchange.adapter.CalendarSyncAdapter;
import com.android.exchange.adapter.ContactsSyncAdapter;
import com.android.exchange.utility.FileLogger;
import org.apache.http.conn.ClientConnectionManager;
@ -66,21 +67,21 @@ import android.database.ContentObserver;
import android.database.Cursor;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.net.NetworkInfo.State;
import android.net.Uri;
import android.os.Bundle;
import android.os.Debug;
import android.os.Handler;
import android.os.IBinder;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.os.Process;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.PowerManager.WakeLock;
import android.provider.Calendar;
import android.provider.ContactsContract;
import android.provider.Calendar.Calendars;
import android.provider.Calendar.Events;
import android.provider.ContactsContract;
import android.util.Log;
import java.io.BufferedReader;
@ -448,6 +449,31 @@ public class ExchangeService extends Service implements Runnable {
public void moveMessage(long messageId, long mailboxId) throws RemoteException {
sendMessageRequest(new MessageMoveRequest(messageId, mailboxId));
}
/**
* Delete PIM (calendar, contacts) data for the specified account
*
* @param accountId the account whose data should be deleted
* @throws RemoteException
*/
public void deleteAccountPIMData(long accountId) throws RemoteException {
ExchangeService exchangeService = INSTANCE;
if (exchangeService == null) return;
Mailbox mailbox =
Mailbox.restoreMailboxOfType(exchangeService, accountId, Mailbox.TYPE_CONTACTS);
if (mailbox != null) {
EasSyncService service = new EasSyncService(exchangeService, mailbox);
ContactsSyncAdapter adapter = new ContactsSyncAdapter(service);
adapter.wipe();
}
mailbox =
Mailbox.restoreMailboxOfType(exchangeService, accountId, Mailbox.TYPE_CALENDAR);
if (mailbox != null) {
EasSyncService service = new EasSyncService(exchangeService, mailbox);
CalendarSyncAdapter adapter = new CalendarSyncAdapter(service);
adapter.wipe();
}
}
};
static class AccountList extends ArrayList<Account> {
@ -796,7 +822,7 @@ public class ExchangeService extends Service implements Runnable {
EasSyncService service =
new EasSyncService(INSTANCE, mailbox);
CalendarSyncAdapter adapter =
new CalendarSyncAdapter(mailbox, service);
new CalendarSyncAdapter(service);
try {
adapter.setSyncKey("0", false);
} catch (IOException e) {

View File

@ -23,6 +23,7 @@ import com.android.email.provider.EmailContent.Mailbox;
import com.android.exchange.Eas;
import com.android.exchange.EasSyncService;
import android.content.ContentResolver;
import android.content.Context;
import java.io.IOException;
@ -46,6 +47,7 @@ public abstract class AbstractSyncAdapter {
public EasSyncService mService;
public Context mContext;
public Account mAccount;
public final ContentResolver mContentResolver;
public final android.accounts.Account mAccountManagerAccount;
// Create the data for local changes that need to be sent up to the server
@ -62,18 +64,23 @@ public abstract class AbstractSyncAdapter {
// Add sync options (filter, body type - html vs plain, and truncation)
public abstract void sendSyncOptions(Double protocolVersion, Serializer s)
throws IOException;
/**
* Delete all records of this class in this account
*/
public abstract void wipe();
public boolean isLooping() {
return false;
}
public AbstractSyncAdapter(Mailbox mailbox, EasSyncService service) {
mMailbox = mailbox;
public AbstractSyncAdapter(EasSyncService service) {
mService = service;
mMailbox = service.mMailbox;
mContext = service.mContext;
mAccount = service.mAccount;
mAccountManagerAccount = new android.accounts.Account(mAccount.mEmailAddress,
Email.EXCHANGE_ACCOUNT_MANAGER_TYPE);
mContentResolver = mContext.getContentResolver();
}
public void userLog(String ...strings) {

View File

@ -75,11 +75,6 @@ public abstract class AbstractSyncParser extends Parser {
*/
public abstract void commit() throws IOException;
/**
* Delete all records of this class in this account
*/
public abstract void wipe();
public boolean isLooping() {
return mLooping;
}
@ -121,7 +116,7 @@ public abstract class AbstractSyncParser extends Parser {
// TODO Make frequency conditional on user settings!
mMailbox.mSyncInterval = Mailbox.CHECK_INTERVAL_PUSH;
mService.errorLog("Bad sync key; RESET and delete data");
wipe();
mAdapter.wipe();
// Indicate there's more so that we'll start syncing again
moreAvailable = true;
} else if (status == 8) {

View File

@ -1,6 +1,5 @@
package com.android.exchange.adapter;
import com.android.email.provider.EmailContent.Mailbox;
import com.android.exchange.EasSyncService;
import java.io.IOException;
@ -8,14 +7,18 @@ import java.io.InputStream;
public class AccountSyncAdapter extends AbstractSyncAdapter {
public AccountSyncAdapter(Mailbox mailbox, EasSyncService service) {
super(mailbox, service);
public AccountSyncAdapter(EasSyncService service) {
super(service);
}
@Override
public void cleanup() {
}
@Override
public void wipe() {
}
@Override
public String getCollectionName() {
return null;

View File

@ -20,7 +20,6 @@ package com.android.exchange.adapter;
import com.android.email.Email;
import com.android.email.Utility;
import com.android.email.provider.EmailContent;
import com.android.email.provider.EmailContent.Mailbox;
import com.android.email.provider.EmailContent.Message;
import com.android.exchange.Eas;
import com.android.exchange.EasOutboxService;
@ -35,14 +34,13 @@ import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Entity;
import android.content.Entity.NamedContentValues;
import android.content.EntityIterator;
import android.content.OperationApplicationException;
import android.content.Entity.NamedContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.os.RemoteException;
import android.provider.Calendar;
import android.provider.SyncStateContract;
import android.provider.Calendar.Attendees;
import android.provider.Calendar.Calendars;
import android.provider.Calendar.Events;
@ -51,6 +49,7 @@ import android.provider.Calendar.ExtendedProperties;
import android.provider.Calendar.Reminders;
import android.provider.Calendar.SyncState;
import android.provider.ContactsContract.RawContacts;
import android.provider.SyncStateContract;
import android.text.TextUtils;
import android.util.Log;
@ -59,10 +58,10 @@ import java.io.InputStream;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.GregorianCalendar;
import java.util.Map.Entry;
import java.util.StringTokenizer;
import java.util.TimeZone;
import java.util.UUID;
import java.util.Map.Entry;
/**
* Sync adapter class for EAS calendars
@ -161,8 +160,8 @@ public class CalendarSyncAdapter extends AbstractSyncAdapter {
private ArrayList<Long> mSendCancelIdList = new ArrayList<Long>();
private ArrayList<Message> mOutgoingMailList = new ArrayList<Message>();
public CalendarSyncAdapter(Mailbox mailbox, EasSyncService service) {
super(mailbox, service);
public CalendarSyncAdapter(EasSyncService service) {
super(service);
mEmailAddress = mAccount.mEmailAddress;
Cursor c = mService.mContentResolver.query(Calendars.CONTENT_URI,
new String[] {Calendars._ID}, CALENDAR_SELECTION,
@ -190,6 +189,13 @@ public class CalendarSyncAdapter extends AbstractSyncAdapter {
public void cleanup() {
}
@Override
public void wipe() {
// Delete the calendar associated with this account
mContentResolver.delete(Calendars.CONTENT_URI, CALENDAR_SELECTION,
new String[] {mEmailAddress, Email.EXCHANGE_ACCOUNT_MANAGER_TYPE});
}
@Override
public void sendSyncOptions(Double protocolVersion, Serializer s) throws IOException {
setPimSyncOptions(protocolVersion, Eas.FILTER_2_WEEKS, s);
@ -284,14 +290,6 @@ public class CalendarSyncAdapter extends AbstractSyncAdapter {
mAccountUri = Events.CONTENT_URI;
}
@Override
public void wipe() {
// Delete the calendar associated with this account
// TODO Make sure the Events, etc. are also deleted
mContentResolver.delete(Calendars.CONTENT_URI, CALENDAR_SELECTION,
new String[] {mEmailAddress, Email.EXCHANGE_ACCOUNT_MANAGER_TYPE});
}
private void addOrganizerToAttendees(CalendarOperations ops, long eventId,
String organizerName, String organizerEmail) {
// Handle the organizer (who IS an attendee on device, but NOT in EAS)

View File

@ -17,32 +17,24 @@
package com.android.exchange.adapter;
import com.android.email.provider.EmailContent.Mailbox;
import com.android.exchange.Eas;
import com.android.exchange.EasSyncService;
import android.content.ContentProviderClient;
import android.content.ContentProviderOperation;
import android.content.ContentProviderOperation.Builder;
import android.content.ContentProviderResult;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Entity;
import android.content.Entity.NamedContentValues;
import android.content.EntityIterator;
import android.content.OperationApplicationException;
import android.content.ContentProviderOperation.Builder;
import android.content.Entity.NamedContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.os.RemoteException;
import android.provider.ContactsContract;
import android.provider.SyncStateContract;
import android.provider.ContactsContract.Data;
import android.provider.ContactsContract.Groups;
import android.provider.ContactsContract.RawContacts;
import android.provider.ContactsContract.RawContactsEntity;
import android.provider.ContactsContract.Settings;
import android.provider.ContactsContract.SyncState;
import android.provider.ContactsContract.CommonDataKinds.Email;
import android.provider.ContactsContract.CommonDataKinds.Event;
import android.provider.ContactsContract.CommonDataKinds.GroupMembership;
@ -56,6 +48,13 @@ import android.provider.ContactsContract.CommonDataKinds.Relation;
import android.provider.ContactsContract.CommonDataKinds.StructuredName;
import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
import android.provider.ContactsContract.CommonDataKinds.Website;
import android.provider.ContactsContract.Data;
import android.provider.ContactsContract.Groups;
import android.provider.ContactsContract.RawContacts;
import android.provider.ContactsContract.RawContactsEntity;
import android.provider.ContactsContract.Settings;
import android.provider.ContactsContract.SyncState;
import android.provider.SyncStateContract;
import android.text.TextUtils;
import android.text.util.Rfc822Token;
import android.text.util.Rfc822Tokenizer;
@ -124,10 +123,14 @@ public class ContactsSyncAdapter extends AbstractSyncAdapter {
ArrayList<Long> mDeletedIdList = new ArrayList<Long>();
ArrayList<Long> mUpdatedIdList = new ArrayList<Long>();
private final Uri mAccountUri;
private final ContentResolver mContentResolver;
private boolean mGroupsUsed = false;
public ContactsSyncAdapter(Mailbox mailbox, EasSyncService service) {
super(mailbox, service);
public ContactsSyncAdapter(EasSyncService service) {
super(service);
mAccountUri = uriWithAccountAndIsSyncAdapter(RawContacts.CONTENT_URI);
mContentResolver = mContext.getContentResolver();
}
static Uri addCallerIsSyncAdapterParameter(Uri uri) {
@ -153,6 +156,12 @@ public class ContactsSyncAdapter extends AbstractSyncAdapter {
return p.parse();
}
@Override
public void wipe() {
mContentResolver.delete(mAccountUri, null, null);
}
interface UntypedRow {
public void addValues(RowBuilder builder);
public boolean isSameAs(int type, String value);
@ -331,18 +340,11 @@ public class ContactsSyncAdapter extends AbstractSyncAdapter {
String[] mBindArgument = new String[1];
String mMailboxIdAsString;
Uri mAccountUri;
ContactOperations ops = new ContactOperations();
public EasContactsSyncParser(InputStream in, ContactsSyncAdapter adapter)
throws IOException {
super(in, adapter);
mAccountUri = uriWithAccountAndIsSyncAdapter(RawContacts.CONTENT_URI);
}
@Override
public void wipe() {
mContentResolver.delete(mAccountUri, null, null);
}
public void addData(String serverId, ContactOperations ops, Entity entity)

View File

@ -28,7 +28,6 @@ import com.android.email.mail.internet.MimeMessage;
import com.android.email.mail.internet.MimeUtility;
import com.android.email.provider.AttachmentProvider;
import com.android.email.provider.EmailContent;
import com.android.email.provider.EmailProvider;
import com.android.email.provider.EmailContent.Account;
import com.android.email.provider.EmailContent.AccountColumns;
import com.android.email.provider.EmailContent.Attachment;
@ -37,6 +36,7 @@ import com.android.email.provider.EmailContent.Mailbox;
import com.android.email.provider.EmailContent.Message;
import com.android.email.provider.EmailContent.MessageColumns;
import com.android.email.provider.EmailContent.SyncColumns;
import com.android.email.provider.EmailProvider;
import com.android.email.service.MailService;
import com.android.exchange.Eas;
import com.android.exchange.EasSyncService;
@ -102,8 +102,18 @@ public class EmailSyncAdapter extends AbstractSyncAdapter {
// Holds the parser's value for isLooping()
boolean mIsLooping = false;
public EmailSyncAdapter(Mailbox mailbox, EasSyncService service) {
super(mailbox, service);
public EmailSyncAdapter(EasSyncService service) {
super(service);
}
@Override
public void wipe() {
mContentResolver.delete(Message.CONTENT_URI,
Message.MAILBOX_KEY + "=" + mMailbox.mId, null);
mContentResolver.delete(Message.DELETED_CONTENT_URI,
Message.MAILBOX_KEY + "=" + mMailbox.mId, null);
mContentResolver.delete(Message.UPDATED_CONTENT_URI,
Message.MAILBOX_KEY + "=" + mMailbox.mId, null);
}
private String getEmailFilter() {
@ -238,16 +248,6 @@ public class EmailSyncAdapter extends AbstractSyncAdapter {
mMailboxIdAsString = Long.toString(mMailbox.mId);
}
@Override
public void wipe() {
mContentResolver.delete(Message.CONTENT_URI,
Message.MAILBOX_KEY + "=" + mMailbox.mId, null);
mContentResolver.delete(Message.DELETED_CONTENT_URI,
Message.MAILBOX_KEY + "=" + mMailbox.mId, null);
mContentResolver.delete(Message.UPDATED_CONTENT_URI,
Message.MAILBOX_KEY + "=" + mMailbox.mId, null);
}
public void addData (Message msg) throws IOException {
ArrayList<Attachment> atts = new ArrayList<Attachment>();
boolean truncated = false;

View File

@ -20,10 +20,10 @@ package com.android.exchange.adapter;
import com.android.email.Utility;
import com.android.email.provider.AttachmentProvider;
import com.android.email.provider.EmailContent;
import com.android.email.provider.EmailProvider;
import com.android.email.provider.EmailContent.AccountColumns;
import com.android.email.provider.EmailContent.Mailbox;
import com.android.email.provider.EmailContent.MailboxColumns;
import com.android.email.provider.EmailProvider;
import com.android.exchange.Eas;
import com.android.exchange.ExchangeService;
import com.android.exchange.MockParserStream;
@ -464,10 +464,6 @@ public class FolderSyncParser extends AbstractSyncParser {
public void commit() throws IOException {
}
@Override
public void wipe() {
}
@Override
public void responsesParser() throws IOException {
}

View File

@ -96,10 +96,6 @@ public class ProvisionParser extends Parser {
break;
case Tags.PROVISION_DEVICE_PASSWORD_EXPIRATION:
passwordExpiration = getValueInt();
// We don't yet support this
if (passwordExpiration > 0) {
tagIsSupported = false;
}
break;
case Tags.PROVISION_DEVICE_PASSWORD_HISTORY:
passwordHistory = getValueInt();

View File

@ -17,12 +17,12 @@
package com.android.exchange.adapter;
import com.android.email.provider.EmailContent;
import com.android.email.provider.ProviderTestUtils;
import com.android.email.provider.EmailContent.Account;
import com.android.email.provider.EmailContent.Body;
import com.android.email.provider.EmailContent.Mailbox;
import com.android.email.provider.EmailContent.Message;
import com.android.email.provider.EmailContent.SyncColumns;
import com.android.email.provider.ProviderTestUtils;
import com.android.exchange.EasSyncService;
import com.android.exchange.adapter.EmailSyncAdapter.EasEmailSyncParser;
import com.android.exchange.adapter.EmailSyncAdapter.EasEmailSyncParser.ServerChange;
@ -48,7 +48,7 @@ public class EmailSyncAdapterTests extends SyncAdapterTestCase<EmailSyncAdapter>
*/
public void testGetMimeTypeFromFileName() throws IOException {
EasSyncService service = getTestService();
EmailSyncAdapter adapter = new EmailSyncAdapter(service.mMailbox, service);
EmailSyncAdapter adapter = new EmailSyncAdapter(service);
EasEmailSyncParser p = adapter.new EasEmailSyncParser(getTestInputStream(), adapter);
// Test a few known types
String mimeType = p.getMimeTypeFromFileName("foo.jpg");
@ -87,7 +87,7 @@ public class EmailSyncAdapterTests extends SyncAdapterTestCase<EmailSyncAdapter>
public void testSendDeletedItems() throws IOException {
EasSyncService service = getTestService();
EmailSyncAdapter adapter = new EmailSyncAdapter(service.mMailbox, service);
EmailSyncAdapter adapter = new EmailSyncAdapter(service);
Serializer s = new Serializer();
ArrayList<Long> ids = new ArrayList<Long>();
ArrayList<Long> deletedIds = new ArrayList<Long>();
@ -150,7 +150,7 @@ public class EmailSyncAdapterTests extends SyncAdapterTestCase<EmailSyncAdapter>
void setupSyncParserAndAdapter(Account account, Mailbox mailbox) throws IOException {
EasSyncService service = getTestService(account, mailbox);
mSyncAdapter = new EmailSyncAdapter(mailbox, service);
mSyncAdapter = new EmailSyncAdapter(service);
mSyncParser = mSyncAdapter.new EasEmailSyncParser(getTestInputStream(), mSyncAdapter);
}

View File

@ -16,9 +16,9 @@
package com.android.exchange.adapter;
import com.android.email.provider.ProviderTestUtils;
import com.android.email.provider.EmailContent.Account;
import com.android.email.provider.EmailContent.Mailbox;
import com.android.email.provider.ProviderTestUtils;
import com.android.exchange.EasSyncService;
import java.io.IOException;
@ -37,7 +37,7 @@ public class FolderSyncParserTests extends SyncAdapterTestCase<EmailSyncAdapter>
public void testIsValidMailFolder() throws IOException {
EasSyncService service = getTestService();
EmailSyncAdapter adapter = new EmailSyncAdapter(service.mMailbox, service);
EmailSyncAdapter adapter = new EmailSyncAdapter(service);
FolderSyncParser parser = new FolderSyncParser(getTestInputStream(), adapter);
HashMap<String, Mailbox> mailboxMap = new HashMap<String, Mailbox>();
Account acct = ProviderTestUtils.setupAccount("account", true, mMockContext);