Bug 1742933 - part 11: Create a pref to get back the traditional behavior r=m_kato

For avoiding simple back-out of the patches when we get serious regression
reports, we should have a pref to disable the new pref.

Differential Revision: https://phabricator.services.mozilla.com/D140475
This commit is contained in:
Masayuki Nakano
2022-03-11 09:21:36 +00:00
parent 846510e59b
commit 16c8061d35
5 changed files with 133 additions and 59 deletions

View File

@@ -3052,15 +3052,21 @@ EditActionResult HTMLEditor::ChangeSelectedHardLinesToList(
[&](Element& aListElement) MOZ_CAN_RUN_SCRIPT_BOUNDARY {
Result<RefPtr<Element>, nsresult> listItemElementOrError =
CreateAndInsertElement(
WithTransaction::No, aListItemElementTagName,
aListElement.IsInComposedDoc() ? WithTransaction::Yes
: WithTransaction::No,
aListItemElementTagName,
EditorDOMPoint(&aListElement, 0u),
[](Element& aListItemElement) -> nsresult {
return NS_OK;
});
if (listItemElementOrError.isErr()) {
NS_WARNING(
"HTMLEditor::CreateAndInsertElement(WithTransaction::Yes) "
"failed");
NS_WARNING(nsPrintfCString(
"HTMLEditor::CreateAndInsertElement(%s) failed",
ToString(aListElement.IsInComposedDoc()
? WithTransaction::Yes
: WithTransaction::No)
.c_str())
.get());
return listItemElementOrError.unwrapErr();
}
MOZ_ASSERT(listItemElementOrError.inspect());
@@ -5707,13 +5713,17 @@ nsresult HTMLEditor::AlignBlockContentsWithDivElement(
WithTransaction::Yes, *nsGkAtoms::div, EditorDOMPoint(&aBlockElement, 0u),
// MOZ_CAN_RUN_SCRIPT_BOUNDARY due to bug 1758868
[&](Element& aDivElement) MOZ_CAN_RUN_SCRIPT_BOUNDARY {
// aDivElement has not been connected yet so that we do not need
// transaction of setting align attribute here.
nsresult rv = SetAttributeOrEquivalent(&aDivElement, nsGkAtoms::align,
aAlignType, false);
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
"EditorBase::SetAttributeOrEquivalent("
"nsGkAtoms::align) failed");
// If aDivElement has not been connected yet, we do not need transaction
// of setting align attribute here.
nsresult rv =
SetAttributeOrEquivalent(&aDivElement, nsGkAtoms::align, aAlignType,
!aDivElement.IsInComposedDoc());
NS_WARNING_ASSERTION(
NS_SUCCEEDED(rv),
nsPrintfCString("EditorBase::SetAttributeOrEquivalent(nsGkAtoms:: "
"align, \"...\", %s) failed",
!aDivElement.IsInComposedDoc() ? "true" : "false")
.get());
return rv;
});
if (maybeNewDivElement.isErr()) {
@@ -6953,15 +6963,23 @@ nsresult HTMLEditor::HandleInsertParagraphInHeadingElement(
[&](Element& aDivOrParagraphElement) MOZ_CAN_RUN_SCRIPT_BOUNDARY {
// We don't make inserting new <br> element undoable
// because removing the new element from the DOM tree
// gets same result for the user.
// gets same result for the user if aDivOrParagraphElement
// has not been connected yet.
Result<RefPtr<Element>, nsresult> brElementOrError =
InsertBRElement(
WithTransaction::No,
aDivOrParagraphElement.IsInComposedDoc()
? WithTransaction::Yes
: WithTransaction::No,
EditorDOMPoint(&aDivOrParagraphElement, 0u));
if (brElementOrError.isErr()) {
NS_WARNING(
"HTMLEditor::InsertBRElement(WithTransaction::No) "
"failed");
nsPrintfCString(
"HTMLEditor::InsertBRElement(%s) failed",
ToString(aDivOrParagraphElement.IsInComposedDoc()
? WithTransaction::Yes
: WithTransaction::No)
.c_str())
.get());
return brElementOrError.unwrapErr();
}
return NS_OK;
@@ -7392,13 +7410,20 @@ nsresult HTMLEditor::HandleInsertParagraphInListItemElement(
[&](Element& aDivOrParagraphElement) MOZ_CAN_RUN_SCRIPT_BOUNDARY {
// We don't make inserting new <br> element undoable because
// removing the new element from the DOM tree gets same result for
// the user.
// the user if aDivOrParagraphElement has not been connected yet.
Result<RefPtr<Element>, nsresult> brElementOrError =
InsertBRElement(WithTransaction::No,
InsertBRElement(aDivOrParagraphElement.IsInComposedDoc()
? WithTransaction::Yes
: WithTransaction::No,
EditorDOMPoint(&aDivOrParagraphElement, 0u));
if (brElementOrError.isErr()) {
NS_WARNING(
"HTMLEditor::InsertBRElement(WithTransaction::No) failed");
NS_WARNING(nsPrintfCString(
"HTMLEditor::InsertBRElement(%s) failed",
ToString(aDivOrParagraphElement.IsInComposedDoc()
? WithTransaction::Yes
: WithTransaction::No)
.c_str())
.get());
return brElementOrError.unwrapErr();
}
return NS_OK;

View File

@@ -473,21 +473,29 @@ NS_IMETHODIMP HTMLEditor::SetDocumentCharacterSet(
CreateAndInsertElement(
WithTransaction::Yes, *nsGkAtoms::meta,
EditorDOMPoint(primaryHeadElement, 0), [&](Element& aMetaElement) {
DebugOnly<nsresult> rvIgnored =
aMetaElement.SetAttr(kNameSpaceID_None, nsGkAtoms::httpEquiv,
u"Content-Type"_ns, false);
DebugOnly<nsresult> rvIgnored = aMetaElement.SetAttr(
kNameSpaceID_None, nsGkAtoms::httpEquiv, u"Content-Type"_ns,
aMetaElement.IsInComposedDoc());
NS_WARNING_ASSERTION(
NS_SUCCEEDED(rvIgnored),
"Element::SetAttr(nsGkAtoms::httpEquiv, Content-Type) "
"failed, but ignored");
nsPrintfCString(
"Element::SetAttr(nsGkAtoms::httpEquiv, \"Content-Type\", "
"%s) failed, but ignored",
aMetaElement.IsInComposedDoc() ? "true" : "false")
.get());
rvIgnored =
aMetaElement.SetAttr(kNameSpaceID_None, nsGkAtoms::content,
u"text/html;charset="_ns +
NS_ConvertASCIItoUTF16(aCharacterSet),
false);
aMetaElement.IsInComposedDoc());
NS_WARNING_ASSERTION(
NS_SUCCEEDED(rvIgnored),
"Element::SetAttr(nsGkAtoms::content) failed, but ignored");
nsPrintfCString(
"Element::SetAttr(nsGkAtoms::content, "
"\"text/html;charset=%s\", %s) failed, but ignored",
nsPromiseFlatCString(aCharacterSet).get(),
aMetaElement.IsInComposedDoc() ? "true" : "false")
.get());
return NS_OK;
});
if (maybeNewMetaElement.isErr()) {
@@ -2975,9 +2983,8 @@ Result<RefPtr<Element>, nsresult> HTMLEditor::CreateAndInsertElement(
// CreatElementTransaction since we can use InsertNodeTransaction
// instead.
RefPtr<Element> newElement;
nsresult rv;
newElement = CreateHTMLContent(&aTagName);
RefPtr<Element> newElement = CreateHTMLContent(&aTagName);
NS_WARNING_ASSERTION(newElement, "EditorBase::CreateHTMLContent() failed");
if (MOZ_LIKELY(newElement)) {
rv = MarkElementDirty(*newElement);
@@ -2988,12 +2995,14 @@ Result<RefPtr<Element>, nsresult> HTMLEditor::CreateAndInsertElement(
NS_WARNING_ASSERTION(
NS_SUCCEEDED(rv),
"EditorBase::MarkElementDirty() failed, but ignored");
if (StaticPrefs::editor_initialize_element_before_connect()) {
rv = aInitializer(*newElement);
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "aInitializer failed");
if (MOZ_UNLIKELY(rv != NS_ERROR_EDITOR_DESTROYED &&
NS_WARN_IF(Destroyed()))) {
rv = NS_ERROR_EDITOR_DESTROYED;
}
}
if (NS_SUCCEEDED(rv)) {
RefPtr<InsertNodeTransaction> transaction =
InsertNodeTransaction::Create(*this, *newElement, aPointToInsert);
@@ -3046,6 +3055,18 @@ Result<RefPtr<Element>, nsresult> HTMLEditor::CreateAndInsertElement(
return Err(rv);
}
if (!StaticPrefs::editor_initialize_element_before_connect() && newElement) {
rv = aInitializer(*newElement);
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "aInitializer failed");
if (MOZ_UNLIKELY(rv != NS_ERROR_EDITOR_DESTROYED &&
NS_WARN_IF(Destroyed()))) {
rv = NS_ERROR_EDITOR_DESTROYED;
}
if (NS_FAILED(rv)) {
return Err(rv);
}
}
return newElement;
}

View File

@@ -1498,10 +1498,10 @@ class HTMLEditor final : public EditorBase,
* Note that this point will be invalid once this
* method inserts the new element.
* @param aInitializer A function to initialize the new element before
* connecting the element into the DOM tree.
* Note that this should not touch outside given
* element because doing it would break range
* updater's result.
* or after (depends on the pref) connecting the
* element into the DOM tree. Note that this should
* not touch outside given element because doing it
* would break range updater's result.
* @return The created new element node or an error.
*/
[[nodiscard]] MOZ_CAN_RUN_SCRIPT Result<RefPtr<Element>, nsresult>
@@ -1545,10 +1545,10 @@ class HTMLEditor final : public EditorBase,
* kept if and only if a <br> element follows
* split point.
* @param aInitializer A function to initialize the new element before
* connecting the element into the DOM tree.
* Note that this should not touch outside given
* element because doing it would break range
* updater's result.
* or after (depends on the pref) connecting the
* element into the DOM tree. Note that this should
* not touch outside given element because doing it
* would break range updater's result.
*/
enum class BRElementNextToSplitPoint { Keep, Delete };
[[nodiscard]] MOZ_CAN_RUN_SCRIPT Result<RefPtr<Element>, nsresult>
@@ -3428,10 +3428,10 @@ class HTMLEditor final : public EditorBase,
*
* @param aTag The element name to be created.
* @param aInitializer A function to initialize the new element before
* connecting the element into the DOM tree.
* Note that this should not touch outside given
* element because doing it would break range
* updater's result.
* or after (depends on the pref) connecting the
* element into the DOM tree. Note that this should
* not touch outside given element because doing it
* would break range updater's result.
*/
MOZ_CAN_RUN_SCRIPT Result<RefPtr<Element>, nsresult>
DeleteSelectionAndCreateElement(

View File

@@ -64,6 +64,7 @@
#include "nsLinebreakConverter.h"
#include "nsLiteralString.h"
#include "nsNetUtil.h"
#include "nsPrintfCString.h"
#include "nsRange.h"
#include "nsReadableUtils.h"
#include "nsServiceManagerUtils.h"
@@ -2485,10 +2486,15 @@ nsresult HTMLEditor::PasteAsQuotationAsAction(int32_t aClipboardType,
// MOZ_CAN_RUN_SCRIPT_BOUNDARY due to bug 1758868
[&](Element& aBlockquoteElement) MOZ_CAN_RUN_SCRIPT_BOUNDARY {
DebugOnly<nsresult> rvIgnored = aBlockquoteElement.SetAttr(
kNameSpaceID_None, nsGkAtoms::type, u"cite"_ns, false);
kNameSpaceID_None, nsGkAtoms::type, u"cite"_ns,
aBlockquoteElement.IsInComposedDoc());
NS_WARNING_ASSERTION(
NS_SUCCEEDED(rvIgnored),
"Element::SetAttr(nsGkAtoms::type, cite) failed, but ignored");
nsPrintfCString(
"Element::SetAttr(nsGkAtoms::type, \"cite\", %s) "
"failed, but ignored",
aBlockquoteElement.IsInComposedDoc() ? "true" : "false")
.get());
return NS_OK;
});
if (MOZ_UNLIKELY(blockquoteElementOrError.isErr() ||
@@ -2892,10 +2898,15 @@ nsresult HTMLEditor::InsertAsPlaintextQuotation(const nsAString& aQuotedText,
*nsGkAtoms::span, [](Element& aSpanElement) {
// Add an attribute on the pre node so we'll know it's a quotation.
DebugOnly<nsresult> rvIgnored = aSpanElement.SetAttr(
kNameSpaceID_None, nsGkAtoms::mozquote, u"true"_ns, false);
NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored),
"Element::SetAttr(nsGkAtoms::mozquote, "
"\"true\", false) failed");
kNameSpaceID_None, nsGkAtoms::mozquote, u"true"_ns,
aSpanElement.IsInComposedDoc());
NS_WARNING_ASSERTION(
NS_SUCCEEDED(rvIgnored),
nsPrintfCString(
"Element::SetAttr(nsGkAtoms::mozquote, \"true\", %s) "
"failed",
aSpanElement.IsInComposedDoc() ? "true" : "false")
.get());
// Allow wrapping on spans so long lines get wrapped to the screen.
if (aSpanElement.GetParent() &&
aSpanElement.GetParent()->IsHTMLElement(nsGkAtoms::body)) {
@@ -3151,16 +3162,26 @@ nsresult HTMLEditor::InsertAsCitedQuotationInternal(
[&](Element& aBlockquoteElement) MOZ_CAN_RUN_SCRIPT_BOUNDARY {
// Try to set type=cite. Ignore it if this fails.
DebugOnly<nsresult> rvIgnored = aBlockquoteElement.SetAttr(
kNameSpaceID_None, nsGkAtoms::type, u"cite"_ns, false);
NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored),
"Element::SetAttr(nsGkAtoms::type, "
"\"cite\", false) failed, but ignored");
kNameSpaceID_None, nsGkAtoms::type, u"cite"_ns,
aBlockquoteElement.IsInComposedDoc());
NS_WARNING_ASSERTION(
NS_SUCCEEDED(rvIgnored),
nsPrintfCString(
"Element::SetAttr(nsGkAtoms::type, \"cite\", %s) failed, "
"but ignored",
aBlockquoteElement.IsInComposedDoc() ? "true" : "false")
.get());
if (!aCitation.IsEmpty()) {
DebugOnly<nsresult> rvIgnored = aBlockquoteElement.SetAttr(
kNameSpaceID_None, nsGkAtoms::cite, aCitation, false);
NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored),
"Element::SetAttr(nsGkAtoms::cite, "
"\"...\", false) failed, but ignored");
kNameSpaceID_None, nsGkAtoms::cite, aCitation,
aBlockquoteElement.IsInComposedDoc());
NS_WARNING_ASSERTION(
NS_SUCCEEDED(rvIgnored),
nsPrintfCString(
"Element::SetAttr(nsGkAtoms::cite, \"...\", %s) failed, "
"but ignored",
aBlockquoteElement.IsInComposedDoc() ? "true" : "false")
.get());
}
return NS_OK;
});

View File

@@ -4422,6 +4422,13 @@
value: true
mirror: always
# Whether editor initializes attributes and/or child nodes of newly inserting
# element before or after connecting to the DOM tree.
- name: editor.initialize_element_before_connect
type: bool
value: true
mirror: always
# Delay to mask last input character in password fields.
# If negative value, to use platform's default behavior.
# If 0, no delay to mask password.