AI 146360: Provide an API by which the server (or store) can tag some
of the role-specific folders such as Drafts, Sent, or Trash. This allows us to properly target these folders even on systems where they have different names. I capture the tagged names into the existing columns in the account data, where they are used elsewhere in the code (no changes necessary). Use default implementations on POP3 and IMAP for now - no change from original behavior. The new code is primarily to support EAS (for now). BUG=1790798 Automated import of CL 146360
This commit is contained in:
parent
4836f3c289
commit
1f48259d22
|
@ -16,21 +16,6 @@
|
|||
|
||||
package com.android.email;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
|
||||
import android.app.Application;
|
||||
import android.content.Context;
|
||||
import android.os.Process;
|
||||
import android.util.Config;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.email.mail.FetchProfile;
|
||||
import com.android.email.mail.Flag;
|
||||
import com.android.email.mail.Folder;
|
||||
|
@ -48,6 +33,20 @@ import com.android.email.mail.store.LocalStore.LocalFolder;
|
|||
import com.android.email.mail.store.LocalStore.LocalMessage;
|
||||
import com.android.email.mail.store.LocalStore.PendingCommand;
|
||||
|
||||
import android.app.Application;
|
||||
import android.content.Context;
|
||||
import android.os.Process;
|
||||
import android.util.Config;
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
|
||||
/**
|
||||
* Starts a long running (application) Thread that will run through commands
|
||||
* that require remote mailbox access. This class is used to serialize and
|
||||
|
@ -214,6 +213,7 @@ public class MessagingController implements Runnable {
|
|||
account.getStoreCallbacks());
|
||||
|
||||
Folder[] remoteFolders = store.getPersonalNamespaces();
|
||||
updateAccountFolderNames(account, remoteFolders);
|
||||
|
||||
Store localStore = Store.getInstance(
|
||||
account.getLocalStoreUri(), mApplication, null);
|
||||
|
@ -267,6 +267,35 @@ public class MessagingController implements Runnable {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Asks the store for a list of server-specific folder names and, if provided, updates
|
||||
* the account record for future getFolder() operations.
|
||||
*
|
||||
* NOTE: Inbox is not queried, because we require it to be INBOX, and outbox is not
|
||||
* queried, because outbox is local-only.
|
||||
*/
|
||||
/* package */ static void updateAccountFolderNames(Account account, Folder[] remoteFolders) {
|
||||
String trash = null;
|
||||
String sent = null;
|
||||
String drafts = null;
|
||||
|
||||
for (Folder folder : remoteFolders) {
|
||||
Folder.FolderRole role = folder.getRole();
|
||||
if (role == Folder.FolderRole.TRASH) {
|
||||
trash = folder.getName();
|
||||
} else if (role == Folder.FolderRole.SENT) {
|
||||
sent = folder.getName();
|
||||
} else if (role == Folder.FolderRole.DRAFTS) {
|
||||
drafts = folder.getName();
|
||||
}
|
||||
}
|
||||
|
||||
// Do not update when null (defaults are already in place)
|
||||
if (trash != null) account.setTrashFolderName(trash);
|
||||
if (sent != null) account.setSentFolderName(sent);
|
||||
if (drafts != null) account.setDraftsFolderName(drafts);
|
||||
}
|
||||
|
||||
/**
|
||||
* List the local message store for the given folder. This work is done
|
||||
|
|
|
@ -25,6 +25,20 @@ public abstract class Folder {
|
|||
public enum FolderType {
|
||||
HOLDS_FOLDERS, HOLDS_MESSAGES,
|
||||
}
|
||||
|
||||
/**
|
||||
* Identifiers of "special" folders.
|
||||
*/
|
||||
public enum FolderRole {
|
||||
INBOX, // NOTE: The folder's name must be INBOX
|
||||
TRASH,
|
||||
SENT,
|
||||
DRAFTS,
|
||||
|
||||
OUTBOX, // Local folders only - not used in remote Stores
|
||||
OTHER, // this folder has no specific role
|
||||
UNKNOWN // the role of this folder is unknown
|
||||
}
|
||||
|
||||
/**
|
||||
* Forces an open of the MailProvider. If the provider is already open this
|
||||
|
@ -109,6 +123,20 @@ public abstract class Folder {
|
|||
|
||||
public abstract Flag[] getPermanentFlags() throws MessagingException;
|
||||
|
||||
/**
|
||||
* This method returns a string identifying the name of a "role" folder
|
||||
* (such as inbox, draft, sent, or trash). Stores that do not implement this
|
||||
* feature can be used - the account UI will provide default strings. To
|
||||
* let the server identify specific folder roles, simply override this method.
|
||||
*
|
||||
* @return The server- or protocol- specific role for this folder. If some roles are known
|
||||
* but this is not one of them, return FolderRole.OTHER. If roles are unsupported here,
|
||||
* return FolderRole.UNKNOWN.
|
||||
*/
|
||||
public FolderRole getRole() {
|
||||
return FolderRole.UNKNOWN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback interface by which a Folder can read and write persistent data.
|
||||
* TODO This needs to be made more generic & flexible
|
||||
|
|
|
@ -0,0 +1,145 @@
|
|||
/*
|
||||
* Copyright (C) 2009 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;
|
||||
|
||||
import com.android.email.mail.FetchProfile;
|
||||
import com.android.email.mail.Flag;
|
||||
import com.android.email.mail.Folder;
|
||||
import com.android.email.mail.Message;
|
||||
import com.android.email.mail.MessageRetrievalListener;
|
||||
import com.android.email.mail.MessagingException;
|
||||
import com.android.email.mail.MockFolder;
|
||||
import com.android.email.mail.Store;
|
||||
import com.android.email.mail.Folder.FolderRole;
|
||||
|
||||
import android.content.SharedPreferences;
|
||||
import android.test.AndroidTestCase;
|
||||
import android.test.suitebuilder.annotation.SmallTest;
|
||||
|
||||
/**
|
||||
* This is a series of unit tests for the MessagingController class.
|
||||
*
|
||||
* Technically these are functional because they use the underlying preferences framework.
|
||||
*/
|
||||
@SmallTest
|
||||
public class MessagingControllerUnitTests extends AndroidTestCase {
|
||||
|
||||
private Preferences mPreferences;
|
||||
|
||||
private String mUuid;
|
||||
private Account mAccount;
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
|
||||
mPreferences = Preferences.getPreferences(getContext());
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete any dummy accounts we set up for this test
|
||||
*/
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
super.tearDown();
|
||||
|
||||
if (mAccount != null && mPreferences != null) {
|
||||
mAccount.delete(mPreferences);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the code that copies server-supplied folder names into the account data
|
||||
*/
|
||||
public void testUpdateAccountFolderNames() {
|
||||
// Create a dummy account
|
||||
createTestAccount();
|
||||
// Refresh it to fill in all fields (many will have default values)
|
||||
mAccount.refresh(mPreferences);
|
||||
|
||||
// Replace one entry, others are not included
|
||||
Folder[] folders1 = new Folder[] {
|
||||
new MyMockFolder(Folder.FolderRole.DRAFTS, "DRAFTS_1"),
|
||||
};
|
||||
MessagingController.updateAccountFolderNames(mAccount, folders1);
|
||||
checkServerFolderNames("folders1", "DRAFTS_1", "Sent", "Trash", "Outbox");
|
||||
|
||||
// Replace one entry, others are included but called out as unknown
|
||||
Folder[] folders2 = new Folder[] {
|
||||
new MyMockFolder(Folder.FolderRole.UNKNOWN, "DRAFTS_2"),
|
||||
new MyMockFolder(Folder.FolderRole.SENT, "SENT_2"),
|
||||
new MyMockFolder(Folder.FolderRole.UNKNOWN, "TRASH_2"),
|
||||
new MyMockFolder(Folder.FolderRole.UNKNOWN, "OUTBOX_2"),
|
||||
};
|
||||
MessagingController.updateAccountFolderNames(mAccount, folders2);
|
||||
checkServerFolderNames("folders2", "DRAFTS_1", "SENT_2", "Trash", "Outbox");
|
||||
|
||||
// Replace one entry, check that "other" is ignored, check that Outbox is ignored
|
||||
Folder[] folders3 = new Folder[] {
|
||||
new MyMockFolder(Folder.FolderRole.OTHER, "OTHER_3a"),
|
||||
new MyMockFolder(Folder.FolderRole.TRASH, "TRASH_3"),
|
||||
new MyMockFolder(Folder.FolderRole.OTHER, "OTHER_3b"),
|
||||
new MyMockFolder(Folder.FolderRole.OUTBOX, "OUTBOX_3"),
|
||||
};
|
||||
MessagingController.updateAccountFolderNames(mAccount, folders3);
|
||||
checkServerFolderNames("folders2", "DRAFTS_1", "SENT_2", "TRASH_3", "Outbox");
|
||||
}
|
||||
|
||||
/**
|
||||
* Quickly check all four folder name slots in mAccount
|
||||
*/
|
||||
private void checkServerFolderNames(String diagnostic,
|
||||
String drafts, String sent, String trash, String outbox) {
|
||||
assertEquals(diagnostic, drafts, mAccount.getDraftsFolderName());
|
||||
assertEquals(diagnostic, sent, mAccount.getSentFolderName());
|
||||
assertEquals(diagnostic, trash, mAccount.getTrashFolderName());
|
||||
assertEquals(diagnostic, outbox, mAccount.getOutboxFolderName());
|
||||
}
|
||||
|
||||
/**
|
||||
* MockFolder allows setting and retrieving role & name
|
||||
*/
|
||||
private static class MyMockFolder extends MockFolder {
|
||||
private FolderRole mRole;
|
||||
private String mName;
|
||||
|
||||
public MyMockFolder(FolderRole role, String name) {
|
||||
mRole = role;
|
||||
mName = name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return mName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FolderRole getRole() {
|
||||
return mRole;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a dummy account with minimal fields
|
||||
*/
|
||||
private void createTestAccount() {
|
||||
mAccount = new Account(getContext());
|
||||
mAccount.save(mPreferences);
|
||||
|
||||
mUuid = mAccount.getUuid();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,144 @@
|
|||
/*
|
||||
* Copyright (C) 2009 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.mail;
|
||||
|
||||
public class MockFolder extends Folder {
|
||||
|
||||
@Override
|
||||
public void appendMessages(Message[] messages) throws MessagingException {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close(boolean expunge) throws MessagingException {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void copyMessages(Message[] msgs, Folder folder) throws MessagingException {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean create(FolderType type) throws MessagingException {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(boolean recurse) throws MessagingException {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean exists() throws MessagingException {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Message[] expunge() throws MessagingException {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fetch(Message[] messages, FetchProfile fp, MessageRetrievalListener listener)
|
||||
throws MessagingException {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Message getMessage(String uid) throws MessagingException {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMessageCount() throws MessagingException {
|
||||
// TODO Auto-generated method stub
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Message[] getMessages(int start, int end, MessageRetrievalListener listener)
|
||||
throws MessagingException {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Message[] getMessages(MessageRetrievalListener listener) throws MessagingException {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Message[] getMessages(String[] uids, MessageRetrievalListener listener)
|
||||
throws MessagingException {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OpenMode getMode() throws MessagingException {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Flag[] getPermanentFlags() throws MessagingException {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getUnreadMessageCount() throws MessagingException {
|
||||
// TODO Auto-generated method stub
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOpen() {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void open(OpenMode mode, PersistentDataCallbacks callbacks) throws MessagingException {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFlags(Message[] messages, Flag[] flags, boolean value) throws MessagingException {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -16,19 +16,18 @@
|
|||
|
||||
package com.android.email.mail.store;
|
||||
|
||||
import com.android.email.mail.Folder;
|
||||
import com.android.email.mail.MessagingException;
|
||||
import com.android.email.mail.Transport;
|
||||
import com.android.email.mail.Folder.OpenMode;
|
||||
import com.android.email.mail.internet.BinaryTempFileBody;
|
||||
import com.android.email.mail.store.ImapResponseParser;
|
||||
import com.android.email.mail.transport.MockTransport;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
|
||||
import android.test.AndroidTestCase;
|
||||
import android.test.suitebuilder.annotation.SmallTest;
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* This is a series of unit tests for the ImapStore class. These tests must be locally
|
||||
|
@ -117,6 +116,15 @@ public class ImapStoreUnitTests extends AndroidTestCase {
|
|||
* TODO: Test small Folder functions that don't really do anything in Imap (if any)
|
||||
*/
|
||||
|
||||
/**
|
||||
* Lightweight test to confirm that IMAP hasn't implemented any folder roles yet.
|
||||
*
|
||||
* TODO: Test this with multiple folders provided by mock server
|
||||
*/
|
||||
public void testNoFolderRolesYet() {
|
||||
assertEquals(Folder.FolderRole.UNKNOWN, mFolder.getRole());
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: Test the process of opening and indexing a mailbox with one unread message in it.
|
||||
*/
|
||||
|
|
|
@ -312,6 +312,16 @@ public class LocalStoreUnitTests extends AndroidTestCase {
|
|||
assertEquals(Email.VISIBLE_LIMIT_DEFAULT, folder2.getVisibleLimit());
|
||||
}
|
||||
|
||||
/**
|
||||
* Lightweight test to confirm that LocalStore hasn't implemented any folder roles yet.
|
||||
*/
|
||||
public void testNoFolderRolesYet() throws MessagingException {
|
||||
Folder[] localFolders = mStore.getPersonalNamespaces();
|
||||
for (Folder folder : localFolders) {
|
||||
assertEquals(Folder.FolderRole.UNKNOWN, folder.getRole());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests for database version.
|
||||
*/
|
||||
|
|
|
@ -248,6 +248,16 @@ public class Pop3StoreUnitTests extends AndroidTestCase {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Lightweight test to confirm that POP3 hasn't implemented any folder roles yet.
|
||||
*/
|
||||
public void testNoFolderRolesYet() throws MessagingException {
|
||||
Folder[] remoteFolders = mStore.getPersonalNamespaces();
|
||||
for (Folder folder : remoteFolders) {
|
||||
assertEquals(Folder.FolderRole.UNKNOWN, folder.getRole());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the process of opening and indexing a mailbox with one unread message in it.
|
||||
*
|
||||
|
|
Loading…
Reference in New Issue