Bug 1622231 - Make HTMLEditor::SetInlinePropertyAsAction() override property if it's called for XUL cmd_fontFace with a magic value "tt" r=m_kato

`FontFaceStateCommand::SetState()` called
`HTMLEditor::SetInlinePropertyAsAction()` with `nsGkAtoms::tt` when given value
is "tt".
https://searchfox.org/mozilla-central/rev/bc5737c51b8da4e758cf4db0ddb606f0aea81a7d/editor/libeditor/HTMLEditorCommands.cpp#626-627

However, I accidentally not ported this to
`HTMLEditor::SetInlinePropertyAsAction()`.  Therefore, this patch restores the
old code for the magic value.

Differential Revision: https://phabricator.services.mozilla.com/D74379
This commit is contained in:
Masayuki Nakano 2020-05-11 07:30:47 +00:00
parent 2158dd66ed
commit e317a8bfb7
3 changed files with 103 additions and 8 deletions

View File

@ -79,6 +79,10 @@ nsresult HTMLEditor::SetInlinePropertyAsAction(nsAtom& aProperty,
AutoPlaceholderBatch treatAsOneTransaction(*this);
nsAtom* property = &aProperty;
nsAtom* attribute = aAttribute;
nsAutoString value(aValue);
if (&aProperty == nsGkAtoms::sup) {
// Superscript and Subscript styles are mutually exclusive.
nsresult rv = RemoveInlinePropertyInternal(nsGkAtoms::sub, nullptr,
@ -116,17 +120,34 @@ nsresult HTMLEditor::SetInlinePropertyAsAction(nsAtom& aProperty,
return EditorBase::ToGenericNSResult(rv);
}
} else if (&aProperty == nsGkAtoms::font && aAttribute == nsGkAtoms::face) {
nsresult rv = RemoveInlinePropertyInternal(nsGkAtoms::tt, nullptr,
RemoveRelatedElements::No);
if (NS_FAILED(rv)) {
NS_WARNING(
"HTMLEditor::RemoveInlinePropertyInternal(nsGkAtoms::tt, "
"RemoveRelatedElements::No) failed");
return EditorBase::ToGenericNSResult(rv);
if (!value.LowerCaseEqualsASCII("tt")) {
nsresult rv = RemoveInlinePropertyInternal(nsGkAtoms::tt, nullptr,
RemoveRelatedElements::No);
if (NS_FAILED(rv)) {
NS_WARNING(
"HTMLEditor::RemoveInlinePropertyInternal(nsGkAtoms::tt, "
"RemoveRelatedElements::No) failed");
return EditorBase::ToGenericNSResult(rv);
}
} else {
nsresult rv = RemoveInlinePropertyInternal(
nsGkAtoms::font, nsGkAtoms::face, RemoveRelatedElements::No);
if (NS_FAILED(rv)) {
NS_WARNING(
"HTMLEditor::RemoveInlinePropertyInternal(nsGkAtoms::font, "
"nsGkAtoms::face, RemoveRelatedElements::No) failed");
return EditorBase::ToGenericNSResult(rv);
}
// Override property, attribute and value if the new font face value is
// "tt".
property = nsGkAtoms::tt;
attribute = nullptr;
value.Truncate();
}
}
}
rv = SetInlinePropertyInternal(aProperty, aAttribute, aValue);
rv = SetInlinePropertyInternal(MOZ_KnownLive(*property),
MOZ_KnownLive(attribute), value);
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
"HTMLEditor::SetInlinePropertyInternal() failed");
return EditorBase::ToGenericNSResult(rv);

View File

@ -233,6 +233,7 @@ skip-if = os == "android" #Bug 1575739
skip-if = os == 'android' # Bug 1525959
[test_CF_HTML_clipboard.html]
skip-if = os != 'mac' # bug 574005
[test_cmd_fontFace_with_tt.html]
[test_composition_event_created_in_chrome.html]
[test_contenteditable_focus.html]
[test_cut_copy_delete_command_enabled.html]

View File

@ -0,0 +1,73 @@
<!doctype html>
<html>
<head>
<title>Testing font face "tt"</title>
<link rel="stylesheet" href="/tests/SimpleTest/test.css">
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<script src="/tests/SimpleTest/EventUtils.js"></script>
</head>
<body>
<div id="display">
</div>
<div id="content" contenteditable>abc</div>
<pre id="test">
</pre>
<script class="testbody">
"use strict";
SimpleTest.waitForExplicitFinish();
SimpleTest.waitForFocus(() => {
let editor = document.querySelector("div[contenteditable]");
editor.focus();
let selection = document.getSelection();
// "tt" is a magic value of "cmd_fontFace", it should work as "cmd_tt".
editor.innerHTML = "abc";
selection.setBaseAndExtent(editor.firstChild, 1, editor.firstChild, 2);
SpecialPowers.doCommand(window, "cmd_fontFace", "tt");
is(editor.innerHTML, "a<tt>b</tt>c",
"\"cmd_fontFace\" with \"tt\" should wrap selected text <tt> element");
editor.innerHTML = "<br>";
selection.collapse(editor, 0);
SpecialPowers.doCommand(window, "cmd_fontFace", "tt");
synthesizeKey("t");
synthesizeKey("t");
is(editor.innerHTML, "<tt>tt</tt><br>",
"Typed text after \"cmd_fontFace\" with \"tt\" should be wrapped by <tt> element");
// But it shouldn't work with `Document.execCommand()`.
editor.innerHTML = "abc";
selection.setBaseAndExtent(editor.firstChild, 1, editor.firstChild, 2);
document.execCommand("fontname", false, "tt");
is(editor.innerHTML, "a<font face=\"tt\">b</font>c",
"execCommand(\"fontname\") with \"tt\" should wrap selected text with <font> element");
editor.innerHTML = "<br>";
selection.collapse(editor, 0);
document.execCommand("fontname", false, "tt");
synthesizeKey("t");
synthesizeKey("t");
is(editor.innerHTML, "<font face=\"tt\">tt</font><br>",
"Typed text after execCommand(\"fontname\") with \"tt\" should be wrapped by <font> element");
// "cmd_fontFace" with "tt" should remove `<font>` element.
editor.innerHTML = "a<font face=\"sans-serif\">b</font>c";
selection.selectAllChildren(editor.querySelector("font"));
SpecialPowers.doCommand(window, "cmd_fontFace", "tt");
is(editor.innerHTML, "a<tt>b</tt>c",
"\"cmd_fontFace\" with \"tt\" should wrap selected text <tt> element after removing <font> element");
editor.innerHTML = "<font face=\"sans-serif\">abc</font>";
selection.setBaseAndExtent(editor.firstChild.firstChild, 1, editor.firstChild.firstChild, 2);
SpecialPowers.doCommand(window, "cmd_fontFace", "tt");
is(editor.innerHTML, "<font face=\"sans-serif\">a</font><tt>b</tt><font face=\"sans-serif\">c</font>",
"\"cmd_fontFace\" with \"tt\" should wrap selected text <tt> element after removing <font> element");
SimpleTest.finish();
});
</script>
</body>
</html>