DO NOT MERGE: Backport fix for IMAP delete bug
Original CL comment: Always set a delete policy for legacy accounts The delete policy can only be set for POP3 accounts. However, the delete policy is used for all legacy accounts (that includes IMAP). As such, we need to make sure IMAP accounts also have their policy set; even though the setting is not configurable by the user. The delete policy does not mean anything for Exchange accounts, so, we do not need to modify the account setup code for them. bug 3074164 Original Change-Id: Iab10d2997404b3b0c10a60a64fb652540c0d2d1a Change-Id: Idc290aa1b8ff4f17a0c8fd57333523becef0c8e5
This commit is contained in:
parent
66d4a38050
commit
067c874c31
@ -20,6 +20,7 @@ import com.android.email.AccountBackupRestore;
|
||||
import com.android.email.Email;
|
||||
import com.android.email.R;
|
||||
import com.android.email.Utility;
|
||||
import com.android.email.mail.Store;
|
||||
import com.android.email.provider.EmailContent;
|
||||
import com.android.email.provider.EmailContent.Account;
|
||||
|
||||
@ -334,17 +335,21 @@ public class AccountSetupIncomingFragment extends AccountServerBaseFragment {
|
||||
mPasswordView.setText(password);
|
||||
}
|
||||
|
||||
if (uri.getScheme().startsWith("pop3")) {
|
||||
mLoadedDeletePolicy = account.getDeletePolicy();
|
||||
SpinnerOption.setSpinnerOptionValue(mDeletePolicyView, mLoadedDeletePolicy);
|
||||
} else if (uri.getScheme().startsWith("imap")) {
|
||||
if (uri.getScheme().startsWith(Store.STORE_SCHEME_IMAP)) {
|
||||
if (uri.getPath() != null && uri.getPath().length() > 0) {
|
||||
mImapPathPrefixView.setText(uri.getPath().substring(1));
|
||||
}
|
||||
} else {
|
||||
} else if (!uri.getScheme().startsWith(Store.STORE_SCHEME_POP3)) {
|
||||
// Account must either be IMAP or POP3
|
||||
throw new Error("Unknown account type: " + account.getStoreUri(mContext));
|
||||
}
|
||||
|
||||
// The delete policy is set for all accounts. For POP3 accounts, the user sets
|
||||
// the policy explicitly. For IMAP accounts, the policy is set when the Account object
|
||||
// is created. @see AccountSetupBasics#populateSetupData
|
||||
mLoadedDeletePolicy = account.getDeletePolicy();
|
||||
SpinnerOption.setSpinnerOptionValue(mDeletePolicyView, mLoadedDeletePolicy);
|
||||
|
||||
for (int i = 0; i < mAccountSchemes.length; i++) {
|
||||
if (mAccountSchemes[i].equals(uri.getScheme())) {
|
||||
SpinnerOption.setSpinnerOptionValue(mSecurityTypeView, i);
|
||||
|
@ -22,14 +22,23 @@ import com.android.email.Preferences;
|
||||
import com.android.email.SecurityPolicy;
|
||||
import com.android.email.VendorPolicyLoader;
|
||||
import com.android.email.activity.setup.AccountSettingsXL;
|
||||
import com.android.email.mail.Store;
|
||||
import com.android.email.provider.EmailContent.Account;
|
||||
import com.android.email.provider.EmailContent.AccountColumns;
|
||||
import com.android.email.provider.EmailContent.HostAuth;
|
||||
import com.android.email.provider.WidgetProvider;
|
||||
|
||||
import android.accounts.AccountManager;
|
||||
import android.app.IntentService;
|
||||
import android.content.ComponentName;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.ContentUris;
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
@ -155,6 +164,12 @@ public class EmailBroadcastProcessorService extends IntentService {
|
||||
ExchangeUtils.enableEasCalendarSync(this);
|
||||
}
|
||||
|
||||
if (progress < 2) {
|
||||
Log.i(Email.LOG_TAG, "Onetime initialization: 2");
|
||||
progress = 2;
|
||||
setImapDeletePolicy(this);
|
||||
}
|
||||
|
||||
// Add your initialization steps here.
|
||||
// Use "progress" to skip the initializations that's already done before.
|
||||
// Using this preference also makes it safe when a user skips an upgrade. (i.e. upgrading
|
||||
@ -166,6 +181,34 @@ public class EmailBroadcastProcessorService extends IntentService {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the delete policy to the correct value for all IMAP accounts. This will have no
|
||||
* effect on either EAS or POP3 accounts.
|
||||
*/
|
||||
/*package*/ static void setImapDeletePolicy(Context context) {
|
||||
ContentResolver resolver = context.getContentResolver();
|
||||
Cursor c = resolver.query(Account.CONTENT_URI, Account.CONTENT_PROJECTION,
|
||||
null, null, null);
|
||||
try {
|
||||
while (c.moveToNext()) {
|
||||
long recvAuthKey = c.getLong(Account.CONTENT_HOST_AUTH_KEY_RECV_COLUMN);
|
||||
HostAuth recvAuth = HostAuth.restoreHostAuthWithId(context, recvAuthKey);
|
||||
if (Store.STORE_SCHEME_IMAP.equals(recvAuth.mProtocol)) {
|
||||
int flags = c.getInt(Account.CONTENT_FLAGS_COLUMN);
|
||||
flags &= ~Account.FLAGS_DELETE_POLICY_MASK;
|
||||
flags |= Account.DELETE_POLICY_ON_DELETE << Account.FLAGS_DELETE_POLICY_SHIFT;
|
||||
ContentValues cv = new ContentValues();
|
||||
cv.put(AccountColumns.FLAGS, flags);
|
||||
long accountId = c.getLong(Account.CONTENT_ID_COLUMN);
|
||||
Uri uri = ContentUris.withAppendedId(Account.CONTENT_URI, accountId);
|
||||
resolver.update(uri, cv, null, null);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
c.close();
|
||||
}
|
||||
}
|
||||
|
||||
private void setComponentEnabled(Class<?> clazz, boolean enabled) {
|
||||
final ComponentName c = new ComponentName(this, clazz.getName());
|
||||
getPackageManager().setComponentEnabledSetting(c,
|
||||
|
@ -0,0 +1,138 @@
|
||||
/*
|
||||
* Copyright (C) 2011 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.email.service;
|
||||
|
||||
import com.android.email.AccountTestCase;
|
||||
import com.android.email.Utility;
|
||||
import com.android.email.provider.EmailContent.Account;
|
||||
import com.android.email.provider.EmailContent.AccountColumns;
|
||||
import com.android.email.provider.EmailContent.HostAuth;
|
||||
import com.android.email.provider.ProviderTestUtils;
|
||||
|
||||
import android.content.ContentUris;
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
/**
|
||||
* Tests of the Email provider.
|
||||
*
|
||||
* You can run this entire test case with:
|
||||
* runtest -c com.android.email.service.EmailBroadcastProcessorServiceTests email
|
||||
*/
|
||||
public class EmailBroadcastProcessorServiceTests extends AccountTestCase {
|
||||
|
||||
Context mMockContext;
|
||||
|
||||
public EmailBroadcastProcessorServiceTests() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
mMockContext = getMockContext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tearDown() throws Exception {
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a simple HostAuth with protocol
|
||||
*/
|
||||
private HostAuth setupSimpleHostAuth(String protocol) {
|
||||
HostAuth hostAuth = ProviderTestUtils.setupHostAuth(protocol, "name", 1L, false, mContext);
|
||||
hostAuth.mProtocol = protocol;
|
||||
return hostAuth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the flags for the specified account. Throws an exception if the account cannot
|
||||
* be found.
|
||||
*/
|
||||
private int getAccountFlags(long accountId) throws NoSuchElementException {
|
||||
Uri uri = ContentUris.withAppendedId(Account.CONTENT_URI, accountId);
|
||||
Integer flags = Utility.getFirstRowInt(mMockContext, uri,
|
||||
new String[] { AccountColumns.FLAGS }, null, null, null, 0);
|
||||
if (flags == null) {
|
||||
throw new NoSuchElementException("No cursor");
|
||||
}
|
||||
return flags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initial testing on setupSyncReportsLocked, making sure that EAS accounts aren't scheduled
|
||||
*/
|
||||
public void testSetImapDeletePolicy() {
|
||||
// Setup accounts of each type, all with manual sync at different intervals
|
||||
Account account1 = ProviderTestUtils.setupAccount("eas-account1", false, mMockContext);
|
||||
account1.mHostAuthRecv = setupSimpleHostAuth("eas");
|
||||
account1.mHostAuthSend = account1.mHostAuthRecv;
|
||||
account1.save(mMockContext);
|
||||
long accountId1 = account1.mId;
|
||||
Account account2 = ProviderTestUtils.setupAccount("pop-account1", false, mMockContext);
|
||||
account2.mHostAuthRecv = setupSimpleHostAuth("pop3");
|
||||
account2.mHostAuthSend = setupSimpleHostAuth("smtp");
|
||||
account2.mFlags = 0x08; // set delete policy
|
||||
account2.save(mMockContext);
|
||||
long accountId2 = account2.mId;
|
||||
Account account3 = ProviderTestUtils.setupAccount("pop-account2", false, mMockContext);
|
||||
account3.mHostAuthRecv = setupSimpleHostAuth("pop3");
|
||||
account3.mHostAuthSend = setupSimpleHostAuth("smtp");
|
||||
account3.save(mMockContext);
|
||||
long accountId3 = account3.mId;
|
||||
Account account4 = ProviderTestUtils.setupAccount("imap-account1", false, mMockContext);
|
||||
account4.mHostAuthRecv = setupSimpleHostAuth("imap");
|
||||
account4.mHostAuthSend = setupSimpleHostAuth("smtp");
|
||||
account4.mFlags = 0xa5a5a5a5; // Alternating bits; includes bad delete policy
|
||||
account4.save(mMockContext);
|
||||
long accountId4 = account4.mId;
|
||||
Account account5 = ProviderTestUtils.setupAccount("imap-account2", false, mMockContext);
|
||||
account5.mHostAuthRecv = setupSimpleHostAuth("imap");
|
||||
account5.mHostAuthSend = setupSimpleHostAuth("smtp");
|
||||
account5.mFlags = 0x0c; // All delete policy bits set
|
||||
account5.save(mMockContext);
|
||||
long accountId5 = account5.mId;
|
||||
Account account6 = ProviderTestUtils.setupAccount("imap-account3", false, mMockContext);
|
||||
account6.mHostAuthRecv = setupSimpleHostAuth("imap");
|
||||
account6.mHostAuthSend = setupSimpleHostAuth("smtp");
|
||||
account6.mFlags = 0; // No delete policy bits set
|
||||
account6.save(mMockContext);
|
||||
long accountId6 = account6.mId;
|
||||
|
||||
// Run the account migration
|
||||
EmailBroadcastProcessorService.setImapDeletePolicy(mMockContext);
|
||||
|
||||
// Test the results
|
||||
int accountFlags1 = getAccountFlags(accountId1);
|
||||
assertEquals(4, accountFlags1); // not IMAP; no changes
|
||||
int accountFlags2 = getAccountFlags(accountId2);
|
||||
assertEquals(8, accountFlags2); // not IMAP; no changes
|
||||
int accountFlags3 = getAccountFlags(accountId3);
|
||||
assertEquals(4, accountFlags3); // not IMAP; no changes
|
||||
int accountFlags4 = getAccountFlags(accountId4);
|
||||
assertEquals(0xa5a5a5a9, accountFlags4); // Only update delete policy bits
|
||||
int accountFlags5 = getAccountFlags(accountId5);
|
||||
assertEquals(0x00000008, accountFlags5);
|
||||
int accountFlags6 = getAccountFlags(accountId6);
|
||||
assertEquals(0x00000008, accountFlags6);
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user