tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit 920ab7c1733347ebb766e3ab38653c03e5da7f85
parent e14e162ea0a9bc1d598f99f67d46238eada88de7
Author: Alexandru Marc <amarc@mozilla.com>
Date:   Wed,  5 Nov 2025 03:07:21 +0200

Revert "Bug 1650720 - Part 4: Add line break tests for copying selection; r=masayuki" for causing mochitest failures @ test_aboutmemory3.xhtml

This reverts commit 62ce647fff1bead097d8f508383c4532974ec0ca.

Revert "Bug 1650720 - Part 3: Align link break coversion for clipboard copy with other browsers; r=masayuki"

This reverts commit 3ced2a72e8f763cfb4c49c9d4d5abac0037732c1.

Revert "Bug 1650720 - Part 2: Simplify nsPlainTextSerializer::ConvertToLinesAndOutput; r=masayuki"

This reverts commit 5e63b05f5423767984fbaed39ae09b5b5c01df62.

Revert "Bug 1650720 - Part 1: Add plaintext serializer tests for linebreak; r=masayuki"

This reverts commit 21953f6384e82c6ad50f6eafd9adeecb47ef65af.

Diffstat:
Mdom/base/nsCopySupport.cpp | 1-
Mdom/serializers/nsPlainTextSerializer.cpp | 70++++++++++++++++++++++++++++++----------------------------------------
Mdom/serializers/nsPlainTextSerializer.h | 12++++++------
Mdom/serializers/tests/mochitest/mochitest.toml | 2--
Ddom/serializers/tests/mochitest/test_plaintext_linebreak.html | 146-------------------------------------------------------------------------------
Dtesting/web-platform/meta/clipboard-apis/clipboard-copy-selection-line-break.https.html.ini | 70----------------------------------------------------------------------
Dtesting/web-platform/tests/clipboard-apis/clipboard-copy-selection-line-break.https.html | 119-------------------------------------------------------------------------------
Mtesting/web-platform/tests/clipboard-apis/resources/user-activation.js | 11-----------
8 files changed, 36 insertions(+), 395 deletions(-)

diff --git a/dom/base/nsCopySupport.cpp b/dom/base/nsCopySupport.cpp @@ -132,7 +132,6 @@ static nsresult EncodeForTextUnicode(nsIDocumentEncoder& aEncoder, } else { // Redo the encoding, but this time use pretty printing. flags = nsIDocumentEncoder::OutputSelectionOnly | - nsIDocumentEncoder::OutputForPlainTextClipboardCopy | nsIDocumentEncoder::OutputAbsoluteLinks | nsIDocumentEncoder::SkipInvisibleContent | nsIDocumentEncoder::OutputDropInvisibleBreak | diff --git a/dom/serializers/nsPlainTextSerializer.cpp b/dom/serializers/nsPlainTextSerializer.cpp @@ -219,8 +219,8 @@ void nsPlainTextSerializer::OutputManager::Append(const nsAString& aString) { } } -void nsPlainTextSerializer::OutputManager::AppendLineBreak(bool aForceCRLF) { - mOutput.Append(aForceCRLF ? u"\r\n"_ns : mLineBreak); +void nsPlainTextSerializer::OutputManager::AppendLineBreak() { + mOutput.Append(mLineBreak); mAtFirstColumn = true; } @@ -482,13 +482,6 @@ nsPlainTextSerializer::AppendText(Text* aText, int32_t aStartOffset, TextEditor::MaskString(textstr, *aText, 0, aStartOffset); } - if (mSettings.HasFlag(nsIDocumentEncoder::OutputForPlainTextClipboardCopy)) { - // XXX it would be nice if we could just use the Write() to handle the line - // breaks for all cases (bug 1993406). - Write(textstr); - return rv; - } - // We have to split the string across newlines // to match parser behavior int32_t start = 0; @@ -1503,55 +1496,60 @@ static void ReplaceVisiblyTrailingNbsps(nsAString& aString) { } void nsPlainTextSerializer::ConvertToLinesAndOutput(const nsAString& aString) { - nsAString::const_iterator iter; - aString.BeginReading(iter); - nsAString::const_iterator done_searching; - aString.EndReading(done_searching); + const int32_t totLen = aString.Length(); + int32_t newline{0}; // Put the mail quote "> " chars in, if appropriate. // Have to put it in before every line. - while (iter != done_searching) { - nsAString::const_iterator bol = iter; - nsAString::const_iterator newline = done_searching; + int32_t bol = 0; + while (bol < totLen) { + bool outputLineBreak = false; + bool spacesOnly = true; // Find one of '\n' or '\r' using iterators since nsAString // doesn't have the old FindCharInSet function. - bool spacesOnly = true; + nsAString::const_iterator iter; + aString.BeginReading(iter); + nsAString::const_iterator done_searching; + aString.EndReading(done_searching); + iter.advance(bol); + int32_t new_newline = bol; + newline = kNotFound; while (iter != done_searching) { if ('\n' == *iter || '\r' == *iter) { - newline = iter; + newline = new_newline; break; } if (' ' != *iter) { spacesOnly = false; } + ++new_newline; ++iter; } // Done searching nsAutoString stringpart; - bool outputLineBreak = false; - bool isNewLineCRLF = false; - if (newline == done_searching) { + if (newline == kNotFound) { // No new lines. - stringpart.Assign(Substring(bol, newline)); + stringpart.Assign(Substring(aString, bol, totLen - bol)); if (!stringpart.IsEmpty()) { char16_t lastchar = stringpart.Last(); mInWhitespace = IsLineFeedCarriageReturnBlankOrTab(lastchar); } mEmptyLines = -1; + bol = totLen; } else { // There is a newline - stringpart.Assign(Substring(bol, newline)); + stringpart.Assign(Substring(aString, bol, newline - bol)); mInWhitespace = true; outputLineBreak = true; mEmptyLines = 0; - if ('\r' == *iter++ && '\n' == *iter) { + bol = newline + 1; + if ('\r' == *iter && bol < totLen && '\n' == *++iter) { // There was a CRLF in the input. This used to be illegal and // stripped by the parser. Apparently not anymore. Let's skip // over the LF. - newline = iter++; - isNewLineCRLF = true; + bol++; } } @@ -1570,19 +1568,15 @@ void nsPlainTextSerializer::ConvertToLinesAndOutput(const nsAString& aString) { mOutputManager->Append(mCurrentLine, OutputManager::StripTrailingWhitespaces::kNo); if (outputLineBreak) { - if (mSettings.HasFlag( - nsIDocumentEncoder::OutputForPlainTextClipboardCopy)) { - // This is aligned with other browsers that they don't convert CRLF to - // the platform line break. - ('\n' == *newline) ? mOutputManager->AppendLineBreak(isNewLineCRLF) - : mOutputManager->Append(u"\r"_ns); - } else { - mOutputManager->AppendLineBreak(); - } + mOutputManager->AppendLineBreak(); } mCurrentLine.ResetContentAndIndentationHeader(); } + +#ifdef DEBUG_wrapping + printf("No wrapping: newline is %d, totLen is %d\n", newline, totLen); +#endif } /** @@ -1681,14 +1675,10 @@ void nsPlainTextSerializer::Write(const nsAString& aStr) { continue; } - if (nextpos == bol && - !mSettings.HasFlag( - nsIDocumentEncoder::OutputForPlainTextClipboardCopy)) { + if (nextpos == bol) { // Note that we are in whitespace. mInWhitespace = true; offsetIntoBuffer = str.get() + nextpos; - // XXX Why do we need to keep the very first character when compressing - // the reset? AddToLine(offsetIntoBuffer, 1); bol++; continue; diff --git a/dom/serializers/nsPlainTextSerializer.h b/dom/serializers/nsPlainTextSerializer.h @@ -283,12 +283,7 @@ class nsPlainTextSerializer final : public nsIContentSerializer { void Append(const CurrentLine& aCurrentLine, StripTrailingWhitespaces aStripTrailingWhitespaces); - /** - * @param aString Last character is expected to not be a line break. - */ - void Append(const nsAString& aString); - - void AppendLineBreak(bool aForceCRLF = false); + void AppendLineBreak(); /** * This empties the current line cache without adding a NEWLINE. @@ -305,6 +300,11 @@ class nsPlainTextSerializer final : public nsIContentSerializer { uint32_t GetOutputLength() const; private: + /** + * @param aString Last character is expected to not be a line break. + */ + void Append(const nsAString& aString); + // As defined in nsIDocumentEncoder.idl. const int32_t mFlags; diff --git a/dom/serializers/tests/mochitest/mochitest.toml b/dom/serializers/tests/mochitest/mochitest.toml @@ -123,5 +123,3 @@ skip-if = [ ["test_htmlcopyencoder.html"] ["test_htmlcopyencoder.xhtml"] - -["test_plaintext_linebreak.html"] diff --git a/dom/serializers/tests/mochitest/test_plaintext_linebreak.html b/dom/serializers/tests/mochitest/test_plaintext_linebreak.html @@ -1,146 +0,0 @@ -<!DOCTYPE HTML> -<html> -<head> -<title>Test line breaks for plaintext serializer</title> -<script src="/tests/SimpleTest/SimpleTest.js"></script> -<script 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=1650720">Mozilla Bug 1650720</a> -<p id="display"></p> -<div id="content" style="display: none"> -</div> -<pre id="preformatted"></pre> -<div id="container"></div> -<script> - -const de = SpecialPowers.Ci.nsIDocumentEncoder; -const platformLineBreak = navigator.platform.indexOf("Win") == 0 ? "\r\n" : "\n"; -const CASES = [ - "\r", - "\n", - "\r\r", - "\r\n", - "\n\r", - "\n\n", - "\r\r\r", - "\r\r\n", - "\r\n\r", - "\r\n\n", - "\n\r\r", - "\n\r\n", - "\n\n\r", - "\n\n\n", - "\r \n", - "\n \r", -]; - -function convertLineBreaksForTestResult(aText) { - return aText.replace(/\r?\n|\r(?!\n)/g, platformLineBreak); -} - -function convertLineBreaksForClipboardTestResult(aText) { - return aText.replace(/(?<!\r)\n/g, platformLineBreak); -} - -function selectAndEncode(aElement, aEncoderFlags = 0) { - // Select the element. - const selection = window.getSelection(); - selection.removeAllRanges(); - selection.selectAllChildren(aElement); - - const encoder = SpecialPowers.Cu.createHTMLCopyEncoder(); - encoder.init(document, "text/plain", de.OutputSelectionOnly | aEncoderFlags); - encoder.setSelection(selection); - return encoder.encodeToString(); -} - -CASES.forEach((lineBreaks) => { - const text = `${lineBreaks}First${lineBreaks}Second${lineBreaks}`; - - add_task(async function test_pre_text() { - info(`Testing line breaks: ${JSON.stringify(lineBreaks)}`); - - const pre = document.getElementById("preformatted"); - pre.textContent = text; - - is(selectAndEncode(pre), text.replace(/\r|\n/g, platformLineBreak), - `Encoded data for line breaks: ${JSON.stringify(lineBreaks)}`); - is(selectAndEncode(pre, de.OutputForPlainTextClipboardCopy), convertLineBreaksForClipboardTestResult(text), - `Encoded data for line breaks: ${JSON.stringify(lineBreaks)} (OutputForPlainTextClipboardCopy)`); - }); - - add_task(async function test_pre_img_alt() { - info(`Testing line breaks: ${JSON.stringify(lineBreaks)}`); - - const pre = document.getElementById("preformatted"); - const img = document.createElement("img"); - img.alt = text; - pre.replaceChildren(img); - - is(selectAndEncode(pre), convertLineBreaksForTestResult(text), - `Encoded data for line breaks: ${JSON.stringify(lineBreaks)}`); - is(selectAndEncode(pre, de.OutputForPlainTextClipboardCopy), convertLineBreaksForClipboardTestResult(text), - `Encoded data for line breaks: ${JSON.stringify(lineBreaks)} (OutputForPlainTextClipboardCopy)`); - }); - - add_task(async function test_pre_img_title() { - info(`Testing line breaks: ${JSON.stringify(lineBreaks)}`); - - const pre = document.getElementById("preformatted"); - const img = document.createElement("img"); - img.title = text; - pre.replaceChildren(img); - - is(selectAndEncode(pre), ` [${convertLineBreaksForTestResult(text)}] `, - `Encoded data for line breaks: ${JSON.stringify(lineBreaks)}`); - is(selectAndEncode(pre, de.OutputForPlainTextClipboardCopy), ` [${convertLineBreaksForClipboardTestResult(text)}] `, - `Encoded data for line breaks: ${JSON.stringify(lineBreaks)} (OutputForPlainTextClipboardCopy)`); - }); - - add_task(async function test_div_text() { - info(`Testing line breaks: ${JSON.stringify(lineBreaks)}`); - - const div = document.getElementById("container"); - div.textContent = text; - - is(selectAndEncode(div), ` First Second `, - `Encoded data for line breaks: ${JSON.stringify(lineBreaks)}`); - is(selectAndEncode(div, de.OutputForPlainTextClipboardCopy), ` First Second `, - `Encoded data for line breaks: ${JSON.stringify(lineBreaks)} (OutputForPlainTextClipboardCopy)`); - }); - - add_task(async function test_div_img_alt() { - info(`Testing line breaks: ${JSON.stringify(lineBreaks)}`); - - const div = document.getElementById("container"); - const img = document.createElement("img"); - img.alt = text; - div.replaceChildren(img); - - // Our plain text serializer keep the first CR/LF. - is(selectAndEncode(div), `${lineBreaks[0]}First Second `, - `Encoded data for line breaks: ${JSON.stringify(lineBreaks)}`); - is(selectAndEncode(div, de.OutputForPlainTextClipboardCopy), ` First Second `, - `Encoded data for line breaks: ${JSON.stringify(lineBreaks)} (OutputForPlainTextClipboardCopy)`); - }); - - add_task(async function test_div_img_title() { - info(`Testing line breaks: ${JSON.stringify(lineBreaks)}`); - - const div = document.getElementById("container"); - const img = document.createElement("img"); - img.title = text; - div.replaceChildren(img); - - is(selectAndEncode(div), ` [ First Second ] `, - `Encoded data for line breaks: ${JSON.stringify(lineBreaks)}`); - is(selectAndEncode(div, de.OutputForPlainTextClipboardCopy), ` [ First Second ] `, - `Encoded data for line breaks: ${JSON.stringify(lineBreaks)} (OutputForPlainTextClipboardCopy)`); - }); -}); - -</script> -</body> -</html> diff --git a/testing/web-platform/meta/clipboard-apis/clipboard-copy-selection-line-break.https.html.ini b/testing/web-platform/meta/clipboard-apis/clipboard-copy-selection-line-break.https.html.ini @@ -1,70 +0,0 @@ -[clipboard-copy-selection-line-break.https.html?31-last] - [test preformatted text with line breaks: "\\n \\r"] - expected: - if (os == "win") or (os == "linux"): FAIL # https://bugzilla.mozilla.org/show_bug.cgi?id=1997585 - - -[clipboard-copy-selection-line-break.https.html?1-10] - [test preformatted text with line breaks: "\\r"] - expected: - if (os == "win") or (os == "linux"): FAIL # https://bugzilla.mozilla.org/show_bug.cgi?id=1997585 - - [test preformatted text with line breaks: "\\n"] - expected: - if os == "win": FAIL # https://bugzilla.mozilla.org/show_bug.cgi?id=1997585 - - [test preformatted text with line breaks: "\\r\\r"] - expected: - if (os == "win") or (os == "linux"): FAIL # https://bugzilla.mozilla.org/show_bug.cgi?id=1997585 - - [test preformatted text with line breaks: "\\r\\n"] - expected: - if (os == "win") or (os == "linux"): FAIL # https://bugzilla.mozilla.org/show_bug.cgi?id=1997585 - - [test preformatted text with line breaks: "\\n\\r"] - expected: - if (os == "win") or (os == "linux"): FAIL # https://bugzilla.mozilla.org/show_bug.cgi?id=1997585 - - -[clipboard-copy-selection-line-break.https.html?11-20] - [test preformatted text with line breaks: "\\n\\n"] - expected: - if os == "win": FAIL # https://bugzilla.mozilla.org/show_bug.cgi?id=1997585 - - [test preformatted text with line breaks: "\\r\\r\\r"] - expected: - if (os == "win") or (os == "linux"): FAIL # https://bugzilla.mozilla.org/show_bug.cgi?id=1997585 - - [test preformatted text with line breaks: "\\r\\r\\n"] - expected: - if (os == "win") or (os == "linux"): FAIL # https://bugzilla.mozilla.org/show_bug.cgi?id=1997585 - - [test preformatted text with line breaks: "\\r\\n\\r"] - expected: - if (os == "win") or (os == "linux"): FAIL # https://bugzilla.mozilla.org/show_bug.cgi?id=1997585 - - [test preformatted text with line breaks: "\\r\\n\\n"] - expected: - if (os == "win") or (os == "linux"): FAIL # https://bugzilla.mozilla.org/show_bug.cgi?id=1997585 - - -[clipboard-copy-selection-line-break.https.html?21-30] - [test preformatted text with line breaks: "\\n\\r\\r"] - expected: - if (os == "win") or (os == "linux"): FAIL # https://bugzilla.mozilla.org/show_bug.cgi?id=1997585 - - [test preformatted text with line breaks: "\\n\\r\\n"] - expected: - if (os == "win") or (os == "linux"): FAIL # https://bugzilla.mozilla.org/show_bug.cgi?id=1997585 - - [test preformatted text with line breaks: "\\n\\n\\r"] - expected: - if (os == "win") or (os == "linux"): FAIL # https://bugzilla.mozilla.org/show_bug.cgi?id=1997585 - - [test preformatted text with line breaks: "\\n\\n\\n"] - expected: - if os == "win": FAIL # https://bugzilla.mozilla.org/show_bug.cgi?id=1997585 - - [test preformatted text with line breaks: "\\r \\n"] - expected: - if (os == "win") or (os == "linux"): FAIL # https://bugzilla.mozilla.org/show_bug.cgi?id=1997585 diff --git a/testing/web-platform/tests/clipboard-apis/clipboard-copy-selection-line-break.https.html b/testing/web-platform/tests/clipboard-apis/clipboard-copy-selection-line-break.https.html @@ -1,119 +0,0 @@ -<!doctype html> -<meta charset="utf-8"> -<meta name="timeout" content="long"> -<meta name="variant" content="?1-10"> -<meta name="variant" content="?11-20"> -<meta name="variant" content="?21-30"> -<meta name="variant" content="?31-last"> -<title>Clipboard copy selection tests - Line breaks</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<script src="/resources/testdriver.js"></script> -<script src="/resources/testdriver-vendor.js"></script> -<script src="/resources/testdriver-actions.js"></script> -<script src="/common/subset-tests.js"></script> -<script src="resources/user-activation.js"></script> -<body> -Body needed for test_driver.click()<br> -<div id="paragraph"></div> -<pre id="preformatted"></pre> -<script> - - const CASES = [ - "\r", - "\n", - "\r\r", - "\r\n", - "\n\r", - "\n\n", - "\r\r\r", - "\r\r\n", - "\r\n\r", - "\r\n\n", - "\n\r\r", - "\n\r\n", - "\n\n\r", - "\n\n\n", - "\r \n", - "\n \r", - ]; - - function normalizeForPrinting(s) { - return s.replace(/\r/g, "\\r").replace(/\n/g, "\\n"); - } - - function normalizeForComparison(s) { - // Convert LF to CRLF on Windows. - return navigator.platform.includes('Win') ? s.replace(/\r?\n/g, '\r\n') : s; - } - - // Permissions are required in order to invoke navigator.clipboard functions in - // an automated test. - async function getPermissions() { - await tryGrantReadPermission(); - await tryGrantWritePermission(); - await waitForUserActivation(); - } - - async function selectTextAndCopy(id, text) { - const element = document.getElementById(id); - element.textContent = text; - - await waitForUserActivation(); - - // Select the text. - const selection = window.getSelection(); - selection.removeAllRanges(); - selection.selectAllChildren(element); - - // Copy the selection to the clipboard. - await new Promise((resolve) => { - document.addEventListener("copy", e => { - assert_true(true, "selection copid to clipboard"); - resolve(); - }, { once: true }); - document.execCommand("copy"); - }); - } - - async function getTextFromPasteEvent() { - return new Promise((resolve) => { - document.addEventListener("paste", e => { - e.preventDefault(); - resolve(e.clipboardData.getData("text/plain")); - }, { once: true }); - sendPasteShortcutKey(); - }); - } - - async function getTextFromClipboardReadText() { - await waitForUserActivation(); - return navigator.clipboard.readText(); - } - - CASES.forEach(testCase => { - const text = `First${testCase}Second`; - - subsetTest(promise_test, async t => { - await getPermissions(); - await selectTextAndCopy("preformatted", text); - let clipboardText = await getTextFromPasteEvent(); - assert_equals(clipboardText, normalizeForComparison(text), "Check result from DataTransfer in paste event"); - - clipboardText = await getTextFromClipboardReadText(); - assert_equals(clipboardText, normalizeForComparison(text), "Check result from navigator.clipboard.readText()"); - }, `test preformatted text with line breaks: "${normalizeForPrinting(testCase)}"`); - - subsetTest(promise_test, async t => { - await getPermissions(); - await selectTextAndCopy("paragraph", text); - let clipboardText = await getTextFromPasteEvent(); - assert_equals(clipboardText, `First Second`, "Check result from DataTransfer in paste event"); - - clipboardText = await getTextFromClipboardReadText(); - assert_equals(clipboardText, `First Second`, "Check result from navigator.clipboard.readText()"); - }, `test paragraph text with line breaks: "${normalizeForPrinting(testCase)}"`); - }); - -</script> -</body> diff --git a/testing/web-platform/tests/clipboard-apis/resources/user-activation.js b/testing/web-platform/tests/clipboard-apis/resources/user-activation.js @@ -42,14 +42,3 @@ async function tryGrantWritePermission() { await trySetPermission("clipboard-write", "granted"); } -async function sendPasteShortcutKey() { - const modifier = navigator.platform.includes("Mac") ? "\uE03d" // META - : "\uE009"; // CONTROL - await new test_driver.Actions() - .keyDown(modifier) - .keyDown("v") - .keyUp("v") - .keyUp(modifier) - .send(); -} -