Bug 888839 - Don't pretty print text/plain when copying and pasting non-(X)HTML documents. r=smaug
☠☠ backed out by 646cba66eb0c ☠ ☠
authorDrew Willcoxon <adw@mozilla.com>
Fri, 19 Jul 2013 19:56:18 -0700
changeset 151649 9e7d1f4496ffec08ad3a0cd72df54c8f320b6fed
parent 151648 9437024e3bf993c6e76fbe3695d0820c3706f920
child 151650 8e995398c00adf7b3a0893332c00c44d875b964c
push id2859
push userakeybl@mozilla.com
push dateMon, 16 Sep 2013 19:14:59 +0000
treeherdermozilla-beta@87d3c51cd2bf [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs888839
milestone25.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 888839 - Don't pretty print text/plain when copying and pasting non-(X)HTML documents. r=smaug
content/base/src/nsCopySupport.cpp
content/base/test/Makefile.in
content/base/test/copypaste.js
content/base/test/test_copypaste.html
content/base/test/test_copypaste.xhtml
content/base/test/test_copypaste.xul
--- a/content/base/src/nsCopySupport.cpp
+++ b/content/base/src/nsCopySupport.cpp
@@ -111,20 +111,31 @@ SelectionCopyHelper(nsISelection *aSel, 
   rv = docEncoder->GetMimeType(mimeType);
   NS_ENSURE_SUCCESS(rv, rv);
   bool selForcedTextPlain = mimeType.EqualsLiteral(kTextMime);
 
   nsAutoString buf;
   rv = docEncoder->EncodeToString(buf);
   NS_ENSURE_SUCCESS(rv, rv);
 
+  rv = docEncoder->GetMimeType(mimeType);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  if (!selForcedTextPlain && mimeType.EqualsLiteral(kTextMime)) {
+    // SetSelection and EncodeToString use this case to signal that text/plain
+    // was forced because the document is either not an nsIHTMLDocument or it's
+    // XHTML.  We want to pretty print XHTML but not non-nsIHTMLDocuments.
+    nsCOMPtr<nsIHTMLDocument> htmlDoc = do_QueryInterface(aDoc);
+    if (!htmlDoc) {
+      selForcedTextPlain = true;
+    }
+  }
+
   // The mime type is ultimately text/html if the encoder successfully encoded
   // the selection as text/html.
-  rv = docEncoder->GetMimeType(mimeType);
-  NS_ENSURE_SUCCESS(rv, rv);
   bool encodedTextHTML = mimeType.EqualsLiteral(kHTMLMime);
 
   // First, prepare the text/plain clipboard flavor.
   nsAutoString textPlainBuf;
   if (selForcedTextPlain) {
     // Nothing to do.  buf contains the final, preformatted, raw text/plain.
     textPlainBuf.Assign(buf);
   } else {
--- a/content/base/test/Makefile.in
+++ b/content/base/test/Makefile.in
@@ -328,16 +328,18 @@ MOCHITEST_FILES_B = \
 		file_mozfiledataurl_doc.html \
 		file_mozfiledataurl_text.txt \
 		test_bug475156.html \
 		bug475156.sjs \
 		test_bug544642.html \
 		test_bug564863.xhtml \
 		test_bug588990.html \
 		test_copypaste.html \
+		test_copypaste.xhtml \
+		copypaste.js \
 		test_bug503481.html \
 		file_bug503481.sjs \
 		test_bug503481b.html \
 		file_bug503481b_inner.html \
 		test_viewport_scroll.html \
 		test_CSP.html \
 		file_CSP.sjs \
 		file_CSP.css \
@@ -650,16 +652,17 @@ MOCHITEST_FILES_B += \
 		test_messagemanager_assertpermission.html \
 		test_child_process_shutdown_message.html \
 		$(NULL)
 endif
 endif
 
 MOCHITEST_CHROME_FILES =	\
 		test_bug357450.js \
+		test_copypaste.xul \
 		$(NULL)
 
 # This test fails on the Mac for some reason
 ifneq (,$(filter gtk2 gtk3 windows,$(MOZ_WIDGET_TOOLKIT)))
 MOCHITEST_FILES_C += \
 		test_copyimage.html \
 		$(NULL)
 endif
new file mode 100644
--- /dev/null
+++ b/content/base/test/copypaste.js
@@ -0,0 +1,269 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+function modifySelection(s) {
+  var g = window.getSelection();
+  var l = g.getRangeAt(0);
+  var d = document.createElement("p");
+  d.innerHTML = s;
+  d.appendChild(l.cloneContents());
+
+  var e = document.createElement("div");
+  document.body.appendChild(e);
+  e.appendChild(d);
+  var a = document.createRange();
+  a.selectNode(d);
+  g.removeAllRanges();
+  g.addRange(a);
+  window.setTimeout(function () {
+      e.parentNode.removeChild(e);
+      g.removeAllRanges();
+      g.addRange(l);
+  }, 0)
+}
+
+function getLoadContext() {
+  var Ci = SpecialPowers.wrap(Components).interfaces;
+  return SpecialPowers.wrap(window).QueryInterface(Ci.nsIInterfaceRequestor)
+                                   .getInterface(Ci.nsIWebNavigation)
+                                   .QueryInterface(Ci.nsILoadContext);
+}
+
+function testCopyPaste (isXHTML) {
+  netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+
+  var suppressUnicodeCheckIfHidden = !!isXHTML;
+  var suppressHTMLCheck = !!isXHTML;
+
+  var webnav = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
+                     .getInterface(Components.interfaces.nsIWebNavigation)
+
+  var docShell = webnav.QueryInterface(Components.interfaces.nsIDocShell);
+
+  var documentViewer = docShell.contentViewer
+                               .QueryInterface(Components.interfaces.nsIContentViewerEdit);
+
+  var clipboard = Components.classes["@mozilla.org/widget/clipboard;1"]
+                            .getService(Components.interfaces.nsIClipboard);
+
+  var textarea = SpecialPowers.wrap(document.getElementById('input'));
+
+  function copySelectionToClipboard(suppressUnicodeCheck) {
+    documentViewer.copySelection();
+    if (!suppressUnicodeCheck)
+      ok(clipboard.hasDataMatchingFlavors(["text/unicode"], 1,1), "check text/unicode");
+    if (!suppressHTMLCheck)
+      ok(clipboard.hasDataMatchingFlavors(["text/html"], 1,1), "check text/html");
+  }
+  function copyToClipboard(node, suppressUnicodeCheck) {
+    textarea.blur();
+    clipboard.emptyClipboard(1);
+    var sel = window.getSelection();
+    sel.removeAllRanges();
+    var r = document.createRange();
+    r.selectNode(node);
+    window.getSelection().addRange(r);
+    copySelectionToClipboard(suppressUnicodeCheck);
+  }
+  function copyRangeToClipboard(startNode,startIndex,endNode,endIndex,suppressUnicodeCheck) {
+    textarea.blur();
+    clipboard.emptyClipboard(1);
+    var sel = window.getSelection();
+    sel.removeAllRanges();
+    var r = document.createRange();
+    r.setStart(startNode,startIndex)
+    r.setEnd(endNode,endIndex)
+    window.getSelection().addRange(r);
+    copySelectionToClipboard(suppressUnicodeCheck);
+  }
+  function copyChildrenToClipboard(id) {
+    textarea.blur();
+    clipboard.emptyClipboard(1);
+    window.getSelection().selectAllChildren(document.getElementById(id));
+    copySelectionToClipboard();
+  }
+  function getClipboardData(mime) {
+    var transferable = Components.classes['@mozilla.org/widget/transferable;1']
+                                 .createInstance(Components.interfaces.nsITransferable);
+    transferable.init(getLoadContext());
+    transferable.addDataFlavor(mime);
+    clipboard.getData(transferable, 1);
+    var data = {};
+    transferable.getTransferData(mime, data, {}) ;
+    return data;
+  }
+  function testClipboardValue(mime, expected) {
+    if (suppressHTMLCheck && mime == "text/html")
+      return null;
+    var data = getClipboardData(mime);
+    is (data.value == null ? data.value :
+        data.value.QueryInterface(Components.interfaces.nsISupportsString).data,
+      expected,
+      mime + " value in the clipboard");
+    return data.value;
+  }
+  function testPasteText(expected) {
+    textarea.value="";
+    textarea.focus();
+    textarea.editor.paste(1);
+    is(textarea.value, expected, "value of the textarea after the paste");
+  }
+  function testSelectionToString(expected) {
+    is(window.getSelection().toString().replace(/\r\n/g,"\n"), expected, "Selection.toString");
+  }
+  function testInnerHTML(id, expected) {
+    var value = document.getElementById(id).innerHTML;
+    is(value, expected, id + ".innerHTML");
+  }
+  function testEmptyChildren(id) {
+    copyChildrenToClipboard(id);
+    testSelectionToString("");
+    testClipboardValue("text/unicode", null);
+    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",
+                     "<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>");
+  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>");
+  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>");
+  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>");
+    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>");
+    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>");
+    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>");
+    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) {
+  testClipboardValue("text/unicode", "");
+  testClipboardValue("text/html", "");
+}
+// END Disabled due to bug 564688
+  testInnerHTML("div6", "div6");
+
+  copyRangeToClipboard($("div7").childNodes[0],0, $("div7").childNodes[0],4,suppressUnicodeCheckIfHidden);
+  testSelectionToString("");
+// START Disabled due to bug 564688
+if (false) {
+  testClipboardValue("text/unicode", "");
+  testClipboardValue("text/html", "");
+}
+// END Disabled due to bug 564688
+  testInnerHTML("div7", "div7");
+
+  copyRangeToClipboard($("div8").childNodes[0],0, $("div8").childNodes[0],4,suppressUnicodeCheckIfHidden);
+  testSelectionToString("");
+// START Disabled due to bug 564688
+if (false) {
+  testClipboardValue("text/unicode", "");
+  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");
+  testInnerHTML("div9", "div9");
+
+  copyToClipboard($("div10"), suppressUnicodeCheckIfHidden);
+  testSelectionToString("");
+  testInnerHTML("div10", "div10");
+
+  copyToClipboard($("div10").firstChild, suppressUnicodeCheckIfHidden);
+  testSelectionToString("");
+
+  copyRangeToClipboard($("div10").childNodes[0],0, $("div10").childNodes[0],1,suppressUnicodeCheckIfHidden);
+  testSelectionToString("");
+
+  copyRangeToClipboard($("div10").childNodes[1],0, $("div10").childNodes[1],1,suppressUnicodeCheckIfHidden);
+  testSelectionToString("");
+
+  // ============ copy/paste test from/to a textarea
+
+  var val = "1\n 2\n  3";
+  textarea.value=val;
+  textarea.select();
+  textarea.editor.copy();
+  
+  textarea.value="";
+  textarea.editor.paste(1);
+  is(textarea.value, val);
+  textarea.value="";
+
+  // ============ NOSCRIPT should not be copied
+
+  copyChildrenToClipboard("div13");
+  testSelectionToString("__");
+  testClipboardValue("text/unicode", "__");
+  testClipboardValue("text/html", "<div id=\"div13\">__</div>");
+  testPasteText("__");
+
+  // ============ converting cell boundaries to tabs in tables
+
+  copyToClipboard($("tr1"));
+  testClipboardValue("text/unicode", "foo\tbar");
+
+  // ============ 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>");
+  setTimeout(function(){testSelectionToString("div11")},0);
+
+  setTimeout(function(){
+    netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+    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>");
+    setTimeout(function(){ 
+      testSelectionToString("div12"); 
+      setTimeout(SimpleTest.finish,0);
+    },0);
+  },0);
+}
--- a/content/base/test/test_copypaste.html
+++ b/content/base/test/test_copypaste.html
@@ -1,276 +1,28 @@
 <!DOCTYPE HTML>
 <html>
 <!--
 -->
 <head>
   <title>Test for copy/paste</title>
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="text/javascript" src="copypaste.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 </head>
 <body>
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=524975">Mozilla Bug </a>
 <p id="display"></p>
 <div id="content" style="display: none">
 </div>
 <pre id="test">
 <script class="testbody" type="text/javascript">
-function modifySelection(s) {
-  var g = window.getSelection();
-  var l = g.getRangeAt(0);
-  var d = document.createElement("p");
-  d.innerHTML = s;
-  d.appendChild(l.cloneContents());
-
-  var e = document.createElement("div");
-  document.body.appendChild(e);
-  e.appendChild(d);
-  var a = document.createRange();
-  a.selectNode(d);
-  g.removeAllRanges();
-  g.addRange(a);
-  window.setTimeout(function () {
-      e.parentNode.removeChild(e);
-      g.removeAllRanges();
-      g.addRange(l);
-  }, 0)
-}
-
-function getLoadContext() {
-  var Ci = SpecialPowers.wrap(Components).interfaces;
-  return SpecialPowers.wrap(window).QueryInterface(Ci.nsIInterfaceRequestor)
-                                   .getInterface(Ci.nsIWebNavigation)
-                                   .QueryInterface(Ci.nsILoadContext);
-}
-
-function testCopyPaste () {
-  netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
-
-  var webnav = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
-                     .getInterface(Components.interfaces.nsIWebNavigation)
-
-  var docShell = webnav.QueryInterface(Components.interfaces.nsIDocShell);
-
-  var documentViewer = docShell.contentViewer
-                               .QueryInterface(Components.interfaces.nsIContentViewerEdit);
-
-  var clipboard = Components.classes["@mozilla.org/widget/clipboard;1"]
-                            .getService(Components.interfaces.nsIClipboard);
-
-  var textarea = SpecialPowers.wrap(document.getElementById('input'));
-
-  function copySelectionToClipboard() {
-    documentViewer.copySelection();
-    ok(clipboard.hasDataMatchingFlavors(["text/unicode"], 1,1), "check text/unicode");
-    ok(clipboard.hasDataMatchingFlavors(["text/html"], 1,1), "check text/html");
-  }
-  function copyToClipboard(node) {
-    textarea.blur();
-    clipboard.emptyClipboard(1);
-    var sel = window.getSelection();
-    sel.removeAllRanges();
-    var r = document.createRange();
-    r.selectNode(node);
-    window.getSelection().addRange(r);
-    copySelectionToClipboard();
-  }
-  function copyRangeToClipboard(startNode,startIndex,endNode,endIndex) {
-    textarea.blur();
-    clipboard.emptyClipboard(1);
-    var sel = window.getSelection();
-    sel.removeAllRanges();
-    var r = document.createRange();
-    r.setStart(startNode,startIndex)
-    r.setEnd(endNode,endIndex)
-    window.getSelection().addRange(r);
-    copySelectionToClipboard();
-  }
-  function copyChildrenToClipboard(id) {
-    textarea.blur();
-    clipboard.emptyClipboard(1);
-    window.getSelection().selectAllChildren(document.getElementById(id));
-    copySelectionToClipboard();
-  }
-  function getClipboardData(mime) {
-    var transferable = Components.classes['@mozilla.org/widget/transferable;1']
-                                 .createInstance(Components.interfaces.nsITransferable);
-    transferable.init(getLoadContext());
-    transferable.addDataFlavor(mime);
-    clipboard.getData(transferable, 1);
-    var data = {};
-    transferable.getTransferData(mime, data, {}) ;
-    return data;
-  }
-  function testClipboardValue(mime, expected) {
-    var data = getClipboardData(mime);
-    is (data.value == null ? data.value :
-        data.value.QueryInterface(Components.interfaces.nsISupportsString).data,
-      expected,
-      mime + " value in the clipboard");
-    return data.value;
-  }
-  function testPasteText(expected) {
-    textarea.value="";
-    textarea.focus();
-    textarea.editor.paste(1);
-    is(textarea.value, expected, "value of the textarea after the paste");
-  }
-  function testSelectionToString(expected) {
-    is(window.getSelection().toString().replace(/\r\n/g,"\n"), expected, "Selection.toString");
-  }
-  function testInnerHTML(id, expected) {
-    var value = document.getElementById(id).innerHTML;
-    is(value, expected, id + ".innerHTML");
-  }
-  function testEmptyChildren(id) {
-    copyChildrenToClipboard(id);
-    testSelectionToString("");
-    testClipboardValue("text/unicode", null);
-    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",
-                     "<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>");
-  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>");
-  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>");
-  testPasteText(" mzla\n\n    foo\n        bazzinga!\n    bar\n\n");
-
-  copyChildrenToClipboard("div4");
-  testSelectionToString(" Tt t t ");
-  testClipboardValue("text/unicode", " Tt t t ");
-  testClipboardValue("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 ");
-  testClipboardValue("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);
-  testSelectionToString("");
-// START Disabled due to bug 564688
-if (false) {
-  testClipboardValue("text/unicode", "");
-  testClipboardValue("text/html", "");
-}
-// END Disabled due to bug 564688
-  testInnerHTML("div6", "div6");
-
-  copyRangeToClipboard($("div7").childNodes[0],0, $("div7").childNodes[0],4);
-  testSelectionToString("");
-// START Disabled due to bug 564688
-if (false) {
-  testClipboardValue("text/unicode", "");
-  testClipboardValue("text/html", "");
-}
-// END Disabled due to bug 564688
-  testInnerHTML("div7", "div7");
-
-  copyRangeToClipboard($("div8").childNodes[0],0, $("div8").childNodes[0],4);
-  testSelectionToString("");
-// START Disabled due to bug 564688
-if (false) {
-  testClipboardValue("text/unicode", "");
-  testClipboardValue("text/html", "");
-}
-// END Disabled due to bug 564688
-  testInnerHTML("div8", "div8");
-
-  copyRangeToClipboard($("div9").childNodes[0],0, $("div9").childNodes[0],4);
-  testSelectionToString("div9");
-  testClipboardValue("text/unicode", "div9");
-  testClipboardValue("text/html", "div9");
-  testInnerHTML("div9", "div9");
-
-  copyToClipboard($("div10"));
-  testSelectionToString("");
-  testInnerHTML("div10", "div10");
-
-  copyToClipboard($("div10").firstChild);
-  testSelectionToString("");
-
-  copyRangeToClipboard($("div10").childNodes[0],0, $("div10").childNodes[0],1);
-  testSelectionToString("");
-
-  copyRangeToClipboard($("div10").childNodes[1],0, $("div10").childNodes[1],1);
-  testSelectionToString("");
-
-  // ============ copy/paste test from/to a textarea
-
-  var val = "1\n 2\n  3";
-  textarea.value=val;
-  textarea.select();
-  textarea.editor.copy();
-  
-  textarea.value="";
-  textarea.editor.paste(1);
-  is(textarea.value, val);
-  textarea.value="";
-
-  // ============ NOSCRIPT should not be copied
-
-  copyChildrenToClipboard("div13");
-  testSelectionToString("__");
-  testClipboardValue("text/unicode", "__");
-  testClipboardValue("text/html", "<div id=\"div13\">__</div>");
-  testPasteText("__");
-
-  // ============ converting cell boundaries to tabs in tables
-
-  copyToClipboard($("tr1"));
-  testClipboardValue("text/unicode", "foo\tbar");
-
-  // ============ 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>");
-  setTimeout(function(){testSelectionToString("div11")},0);
-
-  setTimeout(function(){
-    netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
-    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>");
-    setTimeout(function(){ 
-      testSelectionToString("div12"); 
-      setTimeout(SimpleTest.finish,0);
-    },0);
-  },0);
-}
-
 
 SimpleTest.waitForExplicitFinish();
-
-addLoadEvent(testCopyPaste);
+addLoadEvent(function () testCopyPaste(false));
 
 </script>
 </pre>
 <div>
 
   <div id="draggable" title="title to have a long HTML line">This is a <em>draggable</em> bit of text.</div>
   <textarea id="input" cols="40" rows="10"></textarea>
 
new file mode 100644
--- /dev/null
+++ b/content/base/test/test_copypaste.xhtml
@@ -0,0 +1,108 @@
+<?xml version="1.0"?>
+<!--
+This test is copied from test_copypaste.html, but it's XHTML instead of HTML.
+XHTML is encoded differently from HTML when copied; see bugs 888839 and 723163.
+This test is different from test_copypaste.html in two ways:
+
+  1. The text/html clipboard flavor isn't tested, since nsCopySupport doesn't
+     produce it for XHTML.
+  2. The text/unicode flavor isn't tested when the selection is in hidden
+     elements, since nsCopySupport doesn't produce text/plain for hidden
+     elements, and unlike HTML, neither does it produce text/_moz_htmlcontext
+     and text/_moz_htmlinfo, which the clipboard converts to text/unicode.
+-->
+<html xml:lang="en" xmlns="http://www.w3.org/1999/xhtml">
+<head>
+  <title>Test for copy/paste with XHTML</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="text/javascript" src="copypaste.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=888839">Mozilla Bug 888839</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+<![CDATA[
+
+function modifySelectionDiv12() {
+  modifySelection("X<b style='display:none'>Y</b>");
+}
+
+SimpleTest.waitForExplicitFinish();
+addLoadEvent(function () testCopyPaste(true));
+
+]]>
+</script>
+</pre>
+<div>
+
+  <div id="draggable" title="title to have a long HTML line">This is a <em>draggable</em> bit of text.</div>
+  <textarea id="input" cols="40" rows="10"></textarea>
+
+  <div id="alist">
+    bla
+    <ul>
+      <li>foo</li>
+      <li style="display: none;">baz</li>
+      <li>bar</li>
+    </ul>
+  </div>
+
+  <div id="blist">
+    mozilla
+    <ol>
+      <li>foo</li>
+      <li style="display: none;">baz</li>
+      <li>bar</li>
+    </ol>
+  </div>
+
+  <div id="clist">
+    mzla
+    <ul>
+      <li>foo<ul>
+        <li>bazzinga!</li>
+      </ul></li>
+      <li style="display: none;">baz</li>
+      <li>bar</li>
+    </ul>
+  </div>
+
+<div id="div4">
+  T<textarea>t t t</textarea>
+</div>
+
+<div id="div5">
+  T<textarea>     </textarea>
+</div>
+
+<div id="div6" style="display:none"></div>
+<script>
+var x = $("div6")
+x.appendChild(document.createTextNode('di'))
+x.appendChild(document.createTextNode('v6'))
+</script>
+
+<div id="div7" style="display:none">div7</div>
+<div id="div8" style="visibility:hidden">div8</div>
+<div style="visibility:hidden"><div id="div9" style="visibility:visible">div9</div></div>
+<div style="visibility:hidden"><div><div><div id="div10"></div></div></div></div>
+<script>
+var x = $("div10")
+x.appendChild(document.createTextNode('div'))
+x.appendChild(document.createTextNode('10'))
+</script>
+
+<div id="div11" oncopy="modifySelection('X')"><span>div</span>11</div>
+<div id="div12" oncopy="modifySelectionDiv12()"><span>div</span>12</div>
+
+<div id="div13">_<noscript>FAIL</noscript>_</div>
+
+<table><tr id="tr1"><td>foo</td><td>bar</td></tr></table>
+
+</div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/content/base/test/test_copypaste.xul
@@ -0,0 +1,64 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
+<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=888839
+-->
+<window title="Mozilla Bug 888839"
+        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
+
+  <script type="application/javascript"><![CDATA[
+
+let { classes: Cc, interfaces: Ci } = Components;
+
+SimpleTest.waitForExplicitFinish();
+addLoadEvent(runTest);
+
+function runTest() {
+  let desc = document.querySelector("description");
+  window.getSelection().selectAllChildren(desc);
+
+  let webnav = window.
+               QueryInterface(Ci.nsIInterfaceRequestor).
+               getInterface(Ci.nsIWebNavigation);
+
+  webnav.
+    QueryInterface(Ci.nsIDocShell).
+    contentViewer.
+    QueryInterface(Ci.nsIContentViewerEdit).
+    copySelection();
+
+  let mime = "text/unicode";
+  let whichClipboard = Ci.nsIClipboard.kGlobalClipboard;
+  let clipboard = Cc["@mozilla.org/widget/clipboard;1"].
+                  getService(Ci.nsIClipboard);
+  ok(clipboard.hasDataMatchingFlavors([mime], 1, whichClipboard),
+     "Clipboard should have text/unicode");
+
+  let transferable = Cc["@mozilla.org/widget/transferable;1"].
+                     createInstance(Ci.nsITransferable);
+  transferable.init(webnav.QueryInterface(Ci.nsILoadContext));
+  transferable.addDataFlavor(mime);
+  clipboard.getData(transferable, whichClipboard);
+  var data = {};
+  transferable.getTransferData(mime, data, {});
+  is(data.value.QueryInterface(Ci.nsISupportsString).data,
+     "\n    hello\n    world\n  ",
+     "Paste is not HTML, so it should not be pretty printed");
+
+  SimpleTest.finish();
+}
+
+  ]]></script>
+
+  <description style="-moz-user-focus: normal; -moz-user-select: text;"><![CDATA[
+    hello
+    world
+  ]]></description>
+
+  <body xmlns="http://www.w3.org/1999/xhtml">
+  <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=888839"
+     target="_blank">Mozilla Bug 888839</a>
+  </body>
+</window>