Backed out changeset bb2acd046eae (bug 1497580) for clipboard failures on test_clipboard_events.html. CLOSED TREE
authorNarcis Beleuzu <nbeleuzu@mozilla.com>
Wed, 17 Oct 2018 02:02:33 +0300
changeset 489944 96a0fd705c2abbdd5e7905362bf7bac74f0db8ee
parent 489943 c19d5002228fdea6a41a9e3d1f0d32a54fb08af2
child 489945 973fdd5f75cd556436d7fa5b0ebc8a0629c78cff
push id247
push userfmarier@mozilla.com
push dateSat, 27 Oct 2018 01:06:44 +0000
bugs1497580
milestone64.0a1
backs outbb2acd046eae1fbedfe11348dc3f31530a645fd8
Backed out changeset bb2acd046eae (bug 1497580) for clipboard failures on test_clipboard_events.html. CLOSED TREE
widget/gtk/nsClipboard.cpp
--- a/widget/gtk/nsClipboard.cpp
+++ b/widget/gtk/nsClipboard.cpp
@@ -29,26 +29,22 @@
 
 #include "imgIContainer.h"
 
 #include <gtk/gtk.h>
 #include <gtk/gtkx.h>
 
 #include "mozilla/Encoding.h"
 
+
 using namespace mozilla;
 
 // Idle timeout for receiving selection and property notify events (microsec)
 const int kClipboardTimeout = 500000;
 
-// We add this prefix to HTML markup, so that GetHTMLCharset can correctly
-// detect the HTML as UTF-8 encoded.
-static const char kHTMLMarkupPrefix[] =
-    R"(<meta http-equiv="content-type" content="text/html; charset=utf-8">)";
-
 // Callback when someone asks us for the data
 void
 clipboard_get_cb(GtkClipboard *aGtkClipboard,
                  GtkSelectionData *aSelectionData,
                  guint info,
                  gpointer user_data);
 
 // Callback when someone asks us to clear a clipboard
@@ -526,41 +522,16 @@ nsClipboard::SelectionGetEvent(GtkClipbo
         if (!pixbuf)
             return;
 
         gtk_selection_data_set_pixbuf(aSelectionData, pixbuf);
         g_object_unref(pixbuf);
         return;
     }
 
-    if (selectionTarget == gdk_atom_intern(kHTMLMime, FALSE)) {
-        rv = trans->GetTransferData(kHTMLMime, getter_AddRefs(item), &len);
-        if (!item || NS_FAILED(rv)) {
-            return;
-        }
-
-        nsCOMPtr<nsISupportsString> wideString;
-        wideString = do_QueryInterface(item);
-        if (!wideString) {
-            return;
-        }
-
-        nsAutoString ucs2string;
-        wideString->GetData(ucs2string);
-
-        nsAutoCString html;
-        // Add the prefix so the encoding is correctly detected.
-        html.AppendLiteral(kHTMLMarkupPrefix);
-        AppendUTF16toUTF8(ucs2string, html);
-
-        gtk_selection_data_set(aSelectionData, selectionTarget, 8,
-                               (const guchar*)html.get(), html.Length());
-        return;
-    }
-
     // Try to match up the selection data target to something our
     // transferable provides.
     gchar *target_name = gdk_atom_name(selectionTarget);
     if (!target_name)
         return;
 
     rv = trans->GetTransferData(target_name, getter_AddRefs(item), &len);
     // nothing found?
@@ -569,20 +540,41 @@ nsClipboard::SelectionGetEvent(GtkClipbo
         return;
     }
 
     void *primitive_data = nullptr;
     nsPrimitiveHelpers::CreateDataFromPrimitive(nsDependentCString(target_name),
                                                 item, &primitive_data, len);
 
     if (primitive_data) {
+        // Check to see if the selection data is text/html
+        if (selectionTarget == gdk_atom_intern (kHTMLMime, FALSE)) {
+            /*
+             * "text/html" can be encoded UCS2. It is recommended that
+             * documents transmitted as UCS2 always begin with a ZERO-WIDTH
+             * NON-BREAKING SPACE character (hexadecimal FEFF, also called
+             * Byte Order Mark (BOM)). Adding BOM can help other app to
+             * detect mozilla use UCS2 encoding when copy-paste.
+             */
+            guchar *buffer = (guchar *)
+                    g_malloc((len * sizeof(guchar)) + sizeof(char16_t));
+            if (!buffer)
+                return;
+            char16_t prefix = 0xFEFF;
+            memcpy(buffer, &prefix, sizeof(prefix));
+            memcpy(buffer + sizeof(prefix), primitive_data, len);
+            g_free((guchar *)primitive_data);
+            primitive_data = (guchar *)buffer;
+            len += sizeof(prefix);
+        }
+
         gtk_selection_data_set(aSelectionData, selectionTarget,
                                8, /* 8 bits in a unit */
                                (const guchar *)primitive_data, len);
-        free(primitive_data);
+        g_free(primitive_data);
     }
 
     g_free(target_name);
 
 }
 
 void
 nsClipboard::SelectionClearEvent(GtkClipboard *aGtkClipboard)
@@ -659,50 +651,43 @@ void ConvertHTMLtoUCS2(const char* data,
         auto encoding = Encoding::ForLabelNoReplacement(charset);
         if (!encoding) {
 #ifdef DEBUG_CLIPBOARD
             g_print("        get unicode decoder error\n");
 #endif
             outUnicodeLen = 0;
             return;
         }
-
-        auto dataSpan = MakeSpan(data, dataLength);
-        // Remove kHTMLMarkupPrefix again, it won't necessarily cause any
-        // issues, but might confuse other users.
-        const size_t prefixLen = ArrayLength(kHTMLMarkupPrefix) - 1;
-        if (dataSpan.Length() >= prefixLen &&
-            !strncmp(data, kHTMLMarkupPrefix, prefixLen)) {
-          dataSpan = dataSpan.From(prefixLen);
-        }
-
         auto decoder = encoding->NewDecoder();
-        CheckedInt<size_t> needed =
-            decoder->MaxUTF16BufferLength(dataSpan.Length());
+        CheckedInt<size_t> needed = decoder->MaxUTF16BufferLength(dataLength);
         if (!needed.isValid() || needed.value() > INT32_MAX) {
           outUnicodeLen = 0;
           return;
         }
 
         outUnicodeLen = 0;
         if (needed.value()) {
           *unicodeData = reinterpret_cast<char16_t*>(
             moz_xmalloc((needed.value() + 1) * sizeof(char16_t)));
           uint32_t result;
           size_t read;
           size_t written;
           bool hadErrors;
           Tie(result, read, written, hadErrors) =
-            decoder->DecodeToUTF16(AsBytes(dataSpan),
+            decoder->DecodeToUTF16(AsBytes(MakeSpan(data, dataLength)),
                                    MakeSpan(*unicodeData, needed.value()),
                                    true);
           MOZ_ASSERT(result == kInputEmpty);
-          MOZ_ASSERT(read == size_t(dataSpan.Length()));
+          MOZ_ASSERT(read == size_t(dataLength));
           MOZ_ASSERT(written <= needed.value());
           Unused << hadErrors;
+#ifdef DEBUG_CLIPBOARD
+          if (read != dataLength)
+            printf("didn't consume all the bytes\n");
+#endif
           outUnicodeLen = written;
           // null terminate.
           (*unicodeData)[outUnicodeLen] = '\0';
         } // if valid length
     }
 }
 
 /*