ChangeAttributeTransaction.cpp (7423B)
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* This Source Code Form is subject to the terms of the Mozilla Public 3 * License, v. 2.0. If a copy of the MPL was not distributed with this 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 6 #include "ChangeAttributeTransaction.h" 7 8 #include "EditorDOMAPIWrapper.h" 9 10 #include "mozilla/Logging.h" 11 #include "mozilla/ToString.h" 12 #include "mozilla/dom/Element.h" // for Element 13 14 #include "nsAString.h" 15 #include "nsError.h" // for NS_ERROR_NOT_INITIALIZED, etc. 16 17 namespace mozilla { 18 19 using namespace dom; 20 21 // static 22 already_AddRefed<ChangeAttributeTransaction> ChangeAttributeTransaction::Create( 23 EditorBase& aEditorBase, Element& aElement, nsAtom& aAttribute, 24 const nsAString& aValue) { 25 RefPtr<ChangeAttributeTransaction> transaction = 26 new ChangeAttributeTransaction(aEditorBase, aElement, aAttribute, 27 &aValue); 28 return transaction.forget(); 29 } 30 31 // static 32 already_AddRefed<ChangeAttributeTransaction> 33 ChangeAttributeTransaction::CreateToRemove(EditorBase& aEditorBase, 34 Element& aElement, 35 nsAtom& aAttribute) { 36 RefPtr<ChangeAttributeTransaction> transaction = 37 new ChangeAttributeTransaction(aEditorBase, aElement, aAttribute, 38 nullptr); 39 return transaction.forget(); 40 } 41 42 ChangeAttributeTransaction::ChangeAttributeTransaction(EditorBase& aEditorBase, 43 Element& aElement, 44 nsAtom& aAttribute, 45 const nsAString* aValue) 46 : EditTransactionBase(), 47 mEditorBase(&aEditorBase), 48 mElement(&aElement), 49 mAttribute(&aAttribute), 50 mValue(aValue ? *aValue : u""_ns), 51 mRemoveAttribute(!aValue), 52 mAttributeWasSet(false) {} 53 54 std::ostream& operator<<(std::ostream& aStream, 55 const ChangeAttributeTransaction& aTransaction) { 56 aStream << "{ mElement=" << aTransaction.mElement.get(); 57 if (aTransaction.mElement) { 58 aStream << " (" << *aTransaction.mElement << ")"; 59 } 60 aStream << ", mAttribute=" << nsAtomCString(aTransaction.mAttribute).get() 61 << ", mValue=\"" << NS_ConvertUTF16toUTF8(aTransaction.mValue).get() 62 << "\", mUndoValue=\"" 63 << NS_ConvertUTF16toUTF8(aTransaction.mUndoValue).get() 64 << "\", mRemoveAttribute=" 65 << (aTransaction.mRemoveAttribute ? "true" : "false") 66 << ", mAttributeWasSet=" 67 << (aTransaction.mAttributeWasSet ? "true" : "false") 68 << ", mEditorBase=" << aTransaction.mEditorBase.get() << " }"; 69 return aStream; 70 } 71 72 NS_IMPL_CYCLE_COLLECTION_INHERITED(ChangeAttributeTransaction, 73 EditTransactionBase, mEditorBase, mElement) 74 75 NS_IMPL_ADDREF_INHERITED(ChangeAttributeTransaction, EditTransactionBase) 76 NS_IMPL_RELEASE_INHERITED(ChangeAttributeTransaction, EditTransactionBase) 77 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ChangeAttributeTransaction) 78 NS_INTERFACE_MAP_END_INHERITING(EditTransactionBase) 79 80 NS_IMETHODIMP ChangeAttributeTransaction::DoTransaction() { 81 MOZ_ASSERT(mEditorBase); 82 83 // Need to get the current value of the attribute and save it, and set 84 // mAttributeWasSet 85 mAttributeWasSet = mElement->GetAttr(mAttribute, mUndoValue); 86 87 // XXX: hack until attribute-was-set code is implemented 88 if (!mUndoValue.IsEmpty()) { 89 mAttributeWasSet = true; 90 } 91 // XXX: end hack 92 93 MOZ_LOG(GetLogModule(), LogLevel::Info, 94 ("%p ChangeAttributeTransaction::%s this=%s", this, __FUNCTION__, 95 ToString(*this).c_str())); 96 97 const OwningNonNull<EditorBase> editorBase = *mEditorBase; 98 const OwningNonNull<Element> element = *mElement; 99 // Now set the attribute to the new value 100 if (mRemoveAttribute) { 101 AutoElementAttrAPIWrapper elementWrapper(editorBase, element); 102 nsresult rv = elementWrapper.UnsetAttr(MOZ_KnownLive(mAttribute), true); 103 if (NS_FAILED(rv)) { 104 NS_WARNING("AutoElementAttrAPIWrapper::UnsetAttr() failed"); 105 return rv; 106 } 107 NS_WARNING_ASSERTION( 108 elementWrapper.IsExpectedResult(EmptyString()), 109 "Removing attribute caused other mutations, but ignored"); 110 return NS_OK; 111 } 112 113 AutoElementAttrAPIWrapper elementWrapper(editorBase, element); 114 nsresult rv = elementWrapper.SetAttr(MOZ_KnownLive(mAttribute), mValue, true); 115 if (NS_FAILED(rv)) { 116 NS_WARNING("AutoElementAttrAPIWrapper::SetAttr() failed"); 117 return rv; 118 } 119 NS_WARNING_ASSERTION(elementWrapper.IsExpectedResult(mValue), 120 "Setting attribute caused other mutations, but ignored"); 121 return rv; 122 } 123 124 NS_IMETHODIMP ChangeAttributeTransaction::UndoTransaction() { 125 MOZ_LOG(GetLogModule(), LogLevel::Info, 126 ("%p ChangeAttributeTransaction::%s this=%s", this, __FUNCTION__, 127 ToString(*this).c_str())); 128 129 if (NS_WARN_IF(!mEditorBase) || NS_WARN_IF(!mElement)) { 130 return NS_ERROR_NOT_AVAILABLE; 131 } 132 const OwningNonNull<EditorBase> editorBase = *mEditorBase; 133 const OwningNonNull<Element> element = *mElement; 134 if (mAttributeWasSet) { 135 AutoElementAttrAPIWrapper elementWrapper(editorBase, element); 136 nsresult rv = 137 elementWrapper.SetAttr(MOZ_KnownLive(mAttribute), mUndoValue, true); 138 if (NS_FAILED(rv)) { 139 NS_WARNING("AutoElementAttrAPIWrapper::SetAttr() failed"); 140 return rv; 141 } 142 NS_WARNING_ASSERTION( 143 elementWrapper.IsExpectedResult(mUndoValue), 144 "Setting attribute caused other mutations, but ignored"); 145 return NS_OK; 146 } 147 AutoElementAttrAPIWrapper elementWrapper(editorBase, element); 148 nsresult rv = elementWrapper.UnsetAttr(MOZ_KnownLive(mAttribute), true); 149 if (NS_FAILED(rv)) { 150 NS_WARNING("AutoElementAttrAPIWrapper::UnsetAttr() failed"); 151 return rv; 152 } 153 NS_WARNING_ASSERTION( 154 elementWrapper.IsExpectedResult(EmptyString()), 155 "Removing attribute caused other mutations, but ignored"); 156 return NS_OK; 157 } 158 159 NS_IMETHODIMP ChangeAttributeTransaction::RedoTransaction() { 160 MOZ_LOG(GetLogModule(), LogLevel::Info, 161 ("%p ChangeAttributeTransaction::%s this=%s", this, __FUNCTION__, 162 ToString(*this).c_str())); 163 164 if (NS_WARN_IF(!mEditorBase) || NS_WARN_IF(!mElement)) { 165 return NS_ERROR_NOT_AVAILABLE; 166 } 167 const OwningNonNull<EditorBase> editorBase = *mEditorBase; 168 const OwningNonNull<Element> element = *mElement; 169 if (mRemoveAttribute) { 170 AutoElementAttrAPIWrapper elementWrapper(editorBase, element); 171 nsresult rv = elementWrapper.UnsetAttr(MOZ_KnownLive(mAttribute), true); 172 if (NS_FAILED(rv)) { 173 NS_WARNING("AutoElementAttrAPIWrapper::UnsetAttr() failed"); 174 return rv; 175 } 176 NS_WARNING_ASSERTION( 177 elementWrapper.IsExpectedResult(EmptyString()), 178 "Removing attribute caused other mutations, but ignored"); 179 return NS_OK; 180 } 181 182 AutoElementAttrAPIWrapper elementWrapper(editorBase, element); 183 nsresult rv = elementWrapper.SetAttr(MOZ_KnownLive(mAttribute), mValue, true); 184 if (NS_FAILED(rv)) { 185 NS_WARNING("AutoElementAttrAPIWrapper::SetAttr() failed"); 186 return rv; 187 } 188 NS_WARNING_ASSERTION(elementWrapper.IsExpectedResult(mValue), 189 "Setting attribute caused other mutations, but ignored"); 190 return NS_OK; 191 } 192 193 } // namespace mozilla