Bug 1660378 - part 7: Make `CSSEditUtils::SetCSSEquivalentToHTMLStyle()` take `nsStyledElement&` instead of `Element*` r=m_kato

Differential Revision: https://phabricator.services.mozilla.com/D87988
This commit is contained in:
Masayuki Nakano 2020-08-26 04:48:32 +00:00
Родитель decd85f7d6
Коммит bc279d2448
6 изменённых файлов: 218 добавлений и 100 удалений

Просмотреть файл

@ -819,14 +819,10 @@ void CSSEditUtils::GenerateCSSDeclarationsFromHTMLStyle(
// Add to aNode the CSS inline style equivalent to HTMLProperty/aAttribute/
// aValue for the node, and return in aCount the number of CSS properties set
// by the call. The Element version returns aCount instead.
int32_t CSSEditUtils::SetCSSEquivalentToHTMLStyle(Element* aElement,
nsAtom* aHTMLProperty,
nsAtom* aAttribute,
const nsAString* aValue,
bool aSuppressTransaction) {
MOZ_ASSERT(aElement);
if (!IsCSSEditableProperty(aElement, aHTMLProperty, aAttribute)) {
Result<int32_t, nsresult> CSSEditUtils::SetCSSEquivalentToHTMLStyleInternal(
nsStyledElement& aStyledElement, nsAtom* aHTMLProperty, nsAtom* aAttribute,
const nsAString* aValue, bool aSuppressTransaction) {
if (!IsCSSEditableProperty(&aStyledElement, aHTMLProperty, aAttribute)) {
return 0;
}
@ -836,26 +832,19 @@ int32_t CSSEditUtils::SetCSSEquivalentToHTMLStyle(Element* aElement,
// Find the CSS equivalence to the HTML style
nsTArray<nsStaticAtom*> cssPropertyArray;
nsTArray<nsString> cssValueArray;
GenerateCSSDeclarationsFromHTMLStyle(*aElement, aHTMLProperty, aAttribute,
aValue, cssPropertyArray, cssValueArray,
false);
GenerateCSSDeclarationsFromHTMLStyle(aStyledElement, aHTMLProperty,
aAttribute, aValue, cssPropertyArray,
cssValueArray, false);
// set the individual CSS inline styles
const size_t count = cssPropertyArray.Length();
if (!count) {
return 0;
}
nsCOMPtr<nsStyledElement> styledElement = do_QueryInterface(aElement);
if (NS_WARN_IF(!styledElement)) {
return 0;
}
for (size_t index = 0; index < count; index++) {
nsresult rv = SetCSSPropertyInternal(
*styledElement, MOZ_KnownLive(*cssPropertyArray[index]),
aStyledElement, MOZ_KnownLive(*cssPropertyArray[index]),
cssValueArray[index], aSuppressTransaction);
if (NS_FAILED(rv)) {
NS_WARNING("CSSEditUtils::SetCSSPropertyInternal() failed");
return 0;
return Err(rv);
}
}
return count;

Просмотреть файл

@ -250,14 +250,25 @@ class CSSEditUtils final {
* @param aAttribute [IN] An atom to an attribute name or nullptr
* if irrelevant.
* @param aValue [IN] The attribute value.
* @param aSuppressTransaction [IN] A boolean indicating, when true,
* that no transaction should be recorded.
*
* @return The number of CSS properties set by the call.
*/
MOZ_CAN_RUN_SCRIPT int32_t SetCSSEquivalentToHTMLStyle(
dom::Element* aElement, nsAtom* aProperty, nsAtom* aAttribute,
const nsAString* aValue, bool aSuppressTransaction);
[[nodiscard]] MOZ_CAN_RUN_SCRIPT Result<int32_t, nsresult>
SetCSSEquivalentToHTMLStyleWithTransaction(nsStyledElement& aStyledElement,
nsAtom* aProperty,
nsAtom* aAttribute,
const nsAString* aValue) {
return SetCSSEquivalentToHTMLStyleInternal(aStyledElement, aProperty,
aAttribute, aValue, false);
}
[[nodiscard]] MOZ_CAN_RUN_SCRIPT Result<int32_t, nsresult>
SetCSSEquivalentToHTMLStyleWithoutTransaction(nsStyledElement& aStyledElement,
nsAtom* aProperty,
nsAtom* aAttribute,
const nsAString* aValue) {
return SetCSSEquivalentToHTMLStyleInternal(aStyledElement, aProperty,
aAttribute, aValue, true);
}
/**
* Removes from the node the CSS inline styles equivalent to the HTML style.
@ -427,6 +438,11 @@ class CSSEditUtils final {
[[nodiscard]] MOZ_CAN_RUN_SCRIPT nsresult
SetCSSPropertyInternal(nsStyledElement& aStyledElement, nsAtom& aProperty,
const nsAString& aValue, bool aSuppressTxn = false);
[[nodiscard]] MOZ_CAN_RUN_SCRIPT Result<int32_t, nsresult>
SetCSSEquivalentToHTMLStyleInternal(nsStyledElement& aStyledElement,
nsAtom* aProperty, nsAtom* aAttribute,
const nsAString* aValue,
bool aSuppressTransaction);
private:
HTMLEditor* mHTMLEditor;

Просмотреть файл

@ -20,6 +20,7 @@
#include "nsGkAtoms.h"
#include "nsIContent.h"
#include "nsINode.h"
#include "nsStyledElement.h"
namespace mozilla {
@ -178,6 +179,11 @@ class EditorDOMPointBase final {
return mParent->AsElement();
}
already_AddRefed<nsStyledElement> GetContainerAsStyledElement() const {
nsCOMPtr<nsStyledElement> styledElement = do_QueryInterface(mParent);
return styledElement.forget();
}
dom::Text* GetContainerAsText() const {
return dom::Text::FromNodeOrNull(mParent);
}

Просмотреть файл

@ -8674,11 +8674,23 @@ nsresult HTMLEditor::AlignNodesAndDescendants(
}
if (useCSS) {
mCSSEditUtils->SetCSSEquivalentToHTMLStyle(
MOZ_KnownLive(listOrListItemElement), nullptr, nsGkAtoms::align,
&aAlignType, false);
if (NS_WARN_IF(Destroyed())) {
return NS_ERROR_EDITOR_DESTROYED;
if (nsCOMPtr<nsStyledElement> styledListOrListItemElement =
do_QueryInterface(listOrListItemElement)) {
Result<int32_t, nsresult> result =
mCSSEditUtils->SetCSSEquivalentToHTMLStyleWithTransaction(
*styledListOrListItemElement, nullptr, nsGkAtoms::align,
&aAlignType);
if (result.isErr()) {
if (result.inspectErr() == NS_ERROR_EDITOR_DESTROYED) {
NS_WARNING(
"CSSEditUtils::SetCSSEquivalentToHTMLStyleWithTransaction("
"nsGkAtoms::align) destroyed the editor");
return NS_ERROR_EDITOR_DESTROYED;
}
NS_WARNING(
"CSSEditUtils::SetCSSEquivalentToHTMLStyleWithTransaction("
"nsGkAtoms::align) failed, but ignored");
}
}
createdDivElement = nullptr;
continue;

Просмотреть файл

@ -5176,30 +5176,26 @@ nsresult HTMLEditor::SetAttributeOrEquivalent(Element* aElement,
MOZ_ASSERT(aAttribute);
nsAutoScriptBlocker scriptBlocker;
nsCOMPtr<nsStyledElement> styledElement = do_QueryInterface(aElement);
if (!IsCSSEnabled() || !mCSSEditUtils) {
// we are not in an HTML+CSS editor; let's set the attribute the HTML way
if (mCSSEditUtils) {
if (nsCOMPtr<nsStyledElement> styledElement =
do_QueryInterface(aElement)) {
nsresult rv =
aSuppressTransaction
? mCSSEditUtils
->RemoveCSSEquivalentToHTMLStyleWithoutTransaction(
*styledElement, nullptr, aAttribute, nullptr)
: mCSSEditUtils->RemoveCSSEquivalentToHTMLStyleWithTransaction(
*styledElement, nullptr, aAttribute, nullptr);
if (rv == NS_ERROR_EDITOR_DESTROYED) {
NS_WARNING(
"CSSEditUtils::RemoveCSSEquivalentToHTMLStyle*Transaction() "
"destroyed the editor");
return NS_ERROR_EDITOR_DESTROYED;
}
NS_WARNING_ASSERTION(
NS_SUCCEEDED(rv),
if (mCSSEditUtils && styledElement) {
nsresult rv =
aSuppressTransaction
? mCSSEditUtils->RemoveCSSEquivalentToHTMLStyleWithoutTransaction(
*styledElement, nullptr, aAttribute, nullptr)
: mCSSEditUtils->RemoveCSSEquivalentToHTMLStyleWithTransaction(
*styledElement, nullptr, aAttribute, nullptr);
if (rv == NS_ERROR_EDITOR_DESTROYED) {
NS_WARNING(
"CSSEditUtils::RemoveCSSEquivalentToHTMLStyle*Transaction() "
"failed, but ignored");
"destroyed the editor");
return NS_ERROR_EDITOR_DESTROYED;
}
NS_WARNING_ASSERTION(
NS_SUCCEEDED(rv),
"CSSEditUtils::RemoveCSSEquivalentToHTMLStyle*Transaction() "
"failed, but ignored");
}
if (aSuppressTransaction) {
nsresult rv =
@ -5213,25 +5209,40 @@ nsresult HTMLEditor::SetAttributeOrEquivalent(Element* aElement,
return rv;
}
int32_t count = mCSSEditUtils->SetCSSEquivalentToHTMLStyle(
aElement, nullptr, aAttribute, &aValue, aSuppressTransaction);
if (count) {
// we found an equivalence ; let's remove the HTML attribute itself if it
// is set
nsAutoString existingValue;
if (!aElement->GetAttr(kNameSpaceID_None, aAttribute, existingValue)) {
return NS_OK;
if (styledElement) {
Result<int32_t, nsresult> count =
aSuppressTransaction
? mCSSEditUtils->SetCSSEquivalentToHTMLStyleWithoutTransaction(
*styledElement, nullptr, aAttribute, &aValue)
: mCSSEditUtils->SetCSSEquivalentToHTMLStyleWithTransaction(
*styledElement, nullptr, aAttribute, &aValue);
if (count.isErr()) {
if (count.inspectErr() == NS_ERROR_EDITOR_DESTROYED) {
return NS_ERROR_EDITOR_DESTROYED;
}
NS_WARNING(
"CSSEditUtils::SetCSSEquivalentToHTMLStyle*Transaction() failed, but "
"ignored");
}
if (count.inspect()) {
// we found an equivalence ; let's remove the HTML attribute itself if it
// is set
nsAutoString existingValue;
if (!aElement->GetAttr(kNameSpaceID_None, aAttribute, existingValue)) {
return NS_OK;
}
if (aSuppressTransaction) {
nsresult rv = aElement->UnsetAttr(kNameSpaceID_None, aAttribute, true);
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "Element::UnsetAttr() failed");
if (aSuppressTransaction) {
nsresult rv = aElement->UnsetAttr(kNameSpaceID_None, aAttribute, true);
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "Element::UnsetAttr() failed");
return rv;
}
nsresult rv = RemoveAttributeWithTransaction(*aElement, *aAttribute);
NS_WARNING_ASSERTION(
NS_SUCCEEDED(rv),
"EditorBase::RemoveAttributeWithTransaction() failed");
return rv;
}
nsresult rv = RemoveAttributeWithTransaction(*aElement, *aAttribute);
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
"EditorBase::RemoveAttributeWithTransaction() failed");
return rv;
}
// count is an integer that represents the number of CSS declarations
@ -5406,13 +5417,22 @@ nsresult HTMLEditor::SetCSSBackgroundColorWithTransaction(
// If the range is in a text node, set background color of its parent
// block.
if (startOfRange.IsInTextNode()) {
if (RefPtr<Element> blockElement =
HTMLEditUtils::GetAncestorBlockElement(
*startOfRange.ContainerAsText())) {
mCSSEditUtils->SetCSSEquivalentToHTMLStyle(
blockElement, nullptr, nsGkAtoms::bgcolor, &aColor, false);
if (NS_WARN_IF(Destroyed())) {
return NS_ERROR_EDITOR_DESTROYED;
if (nsCOMPtr<nsStyledElement> blockStyledElement =
do_QueryInterface(HTMLEditUtils::GetAncestorBlockElement(
*startOfRange.ContainerAsText()))) {
Result<int32_t, nsresult> result =
mCSSEditUtils->SetCSSEquivalentToHTMLStyleWithTransaction(
*blockStyledElement, nullptr, nsGkAtoms::bgcolor, &aColor);
if (result.isErr()) {
if (result.inspectErr() == NS_ERROR_EDITOR_DESTROYED) {
NS_WARNING(
"CSSEditUtils::SetCSSEquivalentToHTMLStyleWithTransaction("
"nsGkAtoms::bgcolor) destroyed the editor");
return NS_ERROR_EDITOR_DESTROYED;
}
NS_WARNING(
"CSSEditUtils::SetCSSEquivalentToHTMLStyleWithTransaction("
"nsGkAtoms::bgcolor) failed, but ignored");
}
}
continue;
@ -5424,11 +5444,22 @@ nsresult HTMLEditor::SetCSSBackgroundColorWithTransaction(
// than the `nsRange` is collapsed?
if (startOfRange.GetContainer()->IsHTMLElement(nsGkAtoms::body) &&
selectionIsCollapsed) {
mCSSEditUtils->SetCSSEquivalentToHTMLStyle(
MOZ_KnownLive(startOfRange.GetContainerAsElement()), nullptr,
nsGkAtoms::bgcolor, &aColor, false);
if (NS_WARN_IF(Destroyed())) {
return NS_ERROR_EDITOR_DESTROYED;
if (nsCOMPtr<nsStyledElement> styledElement =
startOfRange.GetContainerAsStyledElement()) {
Result<int32_t, nsresult> result =
mCSSEditUtils->SetCSSEquivalentToHTMLStyleWithTransaction(
*styledElement, nullptr, nsGkAtoms::bgcolor, &aColor);
if (result.isErr()) {
if (result.inspectErr() == NS_ERROR_EDITOR_DESTROYED) {
NS_WARNING(
"CSSEditUtils::SetCSSEquivalentToHTMLStyleWithTransaction("
"nsGkAtoms::bgcolor) destroyed the editor");
return NS_ERROR_EDITOR_DESTROYED;
}
NS_WARNING(
"CSSEditUtils::SetCSSEquivalentToHTMLStyleWithTransaction("
"nsGkAtoms::bgcolor) failed, but ignored");
}
}
continue;
}
@ -5440,13 +5471,22 @@ nsresult HTMLEditor::SetCSSBackgroundColorWithTransaction(
if (NS_WARN_IF(startOfRange.IsInDataNode())) {
continue;
}
if (RefPtr<Element> blockElement =
if (nsCOMPtr<nsStyledElement> blockStyledElement = do_QueryInterface(
HTMLEditUtils::GetInclusiveAncestorBlockElement(
*startOfRange.GetChild())) {
mCSSEditUtils->SetCSSEquivalentToHTMLStyle(
blockElement, nullptr, nsGkAtoms::bgcolor, &aColor, false);
if (NS_WARN_IF(Destroyed())) {
return NS_ERROR_EDITOR_DESTROYED;
*startOfRange.GetChild()))) {
Result<int32_t, nsresult> result =
mCSSEditUtils->SetCSSEquivalentToHTMLStyleWithTransaction(
*blockStyledElement, nullptr, nsGkAtoms::bgcolor, &aColor);
if (result.isErr()) {
if (result.inspectErr() == NS_ERROR_EDITOR_DESTROYED) {
NS_WARNING(
"CSSEditUtils::SetCSSEquivalentToHTMLStyleWithTransaction("
"nsGkAtoms::bgcolor) destroyed the editor");
return NS_ERROR_EDITOR_DESTROYED;
}
NS_WARNING(
"CSSEditUtils::SetCSSEquivalentToHTMLStyleWithTransaction("
"nsGkAtoms::bgcolor) failed, but ignored");
}
}
continue;
@ -5488,10 +5528,22 @@ nsresult HTMLEditor::SetCSSBackgroundColorWithTransaction(
*startOfRange.ContainerAsText());
if (blockElement && handledBlockParent != blockElement) {
handledBlockParent = blockElement;
mCSSEditUtils->SetCSSEquivalentToHTMLStyle(
blockElement, nullptr, nsGkAtoms::bgcolor, &aColor, false);
if (NS_WARN_IF(Destroyed())) {
return NS_ERROR_EDITOR_DESTROYED;
if (nsCOMPtr<nsStyledElement> blockStyledElement =
do_QueryInterface(blockElement)) {
Result<int32_t, nsresult> result =
mCSSEditUtils->SetCSSEquivalentToHTMLStyleWithTransaction(
*blockStyledElement, nullptr, nsGkAtoms::bgcolor, &aColor);
if (result.isErr()) {
if (result.inspectErr() == NS_ERROR_EDITOR_DESTROYED) {
NS_WARNING(
"CSSEditUtils::SetCSSEquivalentToHTMLStyleWithTransaction("
"nsGkAtoms::bgcolor) destroyed the editor");
return NS_ERROR_EDITOR_DESTROYED;
}
NS_WARNING(
"CSSEditUtils::SetCSSEquivalentToHTMLStyleWithTransaction("
"nsGkAtoms::bgcolor) failed, but ignored");
}
}
}
}
@ -5503,10 +5555,22 @@ nsresult HTMLEditor::SetCSSBackgroundColorWithTransaction(
HTMLEditUtils::GetInclusiveAncestorBlockElement(content);
if (blockElement && handledBlockParent != blockElement) {
handledBlockParent = blockElement;
mCSSEditUtils->SetCSSEquivalentToHTMLStyle(
blockElement, nullptr, nsGkAtoms::bgcolor, &aColor, false);
if (NS_WARN_IF(Destroyed())) {
return NS_ERROR_EDITOR_DESTROYED;
if (nsCOMPtr<nsStyledElement> blockStyledElement =
do_QueryInterface(blockElement)) {
Result<int32_t, nsresult> result =
mCSSEditUtils->SetCSSEquivalentToHTMLStyleWithTransaction(
*blockStyledElement, nullptr, nsGkAtoms::bgcolor, &aColor);
if (result.isErr()) {
if (result.inspectErr() == NS_ERROR_EDITOR_DESTROYED) {
NS_WARNING(
"CSSEditUtils::SetCSSEquivalentToHTMLStyleWithTransaction("
"nsGkAtoms::bgcolor) destroyed the editor");
return NS_ERROR_EDITOR_DESTROYED;
}
NS_WARNING(
"CSSEditUtils::SetCSSEquivalentToHTMLStyleWithTransaction("
"nsGkAtoms::bgcolor) failed, but ignored");
}
}
}
}
@ -5519,10 +5583,22 @@ nsresult HTMLEditor::SetCSSBackgroundColorWithTransaction(
RefPtr<Element> blockElement = HTMLEditUtils::GetAncestorBlockElement(
*endOfRange.ContainerAsText());
if (blockElement && handledBlockParent != blockElement) {
mCSSEditUtils->SetCSSEquivalentToHTMLStyle(
blockElement, nullptr, nsGkAtoms::bgcolor, &aColor, false);
if (NS_WARN_IF(Destroyed())) {
return NS_ERROR_EDITOR_DESTROYED;
if (nsCOMPtr<nsStyledElement> blockStyledElement =
do_QueryInterface(blockElement)) {
Result<int32_t, nsresult> result =
mCSSEditUtils->SetCSSEquivalentToHTMLStyleWithTransaction(
*blockStyledElement, nullptr, nsGkAtoms::bgcolor, &aColor);
if (result.isErr()) {
if (result.inspectErr() == NS_ERROR_EDITOR_DESTROYED) {
NS_WARNING(
"CSSEditUtils::SetCSSEquivalentToHTMLStyleWithTransaction("
"nsGkAtoms::bgcolor) destroyed the editor");
return NS_ERROR_EDITOR_DESTROYED;
}
NS_WARNING(
"CSSEditUtils::SetCSSEquivalentToHTMLStyleWithTransaction("
"nsGkAtoms::bgcolor) failed, but ignored");
}
}
}
}

Просмотреть файл

@ -407,14 +407,17 @@ bool HTMLEditor::IsSimpleModifiableNode(nsIContent* aContent, nsAtom* aProperty,
NS_WARNING("EditorBase::CreateHTMLContent(nsGkAtoms::span) failed");
return false;
}
mCSSEditUtils->SetCSSEquivalentToHTMLStyle(newSpanElement, aProperty,
aAttribute, aValue,
/*suppress transaction*/ true);
nsCOMPtr<nsStyledElement> styledNewSpanElement =
do_QueryInterface(newSpanElement);
if (!styledNewSpanElement) {
return false;
}
Result<int32_t, nsresult> result =
mCSSEditUtils->SetCSSEquivalentToHTMLStyleWithoutTransaction(
*styledNewSpanElement, aProperty, aAttribute, aValue);
if (result.isErr()) {
return false; // TODO: Return error if editor is destroyed.
}
nsCOMPtr<nsStyledElement> styledElement = do_QueryInterface(element);
if (!styledElement) {
return false;
@ -623,8 +626,24 @@ nsresult HTMLEditor::SetInlinePropertyOnNodeImpl(nsIContent& aContent,
}
// Add the CSS styles corresponding to the HTML style request
mCSSEditUtils->SetCSSEquivalentToHTMLStyle(spanElement, &aProperty,
aAttribute, &aValue, false);
if (nsCOMPtr<nsStyledElement> spanStyledElement =
do_QueryInterface(spanElement)) {
Result<int32_t, nsresult> result =
mCSSEditUtils->SetCSSEquivalentToHTMLStyleWithTransaction(
*spanStyledElement, &aProperty, aAttribute, &aValue);
if (result.isErr()) {
if (result.inspectErr() == NS_ERROR_EDITOR_DESTROYED) {
NS_WARNING(
"CSSEditUtils::SetCSSEquivalentToHTMLStyleWithTransaction() "
"destroyed the editor");
return NS_ERROR_EDITOR_DESTROYED;
}
NS_WARNING(
"CSSEditUtils::SetCSSEquivalentToHTMLStyleWithTransaction() "
"failed, "
"but ignored");
}
}
return NS_OK;
}