1 // Copyright 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 package org.chromium.ui.base; 6 7 import android.content.ClipData; 8 import android.content.ClipboardManager; 9 import android.content.Context; 10 import android.widget.Toast; 11 12 import org.chromium.base.ApiCompatibilityUtils; 13 import org.chromium.base.CalledByNative; 14 import org.chromium.base.JNINamespace; 15 import org.chromium.ui.R; 16 17 /** 18 * Simple proxy that provides C++ code with an access pathway to the Android 19 * clipboard. 20 */ 21 @JNINamespace("ui") 22 public class Clipboard { 23 // Necessary for coercing clipboard contents to text if they require 24 // access to network resources, etceteras (e.g., URI in clipboard) 25 private final Context mContext; 26 27 private final ClipboardManager mClipboardManager; 28 29 /** 30 * Use the factory constructor instead. 31 * 32 * @param context for accessing the clipboard 33 */ Clipboard(final Context context)34 public Clipboard(final Context context) { 35 mContext = context; 36 mClipboardManager = (ClipboardManager) 37 context.getSystemService(Context.CLIPBOARD_SERVICE); 38 } 39 40 /** 41 * Returns a new Clipboard object bound to the specified context. 42 * 43 * @param context for accessing the clipboard 44 * @return the new object 45 */ 46 @CalledByNative create(final Context context)47 private static Clipboard create(final Context context) { 48 return new Clipboard(context); 49 } 50 51 /** 52 * Emulates the behavior of the now-deprecated 53 * {@link android.text.ClipboardManager#getText()} by invoking 54 * {@link android.content.ClipData.Item#coerceToText(Context)} on the first 55 * item in the clipboard (if any) and returning the result as a string. 56 * <p> 57 * This is quite different than simply calling {@link Object#toString()} on 58 * the clip; consumers of this API should familiarize themselves with the 59 * process described in 60 * {@link android.content.ClipData.Item#coerceToText(Context)} before using 61 * this method. 62 * 63 * @return a string representation of the first item on the clipboard, if 64 * the clipboard currently has an item and coercion of the item into 65 * a string is possible; otherwise, <code>null</code> 66 */ 67 @SuppressWarnings("javadoc") 68 @CalledByNative getCoercedText()69 private String getCoercedText() { 70 final ClipData clip = mClipboardManager.getPrimaryClip(); 71 if (clip != null && clip.getItemCount() > 0) { 72 final CharSequence sequence = clip.getItemAt(0).coerceToText(mContext); 73 if (sequence != null) { 74 return sequence.toString(); 75 } 76 } 77 return null; 78 } 79 80 /** 81 * Gets the HTML text of top item on the primary clip on the Android clipboard. 82 * 83 * @return a Java string with the html text if any, or null if there is no html 84 * text or no entries on the primary clip. 85 */ 86 @CalledByNative getHTMLText()87 private String getHTMLText() { 88 if (isHTMLClipboardSupported()) { 89 final ClipData clip = mClipboardManager.getPrimaryClip(); 90 if (clip != null && clip.getItemCount() > 0) { 91 return clip.getItemAt(0).getHtmlText(); 92 } 93 } 94 return null; 95 } 96 97 /** 98 * Emulates the behavior of the now-deprecated 99 * {@link android.text.ClipboardManager#setText(CharSequence)}, setting the 100 * clipboard's current primary clip to a plain-text clip that consists of 101 * the specified string. 102 * 103 * @param label will become the label of the clipboard's primary clip 104 * @param text will become the content of the clipboard's primary clip 105 */ setText(final String label, final String text)106 public void setText(final String label, final String text) { 107 setPrimaryClipNoException(ClipData.newPlainText(label, text)); 108 } 109 110 /** 111 * Emulates the behavior of the now-deprecated 112 * {@link android.text.ClipboardManager#setText(CharSequence)}, setting the 113 * clipboard's current primary clip to a plain-text clip that consists of 114 * the specified string. 115 * 116 * @param text will become the content of the clipboard's primary clip 117 */ 118 @CalledByNative setText(final String text)119 public void setText(final String text) { 120 setText(null, text); 121 } 122 123 /** 124 * Writes HTML to the clipboard, together with a plain-text representation 125 * of that very data. This API is only available in Android JellyBean+ and 126 * will be a no-operation in older versions. 127 * 128 * @param html The HTML content to be pasted to the clipboard. 129 * @param label The Plain-text label for the HTML content. 130 * @param text Plain-text representation of the HTML content. 131 */ setHTMLText(final String html, final String label, final String text)132 public void setHTMLText(final String html, final String label, final String text) { 133 if (isHTMLClipboardSupported()) { 134 setPrimaryClipNoException(ClipData.newHtmlText(label, text, html)); 135 } 136 } 137 138 /** 139 * Writes HTML to the clipboard, together with a plain-text representation 140 * of that very data. This API is only available in Android JellyBean+ and 141 * will be a no-operation in older versions. 142 * 143 * @param html The HTML content to be pasted to the clipboard. 144 * @param text Plain-text representation of the HTML content. 145 */ 146 @CalledByNative setHTMLText(final String html, final String text)147 public void setHTMLText(final String html, final String text) { 148 setHTMLText(html, null, text); 149 } 150 151 @CalledByNative isHTMLClipboardSupported()152 private static boolean isHTMLClipboardSupported() { 153 return ApiCompatibilityUtils.isHTMLClipboardSupported(); 154 } 155 setPrimaryClipNoException(ClipData clip)156 private void setPrimaryClipNoException(ClipData clip) { 157 try { 158 mClipboardManager.setPrimaryClip(clip); 159 } catch (Exception ex) { 160 // Ignore any exceptions here as certain devices have bugs and will fail. 161 String text = mContext.getString(R.string.copy_to_clipboard_failure_message); 162 Toast.makeText(mContext, text, Toast.LENGTH_SHORT).show(); 163 } 164 } 165 } 166