diff --git a/src/com/android/email/Controller.java b/src/com/android/email/Controller.java index 19eeabf59..5bb365439 100644 --- a/src/com/android/email/Controller.java +++ b/src/com/android/email/Controller.java @@ -98,6 +98,9 @@ public class Controller { private static final String WHERE_MESSAGE_KEY = Body.MESSAGE_KEY + "=?"; private static final String MAILBOXES_FOR_ACCOUNT_SELECTION = MailboxColumns.ACCOUNT_KEY + "=?"; + private static final String MAILBOXES_FOR_ACCOUNT_NOT_INBOX_SELECTION = + MAILBOXES_FOR_ACCOUNT_SELECTION + " AND " + MailboxColumns.TYPE + "!=" + Mailbox.TYPE_INBOX; + private static final String MESSAGES_FOR_ACCOUNT_SELECTION = MessageColumns.ACCOUNT_KEY + "=?"; // Service callbacks as set up via setCallback private static RemoteCallbackList sCallbackList = @@ -989,6 +992,9 @@ public class Controller { * policy requirements are not met, and we don't want to reveal any synced data, but we do * wish to keep the account configured (e.g. to accept remote wipe commands). * + * Also, leave behind an empty inbox, which simplifies things for the UI. + * Also, clear the sync keys on the remaining account & mailbox, since the data is gone. + * * SYNCHRONOUS - do not call from UI thread. * * @param accountId The account to wipe. @@ -997,9 +1003,25 @@ public class Controller { try { // Delete synced attachments AttachmentProvider.deleteAllAccountAttachmentFiles(mProviderContext, accountId); - // Delete synced email - mProviderContext.getContentResolver().delete(Mailbox.CONTENT_URI, - MAILBOXES_FOR_ACCOUNT_SELECTION, new String[] { Long.toString(accountId) }); + + // Delete synced email, leaving only an empty inbox. We do this in two phases: + // 1. Delete all non-inbox mailboxes (which will delete all of their messages) + // 2. Delete all remaining messages (which will be the inbox messages) + ContentResolver resolver = mProviderContext.getContentResolver(); + String[] accountIdArgs = new String[] { Long.toString(accountId) }; + resolver.delete(Mailbox.CONTENT_URI, MAILBOXES_FOR_ACCOUNT_NOT_INBOX_SELECTION, + accountIdArgs); + resolver.delete(Message.CONTENT_URI, MESSAGES_FOR_ACCOUNT_SELECTION, accountIdArgs); + + // Delete sync keys on remaining items + ContentValues cv = new ContentValues(); + cv.putNull(Account.SYNC_KEY); + resolver.update(Account.CONTENT_URI, cv, Account.ID_SELECTION, accountIdArgs); + cv.clear(); + cv.putNull(Mailbox.SYNC_KEY); + resolver.update(Mailbox.CONTENT_URI, cv, + MAILBOXES_FOR_ACCOUNT_SELECTION, accountIdArgs); + // Delete PIM data (contacts, calendar) if applicable IEmailService service = getServiceForAccount(accountId); if (service != null) { diff --git a/tests/src/com/android/email/ControllerProviderOpsTests.java b/tests/src/com/android/email/ControllerProviderOpsTests.java index bfb4b4e11..9f47d0462 100644 --- a/tests/src/com/android/email/ControllerProviderOpsTests.java +++ b/tests/src/com/android/email/ControllerProviderOpsTests.java @@ -378,19 +378,31 @@ public class ControllerProviderOpsTests extends ProviderTestCase2 } /** - * Test wiping an account's synced data (but not the account) + * Test wiping an account's synced data. Everything should go, but account & empty inbox. + * Also ensures that the remaining account and the remaining inbox have cleared their + * server sync keys, to force refresh eventually. */ public void testWipeSyncedData() { - Account account1 = ProviderTestUtils.setupAccount("wipe-synced-1", true, mProviderContext); + Account account1 = ProviderTestUtils.setupAccount("wipe-synced-1", false, mProviderContext); + account1.mSyncKey = "account-1-sync-key"; + account1.save(mProviderContext); long account1Id = account1.mId; - Mailbox box1 = ProviderTestUtils.setupMailbox("box1", account1Id, true, mProviderContext); + Mailbox box1 = ProviderTestUtils.setupMailbox("box1", account1Id, false, mProviderContext); + box1.mType = Mailbox.TYPE_INBOX; + box1.mSyncKey = "box-1-sync-key"; + box1.save(mProviderContext); long box1Id = box1.mId; Mailbox box2 = ProviderTestUtils.setupMailbox("box2", account1Id, true, mProviderContext); long box2Id = box2.mId; - Account account2 = ProviderTestUtils.setupAccount("wipe-synced-2", true, mProviderContext); + Account account2 = ProviderTestUtils.setupAccount("wipe-synced-2", false, mProviderContext); + account2.mSyncKey = "account-2-sync-key"; + account2.save(mProviderContext); long account2Id = account2.mId; - Mailbox box3 = ProviderTestUtils.setupMailbox("box3", account2Id, true, mProviderContext); + Mailbox box3 = ProviderTestUtils.setupMailbox("box3", account2Id, false, mProviderContext); + box3.mSyncKey = "box-3-sync-key"; + box3.mType = Mailbox.TYPE_INBOX; + box3.save(mProviderContext); long box3Id = box3.mId; Mailbox box4 = ProviderTestUtils.setupMailbox("box4", account2Id, true, mProviderContext); long box4Id = box4.mId; @@ -412,12 +424,16 @@ public class ControllerProviderOpsTests extends ProviderTestCase2 // Now wipe account 1's data mTestController.deleteSyncedDataSync(account1Id); - // Confirm: Mailboxes gone, messages gone, account survives - assertNull(Mailbox.restoreMailboxWithId(mProviderContext, box1Id)); + // Confirm: Mailboxes gone (except Inbox), all messages gone, account survives + box1 = Mailbox.restoreMailboxWithId(mProviderContext, box1Id); + assertNotNull(box1); + assertNull(box1.mSyncKey); assertNull(Mailbox.restoreMailboxWithId(mProviderContext, box2Id)); assertNull(Message.restoreMessageWithId(mProviderContext, message1Id)); assertNull(Message.restoreMessageWithId(mProviderContext, message2Id)); - assertNotNull(Account.restoreAccountWithId(mProviderContext, account1Id)); + account1 = Account.restoreAccountWithId(mProviderContext, account1Id); + assertNotNull(account1); + assertNull(account1.mSyncKey); // Confirm: Other account survived assertNotNull(Mailbox.restoreMailboxWithId(mProviderContext, box3Id));