Bug 116083 - Correctly handle the whitespace in all preformatted elements; r=roc
authorEhsan Akhgari <ehsan@mozilla.com>
Mon, 01 Dec 2014 06:38:11 -0500
changeset 218160 d5ef728a519d9f1dd3c2e2652fdbfeca802c7fec
parent 218159 e121302253359416d67a07699afeac40225146f6
child 218161 fd6779c9a336aedfff2982b4335e28ffe3161182
push id27919
push userphilringnalda@gmail.com
push dateTue, 02 Dec 2014 03:07:26 +0000
treeherdermozilla-central@265e01c7ff55 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc
bugs116083
milestone37.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 116083 - Correctly handle the whitespace in all preformatted elements; r=roc Previously this code only handled the special case of a <body> element that had an explicit style attribute, which doesn't really make sense. Now we do the right thing based on the computed white-space style.
dom/base/nsDocumentEncoder.cpp
dom/base/test/mochitest.ini
dom/base/test/test_bug116083.html
--- a/dom/base/nsDocumentEncoder.cpp
+++ b/dom/base/nsDocumentEncoder.cpp
@@ -46,16 +46,17 @@
 #include "nsIFrame.h"
 #include "nsStringBuffer.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/ShadowRoot.h"
 #include "nsIEditor.h"
 #include "nsIHTMLEditor.h"
 #include "nsIDocShell.h"
 #include "mozilla/dom/EncodingUtils.h"
+#include "nsComputedDOMStyle.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 nsresult NS_NewDomSelection(nsISelection **aDomSelection);
 
 enum nsRangeIterationDirection {
   kDirectionOut = -1,
@@ -1384,29 +1385,33 @@ nsHTMLCopyEncoder::SetSelection(nsISelec
     // checking for selection inside a plaintext form widget
     nsIAtom *atom = selContent->Tag();
     if (atom == nsGkAtoms::input ||
         atom == nsGkAtoms::textarea)
     {
       mIsTextWidget = true;
       break;
     }
-    else if (atom == nsGkAtoms::body)
-    {
-      // check for moz prewrap style on body.  If it's there we are 
-      // in a plaintext editor.  This is pretty cheezy but I haven't 
-      // found a good way to tell if we are in a plaintext editor.
-      nsCOMPtr<nsIDOMElement> bodyElem = do_QueryInterface(selContent);
-      nsAutoString wsVal;
-      rv = bodyElem->GetAttribute(NS_LITERAL_STRING("style"), wsVal);
-      if (NS_SUCCEEDED(rv) && (kNotFound != wsVal.Find(NS_LITERAL_STRING("pre-wrap"))))
-      {
-        mIsTextWidget = true;
-        break;
+    else if (selContent->IsElement()) {
+      nsRefPtr<nsStyleContext> styleContext =
+        nsComputedDOMStyle::GetStyleContextForElementNoFlush(selContent->AsElement(),
+                                                             nullptr, nullptr);
+      if (styleContext) {
+        const nsStyleText* textStyle = styleContext->StyleText();
+        switch (textStyle->mWhiteSpace) {
+        case NS_STYLE_WHITESPACE_PRE:
+        case NS_STYLE_WHITESPACE_PRE_WRAP:
+        case NS_STYLE_WHITESPACE_PRE_LINE:
+        case NS_STYLE_WHITESPACE_PRE_SPACE:
+          // Copy as plaintext for all preformatted elements
+          mIsTextWidget = true;
+          break;
+        }
       }
+      break;
     }
   }
   
   // normalize selection if we are not in a widget
   if (mIsTextWidget) 
   {
     mSelection = aSelection;
     mMimeType.AssignLiteral("text/plain");
--- a/dom/base/test/mochitest.ini
+++ b/dom/base/test/mochitest.ini
@@ -238,16 +238,17 @@ support-files =
 [test_anonymousContent_api.html]
 [test_anonymousContent_append_after_reflow.html]
 [test_anonymousContent_insert.html]
 [test_anonymousContent_manipulate_content.html]
 [test_appname_override.html]
 [test_audioWindowUtils.html]
 [test_audioNotification.html]
 skip-if = buildapp == 'mulet'
+[test_bug116083.html]
 [test_bug793311.html]
 [test_bug913761.html]
 [test_bug976673.html]
 [test_bug978522.html]
 [test_bug979109.html]
 [test_bug989665.html]
 [test_bug999456.html]
 [test_bug1022229.html]
new file mode 100644
--- /dev/null
+++ b/dom/base/test/test_bug116083.html
@@ -0,0 +1,48 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=116083
+-->
+<head>
+  <title>Test for Bug 116083</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="application/javascript" src="/tests/SimpleTest/EventUtils.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=116083">Mozilla Bug 116083</a>
+<div id="content">
+<div style="white-space: pre">foo  bar</div>
+<div style="white-space: pre-wrap">foo  bar</div>
+<div style="white-space: pre-line">foo  bar</div>
+<div style="white-space: -moz-pre-space">foo  bar</div>
+<div data-result="&#10;foo bar&#10;">foo  bar</div>
+</div>
+<script type="application/javascript">
+
+SimpleTest.waitForExplicitFinish();
+SimpleTest.waitForFocus(function nextTest() {
+  var div = document.querySelector("#content>div");
+  if (!div) {
+    SimpleTest.finish();
+    return;
+  }
+  getSelection().selectAllChildren(div);
+  var expected = div.hasAttribute("data-result") ?
+                 div.getAttribute("data-result") :
+                 div.textContent;
+  SimpleTest.waitForClipboard(expected, function() {
+    synthesizeKey("C", {accelKey: true});
+  }, function() {
+    ok(true, div.getAttribute("style") + " passed");
+    div.parentNode.removeChild(div);
+    nextTest();
+  }, function() {
+    ok(false, "failed to copy the expected content to the clipboard");
+    SimpleTest.finish();
+  });
+});
+
+</script>
+</body>
+</html>