Bug 1463576 - 7. Simplify clipboard code; r?snorp
Don't use a different thread when accessing the clipboard. The original
issue was using the clipboard required a thread with a Looper, when
GeckoThread did not have one. It does have one now so it's safe to
access the clipboard there.
Also, make hasText() return false for empty strings to avoid us
mistakenly think there is something on the clipboard.
MozReview-Commit-ID: AwKEcNnIkhT
--- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/Clipboard.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/Clipboard.java
@@ -7,101 +7,61 @@ package org.mozilla.gecko;
import java.util.concurrent.SynchronousQueue;
import org.mozilla.gecko.annotation.WrapForJNI;
import org.mozilla.gecko.util.ThreadUtils;
import android.content.ClipboardManager;
import android.content.ClipData;
import android.content.Context;
-import android.util.Log;
+import android.text.TextUtils;
public final class Clipboard {
private final static String LOGTAG = "GeckoClipboard";
- private final static SynchronousQueue<String> sClipboardQueue = new SynchronousQueue<String>();
private Clipboard() {
}
@WrapForJNI(calledFrom = "gecko")
public static String getText(final Context context) {
- // If we're on the UI thread or the background thread, we have a looper on the thread
- // and can just call this directly. For any other threads, post the call to the
- // background thread.
-
- if (ThreadUtils.isOnUiThread() || ThreadUtils.isOnBackgroundThread()) {
- return getClipboardTextImpl(context);
+ final ClipboardManager cm = (ClipboardManager)
+ context.getSystemService(Context.CLIPBOARD_SERVICE);
+ if (cm.hasPrimaryClip()) {
+ ClipData clip = cm.getPrimaryClip();
+ if (clip != null && clip.getItemCount() > 0) {
+ ClipData.Item item = clip.getItemAt(0);
+ return item.coerceToText(context).toString();
+ }
}
-
- ThreadUtils.postToBackgroundThread(new Runnable() {
- @Override
- public void run() {
- String text = getClipboardTextImpl(context);
- try {
- sClipboardQueue.put(text != null ? text : "");
- } catch (InterruptedException ie) { }
- }
- });
-
- try {
- return sClipboardQueue.take();
- } catch (InterruptedException ie) {
- return "";
- }
+ return null;
}
@WrapForJNI(calledFrom = "gecko")
public static void setText(final Context context, final CharSequence text) {
- ThreadUtils.postToBackgroundThread(new Runnable() {
- @Override
- public void run() {
- // In API Level 11 and above, CLIPBOARD_SERVICE returns android.content.ClipboardManager,
- // which is a subclass of android.text.ClipboardManager.
- final ClipboardManager cm = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
- final ClipData clip = ClipData.newPlainText("Text", text);
- try {
- cm.setPrimaryClip(clip);
- } catch (NullPointerException e) {
- // Bug 776223: This is a Samsung clipboard bug. setPrimaryClip() can throw
- // a NullPointerException if Samsung's /data/clipboard directory is full.
- // Fortunately, the text is still successfully copied to the clipboard.
- }
- return;
- }
- });
+ // In API Level 11 and above, CLIPBOARD_SERVICE returns android.content.ClipboardManager,
+ // which is a subclass of android.text.ClipboardManager.
+ final ClipboardManager cm = (ClipboardManager)
+ context.getSystemService(Context.CLIPBOARD_SERVICE);
+ try {
+ cm.setPrimaryClip(ClipData.newPlainText("Text", text));
+ } catch (NullPointerException e) {
+ // Bug 776223: This is a Samsung clipboard bug. setPrimaryClip() can throw
+ // a NullPointerException if Samsung's /data/clipboard directory is full.
+ // Fortunately, the text is still successfully copied to the clipboard.
+ }
}
/**
* @return true if the clipboard is nonempty, false otherwise.
*/
@WrapForJNI(calledFrom = "gecko")
public static boolean hasText(final Context context) {
- final ClipboardManager cm = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
- return cm.hasPrimaryClip();
+ return !TextUtils.isEmpty(getText(context));
}
/**
* Deletes all text from the clipboard.
*/
@WrapForJNI(calledFrom = "gecko")
public static void clearText(final Context context) {
setText(context, null);
}
-
- /**
- * On some devices, access to the clipboard service needs to happen
- * on a thread with a looper, so this function requires a looper is
- * present on the thread.
- */
- @SuppressWarnings("deprecation")
- static String getClipboardTextImpl(final Context context) {
- final ClipboardManager cm = (ClipboardManager)
- context.getSystemService(Context.CLIPBOARD_SERVICE);
- if (cm.hasPrimaryClip()) {
- ClipData clip = cm.getPrimaryClip();
- if (clip != null) {
- ClipData.Item item = clip.getItemAt(0);
- return item.coerceToText(context).toString();
- }
- }
- return null;
- }
}
--- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntime.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntime.java
@@ -116,16 +116,19 @@ public final class GeckoRuntime implemen
mSettings = settings;
// Bug 1453062 -- the EventDispatcher should really live here (or in GeckoThread)
EventDispatcher.getInstance().registerUiThreadListener(mEventListener, "Gecko:Exited");
mSettings.runtime = this;
mSettings.flush();
+
+ // Initialize the system ClipboardManager by accessing it on the main thread.
+ GeckoAppShell.getApplicationContext().getSystemService(Context.CLIPBOARD_SERVICE);
return true;
}
/**
* Create a new runtime with default settings and attach it to the given
* context.
*
* Create will throw if there is already an active Gecko instance running,