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 307986 e1b5927361ac2fbcb7075c19061d1b73a70487dc
parent 307985 9bf9d97873fe66037bd14176d2d09affec617fe2
child 307987 0c34cc2dc429d2ea06415dc977def64d1a7ac72a
push id5513
push userraliiev@mozilla.com
push dateMon, 25 Jan 2016 13:55:34 +0000
treeherdermozilla-beta@5ee97dd05b5c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjimm
bugs586587
milestone45.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 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;
 }
 
 
 //