Allow to paste text or html into a chip

Allows to paste into a chip HTML mime content, as long as
it can be represented by text.

This resolves the inability to paste email addresses copied from
a web page, with content text/html.

Also, fix an IndexOutfOfBounds bug when there is no selection.

Bug: 13361722 users cannot paste html content in chip
Change-Id: I31434105e4326d78e99df338f81d9e56fc5b83c5

Conflicts:
	src/com/android/ex/chips/RecipientEditTextView.java
diff --git a/src/com/android/ex/chips/RecipientEditTextView.java b/src/com/android/ex/chips/RecipientEditTextView.java
index 085182e..fa9d462 100644
--- a/src/com/android/ex/chips/RecipientEditTextView.java
+++ b/src/com/android/ex/chips/RecipientEditTextView.java
@@ -2516,23 +2516,47 @@
     /**
      * Handles pasting a {@link ClipData} to this {@link RecipientEditTextView}.
      */
-    private void handlePasteClip(ClipData clip) {
+    // Visible for testing.
+    void handlePasteClip(ClipData clip) {
+        if (clip == null) {
+            // Do nothing.
+            return;
+        }
+
+        final ClipDescription clipDesc = clip.getDescription();
+        boolean containsSupportedType = clipDesc.hasMimeType(ClipDescription.MIMETYPE_TEXT_PLAIN) ||
+                clipDesc.hasMimeType(ClipDescription.MIMETYPE_TEXT_HTML);
+        if (!containsSupportedType) {
+            return;
+        }
+
         removeTextChangedListener(mTextWatcher);
 
-        if (clip != null && clip.getDescription().hasMimeType(ClipDescription.MIMETYPE_TEXT_PLAIN)){
-            for (int i = 0; i < clip.getItemCount(); i++) {
-                CharSequence paste = clip.getItemAt(i).getText();
-                if (paste != null) {
-                    int start = getSelectionStart();
-                    int end = getSelectionEnd();
-                    Editable editable = getText();
-                    if (start >= 0 && end >= 0 && start != end) {
-                        editable.append(paste, start, end);
-                    } else {
-                        editable.insert(end, paste);
-                    }
-                    handlePasteAndReplace();
+        final ClipDescription clipDescription = clip.getDescription();
+        for (int i = 0; i < clip.getItemCount(); i++) {
+            final String mimeType = clipDescription.getMimeType(i);
+            final boolean supportedType = ClipDescription.MIMETYPE_TEXT_PLAIN.equals(mimeType) ||
+                    ClipDescription.MIMETYPE_TEXT_HTML.equals(mimeType);
+            if (!supportedType) {
+                // Only plain text and html can be pasted.
+                continue;
+            }
+
+            final CharSequence pastedItem = clip.getItemAt(i).getText();
+            if (!TextUtils.isEmpty(pastedItem)) {
+                final Editable editable = getText();
+                final int start = getSelectionStart();
+                final int end = getSelectionEnd();
+                if (start < 0 || end < 1) {
+                    // No selection.
+                    editable.append(pastedItem);
+                } else if (start == end) {
+                    // Insert at position.
+                    editable.insert(start, pastedItem);
+                } else {
+                    editable.append(pastedItem, start, end);
                 }
+                handlePasteAndReplace();
             }
         }
 
diff --git a/tests/src/com/android/ex/chips/ChipsTest.java b/tests/src/com/android/ex/chips/ChipsTest.java
index 9116e26..1528d66 100644
--- a/tests/src/com/android/ex/chips/ChipsTest.java
+++ b/tests/src/com/android/ex/chips/ChipsTest.java
@@ -16,10 +16,13 @@
 
 package com.android.ex.chips;
 
+import android.annotation.TargetApi;
+import android.content.ClipData;
 import android.content.Context;
 import android.graphics.Bitmap;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
+import android.net.Uri;
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.text.Editable;
@@ -844,6 +847,34 @@
         assertEquals(mEditable.toString(), "<user1>, <user2@user.com>, ");
     }
 
+    @TargetApi(16)
+    public void testHandlePasteClip() {
+        MockRecipientEditTextView view = createViewForTesting();
+
+        ClipData clipData = null;
+        mEditable = new SpannableStringBuilder();
+        view.handlePasteClip(clipData);
+        assertEquals("", view.getText().toString());
+
+        clipData = ClipData.newPlainText("user label", "<foo@example.com>");
+        mEditable = new SpannableStringBuilder();
+        view.handlePasteClip(clipData);
+        assertEquals("<foo@example.com>", view.getText().toString());
+
+        clipData = ClipData.newHtmlText("user label",
+                "<bar@example.com>", "<a href=\"mailto:bar@example.com\">email</a>");
+        mEditable = new SpannableStringBuilder();
+        view.handlePasteClip(clipData);
+        assertEquals("<bar@example.com>", view.getText().toString());
+
+        ClipData.Item clipImageData = new ClipData.Item(Uri.parse("content://my/image"));
+        clipData = new ClipData("user label", new String[]{"image/jpeg"}, clipImageData);
+        mEditable = new SpannableStringBuilder();
+        view.handlePasteClip(clipData);
+        assertEquals("", view.getText().toString()
+        );
+    }
+
     public void testGetPastTerminators() {
         MockRecipientEditTextView view = createViewForTesting();
         view.setMoreItem(createTestMoreItem());