AI 149523: Correctly display inline images in Reply and Forward messages.
Integrates CL 148436, 148515, 148833 from imode email. BUG=1814789,1860250 Automated import of CL 149523
This commit is contained in:
parent
39137e51aa
commit
7436601fae
|
@ -32,6 +32,7 @@ import com.android.email.mail.MessagingException;
|
|||
import com.android.email.mail.Multipart;
|
||||
import com.android.email.mail.Part;
|
||||
import com.android.email.mail.Message.RecipientType;
|
||||
import com.android.email.mail.internet.EmailHtmlUtil;
|
||||
import com.android.email.mail.internet.MimeBodyPart;
|
||||
import com.android.email.mail.internet.MimeHeader;
|
||||
import com.android.email.mail.internet.MimeMessage;
|
||||
|
@ -1133,16 +1134,25 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
|
|||
}
|
||||
}
|
||||
|
||||
Part part = MimeUtility.findFirstPartByMimeType(message, "text/plain");
|
||||
Boolean plainTextFlag = false;
|
||||
Part part = MimeUtility.findFirstPartByMimeType(message, "text/html");
|
||||
if (part == null) {
|
||||
part = MimeUtility.findFirstPartByMimeType(message, "text/html");
|
||||
part = MimeUtility.findFirstPartByMimeType(message, "text/plain");
|
||||
plainTextFlag = true;
|
||||
}
|
||||
|
||||
if (part != null) {
|
||||
String text = MimeUtility.getTextFromPart(part);
|
||||
if (text != null) {
|
||||
if (!plainTextFlag) {
|
||||
text = EmailHtmlUtil.resolveInlineImage(
|
||||
getContentResolver(), mAccount, text, message, 0);
|
||||
}
|
||||
text = EmailHtmlUtil.escapeCharacterToDisplay(
|
||||
text, plainTextFlag);
|
||||
mQuotedTextBar.setVisibility(View.VISIBLE);
|
||||
mQuotedText.setVisibility(View.VISIBLE);
|
||||
mQuotedText.loadDataWithBaseURL("email://", text, part.getMimeType(),
|
||||
mQuotedText.loadDataWithBaseURL("email://", text, "text/html",
|
||||
"utf-8", null);
|
||||
}
|
||||
}
|
||||
|
@ -1164,16 +1174,26 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
|
|||
mSubjectView.setText(message.getSubject());
|
||||
}
|
||||
|
||||
Part part = MimeUtility.findFirstPartByMimeType(message, "text/plain");
|
||||
|
||||
Boolean plainTextFlag = false;
|
||||
Part part = MimeUtility.findFirstPartByMimeType(message, "text/html");
|
||||
if (part == null) {
|
||||
part = MimeUtility.findFirstPartByMimeType(message, "text/html");
|
||||
part = MimeUtility.findFirstPartByMimeType(message, "text/plain");
|
||||
plainTextFlag = true;
|
||||
}
|
||||
|
||||
if (part != null) {
|
||||
String text = MimeUtility.getTextFromPart(part);
|
||||
if (text != null) {
|
||||
if (!plainTextFlag) {
|
||||
text = EmailHtmlUtil.resolveInlineImage(
|
||||
getContentResolver(), mAccount, text, message, 0);
|
||||
}
|
||||
text = EmailHtmlUtil.escapeCharacterToDisplay(
|
||||
text, plainTextFlag);
|
||||
mQuotedTextBar.setVisibility(View.VISIBLE);
|
||||
mQuotedText.setVisibility(View.VISIBLE);
|
||||
mQuotedText.loadDataWithBaseURL("email://", text, part.getMimeType(),
|
||||
mQuotedText.loadDataWithBaseURL("email://", text, "text/html",
|
||||
"utf-8", null);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@ import com.android.email.mail.MessagingException;
|
|||
import com.android.email.mail.Multipart;
|
||||
import com.android.email.mail.Part;
|
||||
import com.android.email.mail.Message.RecipientType;
|
||||
import com.android.email.mail.internet.EmailHtmlUtil;
|
||||
import com.android.email.mail.internet.MimeUtility;
|
||||
import com.android.email.mail.store.LocalStore.LocalAttachmentBodyPart;
|
||||
import com.android.email.mail.store.LocalStore.LocalMessage;
|
||||
|
@ -714,69 +715,6 @@ public class MessageView extends Activity
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve attachment id to content URI.
|
||||
*
|
||||
* @param attachmentUri
|
||||
* @return resolved content URI
|
||||
*/
|
||||
private Uri resolveAttachmentIdToContentUri(long attachmentId) {
|
||||
Uri attachmentUri = AttachmentProvider.getAttachmentUri(mAccount, attachmentId);
|
||||
Cursor c = getContentResolver().query(attachmentUri,
|
||||
new String[] { AttachmentProvider.AttachmentProviderColumns.DATA },
|
||||
null, null, null);
|
||||
if (c != null) {
|
||||
try {
|
||||
if (c.moveToFirst()) {
|
||||
return Uri.parse(c.getString(0));
|
||||
}
|
||||
} finally {
|
||||
c.close();
|
||||
}
|
||||
}
|
||||
return attachmentUri;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve content-id reference in src attribute of img tag to AttachmentProvider's
|
||||
* content uri. This method calls itself recursively at most the number of
|
||||
* LocalAttachmentPart that mime type is image and has content id.
|
||||
* The attribute src="cid:content_id" is resolved as src="content://...".
|
||||
* This method is package scope for testing purpose.
|
||||
*
|
||||
* @param text html email text
|
||||
* @param part mime part which may contain inline image
|
||||
* @return html text in which src attribute of img tag may be replaced with content uri
|
||||
*/
|
||||
/* package */ String resolveInlineImage(String text, Part part, int depth)
|
||||
throws MessagingException {
|
||||
// avoid too deep recursive call or null text
|
||||
if (depth >= 10 || text == null) {
|
||||
return text;
|
||||
}
|
||||
String contentType = MimeUtility.unfoldAndDecode(part.getContentType());
|
||||
String contentId = part.getContentId();
|
||||
if (contentType.startsWith("image/") &&
|
||||
contentId != null &&
|
||||
part instanceof LocalAttachmentBodyPart) {
|
||||
LocalAttachmentBodyPart attachment = (LocalAttachmentBodyPart)part;
|
||||
Uri contentUri = resolveAttachmentIdToContentUri(attachment.getAttachmentId());
|
||||
// Regexp which matches ' src="cid:contentId"'.
|
||||
String contentIdRe = "\\s+(?i)src=\"cid(?-i):\\Q" + contentId + "\\E\"";
|
||||
// Replace all occurrences of src attribute with ' src="content://contentUri"'.
|
||||
text = text.replaceAll(contentIdRe, " src=\"" + contentUri + "\"");
|
||||
}
|
||||
|
||||
if (part.getBody() instanceof Multipart) {
|
||||
Multipart mp = (Multipart)part.getBody();
|
||||
for (int i = 0; i < mp.getCount(); i++) {
|
||||
text = resolveInlineImage(text, mp.getBodyPart(i), depth + 1);
|
||||
}
|
||||
}
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
private void renderAttachments(Part part, int depth) throws MessagingException {
|
||||
String contentType = MimeUtility.unfoldAndDecode(part.getContentType());
|
||||
String name = MimeUtility.getHeaderParameter(contentType, "name");
|
||||
|
@ -958,7 +896,8 @@ public class MessageView extends Activity
|
|||
if (part != null) {
|
||||
String text = MimeUtility.getTextFromPart(part);
|
||||
if (part.getMimeType().equalsIgnoreCase("text/html")) {
|
||||
text = resolveInlineImage(text, mMessage, 0);
|
||||
text = EmailHtmlUtil.resolveInlineImage(
|
||||
getContentResolver(), mAccount, text, mMessage, 0);
|
||||
} else {
|
||||
/*
|
||||
* Linkify the plain text and convert it to HTML by replacing
|
||||
|
@ -1066,7 +1005,9 @@ public class MessageView extends Activity
|
|||
try {
|
||||
File file = createUniqueFile(Environment.getExternalStorageDirectory(),
|
||||
attachment.name);
|
||||
Uri uri = resolveAttachmentIdToContentUri(attachment.part.getAttachmentId());
|
||||
Uri uri = AttachmentProvider.resolveAttachmentIdToContentUri(
|
||||
getContentResolver(), AttachmentProvider.getAttachmentUri(
|
||||
mAccount, attachment.part.getAttachmentId()));
|
||||
InputStream in = getContentResolver().openInputStream(uri);
|
||||
OutputStream out = new FileOutputStream(file);
|
||||
IOUtils.copy(in, out);
|
||||
|
@ -1082,7 +1023,9 @@ public class MessageView extends Activity
|
|||
}
|
||||
else {
|
||||
try {
|
||||
Uri uri = resolveAttachmentIdToContentUri(attachment.part.getAttachmentId());
|
||||
Uri uri = AttachmentProvider.resolveAttachmentIdToContentUri(
|
||||
getContentResolver(), AttachmentProvider.getAttachmentUri(
|
||||
mAccount, attachment.part.getAttachmentId()));
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW);
|
||||
intent.setData(uri);
|
||||
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||
|
@ -1173,3 +1116,4 @@ public class MessageView extends Activity
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* Copyright (C) 2008 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.internet;
|
||||
|
||||
import com.android.email.Account;
|
||||
import com.android.email.mail.MessagingException;
|
||||
import com.android.email.mail.Multipart;
|
||||
import com.android.email.mail.Part;
|
||||
import com.android.email.mail.store.LocalStore.LocalAttachmentBodyPart;
|
||||
import com.android.email.provider.AttachmentProvider;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.net.Uri;
|
||||
|
||||
public class EmailHtmlUtil {
|
||||
|
||||
/**
|
||||
* Resolve content-id reference in src attribute of img tag to AttachmentProvider's
|
||||
* content uri. This method calls itself recursively at most the number of
|
||||
* LocalAttachmentPart that mime type is image and has content id.
|
||||
* The attribute src="cid:content_id" is resolved as src="content://...".
|
||||
* This method is package scope for testing purpose.
|
||||
*
|
||||
* @param text html email text
|
||||
* @param part mime part which may contain inline image
|
||||
* @return html text in which src attribute of img tag may be replaced with content uri
|
||||
*/
|
||||
public static String resolveInlineImage(
|
||||
ContentResolver resolver, Account account, String text, Part part, int depth)
|
||||
throws MessagingException {
|
||||
// avoid too deep recursive call.
|
||||
if (depth >= 10 || text == null) {
|
||||
return text;
|
||||
}
|
||||
String contentType = MimeUtility.unfoldAndDecode(part.getContentType());
|
||||
String contentId = part.getContentId();
|
||||
if (contentType.startsWith("image/") &&
|
||||
contentId != null &&
|
||||
part instanceof LocalAttachmentBodyPart) {
|
||||
LocalAttachmentBodyPart attachment = (LocalAttachmentBodyPart)part;
|
||||
Uri contentUri = AttachmentProvider.resolveAttachmentIdToContentUri(
|
||||
resolver, AttachmentProvider.getAttachmentUri(account, attachment.getAttachmentId()));
|
||||
// Regexp which matches ' src="cid:contentId"'.
|
||||
String contentIdRe = "\\s+(?i)src=\"cid(?-i):\\Q" + contentId + "\\E\"";
|
||||
// Replace all occurrences of src attribute with ' src="content://contentUri"'.
|
||||
text = text.replaceAll(contentIdRe, " src=\"" + contentUri + "\"");
|
||||
}
|
||||
|
||||
if (part.getBody() instanceof Multipart) {
|
||||
Multipart mp = (Multipart)part.getBody();
|
||||
for (int i = 0; i < mp.getCount(); i++) {
|
||||
text = resolveInlineImage(resolver, account, text, mp.getBodyPart(i), depth + 1);
|
||||
}
|
||||
}
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
public static String escapeCharacterToDisplay(String text, boolean plainText) {
|
||||
// TODO: implement html escaping as in CL 145919, 148437 to fix bug 1785319
|
||||
|
||||
return text;
|
||||
}
|
||||
}
|
|
@ -25,6 +25,7 @@ import java.io.InputStream;
|
|||
import java.util.List;
|
||||
|
||||
import android.content.ContentProvider;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.ContentValues;
|
||||
import android.database.Cursor;
|
||||
import android.database.MatrixCursor;
|
||||
|
@ -298,4 +299,25 @@ public class AttachmentProvider extends ContentProvider {
|
|||
return null;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Resolve attachment id to content URI.
|
||||
*
|
||||
* @param attachmentUri
|
||||
* @return resolved content URI
|
||||
*/
|
||||
public static Uri resolveAttachmentIdToContentUri(ContentResolver resolver, Uri attachmentUri) {
|
||||
Cursor c = resolver.query(attachmentUri,
|
||||
new String[] { AttachmentProvider.AttachmentProviderColumns.DATA },
|
||||
null, null, null);
|
||||
if (c != null) {
|
||||
try {
|
||||
if (c.moveToFirst()) {
|
||||
return Uri.parse(c.getString(0));
|
||||
}
|
||||
} finally {
|
||||
c.close();
|
||||
}
|
||||
}
|
||||
return attachmentUri;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,8 +28,10 @@ import com.android.email.mail.MessageTestUtils.MessageBuilder;
|
|||
import com.android.email.mail.MessageTestUtils.MultipartBuilder;
|
||||
import com.android.email.mail.MessageTestUtils.TextBuilder;
|
||||
import com.android.email.mail.internet.BinaryTempFileBody;
|
||||
import com.android.email.mail.internet.EmailHtmlUtil;
|
||||
import com.android.email.mail.store.LocalStore;
|
||||
|
||||
import android.app.Application;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
@ -38,6 +40,7 @@ import android.net.Uri;
|
|||
import android.test.ActivityInstrumentationTestCase2;
|
||||
import android.test.suitebuilder.annotation.MediumTest;
|
||||
import android.test.suitebuilder.annotation.Suppress;
|
||||
import android.util.Log;
|
||||
import android.webkit.WebView;
|
||||
import android.widget.TextView;
|
||||
|
||||
|
@ -78,6 +81,7 @@ public class MessageViewTests
|
|||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
|
||||
mContext = getInstrumentation().getTargetContext();
|
||||
Account[] accounts = Preferences.getPreferences(mContext).getAccounts();
|
||||
if (accounts.length > 0)
|
||||
|
@ -86,14 +90,11 @@ public class MessageViewTests
|
|||
mAccount = Preferences.getPreferences(mContext).getDefaultAccount();
|
||||
Email.setServicesEnabled(mContext);
|
||||
}
|
||||
|
||||
// configure a mock controller
|
||||
MessagingController mockController = new MockMessagingController();
|
||||
MessagingController.injectMockController(mockController);
|
||||
|
||||
|
||||
// setup an intent to spin up this activity with something useful
|
||||
ArrayList<String> FOLDER_UIDS = new ArrayList<String>(
|
||||
Arrays.asList(new String[]{ "why", "is", "java", "so", "ugly?" }));
|
||||
// Log.d("MessageViewTest", "--- folder:" + FOLDER_UIDS);
|
||||
Intent i = new Intent()
|
||||
.putExtra(EXTRA_ACCOUNT, mAccount)
|
||||
.putExtra(EXTRA_FOLDER, FOLDER_NAME)
|
||||
|
@ -101,6 +102,11 @@ public class MessageViewTests
|
|||
.putStringArrayListExtra(EXTRA_FOLDER_UIDS, FOLDER_UIDS);
|
||||
this.setActivityIntent(i);
|
||||
|
||||
// configure a mock controller
|
||||
MessagingController mockController =
|
||||
new MockMessagingController(getActivity().getApplication());
|
||||
MessagingController.injectMockController(mockController);
|
||||
|
||||
final MessageView a = getActivity();
|
||||
mToView = (TextView) a.findViewById(R.id.to);
|
||||
mSubjectView = (TextView) a.findViewById(R.id.subject);
|
||||
|
@ -151,115 +157,14 @@ public class MessageViewTests
|
|||
a.handleMenuItem(R.id.mark_as_unread);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests for resolving inline image src cid: reference to content uri.
|
||||
*/
|
||||
|
||||
public void testResolveInlineImage() throws MessagingException, IOException {
|
||||
final MessageView a = getActivity();
|
||||
final LocalStore store = (LocalStore) LocalStore.newInstance(mAccount.getLocalStoreUri(),
|
||||
mContext, null);
|
||||
|
||||
// Single cid case.
|
||||
final String cid1 = "cid.1@android.com";
|
||||
final long aid1 = 10;
|
||||
final Uri uri1 = MessageTestUtils.contentUri(aid1, mAccount);
|
||||
final String text1 = new TextBuilder("text1 > ").addCidImg(cid1).build(" <.");
|
||||
final String expected1 = new TextBuilder("text1 > ").addUidImg(uri1).build(" <.");
|
||||
|
||||
// message with cid1
|
||||
final Message msg1 = new MessageBuilder()
|
||||
.setBody(new MultipartBuilder("multipart/related")
|
||||
.addBodyPart(MessageTestUtils.textPart("text/html", text1))
|
||||
.addBodyPart(MessageTestUtils.imagePart("image/jpeg", "<"+cid1+">", aid1, store))
|
||||
.build())
|
||||
.build();
|
||||
// Simple case.
|
||||
final String actual1 = a.resolveInlineImage(text1, msg1, 0);
|
||||
assertEquals("one content id reference is not resolved",
|
||||
expected1, actual1);
|
||||
|
||||
// Exceed recursive limit.
|
||||
final String actual0 = a.resolveInlineImage(text1, msg1, 10);
|
||||
assertEquals("recursive call limit may exceeded",
|
||||
text1, actual0);
|
||||
|
||||
// Multiple cids case.
|
||||
final String cid2 = "cid.2@android.com";
|
||||
final long aid2 = 20;
|
||||
final Uri uri2 = MessageTestUtils.contentUri(aid2, mAccount);
|
||||
final String text2 = new TextBuilder("text2 ").addCidImg(cid2).build(".");
|
||||
final String expected2 = new TextBuilder("text2 ").addUidImg(uri2).build(".");
|
||||
|
||||
// message with only cid2
|
||||
final Message msg2 = new MessageBuilder()
|
||||
.setBody(new MultipartBuilder("multipart/related")
|
||||
.addBodyPart(MessageTestUtils.textPart("text/html", text1 + text2))
|
||||
.addBodyPart(MessageTestUtils.imagePart("image/gif", cid2, aid2, store))
|
||||
.build())
|
||||
.build();
|
||||
// cid1 is not replaced
|
||||
final String actual2 = a.resolveInlineImage(text1 + text2, msg2, 0);
|
||||
assertEquals("only one of two content id is resolved",
|
||||
text1 + expected2, actual2);
|
||||
|
||||
// message with cid1 and cid2
|
||||
final Message msg3 = new MessageBuilder()
|
||||
.setBody(new MultipartBuilder("multipart/related")
|
||||
.addBodyPart(MessageTestUtils.textPart("text/html", text2 + text1))
|
||||
.addBodyPart(MessageTestUtils.imagePart("image/jpeg", cid1, aid1, store))
|
||||
.addBodyPart(MessageTestUtils.imagePart("image/gif", cid2, aid2, store))
|
||||
.build())
|
||||
.build();
|
||||
// cid1 and cid2 are replaced
|
||||
final String actual3 = a.resolveInlineImage(text2 + text1, msg3, 0);
|
||||
assertEquals("two content ids are resolved correctly",
|
||||
expected2 + expected1, actual3);
|
||||
|
||||
// message with many cids and normal attachments
|
||||
final Message msg4 = new MessageBuilder()
|
||||
.setBody(new MultipartBuilder("multipart/mixed")
|
||||
.addBodyPart(MessageTestUtils.imagePart("image/jpeg", null, 30, store))
|
||||
.addBodyPart(MessageTestUtils.imagePart("application/pdf", cid1, aid1, store))
|
||||
.addBodyPart(new MultipartBuilder("multipart/related")
|
||||
.addBodyPart(MessageTestUtils.textPart("text/html", text2 + text1))
|
||||
.addBodyPart(MessageTestUtils.imagePart("image/jpg", cid1, aid1, store))
|
||||
.addBodyPart(MessageTestUtils.imagePart("image/gif", cid2, aid2, store))
|
||||
.buildBodyPart())
|
||||
.addBodyPart(MessageTestUtils.imagePart("application/pdf", cid2, aid2, store))
|
||||
.build())
|
||||
.build();
|
||||
// cid1 and cid2 are replaced
|
||||
final String actual4 = a.resolveInlineImage(text2 + text1, msg4, 0);
|
||||
assertEquals("two content ids in deep multipart level are resolved",
|
||||
expected2 + expected1, actual4);
|
||||
|
||||
// No crash on null text
|
||||
final String actual5 = a.resolveInlineImage(null, msg4, 0);
|
||||
assertNull(actual5);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for resolveAttachmentIdToContentUri.
|
||||
*/
|
||||
public void testResolveAttachmentIdToContentUri() throws MessagingException, IOException {
|
||||
final ContentResolver contentResolver = mContext.getContentResolver();
|
||||
final MessageView a = getActivity();
|
||||
// create attachments tables.
|
||||
LocalStore.newInstance(mAccount.getLocalStoreUri(), mContext, null);
|
||||
final String dbPath = mContext.getDatabasePath(mAccount.getUuid() + ".db").toString();
|
||||
final SQLiteDatabase db = SQLiteDatabase.openDatabase(dbPath, null, 0);
|
||||
// TODO write unit test
|
||||
}
|
||||
|
||||
/**
|
||||
* Mock Messaging controller, so we can drive its callbacks. This probably should be
|
||||
* generalized since we're likely to use for other tests eventually.
|
||||
*/
|
||||
private static class MockMessagingController extends MessagingController {
|
||||
|
||||
private MockMessagingController() {
|
||||
super(null);
|
||||
private MockMessagingController(Application application) {
|
||||
super(application);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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.internet;
|
||||
|
||||
import com.android.email.Account;
|
||||
import com.android.email.Preferences;
|
||||
import com.android.email.mail.Message;
|
||||
import com.android.email.mail.MessageTestUtils;
|
||||
import com.android.email.mail.MessagingException;
|
||||
import com.android.email.mail.MessageTestUtils.MessageBuilder;
|
||||
import com.android.email.mail.MessageTestUtils.MultipartBuilder;
|
||||
import com.android.email.mail.MessageTestUtils.TextBuilder;
|
||||
import com.android.email.mail.store.LocalStore;
|
||||
|
||||
import android.net.Uri;
|
||||
import android.test.AndroidTestCase;
|
||||
import android.test.suitebuilder.annotation.MediumTest;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@MediumTest
|
||||
public class EmailHtmlUtilTest extends AndroidTestCase {
|
||||
private Account mAccount;
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
Account[] accounts = Preferences.getPreferences(mContext).getAccounts();
|
||||
if (accounts.length > 0)
|
||||
{
|
||||
// This depends on getDefaultAccount() to auto-assign the default account, if necessary
|
||||
mAccount = Preferences.getPreferences(mContext).getAccounts()[0];
|
||||
}
|
||||
|
||||
// This is needed for mime image bodypart.
|
||||
BinaryTempFileBody.setTempDirectory(getContext().getCacheDir());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests for resolving inline image src cid: reference to content uri.
|
||||
*/
|
||||
|
||||
public void testResolveInlineImage() throws MessagingException, IOException {
|
||||
final LocalStore store = (LocalStore) LocalStore.newInstance(mAccount.getLocalStoreUri(),
|
||||
mContext, null);
|
||||
// Single cid case.
|
||||
final String cid1 = "cid.1@android.com";
|
||||
final long aid1 = 10;
|
||||
final Uri uri1 = MessageTestUtils.contentUri(aid1, mAccount);
|
||||
final String text1 = new TextBuilder("text1 > ").addCidImg(cid1).build(" <.");
|
||||
final String expected1 = new TextBuilder("text1 > ").addUidImg(uri1).build(" <.");
|
||||
|
||||
// message with cid1
|
||||
final Message msg1 = new MessageBuilder()
|
||||
.setBody(new MultipartBuilder("multipart/related")
|
||||
.addBodyPart(MessageTestUtils.textPart("text/html", text1))
|
||||
.addBodyPart(MessageTestUtils.imagePart("image/jpeg", "<"+cid1+">", aid1, store))
|
||||
.build())
|
||||
.build();
|
||||
// Simple case.
|
||||
final String actual1 = EmailHtmlUtil.resolveInlineImage(
|
||||
getContext().getContentResolver(), mAccount, text1, msg1, 0);
|
||||
assertEquals("one content id reference is not resolved",
|
||||
expected1, actual1);
|
||||
|
||||
// Exceed recursive limit.
|
||||
final String actual0 = EmailHtmlUtil.resolveInlineImage(
|
||||
getContext().getContentResolver(), mAccount, text1, msg1, 10);
|
||||
assertEquals("recursive call limit may exceeded",
|
||||
text1, actual0);
|
||||
|
||||
// Multiple cids case.
|
||||
final String cid2 = "cid.2@android.com";
|
||||
final long aid2 = 20;
|
||||
final Uri uri2 = MessageTestUtils.contentUri(aid2, mAccount);
|
||||
final String text2 = new TextBuilder("text2 ").addCidImg(cid2).build(".");
|
||||
final String expected2 = new TextBuilder("text2 ").addUidImg(uri2).build(".");
|
||||
|
||||
// message with only cid2
|
||||
final Message msg2 = new MessageBuilder()
|
||||
.setBody(new MultipartBuilder("multipart/related")
|
||||
.addBodyPart(MessageTestUtils.textPart("text/html", text1 + text2))
|
||||
.addBodyPart(MessageTestUtils.imagePart("image/gif", cid2, aid2, store))
|
||||
.build())
|
||||
.build();
|
||||
// cid1 is not replaced
|
||||
final String actual2 = EmailHtmlUtil.resolveInlineImage(
|
||||
getContext().getContentResolver(), mAccount, text1 + text2, msg2, 0);
|
||||
assertEquals("only one of two content id is resolved",
|
||||
text1 + expected2, actual2);
|
||||
|
||||
// message with cid1 and cid2
|
||||
final Message msg3 = new MessageBuilder()
|
||||
.setBody(new MultipartBuilder("multipart/related")
|
||||
.addBodyPart(MessageTestUtils.textPart("text/html", text2 + text1))
|
||||
.addBodyPart(MessageTestUtils.imagePart("image/jpeg", cid1, aid1, store))
|
||||
.addBodyPart(MessageTestUtils.imagePart("image/gif", cid2, aid2, store))
|
||||
.build())
|
||||
.build();
|
||||
// cid1 and cid2 are replaced
|
||||
final String actual3 = EmailHtmlUtil.resolveInlineImage(
|
||||
getContext().getContentResolver(), mAccount, text2 + text1, msg3, 0);
|
||||
assertEquals("two content ids are resolved correctly",
|
||||
expected2 + expected1, actual3);
|
||||
|
||||
// message with many cids and normal attachments
|
||||
final Message msg4 = new MessageBuilder()
|
||||
.setBody(new MultipartBuilder("multipart/mixed")
|
||||
.addBodyPart(MessageTestUtils.imagePart("image/jpeg", null, 30, store))
|
||||
.addBodyPart(MessageTestUtils.imagePart("application/pdf", cid1, aid1, store))
|
||||
.addBodyPart(new MultipartBuilder("multipart/related")
|
||||
.addBodyPart(MessageTestUtils.textPart("text/html", text2 + text1))
|
||||
.addBodyPart(MessageTestUtils.imagePart("image/jpg", cid1, aid1, store))
|
||||
.addBodyPart(MessageTestUtils.imagePart("image/gif", cid2, aid2, store))
|
||||
.buildBodyPart())
|
||||
.addBodyPart(MessageTestUtils.imagePart("application/pdf", cid2, aid2, store))
|
||||
.build())
|
||||
.build();
|
||||
// cid1 and cid2 are replaced
|
||||
final String actual4 = EmailHtmlUtil.resolveInlineImage(
|
||||
getContext().getContentResolver(), mAccount, text2 + text1, msg4, 0);
|
||||
assertEquals("two content ids in deep multipart level are resolved",
|
||||
expected2 + expected1, actual4);
|
||||
|
||||
// No crash on null text
|
||||
final String actual5 = EmailHtmlUtil.resolveInlineImage(getContext().getContentResolver(),
|
||||
mAccount, null, msg4, 0);
|
||||
assertNull(actual5);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue