From 21102f6323b2ee79255c34e1a08a0c2e19822c2f Mon Sep 17 00:00:00 2001 From: Marc Blank Date: Tue, 29 May 2012 08:46:17 -0700 Subject: [PATCH] Handle inline images in EmailProvider * Automatically prefetch these attachments * Use AttachmentProvider properly (to get output stream) Bug: 6437156 Change-Id: I6f594e3b9b6286cb19d7fb7390aa6979ba492c22 --- .../utility/AttachmentUtilities.java | 37 +++++++++++++------ .../android/email/provider/EmailProvider.java | 3 ++ .../service/AttachmentDownloadService.java | 21 ++++++----- 3 files changed, 40 insertions(+), 21 deletions(-) diff --git a/email2/emailcommon/src/com/android/emailcommon/utility/AttachmentUtilities.java b/email2/emailcommon/src/com/android/emailcommon/utility/AttachmentUtilities.java index e62c55893..801edaa42 100644 --- a/email2/emailcommon/src/com/android/emailcommon/utility/AttachmentUtilities.java +++ b/email2/emailcommon/src/com/android/emailcommon/utility/AttachmentUtilities.java @@ -32,6 +32,8 @@ import android.webkit.MimeTypeMap; import com.android.emailcommon.Logging; import com.android.emailcommon.provider.EmailContent.Attachment; import com.android.emailcommon.provider.EmailContent.AttachmentColumns; +import com.android.emailcommon.provider.EmailContent.Body; +import com.android.emailcommon.provider.EmailContent.BodyColumns; import com.android.emailcommon.provider.EmailContent.Message; import com.android.emailcommon.provider.EmailContent.MessageColumns; import com.android.mail.providers.UIProvider; @@ -42,6 +44,7 @@ import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; +import java.io.OutputStream; public class AttachmentUtilities { public static final String AUTHORITY = "com.android.email.attachmentprovider"; @@ -361,8 +364,7 @@ public class AttachmentUtilities { } } - private static long copyFile(InputStream in, File file) throws IOException { - FileOutputStream out = new FileOutputStream(file); + private static long copyFile(InputStream in, OutputStream out) throws IOException { long size = IOUtils.copy(in, out); in.close(); out.flush(); @@ -378,24 +380,20 @@ public class AttachmentUtilities { ContentValues cv = new ContentValues(); long attachmentId = attachment.mId; long accountId = attachment.mAccountKey; - String contentUri; + String contentUri = null; long size; try { + ContentResolver resolver = context.getContentResolver(); if (attachment.mUiDestination == UIProvider.AttachmentDestination.CACHE) { - File saveIn = getAttachmentDirectory(context, accountId); - if (!saveIn.exists()) { - saveIn.mkdirs(); - } - File file = getAttachmentFilename(context, accountId, attachmentId); - file.createNewFile(); - size = copyFile(in, file); - contentUri = getAttachmentUri(accountId, attachmentId).toString(); + Uri attUri = getAttachmentUri(accountId, attachmentId); + size = copyFile(in, resolver.openOutputStream(attUri)); + contentUri = attUri.toString(); } else if (Utility.isExternalStorageMounted()) { File downloads = Environment.getExternalStoragePublicDirectory( Environment.DIRECTORY_DOWNLOADS); downloads.mkdirs(); File file = Utility.createUniqueFile(downloads, attachment.mFileName); - size = copyFile(in, file); + size = copyFile(in, new FileOutputStream(file)); String absolutePath = file.getAbsolutePath(); // Although the download manager can scan media files, scanning only happens @@ -428,5 +426,20 @@ public class AttachmentUtilities { } context.getContentResolver().update(uri, cv, null, null); + // If this is an inline attachment, update the body + if (contentUri != null && attachment.mContentId != null) { + Body body = Body.restoreBodyWithMessageId(context, attachment.mMessageKey); + if (body != null && body.mHtmlContent != null) { + cv.clear(); + String html = body.mHtmlContent; + String contentIdRe = + "\\s+(?i)src=\"cid(?-i):\\Q" + attachment.mContentId + "\\E\""; + String srcContentUri = " src=\"" + contentUri + "\""; + html = html.replaceAll(contentIdRe, srcContentUri); + cv.put(BodyColumns.HTML_CONTENT, html); + context.getContentResolver().update( + ContentUris.withAppendedId(Body.CONTENT_URI, body.mId), cv, null, null); + } + } } } diff --git a/email2/src/com/android/email/provider/EmailProvider.java b/email2/src/com/android/email/provider/EmailProvider.java index c17f7e896..3e8f18879 100644 --- a/email2/src/com/android/email/provider/EmailProvider.java +++ b/email2/src/com/android/email/provider/EmailProvider.java @@ -2333,6 +2333,9 @@ outer: ArrayList uiAtts = new ArrayList(); for (Attachment att : atts) { + if (att.mContentId != null && att.mContentUri != null) { + continue; + } com.android.mail.providers.Attachment uiAtt = new com.android.mail.providers.Attachment(); uiAtt.name = att.mFileName; diff --git a/email2/src/com/android/email/service/AttachmentDownloadService.java b/email2/src/com/android/email/service/AttachmentDownloadService.java index d6c479947..e86e03f37 100644 --- a/email2/src/com/android/email/service/AttachmentDownloadService.java +++ b/email2/src/com/android/email/service/AttachmentDownloadService.java @@ -352,25 +352,28 @@ public class AttachmentDownloadService extends Service implements Runnable { // We'll load up the newest 25 attachments that aren't loaded or queued Uri lookupUri = EmailContent.uriWithLimit(Attachment.CONTENT_URI, MAX_ATTACHMENTS_TO_CHECK); - Cursor c = mContext.getContentResolver().query(lookupUri, AttachmentInfo.PROJECTION, + Cursor c = mContext.getContentResolver().query(lookupUri, + Attachment.CONTENT_PROJECTION, EmailContent.Attachment.PRECACHE_INBOX_SELECTION, null, Attachment.RECORD_ID + " DESC"); File cacheDir = mContext.getCacheDir(); try { while (c.moveToNext()) { - long accountKey = c.getLong(AttachmentInfo.COLUMN_ACCOUNT_KEY); - long id = c.getLong(AttachmentInfo.COLUMN_ID); - Account account = Account.restoreAccountWithId(mContext, accountKey); + Attachment att = new Attachment(); + att.restore(c); + Account account = Account.restoreAccountWithId(mContext, att.mAccountKey); if (account == null) { // Clean up this orphaned attachment; there's no point in keeping it // around; then try to find another one - EmailContent.delete(mContext, Attachment.CONTENT_URI, id); - } else if (canPrefetchForAccount(account, cacheDir)) { + EmailContent.delete(mContext, Attachment.CONTENT_URI, att.mId); + } else { // Check that the attachment meets system requirements for download - AttachmentInfo info = new AttachmentInfo(mContext, c); + AttachmentInfo info = new AttachmentInfo(mContext, att); if (info.isEligibleForDownload()) { - Attachment att = Attachment.restoreAttachmentWithId(mContext, id); - if (att != null) { + // Either the account must be able to prefetch or this must be + // an inline attachment + if (att.mContentId != null || + (canPrefetchForAccount(account, cacheDir))) { Integer tryCount; tryCount = mAttachmentFailureMap.get(att.mId); if (tryCount != null && tryCount > MAX_DOWNLOAD_RETRIES) {