Bug 586587 - support kHTMLMime in the Windows clipboard as CF_HTML. r=jimm
authorAndrew Herron <andrew.herron@ephox.com>
Wed, 22 Jul 2015 16:56:57 +1000
changeset 273876 e1b5927361ac2fbcb7075c19061d1b73a70487dc
parent 273875 9bf9d97873fe66037bd14176d2d09affec617fe2
child 273877 0c34cc2dc429d2ea06415dc977def64d1a7ac72a
push id16386
push userkwierso@gmail.com
push dateWed, 25 Nov 2015 00:57:09 +0000
treeherderfx-team@95ac4f70df1b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjimm
bugs586587
milestone45.0a1
Bug 586587 - support kHTMLMime in the Windows clipboard as CF_HTML. r=jimm
addon-sdk/source/test/test-clipboard.js
browser/base/content/test/general/browser_clipboard.js
dom/base/test/copypaste.js
dom/base/test/test_bug166235.html
dom/base/test/test_copyimage.html
dom/events/DataTransfer.cpp
editor/libeditor/nsHTMLDataTransfer.cpp
editor/libeditor/nsHTMLEditor.h
editor/libeditor/tests/test_bug525389.html
widget/nsPrimitiveHelpers.cpp
widget/nsPrimitiveHelpers.h
widget/windows/nsClipboard.cpp
widget/windows/nsClipboard.h
widget/windows/nsDragService.cpp
--- a/addon-sdk/source/test/test-clipboard.js
+++ b/addon-sdk/source/test/test-clipboard.js
@@ -15,16 +15,20 @@ const io = Cc["@mozilla.org/network/io-s
 
 const base64png = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYA" +
                   "AABzenr0AAAASUlEQVRYhe3O0QkAIAwD0eyqe3Q993AQ3cBSUKpygfsNTy" +
                   "N5ugbQpK0BAADgP0BRDWXWlwEAAAAAgPsA3rzDaAAAAHgPcGrpgAnzQ2FG" +
                   "bWRR9AAAAABJRU5ErkJggg%3D%3D";
 
 const { base64jpeg } = require("./fixtures");
 
+const { platform } = require("sdk/system");
+// For Windows, Mac and Linux, platform returns the following: winnt, darwin and linux.
+var isWindows = platform.toLowerCase().indexOf("win") == 0;
+
 const canvasHTML = "data:text/html," + encodeURIComponent(
   "<html>\
     <body>\
       <canvas width='32' height='32'></canvas>\
     </body>\
   </html>"
 );
 
@@ -94,29 +98,36 @@ exports["test With No Flavor"] = functio
   // Confirm we can still get the clipboard using the full flavor
   assert.equal(clip.get(fullFlavor), contents);
 };
 
 // Test the slightly less common case where we specify the flavor
 exports["test With Flavor"] = function(assert) {
   var contents = "<b>hello there</b>";
   var contentsText = "hello there";
+
+  // On windows, HTML clipboard includes extra data.
+  // The values are from widget/windows/nsDataObj.cpp.
+  var contentsWindowsHtml = "<html><body>\n<!--StartFragment-->" +
+                            contents +
+                            "<!--EndFragment-->\n</body>\n</html>";
+
   var flavor = "html";
   var fullFlavor = "text/html";
   var unicodeFlavor = "text";
   var unicodeFullFlavor = "text/unicode";
   var clip = require("sdk/clipboard");
 
   assert.ok(clip.set(contents, flavor));
 
   assert.equal(clip.currentFlavors[0], unicodeFlavor);
   assert.equal(clip.currentFlavors[1], flavor);
   assert.equal(clip.get(), contentsText);
-  assert.equal(clip.get(flavor), contents);
-  assert.equal(clip.get(fullFlavor), contents);
+  assert.equal(clip.get(flavor), isWindows ? contentsWindowsHtml : contents);
+  assert.equal(clip.get(fullFlavor), isWindows ? contentsWindowsHtml : contents);
   assert.equal(clip.get(unicodeFlavor), contentsText);
   assert.equal(clip.get(unicodeFullFlavor), contentsText);
 };
 
 // Test that the typical case still works when we specify the flavor to set
 exports["test With Redundant Flavor"] = function(assert) {
   var contents = "<b>hello there</b>";
   var flavor = "text";
--- a/browser/base/content/test/general/browser_clipboard.js
+++ b/browser/base/content/test/general/browser_clipboard.js
@@ -9,21 +9,26 @@ add_task(function*() {
   let tab = gBrowser.addTab();
   let browser = gBrowser.getBrowserForTab(tab);
 
   gBrowser.selectedTab = tab;
 
   yield promiseTabLoadEvent(tab, "data:text/html," + escape(testPage));
   yield SimpleTest.promiseFocus(browser.contentWindowAsCPOW);
 
-  const modifier = (content.navigator.platform.indexOf("Mac") >= 0) ?
+  const modifier = (navigator.platform.indexOf("Mac") >= 0) ?
                    Components.interfaces.nsIDOMWindowUtils.MODIFIER_META :
                    Components.interfaces.nsIDOMWindowUtils.MODIFIER_CONTROL;
 
-  let results = yield ContentTask.spawn(browser, { modifier: modifier },
+  // On windows, HTML clipboard includes extra data.
+  // The values are from widget/windows/nsDataObj.cpp.
+  const htmlPrefix = (navigator.platform.indexOf("Win") >= 0) ? "<html><body>\n<!--StartFragment-->" : "";
+  const htmlPostfix = (navigator.platform.indexOf("Win") >= 0) ? "<!--EndFragment-->\n</body>\n</html>" : "";
+
+  let results = yield ContentTask.spawn(browser, { modifier: modifier, htmlPrefix: htmlPrefix, htmlPostfix: htmlPostfix },
                                         function* (arg) {
     var doc = content.document;
     var main = doc.getElementById("main");
     main.focus();
 
     const utils = content.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
                          .getInterface(Components.interfaces.nsIDOMWindowUtils);
 
@@ -66,17 +71,17 @@ add_task(function*() {
     yield new Promise((resolve, reject) => {
       addEventListener("paste", function copyEvent(event) {
         removeEventListener("paste", copyEvent, true);
         let clipboardData = event.clipboardData; 
         is(clipboardData.mozItemCount, 1, "One item on clipboard");
         is(clipboardData.types.length, 2, "Two types on clipboard");
         is(clipboardData.types[0], "text/html", "text/html on clipboard");
         is(clipboardData.types[1], "text/plain", "text/plain on clipboard");
-        is(clipboardData.getData("text/html"), "t <b>Bold</b>", "text/html value");
+        is(clipboardData.getData("text/html"), arg.htmlPrefix + "t <b>Bold</b>" + arg.htmlPostfix, "text/html value");
         is(clipboardData.getData("text/plain"), "t Bold", "text/plain value");
         resolve();
       }, true)
       sendKey("v");
     });
 
     is(main.innerHTML, "Test <b>Bold</b> After Textt <b>Bold</b>", "Copy and paste html");
 
@@ -101,17 +106,17 @@ add_task(function*() {
     yield new Promise((resolve, reject) => {
       addEventListener("paste", function copyEvent(event) {
         removeEventListener("paste", copyEvent, true);
         let clipboardData = event.clipboardData; 
         is(clipboardData.mozItemCount, 1, "One item on clipboard 2");
         is(clipboardData.types.length, 2, "Two types on clipboard 2");
         is(clipboardData.types[0], "text/html", "text/html on clipboard 2");
         is(clipboardData.types[1], "text/plain", "text/plain on clipboard 2");
-        is(clipboardData.getData("text/html"), "<i>Italic</i> ", "text/html value 2");
+        is(clipboardData.getData("text/html"), arg.htmlPrefix + "<i>Italic</i> " + arg.htmlPostfix, "text/html value 2");
         is(clipboardData.getData("text/plain"), "Some text", "text/plain value 2");
         resolve();
       }, true)
       sendKey("v");
     });
 
     is(main.innerHTML, "<i>Italic</i> Test <b>Bold</b> After<b></b>", "Copy and paste html 2");
 
@@ -135,32 +140,33 @@ add_task(function*() {
   document.getElementById("context-copyimage-contents").doCommand();
 
   contextMenu.hidePopup();
   yield promisePopupHidden(contextMenu);
 
   // Focus the content again
   yield SimpleTest.promiseFocus(browser.contentWindowAsCPOW);
 
-  let expectedContent = yield ContentTask.spawn(browser, { modifier: modifier },
+  let expectedContent = yield ContentTask.spawn(browser, { modifier: modifier, htmlPrefix: htmlPrefix, htmlPostfix: htmlPostfix },
                                                 function* (arg) {
     var doc = content.document;
     var main = doc.getElementById("main");
     main.focus();
 
     yield new Promise((resolve, reject) => {
       addEventListener("paste", function copyEvent(event) {
         removeEventListener("paste", copyEvent, true);
         let clipboardData = event.clipboardData;
 
         // DataTransfer doesn't support the image types yet, so only text/html
         // will be present.
-        if (clipboardData.getData("text/html") !=
-            '<img id="img" tabindex="1" src="http://example.org/browser/browser/base/content/test/general/moz.png">') {
-          reject();
+        if (clipboardData.getData("text/html") !== arg.htmlPrefix +
+            '<img id="img" tabindex="1" src="http://example.org/browser/browser/base/content/test/general/moz.png">' +
+            arg.htmlPostfix) {
+          reject('Clipboard Data did not contain an image, was ' + clipboardData.getData("text/html"));
         }
         resolve();
       }, true)
 
       const utils = content.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
                            .getInterface(Components.interfaces.nsIDOMWindowUtils);
 
       const modifier = arg.modifier;
--- a/dom/base/test/copypaste.js
+++ b/dom/base/test/copypaste.js
@@ -87,16 +87,27 @@ function testCopyPaste (isXHTML) {
                                     .createInstance(SpecialPowers.Ci.nsITransferable);
     transferable.init(getLoadContext());
     transferable.addDataFlavor(mime);
     clipboard.getData(transferable, 1);
     var data = SpecialPowers.createBlankObject();
     transferable.getTransferData(mime, data, {}) ;
     return data;
   }
+  function testHtmlClipboardValue(mime, expected) {
+    // For Windows, navigator.platform returns "Win32".
+    var expectedValue = expected;
+    if (navigator.platform.indexOf("Win") >= 0) {
+      // Windows has extra content.
+      var expectedValue = "<html><body>\n<!--StartFragment-->" +
+                          expected.replace(/\n/g, '\n') +
+                          "<!--EndFragment-->\n</body>\n</html>";
+    }
+    testClipboardValue(mime, expectedValue);
+  }
   function testClipboardValue(mime, expected) {
     if (suppressHTMLCheck && mime == "text/html")
       return null;
     var data = SpecialPowers.wrap(getClipboardData(mime));
     is (data.value == null ? data.value :
         data.value.QueryInterface(SpecialPowers.Ci.nsISupportsString).data,
       expected,
       mime + " value in the clipboard");
@@ -128,60 +139,60 @@ function testCopyPaste (isXHTML) {
     testClipboardValue("text/html", null);
     testPasteText("");
   }
 
   copyChildrenToClipboard("draggable");
   testSelectionToString("This is a draggable bit of text.");
   testClipboardValue("text/unicode",
                      "This is a draggable bit of text.");
-  testClipboardValue("text/html",
+  testHtmlClipboardValue("text/html",
                      "<div id=\"draggable\" title=\"title to have a long HTML line\">This is a <em>draggable</em> bit of text.</div>");
   testPasteText("This is a draggable bit of text.");
 
   copyChildrenToClipboard("alist");
   testSelectionToString(" bla\n\n    foo\n    bar\n\n");
   testClipboardValue("text/unicode", " bla\n\n    foo\n    bar\n\n");
-  testClipboardValue("text/html", "<div id=\"alist\">\n    bla\n    <ul>\n      <li>foo</li>\n      \n      <li>bar</li>\n    </ul>\n  </div>");
+  testHtmlClipboardValue("text/html", "<div id=\"alist\">\n    bla\n    <ul>\n      <li>foo</li>\n      \n      <li>bar</li>\n    </ul>\n  </div>");
   testPasteText(" bla\n\n    foo\n    bar\n\n");
 
   copyChildrenToClipboard("blist");
   testSelectionToString(" mozilla\n\n    foo\n    bar\n\n");
   testClipboardValue("text/unicode", " mozilla\n\n    foo\n    bar\n\n");
-  testClipboardValue("text/html", "<div id=\"blist\">\n    mozilla\n    <ol>\n      <li>foo</li>\n      \n      <li>bar</li>\n    </ol>\n  </div>");
+  testHtmlClipboardValue("text/html", "<div id=\"blist\">\n    mozilla\n    <ol>\n      <li>foo</li>\n      \n      <li>bar</li>\n    </ol>\n  </div>");
   testPasteText(" mozilla\n\n    foo\n    bar\n\n");
 
   copyChildrenToClipboard("clist");
   testSelectionToString(" mzla\n\n    foo\n        bazzinga!\n    bar\n\n");
   testClipboardValue("text/unicode", " mzla\n\n    foo\n        bazzinga!\n    bar\n\n");
-  testClipboardValue("text/html", "<div id=\"clist\">\n    mzla\n    <ul>\n      <li>foo<ul>\n        <li>bazzinga!</li>\n      </ul></li>\n      \n      <li>bar</li>\n    </ul>\n  </div>");
+  testHtmlClipboardValue("text/html", "<div id=\"clist\">\n    mzla\n    <ul>\n      <li>foo<ul>\n        <li>bazzinga!</li>\n      </ul></li>\n      \n      <li>bar</li>\n    </ul>\n  </div>");
   testPasteText(" mzla\n\n    foo\n        bazzinga!\n    bar\n\n");
 
   copyChildrenToClipboard("div4");
   testSelectionToString(" Tt t t ");
   testClipboardValue("text/unicode", " Tt t t ");
   if (isXHTML) {
-    testClipboardValue("text/html", "<div id=\"div4\">\n  T<textarea xmlns=\"http://www.w3.org/1999/xhtml\">t t t</textarea>\n</div>");
+    testHtmlClipboardValue("text/html", "<div id=\"div4\">\n  T<textarea xmlns=\"http://www.w3.org/1999/xhtml\">t t t</textarea>\n</div>");
     testInnerHTML("div4", "\n  T<textarea xmlns=\"http://www.w3.org/1999/xhtml\">t t t</textarea>\n");
   }
   else {
-    testClipboardValue("text/html", "<div id=\"div4\">\n  T<textarea>t t t</textarea>\n</div>");
+    testHtmlClipboardValue("text/html", "<div id=\"div4\">\n  T<textarea>t t t</textarea>\n</div>");
     testInnerHTML("div4", "\n  T<textarea>t t t</textarea>\n");
   }
   testPasteText(" Tt t t ");
 
   copyChildrenToClipboard("div5");
   testSelectionToString(" T     ");
   testClipboardValue("text/unicode", " T     ");
   if (isXHTML) {
-    testClipboardValue("text/html", "<div id=\"div5\">\n  T<textarea xmlns=\"http://www.w3.org/1999/xhtml\">     </textarea>\n</div>");
+    testHtmlClipboardValue("text/html", "<div id=\"div5\">\n  T<textarea xmlns=\"http://www.w3.org/1999/xhtml\">     </textarea>\n</div>");
     testInnerHTML("div5", "\n  T<textarea xmlns=\"http://www.w3.org/1999/xhtml\">     </textarea>\n");
   }
   else {
-    testClipboardValue("text/html", "<div id=\"div5\">\n  T<textarea>     </textarea>\n</div>");
+    testHtmlClipboardValue("text/html", "<div id=\"div5\">\n  T<textarea>     </textarea>\n</div>");
     testInnerHTML("div5", "\n  T<textarea>     </textarea>\n");
   }
   testPasteText(" T     ");
 
   copyRangeToClipboard($("div6").childNodes[0],0, $("div6").childNodes[1],1,suppressUnicodeCheckIfHidden);
   testSelectionToString("");
 // START Disabled due to bug 564688
 if (false) {
@@ -209,17 +220,17 @@ if (false) {
   testClipboardValue("text/html", "");
 }
 // END Disabled due to bug 564688
   testInnerHTML("div8", "div8");
 
   copyRangeToClipboard($("div9").childNodes[0],0, $("div9").childNodes[0],4,suppressUnicodeCheckIfHidden);
   testSelectionToString("div9");
   testClipboardValue("text/unicode", "div9");
-  testClipboardValue("text/html", "div9");
+  testHtmlClipboardValue("text/html", "div9");
   testInnerHTML("div9", "div9");
 
   copyToClipboard($("div10"), suppressUnicodeCheckIfHidden);
   testSelectionToString("");
   testInnerHTML("div10", "div10");
 
   copyToClipboard($("div10").firstChild, suppressUnicodeCheckIfHidden);
   testSelectionToString("");
@@ -352,50 +363,50 @@ if (false) {
   is(textarea.value, val);
   textarea.value="";
 
   // ============ NOSCRIPT should not be copied
 
   copyChildrenToClipboard("div13");
   testSelectionToString("__");
   testClipboardValue("text/unicode", "__");
-  testClipboardValue("text/html", "<div id=\"div13\">__</div>");
+  testHtmlClipboardValue("text/html", "<div id=\"div13\">__</div>");
   testPasteText("__");
 
   // ============ converting cell boundaries to tabs in tables
 
   copyToClipboard($("tr1"));
   testClipboardValue("text/unicode", "foo\tbar");
 
   if (!isXHTML) {
     // ============ spanning multiple rows
 
     copyRangeToClipboard($("tr2"),0,$("tr3"),0);
     testClipboardValue("text/unicode", "1\t2\n3\t4\n");
-    testClipboardValue("text/html", '<table><tbody><tr id="tr2"><tr id="tr2"><td>1</td><td>2</td></tr><tr><td>3</td><td>4</td></tr><tr id="tr3"></tr></tr></tbody></table>');
+    testHtmlClipboardValue("text/html", '<table><tbody><tr id="tr2"><tr id="tr2"><td>1</td><td>2</td></tr><tr><td>3</td><td>4</td></tr><tr id="tr3"></tr></tr></tbody></table>');
 
     // ============ spanning multiple rows in multi-range selection
 
     clear();
     addRange($("tr2"),0,$("tr2"),2);
     addRange($("tr3"),0,$("tr3"),2);
     copySelectionToClipboard();
     testClipboardValue("text/unicode", "1\t2\n5\t6");
-    testClipboardValue("text/html", '<table><tbody><tr id="tr2"><td>1</td><td>2</td></tr><tr id="tr3"><td>5</td><td>6</td></tr></tbody></table>');
+    testHtmlClipboardValue("text/html", '<table><tbody><tr id="tr2"><td>1</td><td>2</td></tr><tr id="tr3"><td>5</td><td>6</td></tr></tbody></table>');
   }
 
   // ============ manipulating Selection in oncopy
 
   copyRangeToClipboard($("div11").childNodes[0],0, $("div11").childNodes[1],2);
   testClipboardValue("text/unicode", "Xdiv11");
-  testClipboardValue("text/html", "<div><p>X<span>div</span>11</p></div>");
+  testHtmlClipboardValue("text/html", "<div><p>X<span>div</span>11</p></div>");
   setTimeout(function(){testSelectionToString("div11")},0);
 
   setTimeout(function(){
     copyRangeToClipboard($("div12").childNodes[0],0, $("div12").childNodes[1],2);
     testClipboardValue("text/unicode", "Xdiv12");
-    testClipboardValue("text/html", "<div><p>X<span>div</span>12</p></div>");
+    testHtmlClipboardValue("text/html", "<div><p>X<span>div</span>12</p></div>");
     setTimeout(function(){ 
       testSelectionToString("div12"); 
       setTimeout(SimpleTest.finish,0);
     },0);
   },0);
 }
--- a/dom/base/test/test_bug166235.html
+++ b/dom/base/test/test_bug166235.html
@@ -62,16 +62,24 @@ https://bugzilla.mozilla.org/show_bug.cg
                          .createInstance(SpecialPowers.Ci.nsITransferable);
     transferable.init(getLoadContext());
     transferable.addDataFlavor(mime);
     clipboard.getData(transferable, 1);
     var data = SpecialPowers.createBlankObject();
     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.indexOf("Win") >= 0) {
+      expectedValue = "<html><body>\n<!--StartFragment-->" + expected + "<!--EndFragment-->\n</body>\n</html>";
+    }
+    testClipboardValue(mime, expectedValue, test);
+  }
   function testClipboardValue(mime, expected, test) {
     var data = getClipboardData(mime);
     is (data.value == null ? data.value :
         data.value.QueryInterface(SpecialPowers.Ci.nsISupportsString).data,
       expected,
       mime + " value in the clipboard");
     return data.value;
   }
@@ -135,17 +143,17 @@ var textareaStrings = [
   'This text should be copied.',
   'This text should be copied.'
 ];
 
 for (var i = 0; i < originalStrings.length; i++) {
   var id = 'test' + i;
   copyChildrenToClipboard(id);
   is(window.getSelection().toString(), originalStrings[i], id + ' Selection.toString()');
-  testClipboardValue("text/html", clipboardHTML[i], id);
+  testHtmlClipboardValue("text/html", clipboardHTML[i], id);
   testClipboardValue("text/unicode", clipboardUnicode[i], id);
   testInnerHTML(id, innerHTMLStrings[i]);
   testPasteText(textareaStrings[i], id + '.innerHTML');
 }
 
 </script>
 </pre>
 </body>
--- a/dom/base/test/test_copyimage.html
+++ b/dom/base/test/test_copyimage.html
@@ -66,17 +66,21 @@ function testCopyImage () {
   // Does the clipboard contain text/html data ?
   ok(clipboard.hasDataMatchingFlavors(["text/html"], 1, clipboard.kGlobalClipboard), "clipboard contains html text");
   // Does the clipboard contain image data ?
   ok(clipboard.hasDataMatchingFlavors(["image/png"], 1, clipboard.kGlobalClipboard), "clipboard contains image");
 
   // Is the text/uncodie data correct ?
   testClipboardValue('text/unicode', 'about:logo');
   // Is the text/html data correct ?
-  testClipboardValue('text/html', '<img id="logo" src="about:logo">');
+  var expected = '<img id="logo" src="about:logo">';
+  if (navigator.platform.indexOf("Win") >= 0) {
+    expected = "<html><body>\n<!--StartFragment-->" + expected + "<!--EndFragment-->\n</body>\n</html>";
+  }
+  testClipboardValue('text/html', expected);
 
   SimpleTest.finish();
 }
 
 SimpleTest.waitForExplicitFinish();
 addLoadEvent(function() {
   SpecialPowers.pushPrefEnv({"set": [["clipboard.plainTextOnly", false]]}, testCopyImage);
 });
--- a/dom/events/DataTransfer.cpp
+++ b/dom/events/DataTransfer.cpp
@@ -1356,17 +1356,24 @@ DataTransfer::FillInExternalData(Transfe
 
     nsCOMPtr<nsISupportsString> supportsstr = do_QueryInterface(data);
     if (supportsstr) {
       nsAutoString str;
       supportsstr->GetData(str);
       variant->SetAsAString(str);
     }
     else {
-      variant->SetAsISupports(data);
+      nsCOMPtr<nsISupportsCString> supportscstr = do_QueryInterface(data);
+      if (supportscstr) {
+        nsAutoCString str;
+        supportscstr->GetData(str);
+        variant->SetAsACString(str);
+      } else {
+        variant->SetAsISupports(data);
+      }
     }
 
     aItem.mData = variant;
   }
 
 void
 DataTransfer::FillAllExternalData()
 {
--- a/editor/libeditor/nsHTMLDataTransfer.cpp
+++ b/editor/libeditor/nsHTMLDataTransfer.cpp
@@ -807,18 +807,17 @@ nsHTMLEditor::StripFormattingNodes(nsICo
 }
 
 NS_IMETHODIMP nsHTMLEditor::PrepareTransferable(nsITransferable **transferable)
 {
   return NS_OK;
 }
 
 nsresult
-nsHTMLEditor::PrepareHTMLTransferable(nsITransferable **aTransferable,
-                                      bool aHavePrivFlavor)
+nsHTMLEditor::PrepareHTMLTransferable(nsITransferable **aTransferable)
 {
   // Create generic Transferable for getting the data
   nsresult rv = CallCreateInstance("@mozilla.org/widget/transferable;1", aTransferable);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Get the nsITransferable interface for getting the data from the clipboard
   if (aTransferable)
   {
@@ -826,20 +825,17 @@ nsHTMLEditor::PrepareHTMLTransferable(ns
     nsILoadContext* loadContext = destdoc ? destdoc->GetLoadContext() : nullptr;
     (*aTransferable)->Init(loadContext);
 
     // Create the desired DataFlavor for the type of data
     // we want to get out of the transferable
     // This should only happen in html editors, not plaintext
     if (!IsPlaintextEditor())
     {
-      if (!aHavePrivFlavor)
-      {
-        (*aTransferable)->AddDataFlavor(kNativeHTMLMime);
-      }
+      (*aTransferable)->AddDataFlavor(kNativeHTMLMime);
       (*aTransferable)->AddDataFlavor(kHTMLMime);
       (*aTransferable)->AddDataFlavor(kFileMime);
 
       switch (Preferences::GetInt("clipboard.paste_image_type", 1))
       {
         case 0:  // prefer JPEG over PNG over GIF encoding
           (*aTransferable)->AddDataFlavor(kJPEGImageMime);
           (*aTransferable)->AddDataFlavor(kJPGImageMime);
@@ -1090,16 +1086,17 @@ nsresult nsHTMLEditor::InsertObject(cons
   return NS_OK;
 }
 
 nsresult
 nsHTMLEditor::InsertFromTransferable(nsITransferable *transferable,
                                      nsIDOMDocument *aSourceDoc,
                                      const nsAString & aContextStr,
                                      const nsAString & aInfoStr,
+                                     bool havePrivateHTMLFlavor,
                                      nsIDOMNode *aDestinationNode,
                                      int32_t aDestOffset,
                                      bool aDoDeleteSelection)
 {
   nsresult rv = NS_OK;
   nsXPIDLCString bestFlavor;
   nsCOMPtr<nsISupports> genericDataObj;
   uint32_t len = 0;
@@ -1129,22 +1126,34 @@ nsHTMLEditor::InsertFromTransferable(nsI
         textDataObj->GetData(cfhtml);
         NS_ASSERTION(cfhtml.Length() <= (len), "Invalid length!");
         nsXPIDLString cfcontext, cffragment, cfselection; // cfselection left emtpy for now
 
         rv = ParseCFHTML(cfhtml, getter_Copies(cffragment), getter_Copies(cfcontext));
         if (NS_SUCCEEDED(rv) && !cffragment.IsEmpty())
         {
           nsAutoEditBatch beginBatching(this);
-          rv = DoInsertHTMLWithContext(cffragment,
-                                       cfcontext, cfselection, flavor,
-                                       aSourceDoc,
-                                       aDestinationNode, aDestOffset,
-                                       aDoDeleteSelection,
-                                       isSafe);
+          // If we have our private HTML flavor, we will only use the fragment
+          // from the CF_HTML. The rest comes from the clipboard.
+          if (havePrivateHTMLFlavor) {
+            rv = DoInsertHTMLWithContext(cffragment,
+                                         aContextStr, aInfoStr, flavor,
+                                         aSourceDoc,
+                                         aDestinationNode, aDestOffset,
+                                         aDoDeleteSelection,
+                                         isSafe);
+          } else {
+            rv = DoInsertHTMLWithContext(cffragment,
+                                         cfcontext, cfselection, flavor,
+                                         aSourceDoc,
+                                         aDestinationNode, aDestOffset,
+                                         aDoDeleteSelection,
+                                         isSafe);
+
+          }
         } else {
           // In some platforms (like Linux), the clipboard might return data
           // requested for unknown flavors (for example:
           // application/x-moz-nativehtml).  In this case, treat the data
           // to be pasted as mere HTML to get the best chance of pasting it
           // correctly.
           bestFlavor.AssignLiteral(kHTMLMime);
           // Fall through the next case
@@ -1236,33 +1245,50 @@ nsresult nsHTMLEditor::InsertFromDataTra
         DataTransfer::Cast(aDataTransfer)->GetDataAtNoSecurityCheck(type, aIndex, getter_AddRefs(variant));
         if (variant) {
           nsCOMPtr<nsISupports> object;
           variant->GetAsISupports(getter_AddRefs(object));
           return InsertObject(NS_ConvertUTF16toUTF8(type).get(), object, isSafe,
                               aSourceDoc, aDestinationNode, aDestOffset, aDoDeleteSelection);
         }
       }
-      else if (!hasPrivateHTMLFlavor && type.EqualsLiteral(kNativeHTMLMime)) {
+      else if (type.EqualsLiteral(kNativeHTMLMime)) {
+        // Windows only clipboard parsing.
         nsAutoString text;
-        GetStringFromDataTransfer(aDataTransfer, NS_LITERAL_STRING(kNativeHTMLMime), aIndex, text);
+        GetStringFromDataTransfer(aDataTransfer, type, aIndex, text);
         NS_ConvertUTF16toUTF8 cfhtml(text);
 
         nsXPIDLString cfcontext, cffragment, cfselection; // cfselection left emtpy for now
 
         nsresult rv = ParseCFHTML(cfhtml, getter_Copies(cffragment), getter_Copies(cfcontext));
         if (NS_SUCCEEDED(rv) && !cffragment.IsEmpty())
         {
           nsAutoEditBatch beginBatching(this);
-          return DoInsertHTMLWithContext(cffragment,
-                                         cfcontext, cfselection, type,
-                                         aSourceDoc,
-                                         aDestinationNode, aDestOffset,
-                                         aDoDeleteSelection,
-                                         isSafe);
+
+          if (hasPrivateHTMLFlavor) {
+            // If we have our private HTML flavor, we will only use the fragment
+            // from the CF_HTML. The rest comes from the clipboard.
+            nsAutoString contextString, infoString;
+            GetStringFromDataTransfer(aDataTransfer, NS_LITERAL_STRING(kHTMLContext), aIndex, contextString);
+            GetStringFromDataTransfer(aDataTransfer, NS_LITERAL_STRING(kHTMLInfo), aIndex, infoString);
+            return DoInsertHTMLWithContext(cffragment,
+                                           contextString, infoString, type,
+                                           aSourceDoc,
+                                           aDestinationNode, aDestOffset,
+                                           aDoDeleteSelection,
+                                           isSafe);
+          }
+          else {
+            return DoInsertHTMLWithContext(cffragment,
+                                           cfcontext, cfselection, type,
+                                           aSourceDoc,
+                                           aDestinationNode, aDestOffset,
+                                           aDoDeleteSelection,
+                                           isSafe);
+          }
         }
       }
       else if (type.EqualsLiteral(kHTMLMime)) {
         nsAutoString text, contextString, infoString;
         GetStringFromDataTransfer(aDataTransfer, type, aIndex, text);
         GetStringFromDataTransfer(aDataTransfer, NS_LITERAL_STRING(kHTMLContext), aIndex, contextString);
         GetStringFromDataTransfer(aDataTransfer, NS_LITERAL_STRING(kHTMLInfo), aIndex, infoString);
 
@@ -1316,36 +1342,34 @@ NS_IMETHODIMP nsHTMLEditor::Paste(int32_
     return NS_OK;
   }
 
   // Get Clipboard Service
   nsresult rv;
   nsCOMPtr<nsIClipboard> clipboard(do_GetService("@mozilla.org/widget/clipboard;1", &rv));
   NS_ENSURE_SUCCESS(rv, rv);
 
-  // find out if we have our internal html flavor on the clipboard.  We don't want to mess
-  // around with cfhtml if we do.
-  bool bHavePrivateHTMLFlavor = HavePrivateHTMLFlavor(clipboard);
-
   // Get the nsITransferable interface for getting the data from the clipboard
   nsCOMPtr<nsITransferable> trans;
-  rv = PrepareHTMLTransferable(getter_AddRefs(trans), bHavePrivateHTMLFlavor);
+  rv = PrepareHTMLTransferable(getter_AddRefs(trans));
   NS_ENSURE_SUCCESS(rv, rv);
   NS_ENSURE_TRUE(trans, NS_ERROR_FAILURE);
   // Get the Data from the clipboard
   rv = clipboard->GetData(trans, aSelectionType);
   NS_ENSURE_SUCCESS(rv, rv);
   if (!IsModifiable()) {
     return NS_OK;
   }
 
   // also get additional html copy hints, if present
   nsAutoString contextStr, infoStr;
 
-  // also get additional html copy hints, if present
+  // 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> contextTrans =
                   do_CreateInstance("@mozilla.org/widget/transferable;1");
@@ -1383,17 +1407,17 @@ NS_IMETHODIMP nsHTMLEditor::Paste(int32_
   }
 
   // handle transferable hooks
   nsCOMPtr<nsIDOMDocument> domdoc;
   GetDocument(getter_AddRefs(domdoc));
   if (!nsEditorHookUtils::DoInsertionHook(domdoc, nullptr, trans))
     return NS_OK;
 
-  return InsertFromTransferable(trans, nullptr, contextStr, infoStr,
+  return InsertFromTransferable(trans, nullptr, contextStr, infoStr, bHavePrivateHTMLFlavor,
                                 nullptr, 0, true);
 }
 
 NS_IMETHODIMP nsHTMLEditor::PasteTransferable(nsITransferable *aTransferable)
 {
   // Use an invalid value for the clipboard type as data comes from aTransferable
   // and we don't currently implement a way to put that in the data transfer yet.
   if (!FireClipboardEvent(ePaste, nsIClipboard::kGlobalClipboard)) {
@@ -1401,17 +1425,17 @@ NS_IMETHODIMP nsHTMLEditor::PasteTransfe
   }
 
   // handle transferable hooks
   nsCOMPtr<nsIDOMDocument> domdoc = GetDOMDocument();
   if (!nsEditorHookUtils::DoInsertionHook(domdoc, nullptr, aTransferable))
     return NS_OK;
 
   nsAutoString contextStr, infoStr;
-  return InsertFromTransferable(aTransferable, nullptr, contextStr, infoStr,
+  return InsertFromTransferable(aTransferable, nullptr, contextStr, infoStr, false,
                                 nullptr, 0, true);
 }
 
 //
 // HTML PasteNoFormatting. Ignore any HTML styles and formating in paste source
 //
 NS_IMETHODIMP nsHTMLEditor::PasteNoFormatting(int32_t aSelectionType)
 {
@@ -1431,17 +1455,17 @@ NS_IMETHODIMP nsHTMLEditor::PasteNoForma
   nsCOMPtr<nsITransferable> trans;
   rv = nsPlaintextEditor::PrepareTransferable(getter_AddRefs(trans));
   if (NS_SUCCEEDED(rv) && trans)
   {
     // Get the Data from the clipboard
     if (NS_SUCCEEDED(clipboard->GetData(trans, aSelectionType)) && IsModifiable())
     {
       const nsAFlatString& empty = EmptyString();
-      rv = InsertFromTransferable(trans, nullptr, empty, empty, nullptr, 0,
+      rv = InsertFromTransferable(trans, nullptr, empty, empty, false, nullptr, 0,
                                   true);
     }
   }
 
   return rv;
 }
 
 
--- a/editor/libeditor/nsHTMLEditor.h
+++ b/editor/libeditor/nsHTMLEditor.h
@@ -547,21 +547,22 @@ protected:
   nsresult InsertObject(const char* aType, nsISupports* aObject, bool aIsSafe,
                         nsIDOMDocument *aSourceDoc,
                         nsIDOMNode *aDestinationNode,
                         int32_t aDestOffset,
                         bool aDoDeleteSelection);
 
   // factored methods for handling insertion of data from transferables (drag&drop or clipboard)
   NS_IMETHOD PrepareTransferable(nsITransferable **transferable) override;
-  nsresult PrepareHTMLTransferable(nsITransferable **transferable, bool havePrivFlavor);
+  nsresult PrepareHTMLTransferable(nsITransferable **transferable);
   nsresult InsertFromTransferable(nsITransferable *transferable,
                                     nsIDOMDocument *aSourceDoc,
                                     const nsAString & aContextStr,
                                     const nsAString & aInfoStr,
+                                    bool havePrivateHTMLFlavor,
                                     nsIDOMNode *aDestinationNode,
                                     int32_t aDestinationOffset,
                                     bool aDoDeleteSelection);
   nsresult InsertFromDataTransfer(mozilla::dom::DataTransfer *aDataTransfer,
                                   int32_t aIndex,
                                   nsIDOMDocument *aSourceDoc,
                                   nsIDOMNode *aDestinationNode,
                                   int32_t aDestOffset,
--- a/editor/libeditor/tests/test_bug525389.html
+++ b/editor/libeditor/tests/test_bug525389.html
@@ -21,17 +21,23 @@ function getLoadContext() {
 
 function runTest() {
   var pasteCount = 0;
   var pasteFunc = function (event) { pasteCount++; };
 
   function verifyContent(s) {
     var e = document.getElementById('i1');
     var doc = e.contentDocument;
-    is(doc.body.innerHTML, s, "");
+    if (navigator.platform.indexOf("Win") >= 0) {
+      // On Windows ignore \n which got left over from the removal of the fragment tags
+      // <html><body>\n<!--StartFragment--> and <!--EndFragment-->\n</body>\n</html>.
+      is(doc.body.innerHTML.replace(/\n/g, ""), s, "");
+    } else {
+      is(doc.body.innerHTML, s, "");
+    }
   }
 
   function pasteInto(trans, html, target_id) {
     var e = document.getElementById('i1');
     var doc = e.contentDocument;
     doc.designMode = "on";
     doc.body.innerHTML = html;
     doc.defaultView.focus();
--- a/widget/nsPrimitiveHelpers.cpp
+++ b/widget/nsPrimitiveHelpers.cpp
@@ -74,16 +74,50 @@ nsPrimitiveHelpers :: CreatePrimitiveFor
         primitive->SetData(Substring(start, start + (aDataLen / 2)));
       }
       NS_ADDREF(*aPrimitive = primitive);
     }
   }
 
 } // CreatePrimitiveForData
 
+//
+// CreatePrimitiveForCFHTML
+//
+// Platform specific CreatePrimitive, windows CF_HTML.
+//
+void
+nsPrimitiveHelpers :: CreatePrimitiveForCFHTML ( const void* aDataBuff,
+                                                 uint32_t* aDataLen, nsISupports** aPrimitive )
+{
+  if (!aPrimitive)
+    return;
+
+  nsCOMPtr<nsISupportsString> primitive =
+    do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID);
+  if (!primitive)
+    return;
+
+  // We need to duplicate the input buffer, since the removal of linebreaks
+  // might reallocte it.
+  void* utf8 = moz_xmalloc(*aDataLen);
+  if (!utf8)
+    return;
+  memcpy(utf8, aDataBuff, *aDataLen);
+  int32_t signedLen = static_cast<int32_t>(*aDataLen);
+  nsLinebreakHelpers::ConvertPlatformToDOMLinebreaks(kTextMime, &utf8, &signedLen);
+  *aDataLen = signedLen;
+
+  nsAutoString str(NS_ConvertUTF8toUTF16(reinterpret_cast<const char*>(utf8), *aDataLen));
+  free(utf8);
+  *aDataLen = str.Length() * sizeof(char16_t);
+  primitive->SetData(str);
+  NS_ADDREF(*aPrimitive = primitive);
+}
+
 
 //
 // CreateDataFromPrimitive
 //
 // Given a nsISupports* primitive and the flavor it represents, creates a new data
 // buffer with the data in it. This data will be null terminated, but the length
 // parameter does not reflect that.
 //
--- a/widget/nsPrimitiveHelpers.h
+++ b/widget/nsPrimitiveHelpers.h
@@ -18,16 +18,20 @@ class nsPrimitiveHelpers
 public:
 
     // Given some data and the flavor it corresponds to, creates the appropriate
     // nsISupports* wrapper for passing across IDL boundaries. The length parameter
     // should not include the null if the data is null terminated.
   static void CreatePrimitiveForData ( const char* aFlavor, const void* aDataBuff,
                                          uint32_t aDataLen, nsISupports** aPrimitive ) ;
 
+    // A specific case of CreatePrimitive for windows CF_HTML handling in DataTransfer
+  static void CreatePrimitiveForCFHTML ( const void* aDataBuff,
+                                         uint32_t* aDataLen, nsISupports** aPrimitive ) ;
+
     // Given a nsISupports* primitive and the flavor it represents, creates a new data
     // buffer with the data in it. This data will be null terminated, but the length
     // parameter does not reflect that.
   static void CreateDataFromPrimitive ( const char* aFlavor, nsISupports* aPrimitive, 
                                          void** aDataBuff, uint32_t aDataLen ) ;
 
 }; // class nsPrimitiveHelpers
 
--- a/widget/windows/nsClipboard.cpp
+++ b/widget/windows/nsClipboard.cpp
@@ -97,17 +97,18 @@ UINT nsClipboard::GetFormat(const char* 
     format = CF_UNICODETEXT;
   else if (strcmp(aMimeStr, kJPEGImageMime) == 0 ||
            strcmp(aMimeStr, kJPGImageMime) == 0 ||
            strcmp(aMimeStr, kPNGImageMime) == 0)
     format = CF_DIBV5;
   else if (strcmp(aMimeStr, kFileMime) == 0 ||
            strcmp(aMimeStr, kFilePromiseMime) == 0)
     format = CF_HDROP;
-  else if (strcmp(aMimeStr, kNativeHTMLMime) == 0)
+  else if (strcmp(aMimeStr, kNativeHTMLMime) == 0 ||
+           strcmp(aMimeStr, kHTMLMime) == 0)
     format = CF_HTML;
   else
     format = ::RegisterClipboardFormatW(NS_ConvertASCIItoUTF16(aMimeStr).get());
 
   return format;
 }
 
 //-------------------------------------------------------------------------
@@ -619,29 +620,47 @@ nsresult nsClipboard::GetDataFromDataObj
           if ( strcmp(flavorStr, kFileMime) == 0 ) {
             // we have a file path in |data|. Create an nsLocalFile object.
             nsDependentString filepath(reinterpret_cast<char16_t*>(data));
             nsCOMPtr<nsIFile> file;
             if ( NS_SUCCEEDED(NS_NewLocalFile(filepath, false, getter_AddRefs(file))) )
               genericDataWrapper = do_QueryInterface(file);
             free(data);
           }
-        else if ( strcmp(flavorStr, kNativeHTMLMime) == 0) {
+        else if ( strcmp(flavorStr, kNativeHTMLMime) == 0 ) {
+          uint32_t dummy;
           // the editor folks want CF_HTML exactly as it's on the clipboard, no conversions,
           // no fancy stuff. Pull it off the clipboard, stuff it into a wrapper and hand
           // it back to them.
-          if ( FindPlatformHTML(aDataObject, anIndex, &data, &dataLen) )
+          if ( FindPlatformHTML(aDataObject, anIndex, &data, &dummy, &dataLen) )
             nsPrimitiveHelpers::CreatePrimitiveForData ( flavorStr, data, dataLen, getter_AddRefs(genericDataWrapper) );
           else
           {
             free(data);
             continue;     // something wrong with this flavor, keep looking for other data
           }
           free(data);
         }
+        else if ( strcmp(flavorStr, kHTMLMime) == 0 ) {
+          uint32_t startOfData = 0;
+          // The JS folks want CF_HTML exactly as it is on the clipboard, but
+          // minus the CF_HTML header index information.
+          // It also needs to be converted to UTF16 and have linebreaks changed.
+          if ( FindPlatformHTML(aDataObject, anIndex, &data, &startOfData, &dataLen) ) {
+            dataLen -= startOfData;
+            nsPrimitiveHelpers::CreatePrimitiveForCFHTML ( static_cast<char*>(data) + startOfData,
+                                                           &dataLen, getter_AddRefs(genericDataWrapper) );
+          }
+          else
+          {
+            free(data);
+            continue;     // something wrong with this flavor, keep looking for other data
+          }
+          free(data);
+        }
         else if ( strcmp(flavorStr, kJPEGImageMime) == 0 ||
                   strcmp(flavorStr, kJPGImageMime) == 0 ||
                   strcmp(flavorStr, kPNGImageMime) == 0) {
           nsIInputStream * imageStream = reinterpret_cast<nsIInputStream*>(data);
           genericDataWrapper = do_QueryInterface(imageStream);
           NS_IF_RELEASE(imageStream);
         }
         else {
@@ -673,17 +692,19 @@ nsresult nsClipboard::GetDataFromDataObj
 
 
 //
 // FindPlatformHTML
 //
 // Someone asked for the OS CF_HTML flavor. We give it back to them exactly as-is.
 //
 bool
-nsClipboard :: FindPlatformHTML ( IDataObject* inDataObject, UINT inIndex, void** outData, uint32_t* outDataLen )
+nsClipboard :: FindPlatformHTML ( IDataObject* inDataObject, UINT inIndex,
+                                  void** outData, uint32_t* outStartOfData,
+                                  uint32_t* outDataLen )
 {
   // Reference: MSDN doc entitled "HTML Clipboard Format"
   // http://msdn.microsoft.com/en-us/library/aa767917(VS.85).aspx#unknown_854
   // CF_HTML is UTF8, not unicode. We also can't rely on it being null-terminated
   // so we have to check the CF_HTML header for the correct length. 
   // The length we return is the bytecount from the beginning of the selected data to the end
   // of the selected data, without the null termination. Because it's UTF8, we're guaranteed 
   // the header is ASCII.
@@ -716,16 +737,20 @@ nsClipboard :: FindPlatformHTML ( IDataO
   if (!endOfData || startOfData >= endOfData || 
       static_cast<uint32_t>(endOfData) > *outDataLen) {
     return false;
   }
   
   // We want to return the buffer not offset by startOfData because it will be 
   // parsed out later (probably by nsHTMLEditor::ParseCFHTML) when it is still
   // in CF_HTML format.
+
+  // We return the byte offset from the start of the data buffer to where the
+  // HTML data starts. The caller might want to extract the HTML only.
+  *outStartOfData = startOfData;
   *outDataLen = endOfData;
   return true;
 }
 
 
 //
 // FindURLFromLocalFile
 //
--- a/widget/windows/nsClipboard.h
+++ b/widget/windows/nsClipboard.h
@@ -58,17 +58,18 @@ public:
 protected:
   NS_IMETHOD SetNativeClipboardData ( int32_t aWhichClipboard );
   NS_IMETHOD GetNativeClipboardData ( nsITransferable * aTransferable, int32_t aWhichClipboard );
   
   static bool IsInternetShortcut ( const nsAString& inFileName ) ;
   static bool FindURLFromLocalFile ( IDataObject* inDataObject, UINT inIndex, void** outData, uint32_t* outDataLen ) ;
   static bool FindURLFromNativeURL ( IDataObject* inDataObject, UINT inIndex, void** outData, uint32_t* outDataLen ) ;
   static bool FindUnicodeFromPlainText ( IDataObject* inDataObject, UINT inIndex, void** outData, uint32_t* outDataLen ) ;
-  static bool FindPlatformHTML ( IDataObject* inDataObject, UINT inIndex, void** outData, uint32_t* outDataLen );
+  static bool FindPlatformHTML ( IDataObject* inDataObject, UINT inIndex, void** outData,
+                                 uint32_t* outStartOfData, uint32_t* outDataLen );
   static void ResolveShortcut ( nsIFile* inFileName, nsACString& outURL ) ;
 
   nsIWidget         * mWindow;
 
 };
 
 #define SET_FORMATETC(fe, cf, td, asp, li, med)   \
    {\
--- a/widget/windows/nsDragService.cpp
+++ b/widget/windows/nsDragService.cpp
@@ -534,16 +534,24 @@ nsDragService::IsDataFlavorSupported(con
         // have a file, then we have a URL to give them (the path, or
         // the internal URL if an InternetShortcut).
         format = nsClipboard::GetFormat(kFileMime);
         SET_FORMATETC(fe, format, 0, DVASPECT_CONTENT, -1,
                       TYMED_HGLOBAL | TYMED_FILE | TYMED_GDI);
         if (mDataObject->QueryGetData(&fe) == S_OK)
           *_retval = true;                 // found it!
       }
+      else if (strcmp(aDataFlavor, kHTMLMime) == 0) {
+        // If the client wants html, maybe it's in "HTML Format".
+        format = nsClipboard::GetFormat(kHTMLMime);
+        SET_FORMATETC(fe, format, 0, DVASPECT_CONTENT, -1,
+                      TYMED_HGLOBAL);
+        if (mDataObject->QueryGetData(&fe) == S_OK)
+          *_retval = true;                 // found it!
+      }
     } // else try again
   }
 
   return NS_OK;
 }
 
 
 //