diff options
author | kristianm@chromium.org <kristianm@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-12-04 02:50:15 +0000 |
---|---|---|
committer | kristianm@chromium.org <kristianm@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-12-04 02:50:15 +0000 |
commit | be6fcc7020d8ce58a179b93869afaf2e71d82fdd (patch) | |
tree | 9ac3fe840cdc95ef5dc468fb25ed9719e12dcaaf | |
parent | a188c82ea0c4f25d99ed445b0b36aac0d9cf9121 (diff) | |
download | chromium_src-be6fcc7020d8ce58a179b93869afaf2e71d82fdd.zip chromium_src-be6fcc7020d8ce58a179b93869afaf2e71d82fdd.tar.gz chromium_src-be6fcc7020d8ce58a179b93869afaf2e71d82fdd.tar.bz2 |
Enable pasting HTML content from the Android clipboard
BUG=316717
Review URL: https://codereview.chromium.org/59023007
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@238530 0039d316-1c4b-4281-b951-d872f2087c98
4 files changed, 63 insertions, 38 deletions
diff --git a/base/android/java/src/org/chromium/base/ApiCompatibilityUtils.java b/base/android/java/src/org/chromium/base/ApiCompatibilityUtils.java index b902f93..26ec7b9 100644 --- a/base/android/java/src/org/chromium/base/ApiCompatibilityUtils.java +++ b/base/android/java/src/org/chromium/base/ApiCompatibilityUtils.java @@ -42,6 +42,13 @@ public class ApiCompatibilityUtils { } /** + * @return True if the running version of the Android supports HTML clipboard. + */ + public static boolean isHTMLClipboardSupported() { + return Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN; + } + + /** * @see android.view.View#setLayoutDirection(int) */ public static void setLayoutDirection(View view, int layoutDirection) { diff --git a/ui/android/java/src/org/chromium/ui/base/Clipboard.java b/ui/android/java/src/org/chromium/ui/base/Clipboard.java index e62c84a..9e5cf61 100644 --- a/ui/android/java/src/org/chromium/ui/base/Clipboard.java +++ b/ui/android/java/src/org/chromium/ui/base/Clipboard.java @@ -4,6 +4,7 @@ package org.chromium.ui.base; +import org.chromium.base.ApiCompatibilityUtils; import org.chromium.base.CalledByNative; import org.chromium.base.JNINamespace; @@ -77,6 +78,23 @@ public class Clipboard { } /** + * Gets the HTML text of top item on the primary clip on the Android clipboard. + * + * @return a Java string with the html text if any, or null if there is no html + * text or no entries on the primary clip. + */ + @CalledByNative + private String getHTMLText() { + if (isHTMLClipboardSupported()) { + final ClipData clip = mClipboardManager.getPrimaryClip(); + if (clip != null && clip.getItemCount() > 0) { + return clip.getItemAt(0).getHtmlText(); + } + } + return null; + } + + /** * Emulates the behavior of the now-deprecated * {@link android.text.ClipboardManager#setText(CharSequence)}, setting the * clipboard's current primary clip to a plain-text clip that consists of @@ -100,29 +118,14 @@ public class Clipboard { */ @CalledByNative private void setHTMLText(final String html, final String text) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { + if (isHTMLClipboardSupported()) { mClipboardManager.setPrimaryClip( ClipData.newHtmlText(null, text, html)); } } - /** - * Approximates the behavior of the now-deprecated - * {@link android.text.ClipboardManager#hasText()}, returning true if and - * only if the clipboard has a primary clip and that clip contains a plain - * non-empty text entry (without attempting coercion - URLs and intents - * will cause this method to return false). - * - * @return as described above - */ - @SuppressWarnings("javadoc") @CalledByNative - private boolean hasPlainText() { - final ClipData clip = mClipboardManager.getPrimaryClip(); - if (clip != null && clip.getItemCount() > 0) { - final CharSequence text = clip.getItemAt(0).getText(); - return !TextUtils.isEmpty(text); - } - return false; + private static boolean isHTMLClipboardSupported() { + return ApiCompatibilityUtils.isHTMLClipboardSupported(); } } diff --git a/ui/base/clipboard/clipboard_android.cc b/ui/base/clipboard/clipboard_android.cc index fc9ba00..f0971c4 100644 --- a/ui/base/clipboard/clipboard_android.cc +++ b/ui/base/clipboard/clipboard_android.cc @@ -129,39 +129,50 @@ void ClipboardMap::Clear() { // If the internal map contains a plain-text entry and it does not match that // in the Android clipboard, clear the map and insert the Android text into it. +// If there is an HTML entry in the Android clipboard it gets inserted in the +// map. void ClipboardMap::SyncWithAndroidClipboard() { lock_.AssertAcquired(); JNIEnv* env = AttachCurrentThread(); + // Update the plain text clipboard entry std::map<std::string, std::string>::const_iterator it = map_.find(kPlainTextFormat); - - if (!Java_Clipboard_hasPlainText(env, clipboard_manager_.obj())) { - if (it != map_.end()) + ScopedJavaLocalRef<jstring> java_string_text = + Java_Clipboard_getCoercedText(env, clipboard_manager_.obj()); + if (java_string_text.obj()) { + std::string android_string = ConvertJavaStringToUTF8(java_string_text); + if (!android_string.empty() && + (it == map_.end() || it->second != android_string)) { + // There is a different string in the Android clipboard than we have. + // Clear the map on our side. + map_.clear(); + map_[kPlainTextFormat] = android_string; + } + } else { + if (it != map_.end()) { // We have plain text on this side, but Android doesn't. Nuke ours. map_.clear(); - return; + } } - ScopedJavaLocalRef<jstring> java_string = - Java_Clipboard_getCoercedText(env, clipboard_manager_.obj()); - - if (!java_string.obj()) { - // Tolerate a null value from the Java side, even though that should not - // happen since hasPlainText has already returned true. - // Should only happen if someone is using the clipboard on multiple - // threads and clears it out after hasPlainText but before we get here... - if (it != map_.end()) - // We have plain text on this side, but Android doesn't. Nuke ours. - map_.clear(); + if (!Java_Clipboard_isHTMLClipboardSupported(env)) { return; } - // If Android text differs from ours (or we have none), then copy Android's. - std::string android_string = ConvertJavaStringToUTF8(java_string); - if (it == map_.end() || it->second != android_string) { - map_.clear(); - map_[kPlainTextFormat] = android_string; + // Update the html clipboard entry + ScopedJavaLocalRef<jstring> java_string_html = + Java_Clipboard_getHTMLText(env, clipboard_manager_.obj()); + if (java_string_html.obj()) { + std::string android_string = ConvertJavaStringToUTF8(java_string_html); + if (!android_string.empty()) { + map_[kHTMLFormat] = android_string; + return; + } + } + it = map_.find(kHTMLFormat); + if (it != map_.end()) { + map_.erase(kHTMLFormat); } } diff --git a/ui/base/clipboard/clipboard_unittest.cc b/ui/base/clipboard/clipboard_unittest.cc index c423e41..d3aa530 100644 --- a/ui/base/clipboard/clipboard_unittest.cc +++ b/ui/base/clipboard/clipboard_unittest.cc @@ -89,11 +89,13 @@ TEST_F(ClipboardTest, TextTest) { TEST_F(ClipboardTest, HTMLTest) { string16 markup(ASCIIToUTF16("<string>Hi!</string>")), markup_result; + string16 plain(ASCIIToUTF16("Hi!")), plain_result; std::string url("http://www.example.com/"), url_result; { ScopedClipboardWriter clipboard_writer(&clipboard(), CLIPBOARD_TYPE_COPY_PASTE); + clipboard_writer.WriteText(plain); clipboard_writer.WriteHTML(markup, url); } @@ -175,10 +177,12 @@ TEST_F(ClipboardTest, TrickyHTMLTest) { string16 markup(ASCIIToUTF16("<em>Bye!<!--EndFragment --></em>")), markup_result; std::string url, url_result; + string16 plain(ASCIIToUTF16("Bye!")), plain_result; { ScopedClipboardWriter clipboard_writer(&clipboard(), CLIPBOARD_TYPE_COPY_PASTE); + clipboard_writer.WriteText(plain); clipboard_writer.WriteHTML(markup, url); } |