Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / inspector / DOMEditor.cpp
1 /*
2  * Copyright (C) 2012 Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
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
13  * distribution.
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.
17  *
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.
29  */
30
31 #include "config.h"
32 #include "core/inspector/DOMEditor.h"
33
34 #include "bindings/core/v8/ExceptionState.h"
35 #include "bindings/core/v8/ExceptionStatePlaceholder.h"
36 #include "core/dom/DOMException.h"
37 #include "core/dom/Element.h"
38 #include "core/dom/Node.h"
39 #include "core/dom/Text.h"
40 #include "core/editing/markup.h"
41 #include "core/inspector/DOMPatchSupport.h"
42 #include "core/inspector/InspectorHistory.h"
43 #include "wtf/RefPtr.h"
44
45 namespace blink {
46
47 class DOMEditor::RemoveChildAction final : public InspectorHistory::Action {
48     WTF_MAKE_NONCOPYABLE(RemoveChildAction);
49 public:
50     RemoveChildAction(Node* parentNode, Node* node)
51         : InspectorHistory::Action("RemoveChild")
52         , m_parentNode(parentNode)
53         , m_node(node)
54     {
55     }
56
57     virtual bool perform(ExceptionState& exceptionState) override
58     {
59         m_anchorNode = m_node->nextSibling();
60         return redo(exceptionState);
61     }
62
63     virtual bool undo(ExceptionState& exceptionState) override
64     {
65         m_parentNode->insertBefore(m_node.get(), m_anchorNode.get(), exceptionState);
66         return !exceptionState.hadException();
67     }
68
69     virtual bool redo(ExceptionState& exceptionState) override
70     {
71         m_parentNode->removeChild(m_node.get(), exceptionState);
72         return !exceptionState.hadException();
73     }
74
75     virtual void trace(Visitor* visitor) override
76     {
77         visitor->trace(m_parentNode);
78         visitor->trace(m_node);
79         visitor->trace(m_anchorNode);
80         InspectorHistory::Action::trace(visitor);
81     }
82
83 private:
84     RefPtrWillBeMember<Node> m_parentNode;
85     RefPtrWillBeMember<Node> m_node;
86     RefPtrWillBeMember<Node> m_anchorNode;
87 };
88
89 class DOMEditor::InsertBeforeAction final : public InspectorHistory::Action {
90     WTF_MAKE_NONCOPYABLE(InsertBeforeAction);
91 public:
92     InsertBeforeAction(Node* parentNode, PassRefPtrWillBeRawPtr<Node> node, Node* anchorNode)
93         : InspectorHistory::Action("InsertBefore")
94         , m_parentNode(parentNode)
95         , m_node(node)
96         , m_anchorNode(anchorNode)
97     {
98     }
99
100     virtual bool perform(ExceptionState& exceptionState) override
101     {
102         if (m_node->parentNode()) {
103             m_removeChildAction = adoptRefWillBeNoop(new RemoveChildAction(m_node->parentNode(), m_node.get()));
104             if (!m_removeChildAction->perform(exceptionState))
105                 return false;
106         }
107         m_parentNode->insertBefore(m_node.get(), m_anchorNode.get(), exceptionState);
108         return !exceptionState.hadException();
109     }
110
111     virtual bool undo(ExceptionState& exceptionState) override
112     {
113         m_parentNode->removeChild(m_node.get(), exceptionState);
114         if (exceptionState.hadException())
115             return false;
116         if (m_removeChildAction)
117             return m_removeChildAction->undo(exceptionState);
118         return true;
119     }
120
121     virtual bool redo(ExceptionState& exceptionState) override
122     {
123         if (m_removeChildAction && !m_removeChildAction->redo(exceptionState))
124             return false;
125         m_parentNode->insertBefore(m_node.get(), m_anchorNode.get(), exceptionState);
126         return !exceptionState.hadException();
127     }
128
129     virtual void trace(Visitor* visitor) override
130     {
131         visitor->trace(m_parentNode);
132         visitor->trace(m_node);
133         visitor->trace(m_anchorNode);
134         visitor->trace(m_removeChildAction);
135         InspectorHistory::Action::trace(visitor);
136     }
137
138 private:
139     RefPtrWillBeMember<Node> m_parentNode;
140     RefPtrWillBeMember<Node> m_node;
141     RefPtrWillBeMember<Node> m_anchorNode;
142     RefPtrWillBeMember<RemoveChildAction> m_removeChildAction;
143 };
144
145 class DOMEditor::RemoveAttributeAction final : public InspectorHistory::Action {
146     WTF_MAKE_NONCOPYABLE(RemoveAttributeAction);
147 public:
148     RemoveAttributeAction(Element* element, const AtomicString& name)
149         : InspectorHistory::Action("RemoveAttribute")
150         , m_element(element)
151         , m_name(name)
152     {
153     }
154
155     virtual bool perform(ExceptionState& exceptionState) override
156     {
157         m_value = m_element->getAttribute(m_name);
158         return redo(exceptionState);
159     }
160
161     virtual bool undo(ExceptionState& exceptionState) override
162     {
163         m_element->setAttribute(m_name, m_value, exceptionState);
164         return true;
165     }
166
167     virtual bool redo(ExceptionState&) override
168     {
169         m_element->removeAttribute(m_name);
170         return true;
171     }
172
173     virtual void trace(Visitor* visitor) override
174     {
175         visitor->trace(m_element);
176         InspectorHistory::Action::trace(visitor);
177     }
178
179 private:
180     RefPtrWillBeMember<Element> m_element;
181     AtomicString m_name;
182     AtomicString m_value;
183 };
184
185 class DOMEditor::SetAttributeAction final : public InspectorHistory::Action {
186     WTF_MAKE_NONCOPYABLE(SetAttributeAction);
187 public:
188     SetAttributeAction(Element* element, const AtomicString& name, const AtomicString& value)
189         : InspectorHistory::Action("SetAttribute")
190         , m_element(element)
191         , m_name(name)
192         , m_value(value)
193         , m_hadAttribute(false)
194     {
195     }
196
197     virtual bool perform(ExceptionState& exceptionState) override
198     {
199         const AtomicString& value = m_element->getAttribute(m_name);
200         m_hadAttribute = !value.isNull();
201         if (m_hadAttribute)
202             m_oldValue = value;
203         return redo(exceptionState);
204     }
205
206     virtual bool undo(ExceptionState& exceptionState) override
207     {
208         if (m_hadAttribute)
209             m_element->setAttribute(m_name, m_oldValue, exceptionState);
210         else
211             m_element->removeAttribute(m_name);
212         return true;
213     }
214
215     virtual bool redo(ExceptionState& exceptionState) override
216     {
217         m_element->setAttribute(m_name, m_value, exceptionState);
218         return true;
219     }
220
221     virtual void trace(Visitor* visitor) override
222     {
223         visitor->trace(m_element);
224         InspectorHistory::Action::trace(visitor);
225     }
226
227 private:
228     RefPtrWillBeMember<Element> m_element;
229     AtomicString m_name;
230     AtomicString m_value;
231     bool m_hadAttribute;
232     AtomicString m_oldValue;
233 };
234
235 class DOMEditor::SetOuterHTMLAction final : public InspectorHistory::Action {
236     WTF_MAKE_NONCOPYABLE(SetOuterHTMLAction);
237 public:
238     SetOuterHTMLAction(Node* node, const String& html)
239         : InspectorHistory::Action("SetOuterHTML")
240         , m_node(node)
241         , m_nextSibling(node->nextSibling())
242         , m_html(html)
243         , m_newNode(nullptr)
244         , m_history(adoptPtrWillBeNoop(new InspectorHistory()))
245         , m_domEditor(adoptPtrWillBeNoop(new DOMEditor(m_history.get())))
246     {
247     }
248
249     virtual bool perform(ExceptionState& exceptionState) override
250     {
251         m_oldHTML = createMarkup(m_node.get());
252         ASSERT(m_node->ownerDocument());
253         DOMPatchSupport domPatchSupport(m_domEditor.get(), *m_node->ownerDocument());
254         m_newNode = domPatchSupport.patchNode(m_node.get(), m_html, exceptionState);
255         return !exceptionState.hadException();
256     }
257
258     virtual bool undo(ExceptionState& exceptionState) override
259     {
260         return m_history->undo(exceptionState);
261     }
262
263     virtual bool redo(ExceptionState& exceptionState) override
264     {
265         return m_history->redo(exceptionState);
266     }
267
268     Node* newNode()
269     {
270         return m_newNode;
271     }
272
273     virtual void trace(Visitor* visitor) override
274     {
275         visitor->trace(m_node);
276         visitor->trace(m_nextSibling);
277         visitor->trace(m_newNode);
278         visitor->trace(m_history);
279         visitor->trace(m_domEditor);
280         InspectorHistory::Action::trace(visitor);
281     }
282
283 private:
284     RefPtrWillBeMember<Node> m_node;
285     RefPtrWillBeMember<Node> m_nextSibling;
286     String m_html;
287     String m_oldHTML;
288     RawPtrWillBeMember<Node> m_newNode;
289     OwnPtrWillBeMember<InspectorHistory> m_history;
290     OwnPtrWillBeMember<DOMEditor> m_domEditor;
291 };
292
293 class DOMEditor::ReplaceWholeTextAction final : public InspectorHistory::Action {
294     WTF_MAKE_NONCOPYABLE(ReplaceWholeTextAction);
295 public:
296     ReplaceWholeTextAction(Text* textNode, const String& text)
297         : InspectorHistory::Action("ReplaceWholeText")
298         , m_textNode(textNode)
299         , m_text(text)
300     {
301     }
302
303     virtual bool perform(ExceptionState& exceptionState) override
304     {
305         m_oldText = m_textNode->wholeText();
306         return redo(exceptionState);
307     }
308
309     virtual bool undo(ExceptionState&) override
310     {
311         m_textNode->replaceWholeText(m_oldText);
312         return true;
313     }
314
315     virtual bool redo(ExceptionState&) override
316     {
317         m_textNode->replaceWholeText(m_text);
318         return true;
319     }
320
321     virtual void trace(Visitor* visitor) override
322     {
323         visitor->trace(m_textNode);
324         InspectorHistory::Action::trace(visitor);
325     }
326
327 private:
328     RefPtrWillBeMember<Text> m_textNode;
329     String m_text;
330     String m_oldText;
331 };
332
333 class DOMEditor::ReplaceChildNodeAction final : public InspectorHistory::Action {
334     WTF_MAKE_NONCOPYABLE(ReplaceChildNodeAction);
335 public:
336     ReplaceChildNodeAction(Node* parentNode, PassRefPtrWillBeRawPtr<Node> newNode, Node* oldNode)
337         : InspectorHistory::Action("ReplaceChildNode")
338         , m_parentNode(parentNode)
339         , m_newNode(newNode)
340         , m_oldNode(oldNode)
341     {
342     }
343
344     virtual bool perform(ExceptionState& exceptionState) override
345     {
346         return redo(exceptionState);
347     }
348
349     virtual bool undo(ExceptionState& exceptionState) override
350     {
351         m_parentNode->replaceChild(m_oldNode, m_newNode.get(), exceptionState);
352         return !exceptionState.hadException();
353     }
354
355     virtual bool redo(ExceptionState& exceptionState) override
356     {
357         m_parentNode->replaceChild(m_newNode, m_oldNode.get(), exceptionState);
358         return !exceptionState.hadException();
359     }
360
361     virtual void trace(Visitor* visitor) override
362     {
363         visitor->trace(m_parentNode);
364         visitor->trace(m_newNode);
365         visitor->trace(m_oldNode);
366         InspectorHistory::Action::trace(visitor);
367     }
368
369 private:
370     RefPtrWillBeMember<Node> m_parentNode;
371     RefPtrWillBeMember<Node> m_newNode;
372     RefPtrWillBeMember<Node> m_oldNode;
373 };
374
375 class DOMEditor::SetNodeValueAction final : public InspectorHistory::Action {
376     WTF_MAKE_NONCOPYABLE(SetNodeValueAction);
377 public:
378     SetNodeValueAction(Node* node, const String& value)
379         : InspectorHistory::Action("SetNodeValue")
380         , m_node(node)
381         , m_value(value)
382     {
383     }
384
385     virtual bool perform(ExceptionState&) override
386     {
387         m_oldValue = m_node->nodeValue();
388         return redo(IGNORE_EXCEPTION);
389     }
390
391     virtual bool undo(ExceptionState&) override
392     {
393         m_node->setNodeValue(m_oldValue);
394         return true;
395     }
396
397     virtual bool redo(ExceptionState&) override
398     {
399         m_node->setNodeValue(m_value);
400         return true;
401     }
402
403     virtual void trace(Visitor* visitor) override
404     {
405         visitor->trace(m_node);
406         InspectorHistory::Action::trace(visitor);
407     }
408
409 private:
410     RefPtrWillBeMember<Node> m_node;
411     String m_value;
412     String m_oldValue;
413 };
414
415 DOMEditor::DOMEditor(InspectorHistory* history) : m_history(history) { }
416
417 bool DOMEditor::insertBefore(Node* parentNode, PassRefPtrWillBeRawPtr<Node> node, Node* anchorNode, ExceptionState& exceptionState)
418 {
419     return m_history->perform(adoptRefWillBeNoop(new InsertBeforeAction(parentNode, node, anchorNode)), exceptionState);
420 }
421
422 bool DOMEditor::removeChild(Node* parentNode, Node* node, ExceptionState& exceptionState)
423 {
424     return m_history->perform(adoptRefWillBeNoop(new RemoveChildAction(parentNode, node)), exceptionState);
425 }
426
427 bool DOMEditor::setAttribute(Element* element, const String& name, const String& value, ExceptionState& exceptionState)
428 {
429     return m_history->perform(adoptRefWillBeNoop(new SetAttributeAction(element, AtomicString(name), AtomicString(value))), exceptionState);
430 }
431
432 bool DOMEditor::removeAttribute(Element* element, const String& name, ExceptionState& exceptionState)
433 {
434     return m_history->perform(adoptRefWillBeNoop(new RemoveAttributeAction(element, AtomicString(name))), exceptionState);
435 }
436
437 bool DOMEditor::setOuterHTML(Node* node, const String& html, Node** newNode, ExceptionState& exceptionState)
438 {
439     RefPtrWillBeRawPtr<SetOuterHTMLAction> action = adoptRefWillBeNoop(new SetOuterHTMLAction(node, html));
440     bool result = m_history->perform(action, exceptionState);
441     if (result)
442         *newNode = action->newNode();
443     return result;
444 }
445
446 bool DOMEditor::replaceWholeText(Text* textNode, const String& text, ExceptionState& exceptionState)
447 {
448     return m_history->perform(adoptRefWillBeNoop(new ReplaceWholeTextAction(textNode, text)), exceptionState);
449 }
450
451 bool DOMEditor::replaceChild(Node* parentNode, PassRefPtrWillBeRawPtr<Node> newNode, Node* oldNode, ExceptionState& exceptionState)
452 {
453     return m_history->perform(adoptRefWillBeNoop(new ReplaceChildNodeAction(parentNode, newNode, oldNode)), exceptionState);
454 }
455
456 bool DOMEditor::setNodeValue(Node* node, const String& value, ExceptionState& exceptionState)
457 {
458     return m_history->perform(adoptRefWillBeNoop(new SetNodeValueAction(node, value)), exceptionState);
459 }
460
461 static void populateErrorString(ExceptionState& exceptionState, ErrorString* errorString)
462 {
463     if (exceptionState.hadException())
464         *errorString = DOMException::getErrorName(exceptionState.code());
465 }
466
467 bool DOMEditor::insertBefore(Node* parentNode, PassRefPtrWillBeRawPtr<Node> node, Node* anchorNode, ErrorString* errorString)
468 {
469     TrackExceptionState exceptionState;
470     bool result = insertBefore(parentNode, node, anchorNode, exceptionState);
471     populateErrorString(exceptionState, errorString);
472     return result;
473 }
474
475 bool DOMEditor::removeChild(Node* parentNode, Node* node, ErrorString* errorString)
476 {
477     TrackExceptionState exceptionState;
478     bool result = removeChild(parentNode, node, exceptionState);
479     populateErrorString(exceptionState, errorString);
480     return result;
481 }
482
483 bool DOMEditor::setAttribute(Element* element, const String& name, const String& value, ErrorString* errorString)
484 {
485     TrackExceptionState exceptionState;
486     bool result = setAttribute(element, name, value, exceptionState);
487     populateErrorString(exceptionState, errorString);
488     return result;
489 }
490
491 bool DOMEditor::removeAttribute(Element* element, const String& name, ErrorString* errorString)
492 {
493     TrackExceptionState exceptionState;
494     bool result = removeAttribute(element, name, exceptionState);
495     populateErrorString(exceptionState, errorString);
496     return result;
497 }
498
499 bool DOMEditor::setOuterHTML(Node* node, const String& html, Node** newNode, ErrorString* errorString)
500 {
501     TrackExceptionState exceptionState;
502     bool result = setOuterHTML(node, html, newNode, exceptionState);
503     populateErrorString(exceptionState, errorString);
504     return result;
505 }
506
507 bool DOMEditor::replaceWholeText(Text* textNode, const String& text, ErrorString* errorString)
508 {
509     TrackExceptionState exceptionState;
510     bool result = replaceWholeText(textNode, text, exceptionState);
511     populateErrorString(exceptionState, errorString);
512     return result;
513 }
514
515 void DOMEditor::trace(Visitor* visitor)
516 {
517     visitor->trace(m_history);
518 }
519
520 } // namespace blink
521