Bug 888839 - Don't pretty print text/plain when copying and pasting non-(X)HTML documents. r=smaug
authorDrew Willcoxon <adw@mozilla.com>
Fri, 19 Jul 2013 19:56:18 -0700
changeset 141850 cb05c6b8ae8e59e5ebc585c0ec9534ab23c9ac04
parent 141849 2b9d71496f60a2044f120f502332474251ce4a3b
child 141851 914bf3adc1ed28584a92f7bc63dfe8da39d0c595
push id32250
push userdwillcoxon@mozilla.com
push dateFri, 09 Aug 2013 03:40:23 +0000
treeherdermozilla-inbound@914bf3adc1ed [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs888839
milestone26.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
testing/mochitest/android.json
testing/mochitest/androidx86.json
testing/mochitest/b2g.json
--- 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
@@ -322,16 +322,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 \
@@ -659,16 +661,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>
--- a/testing/mochitest/android.json
+++ b/testing/mochitest/android.json
@@ -6,16 +6,18 @@
  "content/base/test/test_bug466080.html": "",
  "content/base/test/test_bug475156.html": "bug 855762",
  "content/base/test/test_bug482935.html": "bug 855762",
  "content/base/test/test_bug503481.html": "TIMED_OUT",
  "content/base/test/test_bug503481b.html": "TIMED_OUT",
  "content/base/test/test_bug505783.html": "TIMED_OUT",
  "content/base/test/test_bug590812.html": "bug 687032",
  "content/base/test/test_copypaste.html": "",
+ "content/base/test/test_copypaste.xhtml": "",
+ "content/base/test/test_copypaste.xul": "",
  "content/base/test/test_CrossSiteXHR.html": "",
  "content/base/test/test_CrossSiteXHR_cache.html": "",
  "content/base/test/test_CrossSiteXHR_origin.html": "",
  "content/base/test/test_CSP.html": "TIMED_OUT",
  "content/base/test/test_CSP_frameancestors.html": "",
  "content/base/test/test_CSP_inlinescript.html": "",
  "content/base/test/test_CSP_evalscript_getCRMFRequest.html": "bug 824652",
  "content/base/test/test_csp_redirects.html": "TIMED_OUT",
--- a/testing/mochitest/androidx86.json
+++ b/testing/mochitest/androidx86.json
@@ -7,16 +7,18 @@
  "content/base/test/test_bug466080.html": "",
  "content/base/test/test_bug475156.html": "bug 855762",
  "content/base/test/test_bug482935.html": "bug 855762",
  "content/base/test/test_bug503481.html": "TIMED_OUT",
  "content/base/test/test_bug503481b.html": "TIMED_OUT",
  "content/base/test/test_bug505783.html": "TIMED_OUT",
  "content/base/test/test_bug590812.html": "bug 687032",
  "content/base/test/test_copypaste.html": "",
+ "content/base/test/test_copypaste.xhtml": "",
+ "content/base/test/test_copypaste.xul": "",
  "content/base/test/test_CrossSiteXHR.html": "",
  "content/base/test/test_CrossSiteXHR_cache.html": "",
  "content/base/test/test_CrossSiteXHR_origin.html": "",
  "content/base/test/test_CSP.html": "TIMED_OUT",
  "content/base/test/test_CSP_frameancestors.html": "",
  "content/base/test/test_CSP_inlinescript.html": "",
  "content/base/test/test_CSP_evalscript_getCRMFRequest.html": "bug 824652",
  "content/base/test/test_csp_redirects.html": "TIMED_OUT",
--- a/testing/mochitest/b2g.json
+++ b/testing/mochitest/b2g.json
@@ -155,16 +155,18 @@
     "content/base/test/test_bug498433.html":"",
     "content/base/test/test_bug650386_redirect_301.html":"",
     "content/base/test/test_bug650386_redirect_302.html":"",
     "content/base/test/test_bug650386_redirect_303.html":"",
     "content/base/test/test_bug650386_redirect_307.html":"",
     "content/base/test/test_bug717511.html":"",
     "content/base/test/test_child_process_shutdown_message.html":"",
     "content/base/test/test_copypaste.html":"",
+    "content/base/test/test_copypaste.xhtml":"",
+    "content/base/test/test_copypaste.xul":"",
     "content/base/test/test_csp_redirects.html":"",
     "content/base/test/test_fileapi_slice.html":"",
     "content/base/test/test_messagemanager_assertpermission.html":"",
     "content/base/test/test_mixed_content_blocker.html":"",
     "content/base/test/test_mixed_content_blocker_bug803225.html":"",
     "content/base/test/test_mixed_content_blocker_frameNavigation.html":"",
     "content/base/test/test_mozfiledataurl.html":"",
     "content/base/test/test_websocket.html":"",