diff --git a/emailcommon/src/com/android/emailcommon/internet/MimeMessage.java b/emailcommon/src/com/android/emailcommon/internet/MimeMessage.java index d28b0e835..b3ee70ee4 100644 --- a/emailcommon/src/com/android/emailcommon/internet/MimeMessage.java +++ b/emailcommon/src/com/android/emailcommon/internet/MimeMessage.java @@ -120,7 +120,7 @@ public class MimeMessage extends Message { parse(in); } - protected void parse(InputStream in) throws IOException, MessagingException { + private MimeStreamParser init() { // Before parsing the input stream, clear all local fields that may be superceded by // the new incoming message. getMimeHeaders().clear(); @@ -135,10 +135,22 @@ public class MimeMessage extends Message { MimeStreamParser parser = new MimeStreamParser(); parser.setContentHandler(new MimeMessageBuilder()); + return parser; + } + + protected void parse(InputStream in) throws IOException, MessagingException { + MimeStreamParser parser = init(); parser.parse(new EOLConvertingInputStream(in)); mComplete = !parser.getPrematureEof(); } + public void parse(InputStream in, EOLConvertingInputStream.Callback callback) + throws IOException, MessagingException { + MimeStreamParser parser = init(); + parser.parse(new EOLConvertingInputStream(in, getSize(), callback)); + mComplete = !parser.getPrematureEof(); + } + /** * Return the internal mHeader value, with very lazy initialization. * The goal is to save memory by not creating the headers until needed. diff --git a/src/com/android/email/mail/store/Pop3Store.java b/src/com/android/email/mail/store/Pop3Store.java index aee87bf3e..99f54f2af 100644 --- a/src/com/android/email/mail/store/Pop3Store.java +++ b/src/com/android/email/mail/store/Pop3Store.java @@ -43,6 +43,8 @@ import com.android.emailcommon.utility.LoggingInputStream; import com.android.emailcommon.utility.Utility; import com.google.common.annotations.VisibleForTesting; +import org.apache.james.mime4j.EOLConvertingInputStream; + import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; @@ -298,6 +300,8 @@ public class Pop3Store extends Store { } else { mMessageCount = Integer.parseInt(parts[1]); } + } catch (MessagingException me) { + statException = me; } catch (IOException ioe) { statException = ioe; } catch (NumberFormatException nfe) { @@ -596,15 +600,12 @@ public class Pop3Store extends Store { * for any other value. If the server does not support TOP it is * emulated with RETR and extra lines are thrown away. * - * Note: Some servers (e.g. live.com) don't support CAPA, but turn out to - * support TOP after all. For better performance on these servers, we'll always - * probe TOP, and fall back to RETR when it's truly unsupported. - * * @param message * @param lines + * @param optional callback that reports progress of the fetch */ - public void fetchBody(Pop3Message message, int lines) - throws IOException, MessagingException { + public void fetchBody(Pop3Message message, int lines, + EOLConvertingInputStream.Callback callback) throws IOException, MessagingException { String response = null; int messageId = mUidToMsgNumMap.get(message.getUid()); if (lines == -1) { @@ -644,7 +645,7 @@ public class Pop3Store extends Store { if (DEBUG_LOG_RAW_STREAM && MailActivityEmail.DEBUG) { in = new LoggingInputStream(in); } - message.parse(new Pop3ResponseInputStream(in)); + message.parse(new Pop3ResponseInputStream(in), callback); } catch (MessagingException me) { /* diff --git a/src/com/android/email/service/Pop3Service.java b/src/com/android/email/service/Pop3Service.java index 5d1d9914d..0561d666a 100644 --- a/src/com/android/email/service/Pop3Service.java +++ b/src/com/android/email/service/Pop3Service.java @@ -59,6 +59,8 @@ import com.android.mail.providers.UIProvider; import com.android.mail.providers.UIProvider.AccountCapabilities; import com.android.mail.providers.UIProvider.AttachmentState; +import org.apache.james.mime4j.EOLConvertingInputStream; + import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; @@ -197,7 +199,8 @@ public class Pop3Service extends Service { // We'll load them from most recent to oldest for (int i = cnt - 1; i >= 0; i--) { Pop3Message message = unsyncedMessages.get(i); - remoteFolder.fetchBody(message, Pop3Store.FETCH_BODY_SANE_SUGGESTED_SIZE / 76); + remoteFolder.fetchBody(message, Pop3Store.FETCH_BODY_SANE_SUGGESTED_SIZE / 76, + null); int flag = EmailContent.Message.FLAG_LOADED_COMPLETE; if (!message.isComplete()) { flag = EmailContent.Message.FLAG_LOADED_UNKNOWN; @@ -213,6 +216,23 @@ public class Pop3Service extends Service { } } + private static class FetchCallback implements EOLConvertingInputStream.Callback { + private final ContentResolver mResolver; + private final Uri mAttachmentUri; + private final ContentValues mContentValues = new ContentValues(); + + FetchCallback(ContentResolver resolver, Uri attachmentUri) { + mResolver = resolver; + mAttachmentUri = attachmentUri; + } + + @Override + public void report(int bytesRead) { + mContentValues.put(AttachmentColumns.UI_DOWNLOADED_SIZE, bytesRead); + mResolver.update(mAttachmentUri, mContentValues, null, null); + } + } + /** * Synchronizer * @@ -368,15 +388,16 @@ public class Pop3Service extends Service { String uid = msg.mServerId; Pop3Message popMessage = remoteUidMap.get(uid); if (popMessage != null) { + Uri attUri = ContentUris.withAppendedId(Attachment.CONTENT_URI, att.mId); try { - remoteFolder.fetchBody(popMessage, -1); + remoteFolder.fetchBody(popMessage, -1, + new FetchCallback(resolver, attUri)); } catch (IOException e) { throw new MessagingException(MessagingException.IOERROR); } // Say we've downloaded the attachment values.put(AttachmentColumns.UI_STATE, AttachmentState.SAVED); - Uri attUri = ContentUris.withAppendedId(Attachment.CONTENT_URI, att.mId); resolver.update(attUri, values, null, null); int flag = EmailContent.Message.FLAG_LOADED_COMPLETE;