Wed, 31 Dec 2014 07:22:50 +0100
Correct previous dual key logic pending first delivery installment.
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 package org.mozilla.gecko.util;
7 import android.content.ClipData;
8 import android.content.Context;
9 import android.os.Build;
10 import android.util.Log;
12 import org.mozilla.gecko.mozglue.generatorannotations.WrapElementForJNI;
14 import java.util.concurrent.SynchronousQueue;
16 public final class Clipboard {
17 private static Context mContext;
18 private final static String LOGTAG = "GeckoClipboard";
19 private final static SynchronousQueue<String> sClipboardQueue = new SynchronousQueue<String>();
21 private Clipboard() {
22 }
24 public static void init(final Context c) {
25 if (mContext != null) {
26 Log.w(LOGTAG, "Clipboard.init() called twice!");
27 return;
28 }
29 mContext = c.getApplicationContext();
30 }
32 @WrapElementForJNI(stubName = "GetClipboardTextWrapper")
33 public static String getText() {
34 // If we're on the UI thread or the background thread, we have a looper on the thread
35 // and can just call this directly. For any other threads, post the call to the
36 // background thread.
38 if (ThreadUtils.isOnUiThread() || ThreadUtils.isOnBackgroundThread()) {
39 return getClipboardTextImpl();
40 }
42 ThreadUtils.postToBackgroundThread(new Runnable() {
43 @Override
44 public void run() {
45 String text = getClipboardTextImpl();
46 try {
47 sClipboardQueue.put(text != null ? text : "");
48 } catch (InterruptedException ie) {}
49 }
50 });
51 try {
52 return sClipboardQueue.take();
53 } catch (InterruptedException ie) {
54 return "";
55 }
56 }
58 @WrapElementForJNI(stubName = "SetClipboardText")
59 public static void setText(final CharSequence text) {
60 ThreadUtils.postToBackgroundThread(new Runnable() {
61 @Override
62 @SuppressWarnings("deprecation")
63 public void run() {
64 if (Build.VERSION.SDK_INT >= 11) {
65 android.content.ClipboardManager cm = getClipboardManager(mContext);
66 ClipData clip = ClipData.newPlainText("Text", text);
67 try {
68 cm.setPrimaryClip(clip);
69 } catch (NullPointerException e) {
70 // Bug 776223: This is a Samsung clipboard bug. setPrimaryClip() can throw
71 // a NullPointerException if Samsung's /data/clipboard directory is full.
72 // Fortunately, the text is still successfully copied to the clipboard.
73 }
74 } else {
75 android.text.ClipboardManager cm = getDeprecatedClipboardManager(mContext);
76 cm.setText(text);
77 }
78 }
79 });
80 }
82 /**
83 * Returns true if the clipboard is nonempty, false otherwise.
84 *
85 * @return true if the clipboard is nonempty, false otherwise.
86 */
87 @WrapElementForJNI
88 public static boolean hasText() {
89 if (Build.VERSION.SDK_INT >= 11) {
90 android.content.ClipboardManager cm = getClipboardManager(mContext);
91 return cm.hasPrimaryClip();
92 }
94 android.text.ClipboardManager cm = getDeprecatedClipboardManager(mContext);
95 return cm.hasText();
96 }
98 /**
99 * Deletes all text from the clipboard.
100 */
101 @WrapElementForJNI
102 public static void clearText() {
103 setText(null);
104 }
106 private static android.content.ClipboardManager getClipboardManager(Context context) {
107 // In API Level 11 and above, CLIPBOARD_SERVICE returns android.content.ClipboardManager,
108 // which is a subclass of android.text.ClipboardManager.
109 return (android.content.ClipboardManager) mContext.getSystemService(Context.CLIPBOARD_SERVICE);
110 }
112 private static android.text.ClipboardManager getDeprecatedClipboardManager(Context context) {
113 return (android.text.ClipboardManager) mContext.getSystemService(Context.CLIPBOARD_SERVICE);
114 }
116 /* On some devices, access to the clipboard service needs to happen
117 * on a thread with a looper, so this function requires a looper is
118 * present on the thread. */
119 @SuppressWarnings("deprecation")
120 private static String getClipboardTextImpl() {
121 if (Build.VERSION.SDK_INT >= 11) {
122 android.content.ClipboardManager cm = getClipboardManager(mContext);
123 if (cm.hasPrimaryClip()) {
124 ClipData clip = cm.getPrimaryClip();
125 if (clip != null) {
126 ClipData.Item item = clip.getItemAt(0);
127 return item.coerceToText(mContext).toString();
128 }
129 }
130 } else {
131 android.text.ClipboardManager cm = getDeprecatedClipboardManager(mContext);
132 if (cm.hasText()) {
133 return cm.getText().toString();
134 }
135 }
136 return null;
137 }
138 }