From 7a159387636507de95b9b0c052ab593d0e91c433 Mon Sep 17 00:00:00 2001 From: Makoto Onuki Date: Mon, 7 Mar 2011 10:46:09 -0800 Subject: [PATCH] DO NOT MERGE: Make ACTION_SEND_MULTIPLE work with file: URI To determine mime-types of attachments from the ACTION_SEND and _MULTIPLE intents, - Use ContentResolver.getType() for content: URIs - Use inferMimeType() for file: URIs Tested with Gallary and Downloads. Bug 3510624 Backport of Ibfa4b383463f157e18fd634e55f5be4b9adf6aa5 Change-Id: Id2815738673f3822a97e92414b84f6a5d46eb96f --- .../utility/AttachmentUtilities.java | 17 +++ .../email/activity/MessageCompose.java | 40 ++--- .../provider/AttachmentProviderTests.java | 98 ------------ .../utility/AttachmentUtilitiesTests.java | 140 ++++++++++++++++++ 4 files changed, 177 insertions(+), 118 deletions(-) create mode 100644 tests/src/com/android/emailcommon/utility/AttachmentUtilitiesTests.java diff --git a/emailcommon/src/com/android/emailcommon/utility/AttachmentUtilities.java b/emailcommon/src/com/android/emailcommon/utility/AttachmentUtilities.java index 12954c667..e4d119b7a 100644 --- a/emailcommon/src/com/android/emailcommon/utility/AttachmentUtilities.java +++ b/emailcommon/src/com/android/emailcommon/utility/AttachmentUtilities.java @@ -224,6 +224,23 @@ public class AttachmentUtilities { return resultType.toLowerCase(); } + /** + * @return mime-type for a {@link Uri}. + * - Use {@link ContentResolver#getType} for a content: URI. + * - Use {@link #inferMimeType} for a file: URI. + * - Otherwise throw {@link IllegalArgumentException}. + */ + public static String inferMimeTypeForUri(Context context, Uri uri) { + final String scheme = uri.getScheme(); + if ("content".equals(scheme)) { + return context.getContentResolver().getType(uri); + } else if ("file".equals(scheme)) { + return inferMimeType(uri.getLastPathSegment(), ""); + } else { + throw new IllegalArgumentException(); + } + } + /** * Extract and return filename's extension, converted to lower case, and not including the "." * diff --git a/src/com/android/email/activity/MessageCompose.java b/src/com/android/email/activity/MessageCompose.java index 4b279a182..e6ca3a13e 100644 --- a/src/com/android/email/activity/MessageCompose.java +++ b/src/com/android/email/activity/MessageCompose.java @@ -1151,16 +1151,11 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus } } - String contentType = contentResolver.getType(uri); - if (contentType == null) { - contentType = ""; - } - Attachment attachment = new Attachment(); attachment.mFileName = name; attachment.mContentUri = uri.toString(); attachment.mSize = size; - attachment.mMimeType = contentType; + attachment.mMimeType = AttachmentUtilities.inferMimeTypeForUri(this, uri); return attachment; } @@ -1196,16 +1191,29 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus ? View.GONE : View.VISIBLE); } - private void addAttachment(Uri uri) { + private void addAttachmentFromUri(Uri uri) { addAttachment(loadAttachmentInfo(uri), true); } + /** + * Same as {@link #addAttachmentFromUri}, but does the mime-type check against + * {@link AttachmentUtilities#ACCEPTABLE_ATTACHMENT_SEND_INTENT_TYPES}. + */ + private void addAttachmentFromSendIntent(Uri uri) { + final Attachment attachment = loadAttachmentInfo(uri); + final String mimeType = attachment.mMimeType; + if (!TextUtils.isEmpty(mimeType) && MimeUtility.mimeTypeMatches(mimeType, + AttachmentUtilities.ACCEPTABLE_ATTACHMENT_SEND_INTENT_TYPES)) { + addAttachment(attachment, true); + } + } + @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (data == null) { return; } - addAttachment(data.getData()); + addAttachmentFromUri(data.getData()); setDraftNeedsSaving(true); } @@ -1391,13 +1399,9 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus // Next, convert EXTRA_STREAM into an attachment if (Intent.ACTION_SEND.equals(mAction) && intent.hasExtra(Intent.EXTRA_STREAM)) { - String type = intent.getType(); - Uri stream = (Uri) intent.getParcelableExtra(Intent.EXTRA_STREAM); - if (stream != null && type != null) { - if (MimeUtility.mimeTypeMatches(type, - AttachmentUtilities.ACCEPTABLE_ATTACHMENT_SEND_INTENT_TYPES)) { - addAttachment(stream); - } + Uri uri = (Uri) intent.getParcelableExtra(Intent.EXTRA_STREAM); + if (uri != null) { + addAttachmentFromSendIntent(uri); } } @@ -1408,11 +1412,7 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus for (Parcelable parcelable : list) { Uri uri = (Uri) parcelable; if (uri != null) { - Attachment attachment = loadAttachmentInfo(uri); - if (MimeUtility.mimeTypeMatches(attachment.mMimeType, - AttachmentUtilities.ACCEPTABLE_ATTACHMENT_SEND_INTENT_TYPES)) { - addAttachment(attachment, true); - } + addAttachmentFromSendIntent(uri); } } } diff --git a/tests/src/com/android/email/provider/AttachmentProviderTests.java b/tests/src/com/android/email/provider/AttachmentProviderTests.java index 40f031d5e..d68a5225a 100644 --- a/tests/src/com/android/email/provider/AttachmentProviderTests.java +++ b/tests/src/com/android/email/provider/AttachmentProviderTests.java @@ -333,104 +333,6 @@ public class AttachmentProviderTests extends ProviderTestCase2 - * |---------------------------------------------------------| - * | E X T E N S I O N | - * |---------------------------------------------------------| - * | .eml | known(.png) | unknown(.abc) | none | - * | M |-----------------------------------------------------------------------| - * | I | none | msg/rfc822 | image/png | app/abc | app/oct-str | - * | M |-------------| (always | | | | - * | E | app/oct-str | overrides | | | | - * | T |-------------| | |-----------------------------| - * | Y | text/plain | | | text/plain | - * | P |-------------| |-------------------------------------------| - * | E | any/type | | any/type | - * |---|-----------------------------------------------------------------------| - * - * - * Also, all results should be in lowercase. - */ - public void testInferMimeType() { - final String DEFAULT_MIX = "Application/Octet-stream"; - final String DEFAULT_LOWER = DEFAULT_MIX.toLowerCase(); - final String TEXT_PLAIN = "text/plain"; - final String TYPE_IMG_PNG = "image/png"; - final String FILE_PNG = "myfile.false.pNg"; - final String FILE_ABC = "myfile.false.aBc"; - final String FILE_NO_EXT = "myfile"; - - // .eml files always override mime type - assertEquals("message/rfc822", AttachmentUtilities.inferMimeType("a.eml", null)); - assertEquals("message/rfc822", AttachmentUtilities.inferMimeType("a.eml", "")); - assertEquals("message/rfc822", - AttachmentUtilities.inferMimeType("a.eml", DEFAULT_LOWER)); - assertEquals("message/rfc822", - AttachmentUtilities.inferMimeType("a.eMl", TEXT_PLAIN)); - assertEquals("message/rfc822", - AttachmentUtilities.inferMimeType("a.eml", TYPE_IMG_PNG)); - - // Non-generic, non-empty mime type; return it - assertEquals("mime/type", AttachmentUtilities.inferMimeType(FILE_PNG, "Mime/TyPe")); - assertEquals("mime/type", AttachmentUtilities.inferMimeType(FILE_ABC, "Mime/TyPe")); - assertEquals("mime/type", - AttachmentUtilities.inferMimeType(FILE_NO_EXT, "Mime/TyPe")); - assertEquals("mime/type", AttachmentUtilities.inferMimeType(null, "Mime/TyPe")); - assertEquals("mime/type", AttachmentUtilities.inferMimeType("", "Mime/TyPe")); - - // Recognizable file extension; return known type - assertEquals("image/png", AttachmentUtilities.inferMimeType(FILE_PNG, null)); - assertEquals("image/png", AttachmentUtilities.inferMimeType(FILE_PNG, "")); - assertEquals("image/png", AttachmentUtilities.inferMimeType(FILE_PNG, DEFAULT_MIX)); - assertEquals("image/png", AttachmentUtilities.inferMimeType(FILE_PNG, TEXT_PLAIN)); - - // Unrecognized and non-empty file extension, non-"text/plain" type; generate mime type - assertEquals("application/abc", AttachmentUtilities.inferMimeType(FILE_ABC, null)); - assertEquals("application/abc", AttachmentUtilities.inferMimeType(FILE_ABC, "")); - assertEquals("application/abc", - AttachmentUtilities.inferMimeType(FILE_ABC, DEFAULT_MIX)); - - // Unrecognized and empty file extension, non-"text/plain" type; return "app/octet-stream" - assertEquals(DEFAULT_LOWER, AttachmentUtilities.inferMimeType(FILE_NO_EXT, null)); - assertEquals(DEFAULT_LOWER, AttachmentUtilities.inferMimeType(FILE_NO_EXT, "")); - assertEquals(DEFAULT_LOWER, - AttachmentUtilities.inferMimeType(FILE_NO_EXT, DEFAULT_MIX)); - assertEquals(DEFAULT_LOWER, AttachmentUtilities.inferMimeType(null, null)); - assertEquals(DEFAULT_LOWER, AttachmentUtilities.inferMimeType("", "")); - - // Unrecognized or empty file extension, "text/plain" type; return "text/plain" - assertEquals(TEXT_PLAIN, AttachmentUtilities.inferMimeType(FILE_ABC, TEXT_PLAIN)); - assertEquals(TEXT_PLAIN, - AttachmentUtilities.inferMimeType(FILE_NO_EXT, TEXT_PLAIN)); - assertEquals(TEXT_PLAIN, AttachmentUtilities.inferMimeType(null, TEXT_PLAIN)); - assertEquals(TEXT_PLAIN, AttachmentUtilities.inferMimeType("", TEXT_PLAIN)); - } - - /** - * Text extension extractor - */ - public void testGetFilenameExtension() { - final String FILE_NO_EXTENSION = "myfile"; - final String FILE_EXTENSION = "myfile.pDf"; - final String FILE_TWO_EXTENSIONS = "myfile.false.AbC"; - - assertNull(AttachmentUtilities.getFilenameExtension(null)); - assertNull(AttachmentUtilities.getFilenameExtension("")); - assertNull(AttachmentUtilities.getFilenameExtension(FILE_NO_EXTENSION)); - - assertEquals("pdf", AttachmentUtilities.getFilenameExtension(FILE_EXTENSION)); - assertEquals("abc", AttachmentUtilities.getFilenameExtension(FILE_TWO_EXTENSIONS)); - - // The API makes no claim as to how these are handled (it probably should), - // but make sure that they don't crash. - AttachmentUtilities.getFilenameExtension("filename."); - AttachmentUtilities.getFilenameExtension(".extension"); - } - /** * test openFile() * - regular file diff --git a/tests/src/com/android/emailcommon/utility/AttachmentUtilitiesTests.java b/tests/src/com/android/emailcommon/utility/AttachmentUtilitiesTests.java new file mode 100644 index 000000000..851570ab3 --- /dev/null +++ b/tests/src/com/android/emailcommon/utility/AttachmentUtilitiesTests.java @@ -0,0 +1,140 @@ +/* + * Copyright (C) 2011 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.emailcommon.utility; + +import com.android.emailcommon.provider.EmailContent; + +import android.net.Uri; +import android.test.AndroidTestCase; + +import java.io.File; + +public class AttachmentUtilitiesTests extends AndroidTestCase { + /** + * Test static inferMimeType() + * From the method doc: + * + *
+     *                   |---------------------------------------------------------|
+     *                   |                  E X T E N S I O N                      |
+     *                   |---------------------------------------------------------|
+     *                   | .eml        | known(.png) | unknown(.abc) | none        |
+     * | M |-----------------------------------------------------------------------|
+     * | I | none        | msg/rfc822  | image/png   | app/abc       | app/oct-str |
+     * | M |-------------| (always     |             |               |             |
+     * | E | app/oct-str |  overrides  |             |               |             |
+     * | T |-------------|             |             |-----------------------------|
+     * | Y | text/plain  |             |             | text/plain                  |
+     * | P |-------------|             |-------------------------------------------|
+     * | E | any/type    |             | any/type                                  |
+     * |---|-----------------------------------------------------------------------|
+     * 
+ * + * Also, all results should be in lowercase. + */ + public void testInferMimeType() { + final String DEFAULT_MIX = "Application/Octet-stream"; + final String DEFAULT_LOWER = DEFAULT_MIX.toLowerCase(); + final String TEXT_PLAIN = "text/plain"; + final String TYPE_IMG_PNG = "image/png"; + final String FILE_PNG = "myfile.false.pNg"; + final String FILE_ABC = "myfile.false.aBc"; + final String FILE_NO_EXT = "myfile"; + + // .eml files always override mime type + assertEquals("message/rfc822", AttachmentUtilities.inferMimeType("a.eml", null)); + assertEquals("message/rfc822", AttachmentUtilities.inferMimeType("a.eml", "")); + assertEquals("message/rfc822", + AttachmentUtilities.inferMimeType("a.eml", DEFAULT_LOWER)); + assertEquals("message/rfc822", + AttachmentUtilities.inferMimeType("a.eMl", TEXT_PLAIN)); + assertEquals("message/rfc822", + AttachmentUtilities.inferMimeType("a.eml", TYPE_IMG_PNG)); + + // Non-generic, non-empty mime type; return it + assertEquals("mime/type", AttachmentUtilities.inferMimeType(FILE_PNG, "Mime/TyPe")); + assertEquals("mime/type", AttachmentUtilities.inferMimeType(FILE_ABC, "Mime/TyPe")); + assertEquals("mime/type", + AttachmentUtilities.inferMimeType(FILE_NO_EXT, "Mime/TyPe")); + assertEquals("mime/type", AttachmentUtilities.inferMimeType(null, "Mime/TyPe")); + assertEquals("mime/type", AttachmentUtilities.inferMimeType("", "Mime/TyPe")); + + // Recognizable file extension; return known type + assertEquals("image/png", AttachmentUtilities.inferMimeType(FILE_PNG, null)); + assertEquals("image/png", AttachmentUtilities.inferMimeType(FILE_PNG, "")); + assertEquals("image/png", AttachmentUtilities.inferMimeType(FILE_PNG, DEFAULT_MIX)); + assertEquals("image/png", AttachmentUtilities.inferMimeType(FILE_PNG, TEXT_PLAIN)); + + // Unrecognized and non-empty file extension, non-"text/plain" type; generate mime type + assertEquals("application/abc", AttachmentUtilities.inferMimeType(FILE_ABC, null)); + assertEquals("application/abc", AttachmentUtilities.inferMimeType(FILE_ABC, "")); + assertEquals("application/abc", + AttachmentUtilities.inferMimeType(FILE_ABC, DEFAULT_MIX)); + + // Unrecognized and empty file extension, non-"text/plain" type; return "app/octet-stream" + assertEquals(DEFAULT_LOWER, AttachmentUtilities.inferMimeType(FILE_NO_EXT, null)); + assertEquals(DEFAULT_LOWER, AttachmentUtilities.inferMimeType(FILE_NO_EXT, "")); + assertEquals(DEFAULT_LOWER, + AttachmentUtilities.inferMimeType(FILE_NO_EXT, DEFAULT_MIX)); + assertEquals(DEFAULT_LOWER, AttachmentUtilities.inferMimeType(null, null)); + assertEquals(DEFAULT_LOWER, AttachmentUtilities.inferMimeType("", "")); + + // Unrecognized or empty file extension, "text/plain" type; return "text/plain" + assertEquals(TEXT_PLAIN, AttachmentUtilities.inferMimeType(FILE_ABC, TEXT_PLAIN)); + assertEquals(TEXT_PLAIN, + AttachmentUtilities.inferMimeType(FILE_NO_EXT, TEXT_PLAIN)); + assertEquals(TEXT_PLAIN, AttachmentUtilities.inferMimeType(null, TEXT_PLAIN)); + assertEquals(TEXT_PLAIN, AttachmentUtilities.inferMimeType("", TEXT_PLAIN)); + } + + public void testInferMimeTypeForUri() { + String type; + // Test for content URI + type = AttachmentUtilities.inferMimeTypeForUri(getContext(), EmailContent.Body.CONTENT_URI); + assertEquals("vnd.android.cursor.dir/email-body", type); + + // Test for file URI + type = AttachmentUtilities.inferMimeTypeForUri(getContext(), + Uri.fromFile(new File("a.png"))); + assertEquals("image/png", type); + + type = AttachmentUtilities.inferMimeTypeForUri(getContext(), + Uri.fromFile(new File("/a/b/c/d.png"))); + assertEquals("image/png", type); + } + + /** + * Text extension extractor + */ + public void testGetFilenameExtension() { + final String FILE_NO_EXTENSION = "myfile"; + final String FILE_EXTENSION = "myfile.pDf"; + final String FILE_TWO_EXTENSIONS = "myfile.false.AbC"; + + assertNull(AttachmentUtilities.getFilenameExtension(null)); + assertNull(AttachmentUtilities.getFilenameExtension("")); + assertNull(AttachmentUtilities.getFilenameExtension(FILE_NO_EXTENSION)); + + assertEquals("pdf", AttachmentUtilities.getFilenameExtension(FILE_EXTENSION)); + assertEquals("abc", AttachmentUtilities.getFilenameExtension(FILE_TWO_EXTENSIONS)); + + // The API makes no claim as to how these are handled (it probably should), + // but make sure that they don't crash. + AttachmentUtilities.getFilenameExtension("filename."); + AttachmentUtilities.getFilenameExtension(".extension"); + } +}