2 * Copyright (C) 2012 Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
14 * * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 #include "DOMEditor.h"
34 #include "DOMPatchSupport.h"
37 #include "ExceptionCode.h"
38 #include "ExceptionCodeDescription.h"
39 #include "InspectorHistory.h"
43 #include <wtf/RefPtr.h>
47 class DOMEditor::RemoveChildAction : public InspectorHistory::Action {
48 WTF_MAKE_NONCOPYABLE(RemoveChildAction);
50 RemoveChildAction(Node* parentNode, Node* node)
51 : InspectorHistory::Action("RemoveChild")
52 , m_parentNode(parentNode)
57 virtual bool perform(ExceptionCode& ec) override
59 m_anchorNode = m_node->nextSibling();
63 virtual bool undo(ExceptionCode& ec) override
65 return m_parentNode->insertBefore(m_node.get(), m_anchorNode.get(), ec);
68 virtual bool redo(ExceptionCode& ec) override
70 return m_parentNode->removeChild(m_node.get(), ec);
74 RefPtr<Node> m_parentNode;
76 RefPtr<Node> m_anchorNode;
79 class DOMEditor::InsertBeforeAction : public InspectorHistory::Action {
80 WTF_MAKE_NONCOPYABLE(InsertBeforeAction);
82 InsertBeforeAction(Node* parentNode, RefPtr<Node>&& node, Node* anchorNode)
83 : InspectorHistory::Action("InsertBefore")
84 , m_parentNode(parentNode)
85 , m_node(WTF::move(node))
86 , m_anchorNode(anchorNode)
90 virtual bool perform(ExceptionCode& ec) override
92 if (m_node->parentNode()) {
93 m_removeChildAction = std::make_unique<RemoveChildAction>(m_node->parentNode(), m_node.get());
94 if (!m_removeChildAction->perform(ec))
97 return m_parentNode->insertBefore(m_node.get(), m_anchorNode.get(), ec);
100 virtual bool undo(ExceptionCode& ec) override
102 if (!m_parentNode->removeChild(m_node.get(), ec))
104 if (m_removeChildAction)
105 return m_removeChildAction->undo(ec);
109 virtual bool redo(ExceptionCode& ec) override
111 if (m_removeChildAction && !m_removeChildAction->redo(ec))
113 return m_parentNode->insertBefore(m_node.get(), m_anchorNode.get(), ec);
117 RefPtr<Node> m_parentNode;
119 RefPtr<Node> m_anchorNode;
120 std::unique_ptr<RemoveChildAction> m_removeChildAction;
123 class DOMEditor::RemoveAttributeAction : public InspectorHistory::Action {
124 WTF_MAKE_NONCOPYABLE(RemoveAttributeAction);
126 RemoveAttributeAction(Element* element, const String& name)
127 : InspectorHistory::Action("RemoveAttribute")
133 virtual bool perform(ExceptionCode& ec) override
135 m_value = m_element->getAttribute(m_name);
139 virtual bool undo(ExceptionCode& ec) override
141 m_element->setAttribute(m_name, m_value, ec);
145 virtual bool redo(ExceptionCode&) override
147 m_element->removeAttribute(m_name);
152 RefPtr<Element> m_element;
157 class DOMEditor::SetAttributeAction : public InspectorHistory::Action {
158 WTF_MAKE_NONCOPYABLE(SetAttributeAction);
160 SetAttributeAction(Element* element, const String& name, const String& value)
161 : InspectorHistory::Action("SetAttribute")
165 , m_hadAttribute(false)
169 virtual bool perform(ExceptionCode& ec) override
171 m_hadAttribute = m_element->hasAttribute(m_name);
173 m_oldValue = m_element->getAttribute(m_name);
177 virtual bool undo(ExceptionCode& ec) override
180 m_element->setAttribute(m_name, m_oldValue, ec);
182 m_element->removeAttribute(m_name);
186 virtual bool redo(ExceptionCode& ec) override
188 m_element->setAttribute(m_name, m_value, ec);
193 RefPtr<Element> m_element;
200 class DOMEditor::SetOuterHTMLAction : public InspectorHistory::Action {
201 WTF_MAKE_NONCOPYABLE(SetOuterHTMLAction);
203 SetOuterHTMLAction(Node& node, const String& html)
204 : InspectorHistory::Action("SetOuterHTML")
206 , m_nextSibling(node.nextSibling())
209 , m_history(std::make_unique<InspectorHistory>())
210 , m_domEditor(std::make_unique<DOMEditor>(m_history.get()))
214 virtual bool perform(ExceptionCode& ec) override
216 m_oldHTML = createMarkup(m_node.get());
217 DOMPatchSupport domPatchSupport(m_domEditor.get(), &m_node->document());
218 m_newNode = domPatchSupport.patchNode(m_node.get(), m_html, ec);
222 virtual bool undo(ExceptionCode& ec) override
224 return m_history->undo(ec);
227 virtual bool redo(ExceptionCode& ec) override
229 return m_history->redo(ec);
239 RefPtr<Node> m_nextSibling;
243 std::unique_ptr<InspectorHistory> m_history;
244 std::unique_ptr<DOMEditor> m_domEditor;
247 class DOMEditor::ReplaceWholeTextAction : public InspectorHistory::Action {
248 WTF_MAKE_NONCOPYABLE(ReplaceWholeTextAction);
250 ReplaceWholeTextAction(Text* textNode, const String& text)
251 : InspectorHistory::Action("ReplaceWholeText")
252 , m_textNode(textNode)
257 virtual bool perform(ExceptionCode& ec) override
259 m_oldText = m_textNode->wholeText();
263 virtual bool undo(ExceptionCode& ec) override
265 m_textNode->replaceWholeText(m_oldText, ec);
269 virtual bool redo(ExceptionCode& ec) override
271 m_textNode->replaceWholeText(m_text, ec);
276 RefPtr<Text> m_textNode;
281 class DOMEditor::ReplaceChildNodeAction : public InspectorHistory::Action {
282 WTF_MAKE_NONCOPYABLE(ReplaceChildNodeAction);
284 ReplaceChildNodeAction(Node* parentNode, RefPtr<Node>&& newNode, Node* oldNode)
285 : InspectorHistory::Action("ReplaceChildNode")
286 , m_parentNode(parentNode)
287 , m_newNode(WTF::move(newNode))
292 virtual bool perform(ExceptionCode& ec) override
297 virtual bool undo(ExceptionCode& ec) override
299 return m_parentNode->replaceChild(m_oldNode, m_newNode.get(), ec);
302 virtual bool redo(ExceptionCode& ec) override
304 return m_parentNode->replaceChild(m_newNode, m_oldNode.get(), ec);
308 RefPtr<Node> m_parentNode;
309 RefPtr<Node> m_newNode;
310 RefPtr<Node> m_oldNode;
313 class DOMEditor::SetNodeValueAction : public InspectorHistory::Action {
314 WTF_MAKE_NONCOPYABLE(SetNodeValueAction);
316 SetNodeValueAction(Node* node, const String& value)
317 : InspectorHistory::Action("SetNodeValue")
323 virtual bool perform(ExceptionCode& ec) override
325 m_oldValue = m_node->nodeValue();
329 virtual bool undo(ExceptionCode& ec) override
331 m_node->setNodeValue(m_oldValue, ec);
335 virtual bool redo(ExceptionCode& ec) override
337 m_node->setNodeValue(m_value, ec);
347 DOMEditor::DOMEditor(InspectorHistory* history) : m_history(history) { }
349 DOMEditor::~DOMEditor() { }
351 bool DOMEditor::insertBefore(Node* parentNode, RefPtr<Node>&& node, Node* anchorNode, ExceptionCode& ec)
353 return m_history->perform(std::make_unique<InsertBeforeAction>(parentNode, WTF::move(node), anchorNode), ec);
356 bool DOMEditor::removeChild(Node* parentNode, Node* node, ExceptionCode& ec)
358 return m_history->perform(std::make_unique<RemoveChildAction>(parentNode, node), ec);
361 bool DOMEditor::setAttribute(Element* element, const String& name, const String& value, ExceptionCode& ec)
363 return m_history->perform(std::make_unique<SetAttributeAction>(element, name, value), ec);
366 bool DOMEditor::removeAttribute(Element* element, const String& name, ExceptionCode& ec)
368 return m_history->perform(std::make_unique<RemoveAttributeAction>(element, name), ec);
371 bool DOMEditor::setOuterHTML(Node& node, const String& html, Node** newNode, ExceptionCode& ec)
373 auto action = std::make_unique<SetOuterHTMLAction>(node, html);
374 SetOuterHTMLAction* rawAction = action.get();
375 bool result = m_history->perform(WTF::move(action), ec);
377 *newNode = rawAction->newNode();
381 bool DOMEditor::replaceWholeText(Text* textNode, const String& text, ExceptionCode& ec)
383 return m_history->perform(std::make_unique<ReplaceWholeTextAction>(textNode, text), ec);
386 bool DOMEditor::replaceChild(Node* parentNode, RefPtr<Node>&& newNode, Node* oldNode, ExceptionCode& ec)
388 return m_history->perform(std::make_unique<ReplaceChildNodeAction>(parentNode, WTF::move(newNode), oldNode), ec);
391 bool DOMEditor::setNodeValue(Node* node, const String& value, ExceptionCode& ec)
393 return m_history->perform(std::make_unique<SetNodeValueAction>(node, value), ec);
396 static void populateErrorString(const ExceptionCode& ec, ErrorString& errorString)
399 ExceptionCodeDescription description(ec);
400 errorString = description.name;
404 bool DOMEditor::insertBefore(Node* parentNode, RefPtr<Node>&& node, Node* anchorNode, ErrorString& errorString)
406 ExceptionCode ec = 0;
407 bool result = insertBefore(parentNode, WTF::move(node), anchorNode, ec);
408 populateErrorString(ec, errorString);
412 bool DOMEditor::removeChild(Node* parentNode, Node* node, ErrorString& errorString)
414 ExceptionCode ec = 0;
415 bool result = removeChild(parentNode, node, ec);
416 populateErrorString(ec, errorString);
420 bool DOMEditor::setAttribute(Element* element, const String& name, const String& value, ErrorString& errorString)
422 ExceptionCode ec = 0;
423 bool result = setAttribute(element, name, value, ec);
424 populateErrorString(ec, errorString);
428 bool DOMEditor::removeAttribute(Element* element, const String& name, ErrorString& errorString)
430 ExceptionCode ec = 0;
431 bool result = removeAttribute(element, name, ec);
432 populateErrorString(ec, errorString);
436 bool DOMEditor::setOuterHTML(Node& node, const String& html, Node** newNode, ErrorString& errorString)
438 ExceptionCode ec = 0;
439 bool result = setOuterHTML(node, html, newNode, ec);
440 populateErrorString(ec, errorString);
444 bool DOMEditor::replaceWholeText(Text* textNode, const String& text, ErrorString& errorString)
446 ExceptionCode ec = 0;
447 bool result = replaceWholeText(textNode, text, ec);
448 populateErrorString(ec, errorString);
452 } // namespace WebCore