Bug 1951007 - Make style editing commands check whether the editing host is contenteditable="plaintext-only" to consider whether it's enabled r=m_kato

The style editing commands should be disabled in
`contenteditable="plaintext-only"`.  Currently, we return `false` from
`execCommand`, but we still claim that the commands are enabled for
`queryCommandEnabled`.

Differential Revision: https://phabricator.services.mozilla.com/D239985
This commit is contained in:
Masayuki Nakano
2025-03-10 06:06:16 +00:00
parent 4433d745a6
commit de3eb719c4
4 changed files with 48 additions and 14 deletions

View File

@@ -486,6 +486,19 @@ void HTMLEditor::PreDestroy() {
PreDestroyInternal();
}
bool HTMLEditor::IsStyleEditable() const {
if (IsInDesignMode()) {
return true;
}
if (IsPlaintextMailComposer()) {
return false;
}
const Element* const editingHost = ComputeEditingHost(LimitInBodyElement::No);
// Let's return true if there is no focused editing host for the backward
// compatibility.
return !editingHost || !editingHost->IsContentEditablePlainTextOnly();
}
NS_IMETHODIMP HTMLEditor::GetDocumentCharacterSet(nsACString& aCharacterSet) {
nsresult rv = GetDocumentCharsetInternal(aCharacterSet);
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),

View File

@@ -400,6 +400,11 @@ class HTMLEditor final : public EditorBase,
*/
bool IsCSSEnabled() const { return mIsCSSPrefChecked; }
/**
* Return true when editing host is not plaintext-only.
*/
[[nodiscard]] bool IsStyleEditable() const;
/**
* Enable/disable object resizers for <img> elements, <table> elements,
* absolute positioned elements (required absolute position editor enabled).
@@ -418,7 +423,9 @@ class HTMLEditor final : public EditorBase,
mIsObjectResizingEnabled = aEnable;
RefreshEditingUI();
}
bool IsObjectResizerEnabled() const { return mIsObjectResizingEnabled; }
bool IsObjectResizerEnabled() const {
return mIsObjectResizingEnabled && IsStyleEditable();
}
Element* GetResizerTarget() const { return mResizedObject; }
@@ -441,7 +448,7 @@ class HTMLEditor final : public EditorBase,
RefreshEditingUI();
}
bool IsInlineTableEditorEnabled() const {
return mIsInlineTableEditingEnabled;
return mIsInlineTableEditingEnabled && IsStyleEditable();
}
/**
@@ -464,7 +471,7 @@ class HTMLEditor final : public EditorBase,
RefreshEditingUI();
}
bool IsAbsolutePositionEditorEnabled() const {
return mIsAbsolutelyPositioningEnabled;
return mIsAbsolutelyPositioningEnabled && IsStyleEditable();
}
/**

View File

@@ -52,7 +52,8 @@ bool StateUpdatingCommandBase::IsCommandEnabled(Command aCommand,
if (!htmlEditor) {
return false;
}
if (!htmlEditor->IsModifiable() || !htmlEditor->IsSelectionEditable()) {
if (!htmlEditor->IsModifiable() || !htmlEditor->IsSelectionEditable() ||
!htmlEditor->IsStyleEditable()) {
return false;
}
if (aCommand == Command::FormatAbsolutePosition) {
@@ -356,7 +357,8 @@ bool RemoveListCommand::IsCommandEnabled(Command aCommand,
if (!htmlEditor) {
return false;
}
if (!htmlEditor->IsModifiable() || !htmlEditor->IsSelectionEditable()) {
if (!htmlEditor->IsModifiable() || !htmlEditor->IsSelectionEditable() ||
!htmlEditor->IsStyleEditable()) {
return false;
}
@@ -401,7 +403,8 @@ bool IndentCommand::IsCommandEnabled(Command aCommand,
if (!htmlEditor) {
return false;
}
return htmlEditor->IsModifiable() && htmlEditor->IsSelectionEditable();
return htmlEditor->IsModifiable() && htmlEditor->IsSelectionEditable() &&
htmlEditor->IsStyleEditable();
}
nsresult IndentCommand::DoCommand(Command aCommand, EditorBase& aEditorBase,
@@ -434,7 +437,8 @@ bool OutdentCommand::IsCommandEnabled(Command aCommand,
if (!htmlEditor) {
return false;
}
return htmlEditor->IsModifiable() && htmlEditor->IsSelectionEditable();
return htmlEditor->IsModifiable() && htmlEditor->IsSelectionEditable() &&
htmlEditor->IsStyleEditable();
}
nsresult OutdentCommand::DoCommand(Command aCommand, EditorBase& aEditorBase,
@@ -467,7 +471,8 @@ bool MultiStateCommandBase::IsCommandEnabled(Command aCommand,
return false;
}
// should be disabled sometimes, like if the current selection is an image
return htmlEditor->IsModifiable() && htmlEditor->IsSelectionEditable();
return htmlEditor->IsModifiable() && htmlEditor->IsSelectionEditable() &&
htmlEditor->IsStyleEditable();
}
nsresult MultiStateCommandBase::DoCommand(Command aCommand,
@@ -966,7 +971,8 @@ bool DecreaseZIndexCommand::IsCommandEnabled(Command aCommand,
if (!htmlEditor) {
return false;
}
if (!htmlEditor->IsAbsolutePositionEditorEnabled()) {
if (!htmlEditor->IsAbsolutePositionEditorEnabled() ||
!htmlEditor->IsStyleEditable()) {
return false;
}
RefPtr<Element> positionedElement = htmlEditor->GetPositionedElement();
@@ -1008,7 +1014,8 @@ bool IncreaseZIndexCommand::IsCommandEnabled(Command aCommand,
if (!htmlEditor) {
return false;
}
if (!htmlEditor->IsAbsolutePositionEditorEnabled()) {
if (!htmlEditor->IsAbsolutePositionEditorEnabled() ||
!htmlEditor->IsStyleEditable()) {
return false;
}
return !!htmlEditor->GetPositionedElement();
@@ -1047,7 +1054,8 @@ bool RemoveStylesCommand::IsCommandEnabled(Command aCommand,
return false;
}
// test if we have any styles?
return htmlEditor->IsModifiable() && htmlEditor->IsSelectionEditable();
return htmlEditor->IsModifiable() && htmlEditor->IsSelectionEditable() &&
htmlEditor->IsStyleEditable();
}
nsresult RemoveStylesCommand::DoCommand(Command aCommand,
@@ -1085,7 +1093,8 @@ bool IncreaseFontSizeCommand::IsCommandEnabled(Command aCommand,
return false;
}
// test if we are at max size?
return htmlEditor->IsModifiable() && htmlEditor->IsSelectionEditable();
return htmlEditor->IsModifiable() && htmlEditor->IsSelectionEditable() &&
htmlEditor->IsStyleEditable();
}
nsresult IncreaseFontSizeCommand::DoCommand(Command aCommand,
@@ -1121,7 +1130,8 @@ bool DecreaseFontSizeCommand::IsCommandEnabled(Command aCommand,
return false;
}
// test if we are at min size?
return htmlEditor->IsModifiable() && htmlEditor->IsSelectionEditable();
return htmlEditor->IsModifiable() && htmlEditor->IsSelectionEditable() &&
htmlEditor->IsStyleEditable();
}
nsresult DecreaseFontSizeCommand::DoCommand(Command aCommand,
@@ -1213,7 +1223,8 @@ bool InsertTagCommand::IsCommandEnabled(Command aCommand,
if (!htmlEditor) {
return false;
}
return htmlEditor->IsModifiable() && htmlEditor->IsSelectionEditable();
return htmlEditor->IsModifiable() && htmlEditor->IsSelectionEditable() &&
htmlEditor->IsStyleEditable();
}
// corresponding STATE_ATTRIBUTE is: src (img) and href (a)

View File

@@ -61,6 +61,9 @@ addEventListener("load", () => {
function onInput(event) {
inputEvent = `input={inputType="${event.inputType}"}`;
}
test(() => {
assert_false(document.queryCommandEnabled(testing.command));
}, `${t.name}: the command should be disabled`);
let ret;
try {
editingHost.addEventListener("input", onInput);