Backed out 6 changesets (bug 1493292) for bustage on /nsTransferable.cpp. CLOSED TREE
authorCsoregi Natalia <ncsoregi@mozilla.com>
Tue, 20 Nov 2018 17:13:18 +0200
changeset 503665 4b0554a10847e9a879ab193bf16a3bbdaa8e69d4
parent 503664 5bad4fe7108eda1ca69c5f5aac82b4042c874deb
child 503666 4b78e1686da9ba317be1796cf241db3231f9cb75
push id10290
push userffxbld-merge
push dateMon, 03 Dec 2018 16:23:23 +0000
treeherdermozilla-beta@700bed2445e6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1493292
milestone65.0a1
backs outf198bf91320bf774f2c9f204c426ac0c2da95aa2
6487aa307123e63554a714e0cece6273e57017b1
f2cabd69c568bd5e6f50f7f3f5d6f5d55c6b7222
71430fceb4a3f1641b2d786e4f66e83c87149946
3a9b6d65d8c7afb9289b1eca8dbaf84e5da37c69
55769869037ce827861d586735375f064421e7b3
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
Backed out 6 changesets (bug 1493292) for bustage on /nsTransferable.cpp. CLOSED TREE Backed out changeset f198bf91320b (bug 1493292) Backed out changeset 6487aa307123 (bug 1493292) Backed out changeset f2cabd69c568 (bug 1493292) Backed out changeset 71430fceb4a3 (bug 1493292) Backed out changeset 3a9b6d65d8c7 (bug 1493292) Backed out changeset 55769869037c (bug 1493292)
accessible/tests/mochitest/common.js
browser/base/content/browser.js
browser/base/content/test/urlbar/browser_page_action_menu_clipboard.js
browser/components/places/content/controller.js
browser/extensions/mortar/host/common/ppapi-runtime.jsm
devtools/client/webconsole/test/mochitest/browser_jsterm_screenshot_command_clipboard.js
devtools/shared/platform/clipboard.js
dom/base/nsContentAreaDragDrop.cpp
dom/base/nsContentUtils.cpp
dom/base/nsCopySupport.cpp
dom/base/test/copypaste.js
dom/base/test/test_bug166235.html
dom/base/test/test_copyimage.html
dom/events/DataTransfer.cpp
dom/events/DataTransferItem.cpp
editor/libeditor/HTMLEditorDataTransfer.cpp
editor/libeditor/TextEditorDataTransfer.cpp
editor/libeditor/tests/test_CF_HTML_clipboard.html
testing/specialpowers/content/specialpowersAPI.js
toolkit/modules/Finder.jsm
toolkit/mozapps/extensions/internal/AddonRepository.jsm
widget/android/nsClipboard.cpp
widget/cocoa/nsChildView.mm
widget/cocoa/nsClipboard.mm
widget/cocoa/nsDragService.mm
widget/gtk/nsClipboard.cpp
widget/gtk/nsDragService.cpp
widget/headless/HeadlessClipboard.cpp
widget/headless/tests/test_headless_clipboard.js
widget/nsClipboardHelper.cpp
widget/nsClipboardProxy.cpp
widget/nsHTMLFormatConverter.cpp
widget/nsIFormatConverter.idl
widget/nsITransferable.idl
widget/nsTransferable.cpp
widget/nsTransferable.h
widget/tests/test_bug466599.xul
widget/tests/test_bug565392.html
widget/tests/test_clipboard.xul
widget/tests/test_transferable_overflow.xul
widget/windows/nsClipboard.cpp
widget/windows/nsDataObj.cpp
--- a/accessible/tests/mochitest/common.js
+++ b/accessible/tests/mochitest/common.js
@@ -726,22 +726,23 @@ function getTextFromClipboard() {
   trans.init(getLoadContext());
   if (!trans)
     return "";
 
   trans.addDataFlavor("text/unicode");
   Services.clipboard.getData(trans, Services.clipboard.kGlobalClipboard);
 
   var str = {};
-  trans.getTransferData("text/unicode", str);
+  var strLength = {};
+  trans.getTransferData("text/unicode", str, strLength);
 
   if (str)
     str = str.value.QueryInterface(Ci.nsISupportsString);
   if (str)
-    return str.data;
+    return str.data.substring(0, strLength.value / 2);
 
   return "";
 }
 
 /**
  * Extract DOMNode id from an accessible. If e10s is enabled, DOMNode is not
  * present in parent process but, if available, DOMNode id is attached to an
  * accessible object.
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -2499,21 +2499,22 @@ function readFromClipboard() {
 
     // If available, use selection clipboard, otherwise global one
     if (Services.clipboard.supportsSelectionClipboard())
       Services.clipboard.getData(trans, Services.clipboard.kSelectionClipboard);
     else
       Services.clipboard.getData(trans, Services.clipboard.kGlobalClipboard);
 
     var data = {};
-    trans.getTransferData("text/unicode", data);
+    var dataLen = {};
+    trans.getTransferData("text/unicode", data, dataLen);
 
     if (data) {
       data = data.value.QueryInterface(Ci.nsISupportsString);
-      url = data.data;
+      url = data.data.substring(0, dataLen.value / 2);
     }
   } catch (ex) {
   }
 
   return url;
 }
 
 /**
--- a/browser/base/content/test/urlbar/browser_page_action_menu_clipboard.js
+++ b/browser/base/content/test/urlbar/browser_page_action_menu_clipboard.js
@@ -23,14 +23,14 @@ add_task(async function copyURL() {
     // Check the clipboard.
     let transferable = Cc["@mozilla.org/widget/transferable;1"]
                          .createInstance(Ci.nsITransferable);
     transferable.init(null);
     let flavor = "text/unicode";
     transferable.addDataFlavor(flavor);
     Services.clipboard.getData(transferable, Services.clipboard.kGlobalClipboard);
     let strObj = {};
-    transferable.getTransferData(flavor, strObj);
+    transferable.getTransferData(flavor, strObj, {});
     Assert.ok(!!strObj.value);
     strObj.value.QueryInterface(Ci.nsISupportsString);
     Assert.equal(strObj.value.data, gBrowser.selectedBrowser.currentURI.spec);
   });
 });
--- a/browser/components/places/content/controller.js
+++ b/browser/components/places/content/controller.js
@@ -960,17 +960,17 @@ PlacesController.prototype = {
     let action = {};
     let actionOwner;
     try {
       let xferable = Cc["@mozilla.org/widget/transferable;1"].
                      createInstance(Ci.nsITransferable);
       xferable.init(null);
       xferable.addDataFlavor(PlacesUtils.TYPE_X_MOZ_PLACE_ACTION);
       this.clipboard.getData(xferable, Ci.nsIClipboard.kGlobalClipboard);
-      xferable.getTransferData(PlacesUtils.TYPE_X_MOZ_PLACE_ACTION, action);
+      xferable.getTransferData(PlacesUtils.TYPE_X_MOZ_PLACE_ACTION, action, {});
       [action, actionOwner] =
         action.value.QueryInterface(Ci.nsISupportsString).data.split(",");
     } catch (ex) {
       // Paste from external sources don't have any associated action, just
       // fallback to a copy action.
       return "copy";
     }
     // For cuts also check who inited the action, since cuts across different
--- a/browser/extensions/mortar/host/common/ppapi-runtime.jsm
+++ b/browser/extensions/mortar/host/common/ppapi-runtime.jsm
@@ -2613,17 +2613,18 @@ dump(`callFromJSON: < ${JSON.stringify(c
             PP_Flash_Clipboard_Format.PP_FLASH_CLIPBOARD_FORMAT_PLAINTEXT) {
           let trans = Cc["@mozilla.org/widget/transferable;1"]
             .createInstance(Ci.nsITransferable);
           trans.init(null)
           trans.addDataFlavor("text/unicode");
           Services.clipboard.getData(
             trans, Services.clipboard.kGlobalClipboard);
           let str = {};
-          trans.getTransferData("text/unicode", str);
+          let strLength = {};
+          trans.getTransferData("text/unicode", str, strLength);
           let pasteText = str.value.QueryInterface(Ci.nsISupportsString).data;
           return new String_PP_Var(pasteText);
         }
       }
       return new PP_Var();
     },
 
     /**
--- a/devtools/client/webconsole/test/mochitest/browser_jsterm_screenshot_command_clipboard.js
+++ b/devtools/client/webconsole/test/mochitest/browser_jsterm_screenshot_command_clipboard.js
@@ -160,19 +160,21 @@ async function getImageSizeFromClipboard
   const trans = Cc["@mozilla.org/widget/transferable;1"]
                 .createInstance(Ci.nsITransferable);
   const flavor = "image/png";
   trans.init(null);
   trans.addDataFlavor(flavor);
 
   clip.getData(trans, clipid.kGlobalClipboard);
   const data = {};
-  trans.getTransferData(flavor, data);
+  const dataLength = {};
+  trans.getTransferData(flavor, data, dataLength);
 
   ok(data.value, "screenshot exists");
+  ok(dataLength.value > 0, "screenshot has length");
 
   let image = data.value;
 
   // Due to the differences in how images could be stored in the clipboard the
   // checks below are needed. The clipboard could already provide the image as
   // byte streams or as image container. If it's not possible obtain a
   // byte stream, the function throws.
 
--- a/devtools/shared/platform/clipboard.js
+++ b/devtools/shared/platform/clipboard.js
@@ -37,17 +37,17 @@ function getText() {
   // Get the data into our transferable.
   Services.clipboard.getData(
     xferable,
     Services.clipboard.kGlobalClipboard
   );
 
   const data = {};
   try {
-    xferable.getTransferData(flavor, data);
+    xferable.getTransferData(flavor, data, {});
   } catch (e) {
     // Clipboard doesn't contain data in flavor, return null.
     return null;
   }
 
   // There's no data available, return.
   if (!data.value) {
     return null;
--- a/dom/base/nsContentAreaDragDrop.cpp
+++ b/dom/base/nsContentAreaDragDrop.cpp
@@ -225,44 +225,48 @@ CheckAndGetExtensionForMime(const nsCStr
 //    transferable with an nsIFile for the directory we are to
 //    save in. That has to be done by platform-specific code (in
 //    widget), which gets the destination directory from
 //    OS-specific drag information.
 //
 NS_IMETHODIMP
 nsContentAreaDragDropDataProvider::GetFlavorData(nsITransferable *aTransferable,
                                                  const char *aFlavor,
-                                                 nsISupports **aData)
+                                                 nsISupports **aData,
+                                                 uint32_t *aDataLen)
 {
-  NS_ENSURE_ARG_POINTER(aData);
+  NS_ENSURE_ARG_POINTER(aData && aDataLen);
   *aData = nullptr;
+  *aDataLen = 0;
 
   nsresult rv = NS_ERROR_NOT_IMPLEMENTED;
 
   if (strcmp(aFlavor, kFilePromiseMime) == 0) {
     // get the URI from the kFilePromiseURLMime flavor
     NS_ENSURE_ARG(aTransferable);
     nsCOMPtr<nsISupports> tmp;
-    aTransferable->GetTransferData(kFilePromiseURLMime, getter_AddRefs(tmp));
+    uint32_t dataSize = 0;
+    aTransferable->GetTransferData(kFilePromiseURLMime,
+                                   getter_AddRefs(tmp), &dataSize);
     nsCOMPtr<nsISupportsString> supportsString =
       do_QueryInterface(tmp);
     if (!supportsString)
       return NS_ERROR_FAILURE;
 
     nsAutoString sourceURLString;
     supportsString->GetData(sourceURLString);
     if (sourceURLString.IsEmpty())
       return NS_ERROR_FAILURE;
 
     nsCOMPtr<nsIURI> sourceURI;
     rv = NS_NewURI(getter_AddRefs(sourceURI), sourceURLString);
     NS_ENSURE_SUCCESS(rv, rv);
 
     aTransferable->GetTransferData(kFilePromiseDestFilename,
-                                   getter_AddRefs(tmp));
+                                   getter_AddRefs(tmp), &dataSize);
     supportsString = do_QueryInterface(tmp);
     if (!supportsString)
       return NS_ERROR_FAILURE;
 
     nsAutoString targetFilename;
     supportsString->GetData(targetFilename);
     if (targetFilename.IsEmpty())
       return NS_ERROR_FAILURE;
@@ -271,17 +275,17 @@ nsContentAreaDragDropDataProvider::GetFl
     // Use the image request's MIME type to ensure the filename's
     // extension is compatible with the OS's handler for this type.
     // If it isn't, or is missing, replace the extension with the
     // primary extension. On Mac, do this in the parent process
     // because sandboxing blocks access to MIME-handler info from
     // content processes.
     if (XRE_IsParentProcess()) {
       aTransferable->GetTransferData(kImageRequestMime,
-                                     getter_AddRefs(tmp));
+                                     getter_AddRefs(tmp), &dataSize);
       supportsString = do_QueryInterface(tmp);
       if (!supportsString)
         return NS_ERROR_FAILURE;
 
       nsAutoString imageRequestMime;
       supportsString->GetData(imageRequestMime);
 
       // If we have a MIME type, check the extension is compatible
@@ -319,18 +323,19 @@ nsContentAreaDragDropDataProvider::GetFl
     // make the filename safe for the filesystem
     targetFilename.ReplaceChar(FILE_PATH_SEPARATOR FILE_ILLEGAL_CHARACTERS,
                                '-');
 #endif /* defined(XP_MACOSX) */
 
     // get the target directory from the kFilePromiseDirectoryMime
     // flavor
     nsCOMPtr<nsISupports> dirPrimitive;
+    dataSize = 0;
     aTransferable->GetTransferData(kFilePromiseDirectoryMime,
-                                   getter_AddRefs(dirPrimitive));
+                                   getter_AddRefs(dirPrimitive), &dataSize);
     nsCOMPtr<nsIFile> destDirectory = do_QueryInterface(dirPrimitive);
     if (!destDirectory)
       return NS_ERROR_FAILURE;
 
     nsCOMPtr<nsIFile> file;
     rv = destDirectory->Clone(getter_AddRefs(file));
     NS_ENSURE_SUCCESS(rv, rv);
 
@@ -338,16 +343,17 @@ nsContentAreaDragDropDataProvider::GetFl
 
     bool isPrivate = aTransferable->GetIsPrivateData();
 
     nsCOMPtr<nsIPrincipal> principal = aTransferable->GetRequestingPrincipal();
     rv = SaveURIToFile(sourceURI, principal, file, isPrivate);
     // send back an nsIFile
     if (NS_SUCCEEDED(rv)) {
       CallQueryInterface(file, aData);
+      *aDataLen = sizeof(nsIFile*);
     }
   }
 
   return rv;
 }
 
 DragDataProducer::DragDataProducer(nsPIDOMWindowOuter* aWindow,
                                    nsIContent* aTarget,
@@ -783,32 +789,37 @@ DragDataProducer::Produce(DataTransfer* 
     else {
       rv = nsCopySupport::GetTransferableForNode(nodeToSerialize, doc,
                                                  getter_AddRefs(transferable));
     }
     NS_ENSURE_SUCCESS(rv, rv);
 
     nsCOMPtr<nsISupports> supports;
     nsCOMPtr<nsISupportsString> data;
-    rv = transferable->GetTransferData(kHTMLMime, getter_AddRefs(supports));
+    uint32_t dataSize;
+    rv = transferable->GetTransferData(kHTMLMime, getter_AddRefs(supports),
+                                       &dataSize);
     data = do_QueryInterface(supports);
     if (NS_SUCCEEDED(rv)) {
       data->GetData(mHtmlString);
     }
-    rv = transferable->GetTransferData(kHTMLContext, getter_AddRefs(supports));
+    rv = transferable->GetTransferData(kHTMLContext, getter_AddRefs(supports),
+                                       &dataSize);
     data = do_QueryInterface(supports);
     if (NS_SUCCEEDED(rv)) {
       data->GetData(mContextString);
     }
-    rv = transferable->GetTransferData(kHTMLInfo, getter_AddRefs(supports));
+    rv = transferable->GetTransferData(kHTMLInfo, getter_AddRefs(supports),
+                                       &dataSize);
     data = do_QueryInterface(supports);
     if (NS_SUCCEEDED(rv)) {
       data->GetData(mInfoString);
     }
-    rv = transferable->GetTransferData(kUnicodeMime, getter_AddRefs(supports));
+    rv = transferable->GetTransferData(kUnicodeMime, getter_AddRefs(supports),
+                                       &dataSize);
     data = do_QueryInterface(supports);
     NS_ENSURE_SUCCESS(rv, rv); // require plain text at a minimum
     data->GetData(mTitleString);
   }
 
   // default text value is the URL
   if (mTitleString.IsEmpty()) {
     mTitleString = mUrlString;
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -7750,40 +7750,41 @@ nsContentUtils::IPCTransferableToTransfe
       nsCOMPtr<nsISupportsString> dataWrapper =
         do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID, &rv);
       NS_ENSURE_SUCCESS(rv, rv);
 
       const nsString& text = item.data().get_nsString();
       rv = dataWrapper->SetData(text);
       NS_ENSURE_SUCCESS(rv, rv);
 
-      rv = aTransferable->SetTransferData(item.flavor().get(), dataWrapper);
+      rv = aTransferable->SetTransferData(item.flavor().get(), dataWrapper,
+                                  text.Length() * sizeof(char16_t));
 
       NS_ENSURE_SUCCESS(rv, rv);
     } else if (item.data().type() == IPCDataTransferData::TShmem) {
       if (nsContentUtils::IsFlavorImage(item.flavor())) {
         nsCOMPtr<imgIContainer> imageContainer;
         rv = nsContentUtils::DataTransferItemToImage(item,
                                                      getter_AddRefs(imageContainer));
         NS_ENSURE_SUCCESS(rv, rv);
 
-        aTransferable->SetTransferData(item.flavor().get(), imageContainer);
+        aTransferable->SetTransferData(item.flavor().get(), imageContainer, sizeof(nsISupports*));
       } else {
         nsCOMPtr<nsISupportsCString> dataWrapper =
           do_CreateInstance(NS_SUPPORTS_CSTRING_CONTRACTID, &rv);
         NS_ENSURE_SUCCESS(rv, rv);
 
         // The buffer contains the terminating null.
         Shmem itemData = item.data().get_Shmem();
         const nsDependentCSubstring text(itemData.get<char>(),
                                          itemData.Size<char>());
         rv = dataWrapper->SetData(text);
         NS_ENSURE_SUCCESS(rv, rv);
 
-        rv = aTransferable->SetTransferData(item.flavor().get(), dataWrapper);
+        rv = aTransferable->SetTransferData(item.flavor().get(), dataWrapper, text.Length());
 
         NS_ENSURE_SUCCESS(rv, rv);
       }
 
       if (aContentParent) {
         Unused << aContentParent->DeallocShmem(item.data().get_Shmem());
       } else if (aTabChild) {
         Unused << aTabChild->DeallocShmem(item.data().get_Shmem());
@@ -7988,17 +7989,18 @@ nsContentUtils::TransferableToIPCTransfe
 
     for (uint32_t j = 0; j < flavorList.Length(); ++j) {
       nsCString& flavorStr = flavorList[j];
       if (!flavorStr.Length()) {
         continue;
       }
 
       nsCOMPtr<nsISupports> data;
-      aTransferable->GetTransferData(flavorStr.get(), getter_AddRefs(data));
+      uint32_t dataLen = 0;
+      aTransferable->GetTransferData(flavorStr.get(), getter_AddRefs(data), &dataLen);
 
       nsCOMPtr<nsISupportsString> text = do_QueryInterface(data);
       nsCOMPtr<nsISupportsCString> ctext = do_QueryInterface(data);
       if (text) {
         nsAutoString dataAsString;
         text->GetData(dataAsString);
         IPCDataTransferItem* item = aIPCDataTransfer->items().AppendElement();
         item->flavor() = flavorStr;
--- a/dom/base/nsCopySupport.cpp
+++ b/dom/base/nsCopySupport.cpp
@@ -410,17 +410,18 @@ nsCopySupport::ImageCopy(nsIImageLoading
     NS_ENSURE_TRUE(image, NS_ERROR_FAILURE);
 
 #ifdef XP_WIN
     rv = AppendImagePromise(trans, imgRequest, aImageElement);
     NS_ENSURE_SUCCESS(rv, rv);
 #endif
 
     // copy the image data onto the transferable
-    rv = trans->SetTransferData(kNativeImageMime, image);
+    rv = trans->SetTransferData(kNativeImageMime, image,
+                                sizeof(nsISupports*));
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   // get clipboard
   nsCOMPtr<nsIClipboard> clipboard(do_GetService(kCClipboardCID, &rv));
   NS_ENSURE_SUCCESS(rv, rv);
 
   // check whether the system supports the selection clipboard or not.
@@ -448,17 +449,18 @@ static nsresult AppendString(nsITransfer
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = data->SetData(aString);
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = aTransferable->AddDataFlavor(aFlavor);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  return aTransferable->SetTransferData(aFlavor, data);
+  return aTransferable->SetTransferData(aFlavor, data,
+                                        aString.Length() * sizeof(char16_t));
 }
 
 static nsresult AppendDOMNode(nsITransferable *aTransferable,
                               nsINode *aDOMNode)
 {
   nsresult rv;
 
   // serializer
--- a/dom/base/test/copypaste.js
+++ b/dom/base/test/copypaste.js
@@ -80,17 +80,17 @@ async function testCopyPaste (isXHTML) {
   }
   function getClipboardData(mime) {
     var transferable = SpecialPowers.Cc['@mozilla.org/widget/transferable;1']
                                     .createInstance(SpecialPowers.Ci.nsITransferable);
     transferable.init(getLoadContext());
     transferable.addDataFlavor(mime);
     clipboard.getData(transferable, 1);
     var data = SpecialPowers.createBlankObject();
-    transferable.getTransferData(mime, data) ;
+    transferable.getTransferData(mime, data, {}) ;
     return data;
   }
   function testHtmlClipboardValue(mime, expected) {
     // For Windows, navigator.platform returns "Win32".
     var expectedValue = expected;
     if (navigator.platform.includes("Win")) {
       // Windows has extra content.
       var expectedValue = "<html><body>\n<!--StartFragment-->" +
--- a/dom/base/test/test_bug166235.html
+++ b/dom/base/test/test_bug166235.html
@@ -55,17 +55,17 @@ https://bugzilla.mozilla.org/show_bug.cg
   }
   function getClipboardData(mime) {
     var transferable = Cc['@mozilla.org/widget/transferable;1']
                          .createInstance(SpecialPowers.Ci.nsITransferable);
     transferable.init(getLoadContext());
     transferable.addDataFlavor(mime);
     clipboard.getData(transferable, 1);
     var data = SpecialPowers.createBlankObject();
-    transferable.getTransferData(mime, data) ;
+    transferable.getTransferData(mime, data, {}) ;
     return SpecialPowers.wrap(data);
   }
   function testHtmlClipboardValue(mime, expected, test) {
     var expectedValue = expected;
     // For Windows, navigator.platform returns "Win32".
     if (navigator.platform.includes("Win")) {
       expectedValue = "<html><body>\n<!--StartFragment-->" + expected + "<!--EndFragment-->\n</body>\n</html>";
     }
--- a/dom/base/test/test_copyimage.html
+++ b/dom/base/test/test_copyimage.html
@@ -27,17 +27,17 @@ function testCopyImage () {
     var transferable = Cc['@mozilla.org/widget/transferable;1']
                        .createInstance(Ci.nsITransferable);
     var loadingContext = SpecialPowers.wrap(window).docShell
                                       .QueryInterface(Ci.nsILoadContext);
     transferable.init(loadingContext);
     transferable.addDataFlavor(mime);
     clipboard.getData(transferable, 1);
     var data = SpecialPowers.createBlankObject();
-    transferable.getTransferData(mime, data);
+    transferable.getTransferData(mime, data, {});
     return data;
   }
 
   function testClipboardValue(mime, expected) {
     var data = SpecialPowers.wrap(getClipboardData(mime));
     var str = data.value == null ? data.value :
               data.value.QueryInterface(Ci.nsISupportsString).data;
     is(str, expected, "clipboard has correct [" + mime + "] content")
--- a/dom/events/DataTransfer.cpp
+++ b/dom/events/DataTransfer.cpp
@@ -1071,17 +1071,18 @@ DataTransfer::GetTransferable(uint32_t a
 
               nsCString str;
               stringBuffer->ToString(totalCustomLength, str);
               nsCOMPtr<nsISupportsCString>
                 strSupports(do_CreateInstance(NS_SUPPORTS_CSTRING_CONTRACTID));
               strSupports->SetData(str);
 
               nsresult rv = transferable->SetTransferData(kCustomTypesMime,
-                                                          strSupports);
+                                                          strSupports,
+                                                          totalCustomLength);
               if (NS_FAILED(rv)) {
                 return nullptr;
               }
 
               added = true;
             }
           }
         }
@@ -1111,17 +1112,18 @@ DataTransfer::GetTransferable(uint32_t a
         nsCOMPtr<nsIFormatConverter> converter =
           do_QueryInterface(convertedData);
         if (converter) {
           transferable->AddDataFlavor(format);
           transferable->SetConverter(converter);
           continue;
         }
 
-        nsresult rv = transferable->SetTransferData(format, convertedData);
+        nsresult rv = transferable->SetTransferData(format, convertedData,
+                                                    lengthInBytes);
         if (NS_FAILED(rv)) {
           return nullptr;
         }
 
         added = true;
       }
     }
 
--- a/dom/events/DataTransferItem.cpp
+++ b/dom/events/DataTransferItem.cpp
@@ -174,18 +174,19 @@ DataTransferItem::FillInExternalData()
     }
 
     nsresult rv = dragSession->GetData(trans, mIndex);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return;
     }
   }
 
+  uint32_t length = 0;
   nsCOMPtr<nsISupports> data;
-  nsresult rv = trans->GetTransferData(format, getter_AddRefs(data));
+  nsresult rv = trans->GetTransferData(format, getter_AddRefs(data), &length);
   if (NS_WARN_IF(NS_FAILED(rv) || !data)) {
     return;
   }
 
   // Fill the variant
   RefPtr<nsVariantCC> variant = new nsVariantCC();
 
   eKind oldKind = Kind();
--- a/editor/libeditor/HTMLEditorDataTransfer.cpp
+++ b/editor/libeditor/HTMLEditorDataTransfer.cpp
@@ -1580,48 +1580,57 @@ HTMLEditor::PasteInternal(int32_t aClipb
   // also get additional html copy hints, if present
   nsAutoString contextStr, infoStr;
 
   // If we have our internal html flavor on the clipboard, there is special
   // context to use instead of cfhtml context.
   bool bHavePrivateHTMLFlavor = HavePrivateHTMLFlavor(clipboard);
   if (bHavePrivateHTMLFlavor) {
     nsCOMPtr<nsISupports> contextDataObj, infoDataObj;
+    uint32_t contextLen, infoLen;
     nsCOMPtr<nsISupportsString> textDataObj;
 
     nsCOMPtr<nsITransferable> contextTransferable =
       do_CreateInstance("@mozilla.org/widget/transferable;1");
     if (NS_WARN_IF(!contextTransferable)) {
       return NS_ERROR_FAILURE;
     }
     contextTransferable->Init(nullptr);
     contextTransferable->AddDataFlavor(kHTMLContext);
     clipboard->GetData(contextTransferable, aClipboardType);
     contextTransferable->GetTransferData(kHTMLContext,
-                                         getter_AddRefs(contextDataObj));
+                                         getter_AddRefs(contextDataObj),
+                                         &contextLen);
 
     nsCOMPtr<nsITransferable> infoTransferable =
       do_CreateInstance("@mozilla.org/widget/transferable;1");
     if (NS_WARN_IF(!infoTransferable)) {
       return NS_ERROR_FAILURE;
     }
     infoTransferable->Init(nullptr);
     infoTransferable->AddDataFlavor(kHTMLInfo);
     clipboard->GetData(infoTransferable, aClipboardType);
     infoTransferable->GetTransferData(kHTMLInfo,
-                                      getter_AddRefs(infoDataObj));
+                                      getter_AddRefs(infoDataObj),
+                                      &infoLen);
 
     if (contextDataObj) {
+      nsAutoString text;
       textDataObj = do_QueryInterface(contextDataObj);
-      textDataObj->GetData(contextStr);
+      textDataObj->GetData(text);
+      MOZ_ASSERT(text.Length() <= contextLen / 2);
+      contextStr.Assign(text.get(), contextLen / 2);
     }
 
     if (infoDataObj) {
+      nsAutoString text;
       textDataObj = do_QueryInterface(infoDataObj);
-      textDataObj->GetData(infoStr);
+      textDataObj->GetData(text);
+      MOZ_ASSERT(text.Length() <= infoLen / 2);
+      infoStr.Assign(text.get(), infoLen / 2);
     }
   }
 
   rv = InsertFromTransferable(transferable, nullptr, contextStr, infoStr,
                               bHavePrivateHTMLFlavor, true);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
@@ -1780,18 +1789,20 @@ HTMLEditor::CanPasteTransferable(nsITran
     length = ArrayLength(textEditorFlavors);
   } else {
     flavors = textHtmlEditorFlavors;
     length = ArrayLength(textHtmlEditorFlavors);
   }
 
   for (size_t i = 0; i < length; i++, flavors++) {
     nsCOMPtr<nsISupports> data;
+    uint32_t dataLen;
     nsresult rv = aTransferable->GetTransferData(*flavors,
-                                                 getter_AddRefs(data));
+                                                 getter_AddRefs(data),
+                                                 &dataLen);
     if (NS_SUCCEEDED(rv) && data) {
       return true;
     }
   }
 
   return false;
 }
 
--- a/editor/libeditor/TextEditorDataTransfer.cpp
+++ b/editor/libeditor/TextEditorDataTransfer.cpp
@@ -460,18 +460,20 @@ TextEditor::CanPasteTransferable(nsITran
   }
 
   // If |aTransferable| is null, assume that a paste will succeed.
   if (!aTransferable) {
     return true;
   }
 
   nsCOMPtr<nsISupports> data;
+  uint32_t dataLen;
   nsresult rv = aTransferable->GetTransferData(kUnicodeMime,
-                                               getter_AddRefs(data));
+                                               getter_AddRefs(data),
+                                               &dataLen);
   if (NS_SUCCEEDED(rv) && data) {
     return true;
   }
 
   return false;
 }
 
 bool
--- a/editor/libeditor/tests/test_CF_HTML_clipboard.html
+++ b/editor/libeditor/tests/test_CF_HTML_clipboard.html
@@ -50,17 +50,17 @@ function copyCF_HTML(cfhtml, success, fa
 
     var trans = Cc["@mozilla.org/widget/transferable;1"].
                 createInstance(Ci.nsITransferable);
     trans.init(getLoadContext());
     trans.addDataFlavor(CF_HTML);
     cb.getData(trans, cb.kGlobalClipboard);
     var data = SpecialPowers.createBlankObject();
     try {
-      trans.getTransferData(CF_HTML, data);
+      trans.getTransferData(CF_HTML, data, {});
       data = SpecialPowers.wrap(data).value.QueryInterface(Ci.nsISupportsCString).data;
     } catch (e) {
       setTimeout(function() { copyCF_HTML_worker(successFn, failureFn); }, 100);
       return;
     }
     success();
   }
 
--- a/testing/specialpowers/content/specialpowersAPI.js
+++ b/testing/specialpowers/content/specialpowersAPI.js
@@ -1789,17 +1789,17 @@ SpecialPowersAPI.prototype = {
     // for some non-e10s mochi tests, |window| is null whereas |content.window|
     // works fine.  So we take whatever is non-null!
     xferable.init(this._getDocShell(typeof(window) == "undefined" ? this.mm.content.window : window)
                       .QueryInterface(Ci.nsILoadContext));
     xferable.addDataFlavor(flavor);
     Services.clipboard.getData(xferable, whichClipboard);
     var data = {};
     try {
-      xferable.getTransferData(flavor, data);
+      xferable.getTransferData(flavor, data, {});
     } catch (e) {}
     data = data.value || null;
     if (data == null)
       return "";
 
     return data.QueryInterface(Ci.nsISupportsString).data;
   },
 
--- a/toolkit/modules/Finder.jsm
+++ b/toolkit/modules/Finder.jsm
@@ -606,17 +606,18 @@ function GetClipboardSearchString(aLoadC
     let trans = Cc["@mozilla.org/widget/transferable;1"]
                   .createInstance(Ci.nsITransferable);
     trans.init(aLoadContext);
     trans.addDataFlavor("text/unicode");
 
     Clipboard.getData(trans, Ci.nsIClipboard.kFindClipboard);
 
     let data = {};
-    trans.getTransferData("text/unicode", data);
+    let dataLen = {};
+    trans.getTransferData("text/unicode", data, dataLen);
     if (data.value) {
       data = data.value.QueryInterface(Ci.nsISupportsString);
       searchString = data.toString();
     }
   } catch (ex) {}
 
   return searchString;
 }
--- a/toolkit/mozapps/extensions/internal/AddonRepository.jsm
+++ b/toolkit/mozapps/extensions/internal/AddonRepository.jsm
@@ -86,17 +86,18 @@ function convertHTMLToPlainText(html) {
   var converter = Cc["@mozilla.org/widget/htmlformatconverter;1"].
                   createInstance(Ci.nsIFormatConverter);
 
   var input = Cc["@mozilla.org/supports-string;1"].
               createInstance(Ci.nsISupportsString);
   input.data = html.replace(/\n/g, "<br>");
 
   var output = {};
-  converter.convert("text/html", input, "text/unicode", output);
+  converter.convert("text/html", input, input.data.length, "text/unicode",
+                    output, {});
 
   if (output.value instanceof Ci.nsISupportsString)
     return output.value.data.replace(/\r\n/g, "\n");
   return html;
 }
 
 async function getAddonsToCache(aIds) {
   let types = Preferences.get(PREF_GETADDONS_CACHE_TYPES) || DEFAULT_CACHE_TYPES;
--- a/widget/android/nsClipboard.cpp
+++ b/widget/android/nsClipboard.cpp
@@ -28,17 +28,19 @@ nsClipboard::nsClipboard()
 NS_IMETHODIMP
 nsClipboard::SetData(nsITransferable *aTransferable,
                      nsIClipboardOwner *anOwner, int32_t aWhichClipboard)
 {
   if (aWhichClipboard != kGlobalClipboard)
     return NS_ERROR_NOT_IMPLEMENTED;
 
   nsCOMPtr<nsISupports> tmp;
-  nsresult rv  = aTransferable->GetTransferData(kUnicodeMime, getter_AddRefs(tmp));
+  uint32_t len;
+  nsresult rv  = aTransferable->GetTransferData(kUnicodeMime, getter_AddRefs(tmp),
+                                                &len);
   NS_ENSURE_SUCCESS(rv, rv);
   nsCOMPtr<nsISupportsString> supportsString = do_QueryInterface(tmp);
   // No support for non-text data
   NS_ENSURE_TRUE(supportsString, NS_ERROR_NOT_IMPLEMENTED);
   nsAutoString buffer;
   supportsString->GetData(buffer);
 
   java::Clipboard::SetText(java::GeckoAppShell::GetApplicationContext(),
@@ -66,17 +68,18 @@ nsClipboard::GetData(nsITransferable *aT
   rv = dataWrapper->SetData(buffer);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // If our data flavor has already been added, this will fail. But we don't care
   aTransferable->AddDataFlavor(kUnicodeMime);
 
   nsCOMPtr<nsISupports> nsisupportsDataWrapper =
     do_QueryInterface(dataWrapper);
-  rv = aTransferable->SetTransferData(kUnicodeMime, nsisupportsDataWrapper);
+  rv = aTransferable->SetTransferData(kUnicodeMime, nsisupportsDataWrapper,
+                                      buffer.Length() * sizeof(char16_t));
   NS_ENSURE_SUCCESS(rv, rv);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsClipboard::EmptyClipboard(int32_t aWhichClipboard)
 {
--- a/widget/cocoa/nsChildView.mm
+++ b/widget/cocoa/nsChildView.mm
@@ -6246,23 +6246,25 @@ provideDataForType:(NSString*)aType
         for (uint32_t i = 0; i < transferableCount; i++) {
           nsCOMPtr<nsITransferable> item =
             do_QueryElementAt(gDraggedTransferables, i);
           if (!item) {
             NS_ERROR("no transferable");
             continue;
           }
 
-          item->SetTransferData(kFilePromiseDirectoryMime, macLocalFile);
+          item->SetTransferData(kFilePromiseDirectoryMime, macLocalFile,
+                                sizeof(nsIFile*));
 
           // Now request the kFilePromiseMime data, which will invoke the data
           // provider. If successful, the file will have been created.
           nsCOMPtr<nsISupports> fileDataPrimitive;
+          uint32_t dataSize = 0;
           item->GetTransferData(kFilePromiseMime,
-                                getter_AddRefs(fileDataPrimitive));
+                                getter_AddRefs(fileDataPrimitive), &dataSize);
         }
         CFRelease(urlRef);
         CFRelease(pboardRef);
 
         [aPasteboard setPropertyList:[pasteboardOutputDict valueForKey:curType]
                              forType:curType];
       }
     }
--- a/widget/cocoa/nsClipboard.mm
+++ b/widget/cocoa/nsClipboard.mm
@@ -234,17 +234,17 @@ nsClipboard::TransferableFromPasteboard(
            (clipboardDataPtrNoBOM[0] == 0xFFFE))) {
         dataLength -= sizeof(char16_t);
         clipboardDataPtrNoBOM += 1;
       }
 
       nsCOMPtr<nsISupports> genericDataWrapper;
       nsPrimitiveHelpers::CreatePrimitiveForData(flavorStr, clipboardDataPtrNoBOM, dataLength,
                                                  getter_AddRefs(genericDataWrapper));
-      aTransferable->SetTransferData(flavorStr.get(), genericDataWrapper);
+      aTransferable->SetTransferData(flavorStr.get(), genericDataWrapper, dataLength);
       free(clipboardDataPtr);
       break;
     }
     else if (flavorStr.EqualsLiteral(kCustomTypesMime)) {
       NSString* type =
         [cocoaPasteboard availableTypeFromArray:
           [NSArray arrayWithObject:
             [UTIHelper stringFromPboardType:kMozCustomTypesPboardType]]];
@@ -264,17 +264,17 @@ nsClipboard::TransferableFromPasteboard(
         return NS_ERROR_OUT_OF_MEMORY;
       }
       [pasteboardData getBytes:clipboardDataPtr];
 
       nsCOMPtr<nsISupports> genericDataWrapper;
       nsPrimitiveHelpers::CreatePrimitiveForData(flavorStr, clipboardDataPtr, dataLength,
                                                  getter_AddRefs(genericDataWrapper));
 
-      aTransferable->SetTransferData(flavorStr.get(), genericDataWrapper);
+      aTransferable->SetTransferData(flavorStr.get(), genericDataWrapper, dataLength);
       free(clipboardDataPtr);
     }
     else if (flavorStr.EqualsLiteral(kJPEGImageMime) ||
              flavorStr.EqualsLiteral(kJPGImageMime) ||
              flavorStr.EqualsLiteral(kPNGImageMime) ||
              flavorStr.EqualsLiteral(kGIFImageMime)) {
       // Figure out if there's data on the pasteboard we can grab (sanity check)
       NSString* type =
@@ -331,17 +331,17 @@ nsClipboard::TransferableFromPasteboard(
       bool successfullyConverted = CGImageDestinationFinalize(dest);
 
       if (successfullyConverted) {
         // Put the converted data in a form Gecko can understand
         nsCOMPtr<nsIInputStream> byteStream;
         NS_NewByteInputStream(getter_AddRefs(byteStream), (const char*)[encodedData bytes],
                                    [encodedData length], NS_ASSIGNMENT_COPY);
   
-        aTransferable->SetTransferData(flavorStr.get(), byteStream);
+        aTransferable->SetTransferData(flavorStr.get(), byteStream, sizeof(nsIInputStream*));
       }
 
       if (dest)
         CFRelease(dest);
       if (source)
         CFRelease(source);
       
       if (successfullyConverted)
@@ -384,19 +384,20 @@ nsClipboard::GetNativeClipboardData(nsIT
   // transferable. Otherwise clear it because it isn't relevant any more.
   if (mCachedClipboard == aWhichClipboard &&
       mChangeCount == [cocoaPasteboard changeCount]) {
     if (mTransferable) {
       for (uint32_t i = 0; i < flavors.Length(); i++) {
         nsCString& flavorStr = flavors[i];
 
         nsCOMPtr<nsISupports> dataSupports;
-        rv = mTransferable->GetTransferData(flavorStr.get(), getter_AddRefs(dataSupports));
+        uint32_t dataSize = 0;
+        rv = mTransferable->GetTransferData(flavorStr.get(), getter_AddRefs(dataSupports), &dataSize);
         if (NS_SUCCEEDED(rv)) {
-          aTransferable->SetTransferData(flavorStr.get(), dataSupports);
+          aTransferable->SetTransferData(flavorStr.get(), dataSupports, dataSize);
           return NS_OK; // maybe try to fill in more types? Is there a point?
         }
       }
     }
   } else {
     EmptyClipboard(aWhichClipboard);
   }
 
@@ -511,18 +512,19 @@ nsClipboard::PasteboardDictFromTransfera
   for (uint32_t i = 0; i < flavors.Length(); i++) {
     nsCString& flavorStr = flavors[i];
 
     MOZ_LOG(sCocoaLog, LogLevel::Info, ("writing out clipboard data of type %s (%d)\n", flavorStr.get(), i));
 
     NSString *pboardType = nil;
 
     if (nsClipboard::IsStringType(flavorStr, &pboardType)) {
+      uint32_t dataSize = 0;
       nsCOMPtr<nsISupports> genericDataWrapper;
-      rv = aTransferable->GetTransferData(flavorStr.get(), getter_AddRefs(genericDataWrapper));
+      rv = aTransferable->GetTransferData(flavorStr.get(), getter_AddRefs(genericDataWrapper), &dataSize);
       if (NS_FAILED(rv)) {
         [pboardType release];
         continue;
       }
 
       nsAutoString data;
       if (nsCOMPtr<nsISupportsString> text = do_QueryInterface(genericDataWrapper)) {
         text->GetData(data);
@@ -535,18 +537,19 @@ nsClipboard::PasteboardDictFromTransfera
         nativeString = [NSString string];
 
       // be nice to Carbon apps, normalize the receiver's contents using Form C.
       nativeString = [nativeString precomposedStringWithCanonicalMapping];
 
       [pasteboardOutputDict setObject:nativeString forKey:pboardType];
     }
     else if (flavorStr.EqualsLiteral(kCustomTypesMime)) {
+      uint32_t dataSize = 0;
       nsCOMPtr<nsISupports> genericDataWrapper;
-      rv = aTransferable->GetTransferData(flavorStr.get(), getter_AddRefs(genericDataWrapper));
+      rv = aTransferable->GetTransferData(flavorStr.get(), getter_AddRefs(genericDataWrapper), &dataSize);
       if (NS_FAILED(rv)) {
         continue;
       }
 
       nsAutoCString data;
       if (nsCOMPtr<nsISupportsCString> text = do_QueryInterface(genericDataWrapper)) {
         text->GetData(data);
       }
@@ -556,18 +559,19 @@ nsClipboard::PasteboardDictFromTransfera
         NSString* customType =
           [UTIHelper stringFromPboardType:kMozCustomTypesPboardType];
         [pasteboardOutputDict setObject:nativeData forKey:customType];
       }
     }
     else if (flavorStr.EqualsLiteral(kPNGImageMime) || flavorStr.EqualsLiteral(kJPEGImageMime) ||
              flavorStr.EqualsLiteral(kJPGImageMime) || flavorStr.EqualsLiteral(kGIFImageMime) ||
              flavorStr.EqualsLiteral(kNativeImageMime)) {
+      uint32_t dataSize = 0;
       nsCOMPtr<nsISupports> transferSupports;
-      aTransferable->GetTransferData(flavorStr.get(), getter_AddRefs(transferSupports));
+      aTransferable->GetTransferData(flavorStr.get(), getter_AddRefs(transferSupports), &dataSize);
 
       nsCOMPtr<imgIContainer> image(do_QueryInterface(transferSupports));
       if (!image) {
         NS_WARNING("Image isn't an imgIContainer in transferable");
         continue;
       }
 
       RefPtr<SourceSurface> surface =
@@ -604,18 +608,19 @@ nsClipboard::PasteboardDictFromTransfera
       NSString* tiffType =
         [UTIHelper stringFromPboardType:NSPasteboardTypeTIFF];
       [pasteboardOutputDict setObject:(NSMutableData*)tiffData
                                forKey:tiffType];
       if (tiffData)
         CFRelease(tiffData);
     }
     else if (flavorStr.EqualsLiteral(kFileMime)) {
+      uint32_t len = 0;
       nsCOMPtr<nsISupports> genericFile;
-      rv = aTransferable->GetTransferData(flavorStr.get(), getter_AddRefs(genericFile));
+      rv = aTransferable->GetTransferData(flavorStr.get(), getter_AddRefs(genericFile), &len);
       if (NS_FAILED(rv)) {
         continue;
       }
 
       nsCOMPtr<nsIFile> file(do_QueryInterface(genericFile));
       if (!file) {
         continue;
       }
@@ -641,34 +646,35 @@ nsClipboard::PasteboardDictFromTransfera
         [UTIHelper stringFromPboardType:
           (NSString*)kPasteboardTypeFilePromiseContent];
       [pasteboardOutputDict setObject:[NSArray arrayWithObject:@""]
                                forKey:urlPromise];
       [pasteboardOutputDict setObject:[NSArray arrayWithObject:@""]
                                forKey:urlPromiseContent];
     }
     else if (flavorStr.EqualsLiteral(kURLMime)) {
+      uint32_t len = 0;
       nsCOMPtr<nsISupports> genericURL;
-      rv = aTransferable->GetTransferData(flavorStr.get(), getter_AddRefs(genericURL));
+      rv = aTransferable->GetTransferData(flavorStr.get(), getter_AddRefs(genericURL), &len);
       nsCOMPtr<nsISupportsString> urlObject(do_QueryInterface(genericURL));
 
       nsAutoString url;
       urlObject->GetData(url);
 
       NSString* nativeTitle = nil;
 
       // A newline embedded in the URL means that the form is actually URL +
       // title. This embedding occurs in nsDragService::GetData.
       int32_t newlinePos = url.FindChar(char16_t('\n'));
       if (newlinePos >= 0) {
         url.Truncate(newlinePos);
 
         nsAutoString urlTitle;
         urlObject->GetData(urlTitle);
-        urlTitle.Mid(urlTitle, newlinePos + 1, urlTitle.Length() - (newlinePos + 1));
+        urlTitle.Mid(urlTitle, newlinePos + 1, len - (newlinePos + 1));
 
         nativeTitle =
           [NSString stringWithCharacters:
             reinterpret_cast<const unichar*>(urlTitle.get())
                                   length:urlTitle.Length()];
       }
       // The Finder doesn't like getting random binary data aka
       // Unicode, so change it into an escaped URL containing only
--- a/widget/cocoa/nsDragService.mm
+++ b/widget/cocoa/nsDragService.mm
@@ -388,19 +388,20 @@ nsDragService::GetData(nsITransferable* 
   // when the drag started if possible
   if (mDataItems) {
     nsCOMPtr<nsITransferable> currentTransferable = do_QueryElementAt(mDataItems, aItemIndex);
     if (currentTransferable) {
       for (uint32_t i = 0; i < flavors.Length(); i++) {
         nsCString& flavorStr = flavors[i];
 
         nsCOMPtr<nsISupports> dataSupports;
-        rv = currentTransferable->GetTransferData(flavorStr.get(), getter_AddRefs(dataSupports));
+        uint32_t dataSize = 0;
+        rv = currentTransferable->GetTransferData(flavorStr.get(), getter_AddRefs(dataSupports), &dataSize);
         if (NS_SUCCEEDED(rv)) {
-          aTransferable->SetTransferData(flavorStr.get(), dataSupports);
+          aTransferable->SetTransferData(flavorStr.get(), dataSupports, dataSize);
           return NS_OK; // maybe try to fill in more types? Is there a point?
         }
       }
     }
   }
 
   // now check the actual clipboard for data
   for (uint32_t i = 0; i < flavors.Length(); i++) {
@@ -437,17 +438,17 @@ nsDragService::GetData(nsITransferable* 
       clipboardDataPtr[stringLength] = 0; // null terminate
 
       nsCOMPtr<nsIFile> file;
       rv = NS_NewLocalFile(nsDependentString(clipboardDataPtr), true, getter_AddRefs(file));
       free(clipboardDataPtr);
       if (NS_FAILED(rv))
         continue;
 
-      aTransferable->SetTransferData(flavorStr.get(), file);
+      aTransferable->SetTransferData(flavorStr.get(), file, dataLength);
       
       break;
     }
     else if (flavorStr.EqualsLiteral(kCustomTypesMime)) {
       NSString* availableType =
         [item availableTypeFromArray:
           [NSArray arrayWithObject:kMozCustomTypesPboardType]];
       if (!availableType || !IsValidType(availableType, false)) {
@@ -464,17 +465,17 @@ nsDragService::GetData(nsITransferable* 
         return NS_ERROR_OUT_OF_MEMORY;
       }
       [pasteboardData getBytes:clipboardDataPtr];
 
       nsCOMPtr<nsISupports> genericDataWrapper;
       nsPrimitiveHelpers::CreatePrimitiveForData(flavorStr, clipboardDataPtr, dataLength,
                                                  getter_AddRefs(genericDataWrapper));
 
-      aTransferable->SetTransferData(flavorStr.get(), genericDataWrapper);
+      aTransferable->SetTransferData(flavorStr.get(), genericDataWrapper, sizeof(nsIInputStream*));
       free(clipboardDataPtr);
       break;
     }
 
     NSString* pString = nil;
     if (flavorStr.EqualsLiteral(kUnicodeMime)) {
       pString =
         GetStringForType(
@@ -530,17 +531,17 @@ nsDragService::GetData(nsITransferable* 
            (clipboardDataPtrNoBOM[0] == 0xFFFE))) {
         dataLength -= sizeof(char16_t);
         clipboardDataPtrNoBOM += 1;
       }
 
       nsCOMPtr<nsISupports> genericDataWrapper;
       nsPrimitiveHelpers::CreatePrimitiveForData(flavorStr, clipboardDataPtrNoBOM, dataLength,
                                                  getter_AddRefs(genericDataWrapper));
-      aTransferable->SetTransferData(flavorStr.get(), genericDataWrapper);
+      aTransferable->SetTransferData(flavorStr.get(), genericDataWrapper, dataLength);
       free(clipboardDataPtr);
       break;
     }
 
     // We have never supported this on Mac OS X, we should someday. Normally dragging images
     // in is accomplished with a file path drag instead of the image data itself.
     /*
     if (flavorStr.EqualsLiteral(kPNGImageMime) || flavorStr.EqualsLiteral(kJPEGImageMime) ||
--- a/widget/gtk/nsClipboard.cpp
+++ b/widget/gtk/nsClipboard.cpp
@@ -231,17 +231,18 @@ nsClipboard::SetTransferableData(nsITran
                                  const char*      aClipboardData,
                                  uint32_t         aClipboardDataLength)
 {
   nsCOMPtr<nsISupports> wrapper;
   nsPrimitiveHelpers::CreatePrimitiveForData(aFlavor,
                                              aClipboardData,
                                              aClipboardDataLength,
                                              getter_AddRefs(wrapper));
-  aTransferable->SetTransferData(aFlavor.get(), wrapper);
+  aTransferable->SetTransferData(aFlavor.get(),
+                                 wrapper, aClipboardDataLength);
 }
 
 NS_IMETHODIMP
 nsClipboard::GetData(nsITransferable *aTransferable, int32_t aWhichClipboard)
 {
     if (!aTransferable)
         return NS_ERROR_FAILURE;
 
@@ -272,17 +273,18 @@ nsClipboard::GetData(nsITransferable *aT
             if (!clipboardData)
                 continue;
 
             nsCOMPtr<nsIInputStream> byteStream;
             NS_NewByteInputStream(getter_AddRefs(byteStream),
                                   clipboardData,
                                   clipboardDataLength,
                                   NS_ASSIGNMENT_COPY);
-            aTransferable->SetTransferData(flavorStr.get(), byteStream);
+            aTransferable->SetTransferData(flavorStr.get(), byteStream,
+                                           sizeof(nsIInputStream*));
 
             mContext->ReleaseClipboardData(clipboardData);
             return NS_OK;
         }
 
         // Special case text/unicode since we can convert any
         // string into text/unicode
         if (flavorStr.EqualsLiteral(kUnicodeMime)) {
@@ -468,25 +470,27 @@ nsClipboard::SelectionGetEvent(GtkClipbo
       printf("nsClipboard::SelectionGetEvent() - %s clipboard is empty!\n",
              whichClipboard == kSelectionClipboard ? "Selection" : "Global");
 #endif
       return;
     }
 
     nsresult rv;
     nsCOMPtr<nsISupports> item;
+    uint32_t len;
 
     GdkAtom selectionTarget = gtk_selection_data_get_target(aSelectionData);
 
     // Check to see if the selection data is some text type.
     if (gtk_targets_include_text(&selectionTarget, 1)) {
         // Try to convert our internal type into a text string.  Get
         // the transferable for this clipboard and try to get the
         // text/unicode type for it.
-        rv = trans->GetTransferData("text/unicode", getter_AddRefs(item));
+        rv = trans->GetTransferData("text/unicode", getter_AddRefs(item),
+                                    &len);
         if (!item || NS_FAILED(rv))
             return;
 
         nsCOMPtr<nsISupportsString> wideString;
         wideString = do_QueryInterface(item);
         if (!wideString)
             return;
 
@@ -502,17 +506,17 @@ nsClipboard::SelectionGetEvent(GtkClipbo
     // Check to see if the selection data is an image type
     if (gtk_targets_include_image(&selectionTarget, 1, TRUE)) {
         // Look through our transfer data for the image
         static const char* const imageMimeTypes[] = {
             kNativeImageMime, kPNGImageMime, kJPEGImageMime, kJPGImageMime, kGIFImageMime };
         nsCOMPtr<nsISupports> imageItem;
         nsCOMPtr<imgIContainer> image;
         for (uint32_t i = 0; i < ArrayLength(imageMimeTypes); i++) {
-            rv = trans->GetTransferData(imageMimeTypes[i], getter_AddRefs(imageItem));
+            rv = trans->GetTransferData(imageMimeTypes[i], getter_AddRefs(imageItem), &len);
             image = do_QueryInterface(imageItem);
             if (image) {
                 break;
             }
         }
 
         if (!image) { // Not getting an image for an image mime type!?
             return;
@@ -523,17 +527,17 @@ nsClipboard::SelectionGetEvent(GtkClipbo
             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));
+        rv = trans->GetTransferData(kHTMLMime, getter_AddRefs(item), &len);
         if (!item || NS_FAILED(rv)) {
             return;
         }
 
         nsCOMPtr<nsISupportsString> wideString;
         wideString = do_QueryInterface(item);
         if (!wideString) {
             return;
@@ -553,17 +557,17 @@ nsClipboard::SelectionGetEvent(GtkClipbo
     }
 
     // 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));
+    rv = trans->GetTransferData(target_name, getter_AddRefs(item), &len);
     // nothing found?
     if (!item || NS_FAILED(rv)) {
         g_free(target_name);
         return;
     }
 
     void *primitive_data = nullptr;
     uint32_t dataLen = 0;
--- a/widget/gtk/nsDragService.cpp
+++ b/widget/gtk/nsDragService.cpp
@@ -704,27 +704,30 @@ nsDragService::GetData(nsITransferable *
                    ("flavor is %s\n", flavorStr.get()));
             // get the item with the right index
             nsCOMPtr<nsITransferable> item =
                 do_QueryElementAt(mSourceDataItems, aItemIndex);
             if (!item)
                 continue;
 
             nsCOMPtr<nsISupports> data;
+            uint32_t tmpDataLen = 0;
             MOZ_LOG(sDragLm, LogLevel::Debug,
                    ("trying to get transfer data for %s\n",
                    flavorStr.get()));
             rv = item->GetTransferData(flavorStr.get(),
-                                       getter_AddRefs(data));
+                                       getter_AddRefs(data),
+                                       &tmpDataLen);
             if (NS_FAILED(rv)) {
                 MOZ_LOG(sDragLm, LogLevel::Debug, ("failed.\n"));
                 continue;
             }
             MOZ_LOG(sDragLm, LogLevel::Debug, ("succeeded.\n"));
-            rv = aTransferable->SetTransferData(flavorStr.get(), data);
+            rv = aTransferable->SetTransferData(flavorStr.get(), data,
+                                                tmpDataLen);
             if (NS_FAILED(rv)) {
                 MOZ_LOG(sDragLm,
                        LogLevel::Debug,
                        ("fail to set transfer data into transferable!\n"));
                 continue;
             }
             // ok, we got the data
             return NS_OK;
@@ -781,17 +784,18 @@ nsDragService::GetData(nsITransferable *
                                 nsCOMPtr<nsIFile> file;
                                 rv = fileURL->GetFile(getter_AddRefs(file));
                                 if (NS_SUCCEEDED(rv)) {
                                     // The common wrapping code at the end of
                                     // this function assumes the data is text
                                     // and calls text-specific operations.
                                     // Make a secret hideout here for nsIFile
                                     // objects and return early.
-                                    aTransferable->SetTransferData(flavorStr.get(), file);
+                                    aTransferable->SetTransferData(flavorStr.get(), file,
+                                                                   convertedTextLen);
                                     g_free(convertedText);
                                     return NS_OK;
                                 }
                             }
                         }
                         g_free(convertedText);
                     }
                     continue;
@@ -934,17 +938,18 @@ nsDragService::GetData(nsITransferable *
             }
 
             // put it into the transferable.
             nsCOMPtr<nsISupports> genericDataWrapper;
             nsPrimitiveHelpers::CreatePrimitiveForData(flavorStr,
                                 mTargetDragData, mTargetDragDataLen,
                                 getter_AddRefs(genericDataWrapper));
             aTransferable->SetTransferData(flavorStr.get(),
-                                           genericDataWrapper);
+                                           genericDataWrapper,
+                                           mTargetDragDataLen);
             // we found one, get out of this loop!
             MOZ_LOG(sDragLm, LogLevel::Debug, ("dataFound and converted!\n"));
             break;
         }
     }
 
     return NS_OK;
 
@@ -1480,17 +1485,19 @@ CreateURIList(nsIArray* aItems, nsACStri
 
     for (uint32_t i = 0; i < length; ++i) {
         nsCOMPtr<nsITransferable> item = do_QueryElementAt(aItems, i);
         if (!item) {
             continue;
         }
 
         nsCOMPtr<nsISupports> data;
-        nsresult rv = item->GetTransferData(kURLMime, getter_AddRefs(data));
+        uint32_t len = 0;
+        nsresult rv = item->GetTransferData(kURLMime, getter_AddRefs(data),
+                                            &len);
         if (NS_SUCCEEDED(rv)) {
             nsCOMPtr<nsISupportsString> string = do_QueryInterface(data);
 
             nsAutoString text;
             if (string) {
                 string->GetData(text);
             }
 
@@ -1503,17 +1510,17 @@ CreateURIList(nsIArray* aItems, nsACStri
 
             AppendUTF16toUTF8(text, aURIList);
             aURIList.AppendLiteral("\r\n");
             continue;
         }
 
         // There is no URI available. If there is a file available, create
         // a URI from the file.
-        rv = item->GetTransferData(kFileMime, getter_AddRefs(data));
+        rv = item->GetTransferData(kFileMime, getter_AddRefs(data), &len);
         if (NS_SUCCEEDED(rv)) {
             if (nsCOMPtr<nsIFile> file = do_QueryInterface(data)) {
                 nsCOMPtr<nsIURI> fileURI;
                 NS_NewFileURI(getter_AddRefs(fileURI), file);
                 if (fileURI) {
                     nsAutoCString spec;
                     fileURI->GetSpec(spec);
 
@@ -1643,38 +1650,42 @@ nsDragService::SourceDataGet(GtkWidget  
             }
 
             // We have to split the path into a directory and filename,
             // because our internal file-promise API is based on these.
 
             nsCOMPtr<nsIFile> directory;
             file->GetParent(getter_AddRefs(directory));
 
-            item->SetTransferData(kFilePromiseDirectoryMime, directory);
+            item->SetTransferData(kFilePromiseDirectoryMime, directory,
+                                  sizeof(nsIFile*));
 
             nsCOMPtr<nsISupportsString> filenamePrimitive =
                 do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID);
             if (!filenamePrimitive)
                 return;
 
             nsAutoString leafName;
             file->GetLeafName(leafName);
             filenamePrimitive->SetData(leafName);
 
-            item->SetTransferData(kFilePromiseDestFilename, filenamePrimitive);
+            item->SetTransferData(kFilePromiseDestFilename, filenamePrimitive,
+                                  leafName.Length() * sizeof(PRUnichar));
 
             // Request a different type in GetTransferData.
             actualFlavor = kFilePromiseMime;
         } else {
             actualFlavor = mimeFlavor.get();
         }
         nsresult rv;
         nsCOMPtr<nsISupports> data;
+        uint32_t len;
         rv = item->GetTransferData(actualFlavor,
-                                   getter_AddRefs(data));
+                                   getter_AddRefs(data),
+                                   &len);
 
         if (strcmp(actualFlavor, kFilePromiseMime) == 0) {
             if (NS_SUCCEEDED(rv)) {
                 // Indicate success.
                 gtk_selection_data_set(aSelectionData, target, 8,
                                        (guchar *)"S", 1);
             }
             return;
@@ -1734,18 +1745,19 @@ nsDragService::SourceBeginDrag(GdkDragCo
 
     nsTArray<nsCString> flavors;
     nsresult rv = transferable->FlavorsTransferableCanImport(flavors);
     NS_ENSURE_SUCCESS(rv,);
 
     for (uint32_t i = 0; i < flavors.Length(); ++i) {
         if (flavors[i].EqualsLiteral(kFilePromiseDestFilename)) {
             nsCOMPtr<nsISupports> data;
+            uint32_t dataSize = 0;
             transferable->GetTransferData(kFilePromiseDestFilename,
-                                          getter_AddRefs(data));
+                                          getter_AddRefs(data), &dataSize);
             nsCOMPtr<nsISupportsString> fileName = do_QueryInterface(data);
             if (!fileName)
                 return;
 
             nsAutoString fileNameStr;
             fileName->GetData(fileNameStr);
 
             nsCString fileNameCStr;
--- a/widget/headless/HeadlessClipboard.cpp
+++ b/widget/headless/HeadlessClipboard.cpp
@@ -27,18 +27,20 @@ HeadlessClipboard::SetData(nsITransferab
     return NS_ERROR_NOT_IMPLEMENTED;
   }
 
   // Clear out the clipboard in order to set the new data.
   EmptyClipboard(aWhichClipboard);
 
   // Only support plain text for now.
   nsCOMPtr<nsISupports> clip;
+  uint32_t len;
   nsresult rv = aTransferable->GetTransferData(kUnicodeMime,
-                                               getter_AddRefs(clip));
+                                               getter_AddRefs(clip),
+                                               &len);
   if (NS_FAILED(rv)) {
     return rv;
   }
   nsCOMPtr<nsISupportsString> wideString = do_QueryInterface(clip);
   if (!wideString) {
     return NS_ERROR_NOT_IMPLEMENTED;
   }
   nsAutoString utf16string;
@@ -59,17 +61,18 @@ HeadlessClipboard::GetData(nsITransferab
   nsresult rv;
   nsCOMPtr<nsISupportsString> dataWrapper =
     do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID, &rv);
   rv = dataWrapper->SetData(mClipboard->GetText());
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
   nsCOMPtr<nsISupports> genericDataWrapper = do_QueryInterface(dataWrapper);
-  rv = aTransferable->SetTransferData(kUnicodeMime, genericDataWrapper);
+  uint32_t len = mClipboard->GetText().Length() * sizeof(char16_t);
+  rv = aTransferable->SetTransferData(kUnicodeMime, genericDataWrapper, len);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 HeadlessClipboard::EmptyClipboard(int32_t aWhichClipboard)
--- a/widget/headless/tests/test_headless_clipboard.js
+++ b/widget/headless/tests/test_headless_clipboard.js
@@ -11,21 +11,22 @@ function getString(clipboard) {
                         .createInstance(Ci.nsITransferable);
   trans.init(null);
   trans.addDataFlavor("text/unicode");
 
   clipboard.getData(trans, Ci.nsIClipboard.kGlobalClipboard);
 
   try {
     var data = {};
-    trans.getTransferData("text/unicode", data);
+    var dataLen = {};
+    trans.getTransferData("text/unicode", data, dataLen);
 
     if (data) {
       data = data.value.QueryInterface(Ci.nsISupportsString);
-      str = data.data;
+      str = data.data.substring(0, dataLen.value / 2);
     }
   } catch (ex) {
     // If the clipboard is empty getTransferData will throw.
   }
 
   return str;
 }
 
--- a/widget/nsClipboardHelper.cpp
+++ b/widget/nsClipboardHelper.cpp
@@ -92,17 +92,18 @@ nsClipboardHelper::CopyStringToClipboard
 
   // qi the data object an |nsISupports| so that when the transferable holds
   // onto it, it will addref the correct interface.
   nsCOMPtr<nsISupports> genericData(do_QueryInterface(data, &rv));
   NS_ENSURE_SUCCESS(rv, rv);
   NS_ENSURE_TRUE(genericData, NS_ERROR_FAILURE);
 
   // set the transfer data
-  rv = trans->SetTransferData(kUnicodeMime, genericData);
+  rv = trans->SetTransferData(kUnicodeMime, genericData,
+                              aString.Length() * 2);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // put the transferable on the clipboard
   rv = clipboard->SetData(trans, nullptr, aClipboardID);
   NS_ENSURE_SUCCESS(rv, rv);
 
   return NS_OK;
 }
--- a/widget/nsClipboardProxy.cpp
+++ b/widget/nsClipboardProxy.cpp
@@ -62,44 +62,46 @@ nsClipboardProxy::GetData(nsITransferabl
       nsCOMPtr<nsISupportsString> dataWrapper =
         do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID, &rv);
       NS_ENSURE_SUCCESS(rv, rv);
 
       const nsString& data = item.data().get_nsString();
       rv = dataWrapper->SetData(data);
       NS_ENSURE_SUCCESS(rv, rv);
 
-      rv = aTransferable->SetTransferData(item.flavor().get(), dataWrapper);
+      rv = aTransferable->SetTransferData(item.flavor().get(), dataWrapper,
+                                          data.Length() * sizeof(char16_t));
       NS_ENSURE_SUCCESS(rv, rv);
     } else if (item.data().type() == IPCDataTransferData::TShmem) {
       // If this is an image, convert it into an nsIInputStream.
       const nsCString& flavor = item.flavor();
       mozilla::ipc::Shmem data = item.data().get_Shmem();
       if (flavor.EqualsLiteral(kJPEGImageMime) ||
           flavor.EqualsLiteral(kJPGImageMime) ||
           flavor.EqualsLiteral(kPNGImageMime) ||
           flavor.EqualsLiteral(kGIFImageMime)) {
         nsCOMPtr<nsIInputStream> stream;
 
         NS_NewCStringInputStream(getter_AddRefs(stream),
                                  nsDependentCSubstring(data.get<char>(), data.Size<char>()));
 
-        rv = aTransferable->SetTransferData(flavor.get(), stream);
+        rv = aTransferable->SetTransferData(flavor.get(), stream, sizeof(nsISupports*));
         NS_ENSURE_SUCCESS(rv, rv);
       } else if (flavor.EqualsLiteral(kNativeHTMLMime) ||
                  flavor.EqualsLiteral(kRTFMime) ||
                  flavor.EqualsLiteral(kCustomTypesMime)) {
         nsCOMPtr<nsISupportsCString> dataWrapper =
           do_CreateInstance(NS_SUPPORTS_CSTRING_CONTRACTID, &rv);
         NS_ENSURE_SUCCESS(rv, rv);
 
         rv = dataWrapper->SetData(nsDependentCSubstring(data.get<char>(), data.Size<char>()));
         NS_ENSURE_SUCCESS(rv, rv);
 
-        rv = aTransferable->SetTransferData(item.flavor().get(), dataWrapper);
+        rv = aTransferable->SetTransferData(item.flavor().get(), dataWrapper,
+                                            data.Size<char>());
         NS_ENSURE_SUCCESS(rv, rv);
       }
 
       mozilla::Unused << ContentChild::GetSingleton()->DeallocShmem(data);
     }
   }
 
   return NS_OK;
--- a/widget/nsHTMLFormatConverter.cpp
+++ b/widget/nsHTMLFormatConverter.cpp
@@ -97,24 +97,25 @@ nsHTMLFormatConverter::CanConvert(const 
 // accessible from JS. Currently, this only accepts HTML input, so anything else is invalid.
 //
 //XXX This method copies the data WAAAAY too many time for my liking. Grrrrrr. Mostly it's because
 //XXX we _must_ put things into nsStrings so that the parser will accept it. Lame lame lame lame. We
 //XXX also can't just get raw unicode out of the nsString, so we have to allocate heap to get
 //XXX unicode out of the string. Lame lame lame.
 //
 NS_IMETHODIMP
-nsHTMLFormatConverter::Convert(const char *aFromDataFlavor, nsISupports *aFromData,
-                               const char *aToDataFlavor, nsISupports **aToData)
+nsHTMLFormatConverter::Convert(const char *aFromDataFlavor, nsISupports *aFromData, uint32_t aDataLen,
+                               const char *aToDataFlavor, nsISupports **aToData, uint32_t *aDataToLen)
 {
-  if ( !aToData )
+  if ( !aToData || !aDataToLen )
     return NS_ERROR_INVALID_ARG;
 
   nsresult rv = NS_OK;
   *aToData = nullptr;
+  *aDataToLen = 0;
 
   if ( !nsCRT::strcmp(aFromDataFlavor, kHTMLMime) ) {
     nsAutoCString toFlavor ( aToDataFlavor );
 
     // HTML on clipboard is going to always be double byte so it will be in a primitive
     // class of nsISupportsString. Also, since the data is in two byte chunks the
     // length represents the length in 1-byte chars, so we need to divide by two.
     nsCOMPtr<nsISupportsString> dataWrapper0 ( do_QueryInterface(aFromData) );
@@ -126,30 +127,36 @@ nsHTMLFormatConverter::Convert(const cha
     dataWrapper0->GetData ( dataStr );  // COPY #1
     // note: conversion to text/plain is done inside the clipboard. we do not need to worry
     // about it here.
     if ( toFlavor.Equals(kHTMLMime) || toFlavor.Equals(kUnicodeMime) ) {
       nsresult res;
       if (toFlavor.Equals(kHTMLMime)) {
         int32_t dataLen = dataStr.Length() * 2;
         nsPrimitiveHelpers::CreatePrimitiveForData ( toFlavor, dataStr.get(), dataLen, aToData );
+        if ( *aToData )
+          *aDataToLen = dataLen;
       } else {
         nsAutoString outStr;
         res = ConvertFromHTMLToUnicode(dataStr, outStr);
         if (NS_SUCCEEDED(res)) {
           int32_t dataLen = outStr.Length() * 2;
           nsPrimitiveHelpers::CreatePrimitiveForData ( toFlavor, outStr.get(), dataLen, aToData );
+          if ( *aToData )
+            *aDataToLen = dataLen;
         }
       }
     } // else if HTML or Unicode
     else if ( toFlavor.Equals(kAOLMailMime) ) {
       nsAutoString outStr;
       if ( NS_SUCCEEDED(ConvertFromHTMLToAOLMail(dataStr, outStr)) ) {
         int32_t dataLen = outStr.Length() * 2;
         nsPrimitiveHelpers::CreatePrimitiveForData ( toFlavor, outStr.get(), dataLen, aToData );
+        if ( *aToData )
+          *aDataToLen = dataLen;
       }
     } // else if AOL mail
     else {
       rv = NS_ERROR_FAILURE;
     }
   } // if we got html mime
   else
     rv = NS_ERROR_FAILURE;
--- a/widget/nsIFormatConverter.idl
+++ b/widget/nsIFormatConverter.idl
@@ -34,17 +34,17 @@ interface nsIFormatConverter : nsISuppor
 
   /**
     * Converts from one flavor to another.
     *
     * @param  aFromFormatConverter flavor to convert from
     * @param  aFromFormatConverter flavor to convert to (destination own the memory)
     * @returns returns NS_OK if it was converted
     */
-  void convert ( in string aFromDataFlavor, in nsISupports aFromData,
-                   in string aToDataFlavor, out nsISupports aToData ) ; 
+  void convert ( in string aFromDataFlavor, in nsISupports aFromData, in unsigned long aDataLen,
+                   in string aToDataFlavor, out nsISupports aToData, out unsigned long aDataToLen ) ; 
 
 };
 
 
 %{ C++
 
 %}
--- a/widget/nsITransferable.idl
+++ b/widget/nsITransferable.idl
@@ -81,18 +81,19 @@ interface nsIFlavorDataProvider : nsISup
 {
 
   /**
     * Retrieve the data from this data provider.
     *
     * @param  aTransferable (in parameter) the transferable we're being called for.
     * @param  aFlavor (in parameter) the flavor of data to retrieve
     * @param  aData the data. Some variant of class in nsISupportsPrimitives.idl
+    * @param  aDataLen the length of the data
     */
-  void getFlavorData(in nsITransferable aTransferable, in string aFlavor, out nsISupports aData);
+  void getFlavorData(in nsITransferable aTransferable, in string aFlavor, out nsISupports aData, out unsigned long aDataLen);
 };
 
 
 [scriptable, uuid(97e0c418-1c1e-4106-bad1-9fcb11dff2fe)]
 interface nsITransferable : nsISupports
 {
   /**
    * Initializes a transferable object.  This should be called on all
@@ -126,17 +127,17 @@ interface nsITransferable : nsISupports
 
   /**
     * Given a flavor retrieve the data. 
     *
     * @param  aFlavor (in parameter) the flavor of data to retrieve
     * @param  aData the data. Some variant of class in nsISupportsPrimitives.idl
     * @param  aDataLen the length of the data
     */
-  void getTransferData(in string aFlavor, out nsISupports aData);
+  void getTransferData ( in string aFlavor, out nsISupports aData, out unsigned long aDataLen ) ;
 
   /**
     * Returns the best flavor in the transferable, given those that have
     * been added to it with |AddFlavor()|
     *
     * @param  aFlavor (out parameter) the flavor of data that was retrieved
     * @param  aData the data. Some variant of class in nsISupportsPrimitives.idl
     */
@@ -157,17 +158,17 @@ interface nsITransferable : nsISupports
     * Sets the data in the transferable with the specified flavor. The transferable
     * will maintain its own copy the data, so it is not necessary to do that beforehand.
     *
     * @param  aFlavor the flavor of data that is being set
     * @param  aData the data, either some variant of class in nsISupportsPrimitives.idl,
     *         an nsIFile, or an nsIFlavorDataProvider (see above)
     * @param  aDataLen the length of the data, or 0 if passing a nsIFlavorDataProvider
     */
-  void setTransferData(in string aFlavor, in nsISupports aData);
+  void setTransferData ( in string aFlavor, in nsISupports aData, in unsigned long aDataLen ) ;
 
   /**
     * Add the data flavor, indicating that this transferable 
     * can receive this type of flavor
     *
     * @param  aDataFlavor a new data flavor to handle
     */
   void addDataFlavor ( in string aDataFlavor ) ;
--- a/widget/nsTransferable.cpp
+++ b/widget/nsTransferable.cpp
@@ -37,123 +37,119 @@ Notes to self:
 #include "mozilla/UniquePtr.h"
 
 using namespace mozilla;
 
 NS_IMPL_ISUPPORTS(nsTransferable, nsITransferable)
 
 DataStruct::DataStruct(DataStruct&& aRHS)
   : mData(aRHS.mData.forget())
+  , mDataLen(aRHS.mDataLen)
   , mCacheFD(aRHS.mCacheFD)
   , mFlavor(aRHS.mFlavor)
 {
   aRHS.mCacheFD = nullptr;
 }
 
 //-------------------------------------------------------------------------
 DataStruct::~DataStruct()
 {
   if (mCacheFD) {
     PR_Close(mCacheFD);
   }
 }
 
 //-------------------------------------------------------------------------
-
 void
-DataStruct::SetData(nsISupports* aData, bool aIsPrivateData)
+DataStruct::SetData(nsISupports* aData, uint32_t aDataLen, bool aIsPrivateData)
 {
   // Now, check to see if we consider the data to be "too large"
-  // as well as ensuring that private browsing mode is disabled.
-  // File IO is not allowed in content processes.
-  if (!aIsPrivateData && XRE_IsParentProcess()) {
-    void* data = nullptr;
-    uint32_t dataLen = 0;
-    nsPrimitiveHelpers::CreateDataFromPrimitive(mFlavor, aData, &data, &dataLen);
-
-    if (dataLen > kLargeDatasetSize) {
-      // Too large, cache it to disk instead of memory.
-      if (NS_SUCCEEDED(WriteCache(data, dataLen))) {
-        free(data);
-        // Clear previously set small data.
-        mData = nullptr;
-        return;
-      }
-
-      NS_WARNING("Oh no, couldn't write data to the cache file");
+  // as well as ensuring that private browsing mode is disabled
+  if (aDataLen > kLargeDatasetSize && !aIsPrivateData &&
+      // File IO is not allowed in content processes.
+      XRE_IsParentProcess()) {
+    // if so, cache it to disk instead of memory
+    if (NS_SUCCEEDED(WriteCache(aData, aDataLen))) {
+      // Clear previously set small data.
+      mData = nullptr;
+      mDataLen = 0;
+      return;
     }
-
-    free(data);
+    NS_WARNING("Oh no, couldn't write data to the cache file");
   }
 
   if (mCacheFD) {
     // Clear previously set big data.
     PR_Close(mCacheFD);
     mCacheFD = nullptr;
   }
 
   mData = aData;
+  mDataLen = aDataLen;
 }
 
 //-------------------------------------------------------------------------
 void
-DataStruct::GetData(nsISupports** aData)
+DataStruct::GetData(nsISupports** aData, uint32_t* aDataLen)
 {
   // check here to see if the data is cached on disk
   if (mCacheFD) {
     // if so, read it in and pass it back
     // ReadCache creates memory and copies the data into it.
-    if (NS_SUCCEEDED(ReadCache(aData))) {
+    if (NS_SUCCEEDED(ReadCache(aData, aDataLen))) {
       return;
     }
 
     // oh shit, something went horribly wrong here.
     NS_WARNING("Oh no, couldn't read data in from the cache file");
     *aData = nullptr;
+    *aDataLen = 0;
     PR_Close(mCacheFD);
     mCacheFD = nullptr;
     return;
   }
 
   nsCOMPtr<nsISupports> data = mData;
   data.forget(aData);
+  *aDataLen = mDataLen;
 }
 
 //-------------------------------------------------------------------------
 nsresult
-DataStruct::WriteCache(void* aData, uint32_t aDataLen)
+DataStruct::WriteCache(nsISupports* aData, uint32_t aDataLen)
 {
-  MOZ_ASSERT(aData && aDataLen);
-  MOZ_ASSERT(aDataLen <= std::numeric_limits<int32_t>::max(),
-             "too large size for PR_Write");
-
   nsresult rv;
   if (!mCacheFD) {
     rv = NS_OpenAnonymousTemporaryFile(&mCacheFD);
     if (NS_FAILED(rv)) {
       return NS_ERROR_FAILURE;
     }
   } else if (PR_Seek64(mCacheFD, 0, PR_SEEK_SET) == -1) {
     return NS_ERROR_FAILURE;
   }
 
-  // Write out the contents of the clipboard to the file.
-  int32_t written = PR_Write(mCacheFD, aData, aDataLen);
-  if (written == aDataLen) {
-    return NS_OK;
+  // write out the contents of the clipboard to the file
+  void* buff = nullptr;
+  uint32_t dataLen = 0;
+  nsPrimitiveHelpers::CreateDataFromPrimitive(mFlavor, aData, &buff, &dataLen);
+  if (buff) {
+    int32_t written = PR_Write(mCacheFD, buff, dataLen);
+    free(buff);
+    if (written) {
+      return NS_OK;
+    }
   }
-
   PR_Close(mCacheFD);
   mCacheFD = nullptr;
   return NS_ERROR_FAILURE;
 }
 
 //-------------------------------------------------------------------------
 nsresult
-DataStruct::ReadCache(nsISupports** aData)
+DataStruct::ReadCache(nsISupports** aData, uint32_t* aDataLen)
 {
   if (!mCacheFD) {
     return NS_ERROR_FAILURE;
   }
 
   PRFileInfo fileInfo;
   if (PR_GetOpenFileInfo(mCacheFD, &fileInfo) != PR_SUCCESS) {
     return NS_ERROR_FAILURE;
@@ -170,16 +166,17 @@ DataStruct::ReadCache(nsISupports** aDat
 
   uint32_t actual = PR_Read(mCacheFD, data.get(), fileSize);
   if (actual != fileSize) {
     return NS_ERROR_FAILURE;
   }
 
   nsPrimitiveHelpers::CreatePrimitiveForData(
     mFlavor, data.get(), fileSize, aData);
+  *aDataLen = fileSize;
   return NS_OK;
 }
 
 //-------------------------------------------------------------------------
 //
 // Transferable constructor
 //
 //-------------------------------------------------------------------------
@@ -249,71 +246,76 @@ nsTransferable::FindDataFlavor(const cha
 // GetTransferData
 //
 // Returns the data of the requested flavor, obtained from either having the
 // data on hand or using a converter to get it. The data is wrapped in a
 // nsISupports primitive so that it is accessible from JS.
 //
 NS_IMETHODIMP
 nsTransferable::GetTransferData(const char* aFlavor,
-                                nsISupports** aData)
+                                nsISupports** aData,
+                                uint32_t* aDataLen)
 {
   MOZ_ASSERT(mInitialized);
 
   *aData = nullptr;
+  *aDataLen = 0;
 
   nsresult rv = NS_OK;
 
   // First look and see if the data is present in one of the intrinsic flavors.
   if (Maybe<size_t> index = FindDataFlavor(aFlavor)) {
     nsCOMPtr<nsISupports> dataBytes;
-    mDataArray[index.value()].GetData(getter_AddRefs(dataBytes));
+    uint32_t len;
+    mDataArray[index.value()].GetData(getter_AddRefs(dataBytes), &len);
 
     // Do we have a (lazy) data provider?
     if (nsCOMPtr<nsIFlavorDataProvider> dataProvider =
           do_QueryInterface(dataBytes)) {
       rv = dataProvider->GetFlavorData(this, aFlavor,
-                                       getter_AddRefs(dataBytes));
+                                       getter_AddRefs(dataBytes), &len);
       if (NS_FAILED(rv)) {
         dataBytes = nullptr;
         // The provider failed, fall into the converter code below.
       }
     }
 
     if (dataBytes) {
+      *aDataLen = len;
       dataBytes.forget(aData);
       return NS_OK;
     }
 
     // Empty data
   }
 
   // If not, try using a format converter to get the requested flavor.
   if (mFormatConv) {
     for (size_t i = 0; i < mDataArray.Length(); ++i) {
       DataStruct& data = mDataArray.ElementAt(i);
       bool canConvert = false;
       mFormatConv->CanConvert(data.GetFlavor().get(), aFlavor, &canConvert);
       if (canConvert) {
         nsCOMPtr<nsISupports> dataBytes;
-        data.GetData(getter_AddRefs(dataBytes));
+        uint32_t len;
+        data.GetData(getter_AddRefs(dataBytes), &len);
 
         // Do we have a (lazy) data provider?
         if (nsCOMPtr<nsIFlavorDataProvider> dataProvider =
               do_QueryInterface(dataBytes)) {
           rv = dataProvider->GetFlavorData(this, aFlavor,
-                                           getter_AddRefs(dataBytes));
+                                           getter_AddRefs(dataBytes), &len);
           if (NS_FAILED(rv)) {
             // Give up.
             return rv;
           }
         }
 
-        return mFormatConv->Convert(data.GetFlavor().get(), dataBytes, aFlavor,
-                                    aData);
+        return mFormatConv->Convert(data.GetFlavor().get(), dataBytes, len,
+                                    aFlavor, aData, aDataLen);
       }
     }
   }
 
   return NS_ERROR_FAILURE;
 }
 
 //
@@ -327,65 +329,70 @@ nsTransferable::GetAnyTransferData(nsACS
                                    nsISupports** aData)
 {
   MOZ_ASSERT(mInitialized);
 
   for (size_t i = 0; i < mDataArray.Length(); ++i) {
     DataStruct& data = mDataArray.ElementAt(i);
     if (data.IsDataAvailable()) {
       aFlavor.Assign(data.GetFlavor());
-      data.GetData(aData);
+      uint32_t dataLen;
+      data.GetData(aData, &dataLen);
       return NS_OK;
     }
   }
 
   return NS_ERROR_FAILURE;
 }
 
 //
 // SetTransferData
 //
 //
 //
 NS_IMETHODIMP
 nsTransferable::SetTransferData(const char* aFlavor,
-                                nsISupports* aData)
+                                nsISupports* aData,
+                                uint32_t aDataLen)
 {
   MOZ_ASSERT(mInitialized);
 
   // first check our intrinsic flavors to see if one has been registered.
   if (Maybe<size_t> index = FindDataFlavor(aFlavor)) {
     DataStruct& data = mDataArray.ElementAt(index.value());
-    data.SetData(aData, mPrivateData);
+    data.SetData(aData, aDataLen, mPrivateData);
     return NS_OK;
   }
 
   // if not, try using a format converter to find a flavor to put the data in
   if (mFormatConv) {
     for (size_t i = 0; i < mDataArray.Length(); ++i) {
       DataStruct& data = mDataArray.ElementAt(i);
       bool canConvert = false;
       mFormatConv->CanConvert(aFlavor, data.GetFlavor().get(), &canConvert);
 
       if (canConvert) {
         nsCOMPtr<nsISupports> ConvertedData;
+        uint32_t ConvertedLen;
         mFormatConv->Convert(aFlavor,
                              aData,
+                             aDataLen,
                              data.GetFlavor().get(),
-                             getter_AddRefs(ConvertedData));
-        data.SetData(ConvertedData, mPrivateData);
+                             getter_AddRefs(ConvertedData),
+                             &ConvertedLen);
+        data.SetData(ConvertedData, ConvertedLen, mPrivateData);
         return NS_OK;
       }
     }
   }
 
   // Can't set data neither directly nor through converter. Just add this flavor
   // and try again
   if (NS_SUCCEEDED(AddDataFlavor(aFlavor))) {
-    return SetTransferData(aFlavor, aData);
+    return SetTransferData(aFlavor, aData, aDataLen);
   }
 
   return NS_ERROR_FAILURE;
 }
 
 //
 // AddDataFlavor
 //
--- a/widget/nsTransferable.h
+++ b/widget/nsTransferable.h
@@ -20,38 +20,39 @@ class nsIMutableArray;
 //
 // DataStruct
 //
 // Holds a flavor (a mime type) that describes the data and the associated data.
 //
 struct DataStruct
 {
   explicit DataStruct ( const char* aFlavor )
-    : mCacheFD(nullptr), mFlavor(aFlavor) { }
+    : mDataLen(0), mCacheFD(nullptr), mFlavor(aFlavor) { }
   DataStruct(DataStruct&& aRHS);
   ~DataStruct();
-
+  
   const nsCString& GetFlavor() const { return mFlavor; }
-  void SetData(nsISupports* inData, bool aIsPrivateData);
-  void GetData(nsISupports** outData);
-  bool IsDataAvailable() const { return mData || mCacheFD; }
-
+  void SetData( nsISupports* inData, uint32_t inDataLen, bool aIsPrivateData );
+  void GetData( nsISupports** outData, uint32_t *outDataLen );
+  bool IsDataAvailable() const { return mData ? mDataLen > 0 : mCacheFD != nullptr; }
+  
 protected:
 
   enum {
     // The size of data over which we write the data to disk rather than
     // keep it around in memory.
     kLargeDatasetSize = 1000000        // 1 million bytes
   };
-
-  nsresult WriteCache(void* aData, uint32_t aDataLen);
-  nsresult ReadCache(nsISupports** aData);
-
-  // mData OR mCacheFD should be used, not both.
+  
+  nsresult WriteCache(nsISupports* aData, uint32_t aDataLen );
+  nsresult ReadCache(nsISupports** aData, uint32_t* aDataLen );
+  
+  // mData + mDataLen OR mCacheFD should be used, not both.
   nsCOMPtr<nsISupports> mData;   // OWNER - some varient of primitive wrapper
+  uint32_t mDataLen;
   PRFileDesc* mCacheFD;
   const nsCString mFlavor;
 
 private:
   DataStruct(const DataStruct&) = delete;
   DataStruct& operator=(const DataStruct&) = delete;
 
 };
--- a/widget/tests/test_bug466599.xul
+++ b/widget/tests/test_bug466599.xul
@@ -61,21 +61,22 @@ function readFromClipboard()
   var trans =
     Cc['@mozilla.org/widget/transferable;1'].createInstance(Ci.nsITransferable);
   if (!trans)
     return;
   trans.init(getLoadContext());
   trans.addDataFlavor('text/html');
   clip.getData(trans,clipid.kGlobalClipboard);
   var str = new Object();
-  trans.getTransferData("text/html",str);
+  var strLength = new Object();
+  trans.getTransferData("text/html",str,strLength);
   if (str)
     str = str.value.QueryInterface(Ci.nsISupportsString);
   if (str)
-    pastetext = str.data;
+    pastetext = str.data.substring(0,strLength.value / 2);
   return pastetext;
 }
 
 function encodeHtmlEntities(s)
 {
   var result = '';
   for (var i = 0; i < s.length; i++) {
     var c = s.charAt(i);
--- a/widget/tests/test_bug565392.html
+++ b/widget/tests/test_bug565392.html
@@ -28,32 +28,32 @@ https://bugzilla.mozilla.org/show_bug.cg
   function getLoadContext() {
     return window.docShell.QueryInterface(Ci.nsILoadContext);
   }
 
   function getTransferableFile(file) {
     var transferable = Cc['@mozilla.org/widget/transferable;1']
                          .createInstance(Ci.nsITransferable);
     transferable.init(getLoadContext());
-    transferable.setTransferData("application/x-moz-file", file);
+    transferable.setTransferData("application/x-moz-file", file, 0);
     return transferable;
   }
 
   function setClipboardData(transferable) {
     clipboard.setData(transferable, null, 1);
   }
   
   function getClipboardData(mime) {
     var transferable = Cc['@mozilla.org/widget/transferable;1']
                          .createInstance(Ci.nsITransferable);
     transferable.init(getLoadContext());
     transferable.addDataFlavor(mime);
     clipboard.getData(transferable, 1);
     var data = {};
-    transferable.getTransferData(mime, data);
+    transferable.getTransferData(mime, data, {}) ;
     return data;
   }
 
 setClipboardData(getTransferableFile(dir1))
 is(clipboard.hasDataMatchingFlavors(["application/x-moz-file"], 1,1), true);
 var data = getClipboardData("application/x-moz-file");
 var file = data.value.QueryInterface(Ci.nsIFile);
 ok(file.isDirectory(), true);
--- a/widget/tests/test_clipboard.xul
+++ b/widget/tests/test_clipboard.xul
@@ -32,25 +32,26 @@ https://bugzilla.mozilla.org/show_bug.cg
   // Get clipboard data to paste.
   function paste(clipboard) {
     let trans = Cc['@mozilla.org/widget/transferable;1']
                 .createInstance(Ci.nsITransferable);
     trans.init(getLoadContext());
     trans.addDataFlavor("text/unicode");
     clipboard.getData(trans, Ci.nsIClipboard.kGlobalClipboard);
     let str = {};
+    let length = {};
     try {
-      trans.getTransferData('text/unicode', str);
+      trans.getTransferData('text/unicode', str, length);
     } catch (e) {
       str = '';
     }
     if (str) {
       str = str.value.QueryInterface(Ci.nsISupportsString);
       if (str) {
-        str = str.data;
+        str = str.data.substring(0, length.value / 2);
       }
     }
     return str;
   }
 
   function initAndRunTests() {
     let clipboard = Cc['@mozilla.org/widget/clipboard;1']
                     .getService(Ci.nsIClipboard);
--- a/widget/tests/test_transferable_overflow.xul
+++ b/widget/tests/test_transferable_overflow.xul
@@ -25,21 +25,23 @@
   function assignTextToTransferable(transferable, string) {
     var Suppstr = nsSupportsString();
     Suppstr.data = string;
     transferable.setTransferData("text/unicode", Suppstr, string.length * 2);
   }
 
   function checkTransferableText(transferable, expectedString, description) {
     var data = {};
-    transferable.getTransferData("text/unicode", data);
+    var dataLen = {};
+    transferable.getTransferData("text/unicode", data, dataLen);
     var actualValue = data.value.QueryInterface(Ci.nsISupportsString).data;
     // Use ok + shortenString instead of is(...) to avoid dumping millions of characters in the output.
     ok(actualValue === expectedString, description + ": text should match. " +
        "Expected " + shortenString(expectedString)  + ", got " + shortenString(actualValue));
+    is(dataLen.value, expectedString.length * 2, description + ": text length should match");
 
     function shortenString(str) {
       return str && str.length > 30 ? str.slice(0, 10) + "..." + str.slice(-10) : String(str);
     }
   }
 
   function isFDCountingSupported() {
     // On on-Windows we can count the number of file handles for the current process,
--- a/widget/windows/nsClipboard.cpp
+++ b/widget/windows/nsClipboard.cpp
@@ -725,17 +725,17 @@ nsresult nsClipboard::GetDataFromDataObj
           }
         }
 
         nsPrimitiveHelpers::CreatePrimitiveForData(flavorStr, data, dataLen, getter_AddRefs(genericDataWrapper));
         free(data);
       }
       
       NS_ASSERTION ( genericDataWrapper, "About to put null data into the transferable" );
-      aTransferable->SetTransferData(flavorStr.get(), genericDataWrapper);
+      aTransferable->SetTransferData(flavorStr.get(), genericDataWrapper, dataLen);
       res = NS_OK;
 
       // we found one, get out of the loop
       break;
     }
   } // foreach flavor
 
   return res;
--- a/widget/windows/nsDataObj.cpp
+++ b/widget/windows/nsDataObj.cpp
@@ -893,18 +893,19 @@ HRESULT nsDataObj::AddGetFormat(FORMATET
 // imgIContainer, so just QI it.
 //
 HRESULT 
 nsDataObj::GetDib(const nsACString& inFlavor,
                   FORMATETC &aFormat,
                   STGMEDIUM & aSTG)
 {
   ULONG result = E_FAIL;
+  uint32_t len = 0;
   nsCOMPtr<nsISupports> genericDataWrapper;
-  mTransferable->GetTransferData(PromiseFlatCString(inFlavor).get(), getter_AddRefs(genericDataWrapper));
+  mTransferable->GetTransferData(PromiseFlatCString(inFlavor).get(), getter_AddRefs(genericDataWrapper), &len);
   nsCOMPtr<imgIContainer> image ( do_QueryInterface(genericDataWrapper) );
   if ( image ) {
     nsCOMPtr<imgITools> imgTools = do_CreateInstance("@mozilla.org/image/tools;1");
 
     nsAutoString options;
     if (aFormat.cfFormat == CF_DIBV5) {
       options.AppendLiteral("version=5");
     } else {
@@ -1358,32 +1359,31 @@ HRESULT nsDataObj::GetPreferredDropEffec
   aSTG.hGlobal = hGlobalMemory;
   return res;
 }
 
 //-----------------------------------------------------
 HRESULT nsDataObj::GetText(const nsACString & aDataFlavor, FORMATETC& aFE, STGMEDIUM& aSTG)
 {
   void* data = nullptr;
+  uint32_t   len;
   
   // if someone asks for text/plain, look up text/unicode instead in the transferable.
   const char* flavorStr;
   const nsPromiseFlatCString& flat = PromiseFlatCString(aDataFlavor);
   if (aDataFlavor.EqualsLiteral("text/plain"))
     flavorStr = kUnicodeMime;
   else
     flavorStr = flat.get();
 
   // NOTE: CreateDataFromPrimitive creates new memory, that needs to be deleted
   nsCOMPtr<nsISupports> genericDataWrapper;
-  mTransferable->GetTransferData(flavorStr, getter_AddRefs(genericDataWrapper));
-  if ( !genericDataWrapper )
+  mTransferable->GetTransferData(flavorStr, getter_AddRefs(genericDataWrapper), &len);
+  if ( !len )
     return E_FAIL;
-
-  uint32_t   len;
   nsPrimitiveHelpers::CreateDataFromPrimitive(
     nsDependentCString(flavorStr), genericDataWrapper, &data, &len);
   if ( !data )
     return E_FAIL;
 
   HGLOBAL     hGlobalMemory = nullptr;
 
   aSTG.tymed          = TYMED_HGLOBAL;
@@ -1477,19 +1477,21 @@ HRESULT nsDataObj::GetFile(FORMATETC& aF
       dfInx++;
   }
   return E_FAIL;
 }
 
 HRESULT nsDataObj::DropFile(FORMATETC& aFE, STGMEDIUM& aSTG)
 {
   nsresult rv;
+  uint32_t len = 0;
   nsCOMPtr<nsISupports> genericDataWrapper;
 
-  mTransferable->GetTransferData(kFileMime, getter_AddRefs(genericDataWrapper));
+  mTransferable->GetTransferData(kFileMime, getter_AddRefs(genericDataWrapper),
+                                 &len);
   nsCOMPtr<nsIFile> file ( do_QueryInterface(genericDataWrapper) );
   if (!file)
     return E_FAIL;
 
   aSTG.tymed = TYMED_HGLOBAL;
   aSTG.pUnkForRelease = nullptr;
 
   nsAutoString path;
@@ -1530,19 +1532,20 @@ HRESULT nsDataObj::DropFile(FORMATETC& a
 
   return S_OK;
 }
 
 HRESULT nsDataObj::DropImage(FORMATETC& aFE, STGMEDIUM& aSTG)
 {
   nsresult rv;
   if (!mCachedTempFile) {
+    uint32_t len = 0;
     nsCOMPtr<nsISupports> genericDataWrapper;
 
-    mTransferable->GetTransferData(kNativeImageMime, getter_AddRefs(genericDataWrapper));
+    mTransferable->GetTransferData(kNativeImageMime, getter_AddRefs(genericDataWrapper), &len);
     nsCOMPtr<imgIContainer> image(do_QueryInterface(genericDataWrapper));
     if (!image) 
       return E_FAIL;
 
     nsCOMPtr<imgITools> imgTools = do_CreateInstance("@mozilla.org/image/tools;1");
     nsCOMPtr<nsIInputStream> inputStream;
     rv = imgTools->EncodeImage(image, NS_LITERAL_CSTRING(IMAGE_BMP),
                                NS_LITERAL_STRING("version=3"),
@@ -1833,35 +1836,36 @@ void nsDataObj::SetTransferable(nsITrans
 //   <url> <linefeed> <page title>
 //
 nsresult
 nsDataObj :: ExtractShortcutURL ( nsString & outURL )
 {
   NS_ASSERTION ( mTransferable, "We don't have a good transferable" );
   nsresult rv = NS_ERROR_FAILURE;
   
+  uint32_t len = 0;
   nsCOMPtr<nsISupports> genericURL;
-  if ( NS_SUCCEEDED(mTransferable->GetTransferData(kURLMime, getter_AddRefs(genericURL)))) {
+  if ( NS_SUCCEEDED(mTransferable->GetTransferData(kURLMime, getter_AddRefs(genericURL), &len)) ) {
     nsCOMPtr<nsISupportsString> urlObject ( do_QueryInterface(genericURL) );
     if ( urlObject ) {
       nsAutoString url;
       urlObject->GetData ( url );
       outURL = url;
 
       // find the first linefeed in the data, that's where the url ends. trunc the 
       // result string at that point.
       int32_t lineIndex = outURL.FindChar ( '\n' );
       NS_ASSERTION ( lineIndex > 0, "Format for url flavor is <url> <linefeed> <page title>" );
       if ( lineIndex > 0 ) {
         outURL.Truncate ( lineIndex );
         rv = NS_OK;    
       }
     }
-  } else if ( NS_SUCCEEDED(mTransferable->GetTransferData(kURLDataMime, getter_AddRefs(genericURL))) ||
-              NS_SUCCEEDED(mTransferable->GetTransferData(kURLPrivateMime, getter_AddRefs(genericURL))) ) {
+  } else if ( NS_SUCCEEDED(mTransferable->GetTransferData(kURLDataMime, getter_AddRefs(genericURL), &len)) ||
+              NS_SUCCEEDED(mTransferable->GetTransferData(kURLPrivateMime, getter_AddRefs(genericURL), &len)) ) {
     nsCOMPtr<nsISupportsString> urlObject ( do_QueryInterface(genericURL) );
     if ( urlObject ) {
       nsAutoString url;
       urlObject->GetData ( url );
       outURL = url;
 
       rv = NS_OK;    
     }
@@ -1883,29 +1887,30 @@ nsDataObj :: ExtractShortcutURL ( nsStri
 //   <url> <linefeed> <page title>
 //
 nsresult
 nsDataObj :: ExtractShortcutTitle ( nsString & outTitle )
 {
   NS_ASSERTION ( mTransferable, "We'd don't have a good transferable" );
   nsresult rv = NS_ERROR_FAILURE;
   
+  uint32_t len = 0;
   nsCOMPtr<nsISupports> genericURL;
-  if ( NS_SUCCEEDED(mTransferable->GetTransferData(kURLMime, getter_AddRefs(genericURL)) )) {
+  if ( NS_SUCCEEDED(mTransferable->GetTransferData(kURLMime, getter_AddRefs(genericURL), &len)) ) {
     nsCOMPtr<nsISupportsString> urlObject ( do_QueryInterface(genericURL) );
     if ( urlObject ) {
       nsAutoString url;
       urlObject->GetData ( url );
 
       // find the first linefeed in the data, that's where the url ends. we want
       // everything after that linefeed. FindChar() returns -1 if we can't find
       int32_t lineIndex = url.FindChar ( '\n' );
       NS_ASSERTION ( lineIndex != -1, "Format for url flavor is <url> <linefeed> <page title>" );
       if ( lineIndex != -1 ) {
-        url.Mid ( outTitle, lineIndex + 1, url.Length() - (lineIndex + 1) );
+        url.Mid ( outTitle, lineIndex + 1, (len/2) - (lineIndex + 1) );
         rv = NS_OK;    
       }
     }
   } // if found flavor
   
   return rv;
 
 } // ExtractShortcutTitle
@@ -2091,30 +2096,31 @@ HRESULT nsDataObj::GetDownloadDetails(ns
                                       nsAString &aFilename)
 {
   *aSourceURI = nullptr;
 
   NS_ENSURE_TRUE(mTransferable, E_FAIL);
 
   // get the URI from the kFilePromiseURLMime flavor
   nsCOMPtr<nsISupports> urlPrimitive;
-  mTransferable->GetTransferData(kFilePromiseURLMime, getter_AddRefs(urlPrimitive));
+  uint32_t dataSize = 0;
+  mTransferable->GetTransferData(kFilePromiseURLMime, getter_AddRefs(urlPrimitive), &dataSize);
   nsCOMPtr<nsISupportsString> srcUrlPrimitive = do_QueryInterface(urlPrimitive);
   NS_ENSURE_TRUE(srcUrlPrimitive, E_FAIL);
   
   nsAutoString srcUri;
   srcUrlPrimitive->GetData(srcUri);
   if (srcUri.IsEmpty())
     return E_FAIL;
   nsCOMPtr<nsIURI> sourceURI;
   NS_NewURI(getter_AddRefs(sourceURI), srcUri);
 
   nsAutoString srcFileName;
   nsCOMPtr<nsISupports> fileNamePrimitive;
-  mTransferable->GetTransferData(kFilePromiseDestFilename, getter_AddRefs(fileNamePrimitive));
+  mTransferable->GetTransferData(kFilePromiseDestFilename, getter_AddRefs(fileNamePrimitive), &dataSize);
   nsCOMPtr<nsISupportsString> srcFileNamePrimitive = do_QueryInterface(fileNamePrimitive);
   if (srcFileNamePrimitive) {
     srcFileNamePrimitive->GetData(srcFileName);
   } else {
     nsCOMPtr<nsIURL> sourceURL = do_QueryInterface(sourceURI);
     if (!sourceURL)
       return E_FAIL;