Bug 1539827 - Handle RuntimeException when setting clipboard data r=geckoview-reviewers,snorp
authorMakoto Kato <m_kato@ga2.so-net.ne.jp>
Thu, 18 Apr 2019 10:13:38 +0000
changeset 470062 53793d2ea3ece905e5847018f9c7595585f8f388
parent 470061 dc185b8ee50e252d3219e71de31b28b098ec86db
child 470063 0d59dd598e5eb0b7b4618d68d6884c947eb658d6
push id35888
push useraiakab@mozilla.com
push dateFri, 19 Apr 2019 09:47:45 +0000
treeherdermozilla-central@0160424142d1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgeckoview-reviewers, snorp
bugs1539827
milestone68.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1539827 - Handle RuntimeException when setting clipboard data r=geckoview-reviewers,snorp When setting large clipboard data, it may cause `TransactionTooLargeException` in binder IPC. So we have to handle `RuntimeException`. Differential Revision: https://phabricator.services.mozilla.com/D27466
mobile/android/geckoview/src/main/java/org/mozilla/gecko/Clipboard.java
widget/android/nsClipboard.cpp
--- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/Clipboard.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/Clipboard.java
@@ -6,16 +6,17 @@ package org.mozilla.gecko;
 
 import org.mozilla.gecko.annotation.WrapForJNI;
 
 import android.content.ClipboardManager;
 import android.content.ClipData;
 import android.content.ClipDescription;
 import android.content.Context;
 import android.text.TextUtils;
+import android.util.Log;
 
 public final class Clipboard {
     private final static String HTML_MIME = "text/html";
     private final static String UNICODE_MIME = "text/unicode";
     private final static String LOGTAG = "GeckoClipboard";
 
     private Clipboard() {
     }
@@ -63,52 +64,60 @@ public final class Clipboard {
         return null;
     }
 
     /**
      * Set plain text to clipboard
      *
      * @param context application context
      * @param text a plain text to set to clipboard
+     * @return true if copy is successful.
      */
     @WrapForJNI(calledFrom = "gecko")
-    public static void setText(final Context context, final CharSequence text) {
-        setData(context, ClipData.newPlainText("text", text));
+    public static boolean setText(final Context context, final CharSequence text) {
+        return setData(context, ClipData.newPlainText("text", text));
     }
 
     /**
      * Store HTML to clipboard
      *
      * @param context application context
      * @param text a plain text to set to clipboard
      * @param html a html text to set to clipboard
+     * @return true if copy is successful.
      */
     @WrapForJNI(calledFrom = "gecko")
-    public static void setHTML(final Context context, final CharSequence text, final String htmlText) {
-        setData(context, ClipData.newHtmlText("html", text, htmlText));
+    public static boolean setHTML(final Context context, final CharSequence text, final String htmlText) {
+        return setData(context, ClipData.newHtmlText("html", text, htmlText));
     }
 
     /**
      * Store {@link android.content.ClipData} to clipboard
      *
      * @param context application context
      * @param clipData a {@link android.content.ClipData} to set to clipboard
+     * @return true if copy is successful.
      */
-    private static void setData(final Context context, final ClipData clipData) {
+    private static boolean setData(final Context context, final ClipData clipData) {
         // 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);
         } 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.
+        } catch (RuntimeException e) {
+            // If clipData is too large, TransactionTooLargeException occurs.
+            Log.e(LOGTAG, "Couldn't set clip data to clipboard", e);
+            return false;
         }
+        return true;
     }
 
     /**
      * @return true if the clipboard is nonempty, false otherwise.
      */
     @WrapForJNI(calledFrom = "gecko")
     public static boolean hasData(final Context context, final String mimeType) {
         if (HTML_MIME.equals(mimeType) || UNICODE_MIME.equals(mimeType)) {
--- a/widget/android/nsClipboard.cpp
+++ b/widget/android/nsClipboard.cpp
@@ -57,23 +57,23 @@ nsClipboard::SetData(nsITransferable *aT
       }
       nsCOMPtr<nsISupportsString> supportsString = do_QueryInterface(item);
       if (supportsString) {
         supportsString->GetData(html);
       }
     }
   }
 
-  if (!html.IsEmpty()) {
-    java::Clipboard::SetHTML(GeckoAppShell::GetApplicationContext(), text,
-                             html);
+  if (!html.IsEmpty() &&
+      java::Clipboard::SetHTML(GeckoAppShell::GetApplicationContext(), text,
+                               html)) {
     return NS_OK;
   }
-  if (!text.IsEmpty()) {
-    java::Clipboard::SetText(GeckoAppShell::GetApplicationContext(), text);
+  if (!text.IsEmpty() &&
+      java::Clipboard::SetText(GeckoAppShell::GetApplicationContext(), text)) {
     return NS_OK;
   }
 
   return NS_ERROR_FAILURE;
 }
 
 NS_IMETHODIMP
 nsClipboard::GetData(nsITransferable *aTransferable, int32_t aWhichClipboard) {