Bug 1500206 - In macOS clipboard code fallback to native clipboard for images . r=robwu,mixedpuppy
authorTom Schuster <evilpies@gmail.com>
Mon, 22 Oct 2018 14:39:09 +0000
changeset 490693 2e5b99d12a6daf88e4fffa8f80efb7b874f18379
parent 490692 76763ce5587582f94bcdebd9efb3ce6f625085ea
child 490694 d1e4e5029ffb1e38b6328b8c9d422edfb4603107
push id247
push userfmarier@mozilla.com
push dateSat, 27 Oct 2018 01:06:44 +0000
reviewersrobwu, mixedpuppy
bugs1500206
milestone64.0a1
Bug 1500206 - In macOS clipboard code fallback to native clipboard for images . r=robwu,mixedpuppy Differential Revision: https://phabricator.services.mozilla.com/D9132
toolkit/components/extensions/parent/ext-clipboard.js
--- a/toolkit/components/extensions/parent/ext-clipboard.js
+++ b/toolkit/components/extensions/parent/ext-clipboard.js
@@ -11,20 +11,19 @@ const Transferable = Components.Construc
 this.clipboard = class extends ExtensionAPI {
   getAPI(context) {
     return {
       clipboard: {
         async setImageData(imageData, imageType) {
           if (AppConstants.platform == "android") {
             return Promise.reject({message: "Writing images to the clipboard is not supported on Android"});
           }
-          let mimeType = `image/${imageType}`;
           let img;
           try {
-            img = imgTools.decodeImageFromArrayBuffer(imageData, mimeType);
+            img = imgTools.decodeImageFromArrayBuffer(imageData, `image/${imageType}`);
           } catch (e) {
             return Promise.reject({message: `Data is not a valid ${imageType} image`});
           }
 
           // Other applications can only access the copied image once the data
           // is exported via the platform-specific clipboard APIs:
           // nsClipboard::SelectionGetEvent (widget/gtk/nsClipboard.cpp)
           // nsClipboard::PasteDictFromTransferable (widget/cocoa/nsClipboard.mm)
@@ -33,42 +32,37 @@ this.clipboard = class extends Extension
           // The common protocol for exporting a nsITransferable as an image is:
           // - Use nsITransferable::GetTransferData to fetch the stored data.
           // - QI imgIContainer on the pointer.
           // - Convert the image to the native clipboard format.
           //
           // Below we create a nsITransferable in the above format.
           let transferable = new Transferable();
           transferable.init(null);
-          transferable.addDataFlavor(mimeType);
+          const kNativeImageMime = "application/x-moz-nativeimage";
+          transferable.addDataFlavor(kNativeImageMime);
 
           // Internal consumers expect the image data to be stored as a
           // nsIInputStream. On Linux and Windows, pasted data is directly
           // retrieved from the system's native clipboard, and made available
           // as a nsIInputStream.
           //
           // On macOS, nsClipboard::GetNativeClipboardData (nsClipboard.mm) uses
           // a cached copy of nsITransferable if available, e.g. when the copy
-          // was initiated by the same browser instance. Consequently, the
-          // transferable still holds a imgIContainer pointer
-          // instead of a nsIInputStream, and logic that assumes the data to be
-          // a nsIInputStream instance fails.
-          // For example HTMLEditor::InsertObject (HTMLEditorDataTransfer.cpp)
-          // and DataTransferItem::FillInExternalData (DataTransferItem.cpp).
-          //
-          // As a work-around, we force nsClipboard::GetNativeClipboardData to
-          // ignore the cached image data, by passing zero as the length
-          // parameter to transferable.setTransferData. When the length is zero,
-          // nsITransferable::GetTransferData will return NS_ERROR_FAILURE and
-          // conveniently nsClipboard::GetNativeClipboardData will then fall
-          // back to retrieving the data directly from the system's clipboard.
-          //
-          // Note that the length itself is not really used if the data is not
-          // a string type, so the actual value does not matter.
-          transferable.setTransferData(mimeType, img, 0);
+          // was initiated by the same browser instance. To make sure that a
+          // nsIInputStream is returned instead of the cached imgIContainer,
+          // the image is exported as as `kNativeImageMime`. Data associated
+          // with this type is converted to a platform-specific image format
+          // when written to the clipboard. The type is not used when images
+          // are read from the clipboard (on all platforms, not just macOS).
+          // This forces nsClipboard::GetNativeClipboardData to fall back to
+          // the native clipboard, and return the image as a nsITransferable.
+
+          // The length should not be zero. (Bug 1493292)
+          transferable.setTransferData(kNativeImageMime, img, 1);
 
           Services.clipboard.setData(
             transferable, null, Services.clipboard.kGlobalClipboard);
         },
       },
     };
   }
 };