From ea0fea2558f78ba54d9a8fbca6af466d9542d038 Mon Sep 17 00:00:00 2001 From: Mihai Preda Date: Wed, 26 Aug 2009 21:49:31 +0200 Subject: [PATCH] MessageCompose: bug 2080075 & 2077496. - fix bug 2080075, reply to message without text body. - workaround bug 2077496 by temporarilly disabling the address adapter. - unit test for MessageCompose.buildBodyText() - use precompiled regex --- .../android/email/EmailAddressAdapter.java | 6 ++-- .../email/activity/MessageCompose.java | 24 +++++++++---- .../MessageComposeInstrumentationTests.java | 34 ++++++++++++++++++- 3 files changed, 54 insertions(+), 10 deletions(-) diff --git a/src/com/android/email/EmailAddressAdapter.java b/src/com/android/email/EmailAddressAdapter.java index 45636c0b9..2517c28e4 100644 --- a/src/com/android/email/EmailAddressAdapter.java +++ b/src/com/android/email/EmailAddressAdapter.java @@ -16,7 +16,7 @@ package com.android.email; -import static android.provider.Contacts.ContactMethods.CONTENT_EMAIL_URI; +import android.provider.ContactsContract; import android.content.ContentResolver; import android.content.Context; import android.database.Cursor; @@ -83,6 +83,8 @@ public class EmailAddressAdapter extends ResourceCursorAdapter { where = s.toString(); } - return mContentResolver.query(CONTENT_EMAIL_URI, PROJECTION, where, null, SORT_ORDER); + return mContentResolver.query( + ContactsContract.CommonDataKinds.Email.CONTENT_FILTER_EMAIL_URI, + PROJECTION, where, null, SORT_ORDER); } } diff --git a/src/com/android/email/activity/MessageCompose.java b/src/com/android/email/activity/MessageCompose.java index 2b0164f1f..82ac76d04 100644 --- a/src/com/android/email/activity/MessageCompose.java +++ b/src/com/android/email/activity/MessageCompose.java @@ -73,6 +73,8 @@ import java.io.Serializable; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; public class MessageCompose extends Activity implements OnClickListener, OnFocusChangeListener { @@ -100,6 +102,9 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus private static final int ACTIVITY_REQUEST_PICK_ATTACHMENT = 1; + private static final Pattern PATTERN_START_OF_LINE = Pattern.compile("(?m)^"); + private static final Pattern PATTERN_ENDLINE_CRLF = Pattern.compile("\r\n"); + private Account mAccount; // mDraft is null until the first save, afterwards it contains the last saved version. @@ -453,15 +458,16 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus EmailAddressAdapter addressAdapter = new EmailAddressAdapter(this); EmailAddressValidator addressValidator = new EmailAddressValidator(); - mToView.setAdapter(addressAdapter); + // temporarilly disable setAdapter, see BUG 2077496 + // mToView.setAdapter(addressAdapter); mToView.setTokenizer(new Rfc822Tokenizer()); mToView.setValidator(addressValidator); - mCcView.setAdapter(addressAdapter); + // mCcView.setAdapter(addressAdapter); mCcView.setTokenizer(new Rfc822Tokenizer()); mCcView.setValidator(addressValidator); - mBccView.setAdapter(addressAdapter); + // mBccView.setAdapter(addressAdapter); mBccView.setTokenizer(new Rfc822Tokenizer()); mBccView.setValidator(addressValidator); @@ -554,7 +560,7 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus /* * Takes care to append source info and text in a REPLY or FORWARD situation. */ - private String buildBodyText(Message sourceMessage) { + /* package */ String buildBodyText(Message sourceMessage) { /* * Build the Body that will contain the text of the message. We'll decide where to * include it later. @@ -564,13 +570,17 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus if (mQuotedTextBar.getVisibility() == View.VISIBLE && sourceMessage != null) { String quotedText = sourceMessage.mText; - // fix CR-LF line endings to LF-only needed by EditText. - quotedText = quotedText.replaceAll("\r\n", "\n"); + if (quotedText != null) { + // fix CR-LF line endings to LF-only needed by EditText. + Matcher matcher = PATTERN_ENDLINE_CRLF.matcher(quotedText); + quotedText = matcher.replaceAll("\n"); + } String fromAsString = Address.unpackToString(sourceMessage.mFrom); if (ACTION_REPLY.equals(action) || ACTION_REPLY_ALL.equals(action)) { text += getString(R.string.message_compose_reply_header_fmt, fromAsString); if (quotedText != null) { - text += quotedText.replaceAll("(?m)^", ">"); + Matcher matcher = PATTERN_START_OF_LINE.matcher(quotedText); + text += matcher.replaceAll(">"); } } else if (ACTION_FORWARD.equals(action)) { String subject = sourceMessage.mSubject; diff --git a/tests/src/com/android/email/activity/MessageComposeInstrumentationTests.java b/tests/src/com/android/email/activity/MessageComposeInstrumentationTests.java index 4ea8e16dd..0ed40ed8c 100644 --- a/tests/src/com/android/email/activity/MessageComposeInstrumentationTests.java +++ b/tests/src/com/android/email/activity/MessageComposeInstrumentationTests.java @@ -38,6 +38,7 @@ import android.view.View; import android.widget.EditText; import android.widget.AutoCompleteTextView; + /** * Various instrumentation tests for MessageCompose. * @@ -58,7 +59,9 @@ public class MessageComposeInstrumentationTests private static final String RECIPIENT_BCC = "recipient-bcc@android.com"; private static final String SUBJECT = "This is the subject"; private static final String BODY = "This is the body. This is also the body."; - + private static final String REPLY_BODY_SHORT = "\n\n" + SENDER + " wrote:\n\n"; + private static final String REPLY_BODY = REPLY_BODY_SHORT + ">" + BODY; + private static final String UTF16_SENDER = "\u3042\u3044\u3046 \u3048\u304A "; private static final String UTF16_REPLYTO = @@ -133,6 +136,35 @@ public class MessageComposeInstrumentationTests assertEquals(0, mMessageView.length()); } + /** + * Test for buildBodyText(). + * Compare with expected values. + * Also test the situation where the message has no body. + */ + public void testBuildBodyText() throws MessagingException, Throwable { + final Message message = buildTestMessage(RECIPIENT_TO, SENDER, SUBJECT, BODY); + Intent intent = new Intent(ACTION_REPLY); + final MessageCompose a = getActivity(); + a.setIntent(intent); + + runTestOnUiThread(new Runnable() { + public void run() { + a.processSourceMessage(message, null); + String body = a.buildBodyText(message); + assertEquals(REPLY_BODY, body); + } + }); + + message.mText = null; + runTestOnUiThread(new Runnable() { + public void run() { + a.processSourceMessage(message, null); + String body = a.buildBodyText(message); + assertEquals(REPLY_BODY_SHORT, body); + } + }); + } + /** * Test a couple of variations of processSourceMessage() for REPLY * To = Reply-To or From: (if REPLY)