Bug 1324996 - Part 1. Implement nsIAtom version of SetAttribute/RemoveAttribute/CloneAttirubte. r=masayuki
Add nsIAtom version of the following.
- CloneAttribute
- RemoveAttribute
- RemoveAttributeOrEquivalent
- SetAttribute
- SetAttributeOrEquivalent
MozReview-Commit-ID: 8CutpdyVuew
P1
MozReview-Commit-ID: 9MdmGcTqaxT
--- a/editor/libeditor/EditorBase.cpp
+++ b/editor/libeditor/EditorBase.cpp
@@ -1196,22 +1196,33 @@ EditorBase::CanPasteTransferable(nsITran
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
EditorBase::SetAttribute(nsIDOMElement* aElement,
const nsAString& aAttribute,
const nsAString& aValue)
{
+ if (NS_WARN_IF(aAttribute.IsEmpty())) {
+ return NS_ERROR_FAILURE;
+ }
nsCOMPtr<Element> element = do_QueryInterface(aElement);
NS_ENSURE_TRUE(element, NS_ERROR_NULL_POINTER);
nsCOMPtr<nsIAtom> attribute = NS_Atomize(aAttribute);
+ return SetAttribute(element, attribute, aValue);
+}
+
+nsresult
+EditorBase::SetAttribute(Element* aElement,
+ nsIAtom* aAttribute,
+ const nsAString& aValue)
+{
RefPtr<ChangeAttributeTransaction> transaction =
- CreateTxnForSetAttribute(*element, *attribute, aValue);
+ CreateTxnForSetAttribute(*aElement, *aAttribute, aValue);
return DoTransaction(transaction);
}
NS_IMETHODIMP
EditorBase::GetAttributeValue(nsIDOMElement* aElement,
const nsAString& aAttribute,
nsAString& aResultValue,
bool* aResultIsSet)
@@ -1230,22 +1241,32 @@ EditorBase::GetAttributeValue(nsIDOMElem
}
return rv;
}
NS_IMETHODIMP
EditorBase::RemoveAttribute(nsIDOMElement* aElement,
const nsAString& aAttribute)
{
+ if (NS_WARN_IF(aAttribute.IsEmpty())) {
+ return NS_ERROR_FAILURE;
+ }
nsCOMPtr<Element> element = do_QueryInterface(aElement);
NS_ENSURE_TRUE(element, NS_ERROR_NULL_POINTER);
nsCOMPtr<nsIAtom> attribute = NS_Atomize(aAttribute);
+ return RemoveAttribute(element, attribute);
+}
+
+nsresult
+EditorBase::RemoveAttribute(Element* aElement,
+ nsIAtom* aAttribute)
+{
RefPtr<ChangeAttributeTransaction> transaction =
- CreateTxnForRemoveAttribute(*element, *attribute);
+ CreateTxnForRemoveAttribute(*aElement, *aAttribute);
return DoTransaction(transaction);
}
bool
EditorBase::OutputsMozDirty()
{
// Return true for Composer (!eEditorAllowInteraction) or mail
// (eEditorMailMask), but false for webpages.
@@ -2175,35 +2196,38 @@ EditorBase::EndOperation()
}
NS_IMETHODIMP
EditorBase::CloneAttribute(const nsAString& aAttribute,
nsIDOMNode* aDestNode,
nsIDOMNode* aSourceNode)
{
NS_ENSURE_TRUE(aDestNode && aSourceNode, NS_ERROR_NULL_POINTER);
-
- nsCOMPtr<nsIDOMElement> destElement = do_QueryInterface(aDestNode);
- nsCOMPtr<nsIDOMElement> sourceElement = do_QueryInterface(aSourceNode);
+ if (NS_WARN_IF(aAttribute.IsEmpty())) {
+ return NS_ERROR_FAILURE;
+ }
+
+ nsCOMPtr<Element> destElement = do_QueryInterface(aDestNode);
+ nsCOMPtr<Element> sourceElement = do_QueryInterface(aSourceNode);
NS_ENSURE_TRUE(destElement && sourceElement, NS_ERROR_NO_INTERFACE);
+ nsCOMPtr<nsIAtom> attribute = NS_Atomize(aAttribute);
+ return CloneAttribute(attribute, destElement, sourceElement);
+}
+
+nsresult
+EditorBase::CloneAttribute(nsIAtom* aAttribute,
+ Element* aDestElement,
+ Element* aSourceElement)
+{
nsAutoString attrValue;
- bool isAttrSet;
- nsresult rv = GetAttributeValue(sourceElement,
- aAttribute,
- attrValue,
- &isAttrSet);
- NS_ENSURE_SUCCESS(rv, rv);
- if (isAttrSet) {
- rv = SetAttribute(destElement, aAttribute, attrValue);
- } else {
- rv = RemoveAttribute(destElement, aAttribute);
- }
-
- return rv;
+ if (aSourceElement->GetAttr(kNameSpaceID_None, aAttribute, attrValue)) {
+ return SetAttribute(aDestElement, aAttribute, attrValue);
+ }
+ return RemoveAttribute(aDestElement, aAttribute);
}
/**
* @param aDest Must be a DOM element.
* @param aSource Must be a DOM element.
*/
NS_IMETHODIMP
EditorBase::CloneAttributes(nsIDOMNode* aDest,
@@ -4585,31 +4609,42 @@ EditorBase::CreateHTMLContent(nsIAtom* a
"check caller.");
return nullptr;
}
return doc->CreateElem(nsDependentAtomString(aTag), nullptr,
kNameSpaceID_XHTML);
}
-nsresult
+NS_IMETHODIMP
EditorBase::SetAttributeOrEquivalent(nsIDOMElement* aElement,
const nsAString& aAttribute,
const nsAString& aValue,
bool aSuppressTransaction)
{
- return SetAttribute(aElement, aAttribute, aValue);
-}
-
-nsresult
+ nsCOMPtr<Element> element = do_QueryInterface(aElement);
+ if (NS_WARN_IF(!element)) {
+ return NS_ERROR_NULL_POINTER;
+ }
+ nsCOMPtr<nsIAtom> attribute = NS_Atomize(aAttribute);
+ return SetAttributeOrEquivalent(element, attribute, aValue,
+ aSuppressTransaction);
+}
+
+NS_IMETHODIMP
EditorBase::RemoveAttributeOrEquivalent(nsIDOMElement* aElement,
const nsAString& aAttribute,
bool aSuppressTransaction)
{
- return RemoveAttribute(aElement, aAttribute);
+ nsCOMPtr<Element> element = do_QueryInterface(aElement);
+ if (NS_WARN_IF(!element)) {
+ return NS_ERROR_NULL_POINTER;
+ }
+ nsCOMPtr<nsIAtom> attribute = NS_Atomize(aAttribute);
+ return RemoveAttributeOrEquivalent(element, attribute, aSuppressTransaction);
}
nsresult
EditorBase::HandleKeyPressEvent(nsIDOMKeyEvent* aKeyEvent)
{
// NOTE: When you change this method, you should also change:
// * editor/libeditor/tests/test_texteditor_keyevent_handling.html
// * editor/libeditor/tests/test_htmleditor_keyevent_handling.html
--- a/editor/libeditor/EditorBase.h
+++ b/editor/libeditor/EditorBase.h
@@ -229,16 +229,29 @@ public:
nsIAtom* aAttribute = nullptr,
const nsAString* aValue =
nullptr);
nsIContent* SplitNode(nsIContent& aNode, int32_t aOffset,
ErrorResult& aResult);
nsresult JoinNodes(nsINode& aLeftNode, nsINode& aRightNode);
nsresult MoveNode(nsIContent* aNode, nsINode* aParent, int32_t aOffset);
+ nsresult CloneAttribute(nsIAtom* aAttribute, Element* aDestElement,
+ Element* aSourceElement);
+ nsresult RemoveAttribute(Element* aElement, nsIAtom* aAttribute);
+ virtual nsresult RemoveAttributeOrEquivalent(Element* aElement,
+ nsIAtom* aAttribute,
+ bool aSuppressTransaction) = 0;
+ nsresult SetAttribute(Element* aElement, nsIAtom* aAttribute,
+ const nsAString& aValue);
+ virtual nsresult SetAttributeOrEquivalent(Element* aElement,
+ nsIAtom* aAttribute,
+ const nsAString& aValue,
+ bool aSuppressTransaction) = 0;
+
/**
* Method to replace certain CreateElementNS() calls.
*
* @param aTag Tag you want.
*/
already_AddRefed<Element> CreateHTMLContent(nsIAtom* aTag);
/**
--- a/editor/libeditor/HTMLEditor.cpp
+++ b/editor/libeditor/HTMLEditor.cpp
@@ -4442,103 +4442,93 @@ HTMLEditor::IsEmptyNodeImpl(nsINode* aNo
}
return NS_OK;
}
// add to aElement the CSS inline styles corresponding to the HTML attribute
// aAttribute with its value aValue
nsresult
-HTMLEditor::SetAttributeOrEquivalent(nsIDOMElement* aElement,
- const nsAString& aAttribute,
+HTMLEditor::SetAttributeOrEquivalent(Element* aElement,
+ nsIAtom* aAttribute,
const nsAString& aValue,
bool aSuppressTransaction)
{
+ MOZ_ASSERT(aElement);
+ MOZ_ASSERT(aAttribute);
+
nsAutoScriptBlocker scriptBlocker;
- if (IsCSSEnabled() && mCSSEditUtils) {
- nsCOMPtr<dom::Element> element = do_QueryInterface(aElement);
- MOZ_ASSERT(element);
-
- nsCOMPtr<nsIAtom> attribute = NS_Atomize(aAttribute);
- MOZ_ASSERT(attribute);
-
- int32_t count =
- mCSSEditUtils->SetCSSEquivalentToHTMLStyle(element, nullptr,
- attribute, &aValue,
- aSuppressTransaction);
- if (count) {
- // we found an equivalence ; let's remove the HTML attribute itself if it is set
- nsAutoString existingValue;
- bool wasSet = false;
- nsresult rv =
- GetAttributeValue(aElement, aAttribute, existingValue, &wasSet);
- NS_ENSURE_SUCCESS(rv, rv);
- if (!wasSet) {
- return NS_OK;
- }
- return aSuppressTransaction ?
- element->UnsetAttr(kNameSpaceID_None, attribute, true) :
- RemoveAttribute(aElement, aAttribute);
+ if (!IsCSSEnabled() || !mCSSEditUtils) {
+ // we are not in an HTML+CSS editor; let's set the attribute the HTML way
+ return aSuppressTransaction ?
+ aElement->SetAttr(kNameSpaceID_None, aAttribute, aValue, true) :
+ SetAttribute(aElement, aAttribute, aValue);
+ }
+
+ 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;
}
- // count is an integer that represents the number of CSS declarations applied to the
- // element. If it is zero, we found no equivalence in this implementation for the
- // attribute
- if (attribute == nsGkAtoms::style) {
- // if it is the style attribute, just add the new value to the existing style
- // attribute's value
- nsAutoString existingValue;
- bool wasSet = false;
- nsresult rv = GetAttributeValue(aElement, NS_LITERAL_STRING("style"),
- existingValue, &wasSet);
- NS_ENSURE_SUCCESS(rv, rv);
- existingValue.Append(' ');
- existingValue.Append(aValue);
- return aSuppressTransaction ?
- element->SetAttr(kNameSpaceID_None, attribute, existingValue, true) :
- SetAttribute(aElement, aAttribute, existingValue);
- }
-
- // we have no CSS equivalence for this attribute and it is not the style
- // attribute; let's set it the good'n'old HTML way
return aSuppressTransaction ?
- element->SetAttr(kNameSpaceID_None, attribute, aValue, true) :
- SetAttribute(aElement, aAttribute, aValue);
- }
-
- // we are not in an HTML+CSS editor; let's set the attribute the HTML way
- return aSuppressTransaction ? aElement->SetAttribute(aAttribute, aValue) :
- SetAttribute(aElement, aAttribute, aValue);
+ aElement->UnsetAttr(kNameSpaceID_None, aAttribute, true) :
+ RemoveAttribute(aElement, aAttribute);
+ }
+
+ // count is an integer that represents the number of CSS declarations applied
+ // to the element. If it is zero, we found no equivalence in this
+ // implementation for the attribute
+ if (aAttribute == nsGkAtoms::style) {
+ // if it is the style attribute, just add the new value to the existing
+ // style attribute's value
+ nsAutoString existingValue;
+ aElement->GetAttr(kNameSpaceID_None, nsGkAtoms::style, existingValue);
+ existingValue.Append(' ');
+ existingValue.Append(aValue);
+ return aSuppressTransaction ?
+ aElement->SetAttr(kNameSpaceID_None, aAttribute, existingValue, true) :
+ SetAttribute(aElement, aAttribute, existingValue);
+ }
+
+ // we have no CSS equivalence for this attribute and it is not the style
+ // attribute; let's set it the good'n'old HTML way
+ return aSuppressTransaction ?
+ aElement->SetAttr(kNameSpaceID_None, aAttribute, aValue, true) :
+ SetAttribute(aElement, aAttribute, aValue);
}
nsresult
-HTMLEditor::RemoveAttributeOrEquivalent(nsIDOMElement* aElement,
- const nsAString& aAttribute,
+HTMLEditor::RemoveAttributeOrEquivalent(Element* aElement,
+ nsIAtom* aAttribute,
bool aSuppressTransaction)
{
- nsCOMPtr<dom::Element> element = do_QueryInterface(aElement);
- NS_ENSURE_TRUE(element, NS_OK);
-
- nsCOMPtr<nsIAtom> attribute = NS_Atomize(aAttribute);
- MOZ_ASSERT(attribute);
+ MOZ_ASSERT(aElement);
+ MOZ_ASSERT(aAttribute);
if (IsCSSEnabled() && mCSSEditUtils) {
nsresult rv =
mCSSEditUtils->RemoveCSSEquivalentToHTMLStyle(
- element, nullptr, attribute, nullptr, aSuppressTransaction);
+ aElement, nullptr, aAttribute, nullptr, aSuppressTransaction);
NS_ENSURE_SUCCESS(rv, rv);
}
- if (!element->HasAttr(kNameSpaceID_None, attribute)) {
+ if (!aElement->HasAttr(kNameSpaceID_None, aAttribute)) {
return NS_OK;
}
return aSuppressTransaction ?
- element->UnsetAttr(kNameSpaceID_None, attribute, /* aNotify = */ true) :
+ aElement->UnsetAttr(kNameSpaceID_None, aAttribute, /* aNotify = */ true) :
RemoveAttribute(aElement, aAttribute);
}
nsresult
HTMLEditor::SetIsCSSEnabled(bool aIsCSSPrefChecked)
{
if (!mCSSEditUtils) {
return NS_ERROR_NOT_INITIALIZED;
--- a/editor/libeditor/HTMLEditor.h
+++ b/editor/libeditor/HTMLEditor.h
@@ -116,16 +116,26 @@ public:
virtual already_AddRefed<dom::EventTarget> GetDOMEventTarget() override;
virtual Element* GetEditorRoot() override;
virtual already_AddRefed<nsIContent> FindSelectionRoot(
nsINode *aNode) override;
virtual bool IsAcceptableInputEvent(nsIDOMEvent* aEvent) override;
virtual already_AddRefed<nsIContent> GetInputEventTargetContent() override;
virtual bool IsEditable(nsINode* aNode) override;
using EditorBase::IsEditable;
+ virtual nsresult RemoveAttributeOrEquivalent(
+ Element* aElement,
+ nsIAtom* aAttribute,
+ bool aSuppressTransaction) override;
+ virtual nsresult SetAttributeOrEquivalent(Element* aElement,
+ nsIAtom* aAttribute,
+ const nsAString& aValue,
+ bool aSuppressTransaction) override;
+ using EditorBase::RemoveAttributeOrEquivalent;
+ using EditorBase::SetAttributeOrEquivalent;
// nsStubMutationObserver overrides
NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
// nsIHTMLEditor methods
NS_DECL_NSIHTMLEDITOR
@@ -324,24 +334,16 @@ public:
virtual bool IsContainer(nsINode* aNode) override;
virtual bool IsContainer(nsIDOMNode* aNode) override;
/**
* Make the given selection span the entire document.
*/
virtual nsresult SelectEntireDocument(Selection* aSelection) override;
- NS_IMETHOD SetAttributeOrEquivalent(nsIDOMElement* aElement,
- const nsAString& aAttribute,
- const nsAString& aValue,
- bool aSuppressTransaction) override;
- NS_IMETHOD RemoveAttributeOrEquivalent(nsIDOMElement* aElement,
- const nsAString& aAttribute,
- bool aSuppressTransaction) override;
-
/**
* Join together any adjacent editable text nodes in the range.
*/
nsresult CollapseAdjacentTextNodes(nsRange* aRange);
virtual bool AreNodesSameType(nsIContent* aNode1,
nsIContent* aNode2) override;
--- a/editor/libeditor/TextEditor.cpp
+++ b/editor/libeditor/TextEditor.cpp
@@ -1613,25 +1613,25 @@ already_AddRefed<EventTarget>
TextEditor::GetDOMEventTarget()
{
nsCOMPtr<EventTarget> copy = mEventTarget;
return copy.forget();
}
nsresult
-TextEditor::SetAttributeOrEquivalent(nsIDOMElement* aElement,
- const nsAString& aAttribute,
+TextEditor::SetAttributeOrEquivalent(Element* aElement,
+ nsIAtom* aAttribute,
const nsAString& aValue,
bool aSuppressTransaction)
{
return EditorBase::SetAttribute(aElement, aAttribute, aValue);
}
nsresult
-TextEditor::RemoveAttributeOrEquivalent(nsIDOMElement* aElement,
- const nsAString& aAttribute,
+TextEditor::RemoveAttributeOrEquivalent(Element* aElement,
+ nsIAtom* aAttribute,
bool aSuppressTransaction)
{
return EditorBase::RemoveAttribute(aElement, aAttribute);
}
} // namespace mozilla
--- a/editor/libeditor/TextEditor.h
+++ b/editor/libeditor/TextEditor.h
@@ -58,24 +58,27 @@ public:
TextEditor();
// nsIPlaintextEditor methods
NS_DECL_NSIPLAINTEXTEDITOR
// nsIEditorMailSupport overrides
NS_DECL_NSIEDITORMAILSUPPORT
- // Overrides of EditorBase interface methods
- NS_IMETHOD SetAttributeOrEquivalent(nsIDOMElement* aElement,
- const nsAString& aAttribute,
- const nsAString& aValue,
- bool aSuppressTransaction) override;
- NS_IMETHOD RemoveAttributeOrEquivalent(nsIDOMElement* aElement,
- const nsAString& aAttribute,
- bool aSuppressTransaction) override;
+ // Overrides of EditorBase
+ virtual nsresult RemoveAttributeOrEquivalent(
+ Element* aElement,
+ nsIAtom* aAttribute,
+ bool aSuppressTransaction) override;
+ virtual nsresult SetAttributeOrEquivalent(Element* aElement,
+ nsIAtom* aAttribute,
+ const nsAString& aValue,
+ bool aSuppressTransaction) override;
+ using EditorBase::RemoveAttributeOrEquivalent;
+ using EditorBase::SetAttributeOrEquivalent;
NS_IMETHOD Init(nsIDOMDocument* aDoc, nsIContent* aRoot,
nsISelectionController* aSelCon, uint32_t aFlags,
const nsAString& aValue) override;
NS_IMETHOD GetDocumentIsEmpty(bool* aDocumentIsEmpty) override;
NS_IMETHOD GetIsDocumentEditable(bool* aIsDocumentEditable) override;