Web Inspector: implement undo for setOuterHTML via undo-ing nested primitive commands.
authorpfeldman@chromium.org <pfeldman@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 10 Feb 2012 13:15:12 +0000 (13:15 +0000)
committerpfeldman@chromium.org <pfeldman@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 10 Feb 2012 13:15:12 +0000 (13:15 +0000)
https://bugs.webkit.org/show_bug.cgi?id=78346

Reviewed by Yury Semikhatsky.

Source/WebCore:

Tests: inspector/elements/undo-set-outer-html-2.html
       inspector/elements/undo-set-outer-html.html

* inspector/DOMEditor.cpp:
(WebCore::DOMEditor::RemoveChildAction::RemoveChildAction):
(WebCore::DOMEditor::InsertBeforeAction::InsertBeforeAction):
(WebCore::DOMEditor::InsertBeforeAction::undo):
(WebCore::DOMEditor::RemoveAttributeAction::RemoveAttributeAction):
(WebCore::DOMEditor::SetAttributeAction::SetAttributeAction):
(WebCore::DOMEditor::SetOuterHTMLAction::SetOuterHTMLAction):
(WebCore::DOMEditor::SetOuterHTMLAction::perform):
(WebCore::DOMEditor::SetOuterHTMLAction::undo):
(DOMEditor::SetOuterHTMLAction):
(WebCore::DOMEditor::ReplaceWholeTextAction::ReplaceWholeTextAction):
(DOMEditor::ReplaceChildNodeAction):
(WebCore::DOMEditor::ReplaceChildNodeAction::ReplaceChildNodeAction):
(WebCore::DOMEditor::ReplaceChildNodeAction::perform):
(WebCore::DOMEditor::ReplaceChildNodeAction::undo):
(WebCore):
(DOMEditor::SetNodeValueAction):
(WebCore::DOMEditor::SetNodeValueAction::SetNodeValueAction):
(WebCore::DOMEditor::SetNodeValueAction::perform):
(WebCore::DOMEditor::SetNodeValueAction::undo):
(WebCore::DOMEditor::insertBefore):
(WebCore::DOMEditor::removeChild):
(WebCore::DOMEditor::setAttribute):
(WebCore::DOMEditor::removeAttribute):
(WebCore::DOMEditor::setOuterHTML):
(WebCore::DOMEditor::replaceWholeText):
(WebCore::DOMEditor::replaceChild):
(WebCore::DOMEditor::setNodeValue):
(WebCore::populateErrorString):
* inspector/DOMEditor.h:
(DOMEditor):
* inspector/DOMPatchSupport.cpp:
(WebCore::DOMPatchSupport::patchDocument):
(WebCore):
(WebCore::DOMPatchSupport::DOMPatchSupport):
(WebCore::DOMPatchSupport::patchNode):
(WebCore::DOMPatchSupport::innerPatchNode):
(WebCore::DOMPatchSupport::innerPatchChildren):
(WebCore::DOMPatchSupport::insertBeforeAndMarkAsUsed):
(WebCore::DOMPatchSupport::removeChildAndMoveToNew):
* inspector/DOMPatchSupport.h:
(WebCore):
(DOMPatchSupport):
* inspector/InspectorCSSAgent.cpp:
(WebCore::InspectorCSSAgent::StyleSheetAction::perform):
(WebCore::InspectorCSSAgent::StyleSheetAction::undo):
(InspectorCSSAgent::StyleSheetAction):
(WebCore::InspectorCSSAgent::SetStyleSheetTextAction::perform):
(WebCore::InspectorCSSAgent::SetStyleSheetTextAction::undo):
(WebCore::InspectorCSSAgent::SetPropertyTextAction::perform):
(WebCore::InspectorCSSAgent::SetPropertyTextAction::undo):
(WebCore::InspectorCSSAgent::TogglePropertyAction::perform):
(WebCore::InspectorCSSAgent::TogglePropertyAction::undo):
(WebCore::InspectorCSSAgent::setStyleSheetText):
(WebCore::InspectorCSSAgent::setPropertyText):
(WebCore::InspectorCSSAgent::toggleProperty):
(WebCore::InspectorCSSAgent::assertStyleSheetForId):
* inspector/InspectorDOMAgent.cpp:
(WebCore::InspectorDOMAgent::toErrorString):
(WebCore):
(WebCore::InspectorDOMAgent::setAttributesAsText):
(WebCore::InspectorDOMAgent::setOuterHTML):
(WebCore::InspectorDOMAgent::undo):
* inspector/InspectorDOMAgent.h:
(InspectorDOMAgent):
* inspector/InspectorHistory.cpp:
(WebCore::InspectorHistory::perform):
(WebCore::InspectorHistory::undo):
* inspector/InspectorHistory.h:
(WebCore):
(Action):
(InspectorHistory):
* inspector/InspectorPageAgent.cpp:
(WebCore::InspectorPageAgent::setDocumentContent):
* inspector/InspectorStyleSheet.cpp:
(WebCore::InspectorStyle::setPropertyText):
(WebCore::InspectorStyle::toggleProperty):
(WebCore::InspectorStyleSheet::setPropertyText):
(WebCore::InspectorStyleSheet::toggleProperty):
* inspector/InspectorStyleSheet.h:
(InspectorStyle):
(InspectorStyleSheet):

LayoutTests:

* inspector/elements/set-outer-html-2-expected.txt:
* inspector/elements/set-outer-html-test.js:
(initialize_SetOuterHTMLTest.InspectorTest.patchOuterHTML):
(initialize_SetOuterHTMLTest.InspectorTest.patchOuterHTMLUseUndo):
(initialize_SetOuterHTMLTest.InspectorTest.setOuterHTMLUseUndo.bringBack):
(initialize_SetOuterHTMLTest.InspectorTest.setOuterHTMLUseUndo):
(initialize_SetOuterHTMLTest.InspectorTest.innerSetOuterHTML):
(initialize_SetOuterHTMLTest.InspectorTest._dumpOuterHTML.dumpIdentity):
(initialize_SetOuterHTMLTest.InspectorTest._dumpOuterHTML.callback):
(initialize_SetOuterHTMLTest.InspectorTest._dumpOuterHTML):
(initialize_SetOuterHTMLTest):
* inspector/elements/undo-dom-edits-expected.txt:
* inspector/elements/undo-set-outer-html-2-expected.txt: Copied from LayoutTests/inspector/elements/set-outer-html-2-expected.txt.
* inspector/elements/undo-set-outer-html-2.html: Added.
* inspector/elements/undo-set-outer-html-expected.txt: Copied from LayoutTests/inspector/elements/set-outer-html-2-expected.txt.
* inspector/elements/undo-set-outer-html.html: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@107399 268f45cc-cd09-0410-ab3c-d52691b4dbfc

21 files changed:
LayoutTests/ChangeLog
LayoutTests/inspector/elements/set-outer-html-2-expected.txt
LayoutTests/inspector/elements/set-outer-html-test.js
LayoutTests/inspector/elements/undo-dom-edits-expected.txt
LayoutTests/inspector/elements/undo-set-outer-html-2-expected.txt [new file with mode: 0644]
LayoutTests/inspector/elements/undo-set-outer-html-2.html [new file with mode: 0644]
LayoutTests/inspector/elements/undo-set-outer-html-expected.txt [new file with mode: 0644]
LayoutTests/inspector/elements/undo-set-outer-html.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/inspector/DOMEditor.cpp
Source/WebCore/inspector/DOMEditor.h
Source/WebCore/inspector/DOMPatchSupport.cpp
Source/WebCore/inspector/DOMPatchSupport.h
Source/WebCore/inspector/InspectorCSSAgent.cpp
Source/WebCore/inspector/InspectorDOMAgent.cpp
Source/WebCore/inspector/InspectorDOMAgent.h
Source/WebCore/inspector/InspectorHistory.cpp
Source/WebCore/inspector/InspectorHistory.h
Source/WebCore/inspector/InspectorPageAgent.cpp
Source/WebCore/inspector/InspectorStyleSheet.cpp
Source/WebCore/inspector/InspectorStyleSheet.h

index 5896595..1027c39 100644 (file)
@@ -1,3 +1,27 @@
+2012-02-10  Pavel Feldman  <pfeldman@google.com>
+
+        Web Inspector: implement undo for setOuterHTML via undo-ing nested primitive commands.
+        https://bugs.webkit.org/show_bug.cgi?id=78346
+
+        Reviewed by Yury Semikhatsky.
+
+        * inspector/elements/set-outer-html-2-expected.txt:
+        * inspector/elements/set-outer-html-test.js:
+        (initialize_SetOuterHTMLTest.InspectorTest.patchOuterHTML):
+        (initialize_SetOuterHTMLTest.InspectorTest.patchOuterHTMLUseUndo):
+        (initialize_SetOuterHTMLTest.InspectorTest.setOuterHTMLUseUndo.bringBack):
+        (initialize_SetOuterHTMLTest.InspectorTest.setOuterHTMLUseUndo):
+        (initialize_SetOuterHTMLTest.InspectorTest.innerSetOuterHTML):
+        (initialize_SetOuterHTMLTest.InspectorTest._dumpOuterHTML.dumpIdentity):
+        (initialize_SetOuterHTMLTest.InspectorTest._dumpOuterHTML.callback):
+        (initialize_SetOuterHTMLTest.InspectorTest._dumpOuterHTML):
+        (initialize_SetOuterHTMLTest):
+        * inspector/elements/undo-dom-edits-expected.txt:
+        * inspector/elements/undo-set-outer-html-2-expected.txt: Copied from LayoutTests/inspector/elements/set-outer-html-2-expected.txt.
+        * inspector/elements/undo-set-outer-html-2.html: Added.
+        * inspector/elements/undo-set-outer-html-expected.txt: Copied from LayoutTests/inspector/elements/set-outer-html-2-expected.txt.
+        * inspector/elements/undo-set-outer-html.html: Added.
+
 2012-02-10  Csaba Osztrogonác  <ossy@webkit.org>
 
         [Qt][WK2] Refactor on Qt5 Layout tests' structure
index 08ae985..2ad6ce3 100644 (file)
@@ -112,8 +112,12 @@ Bringing things back
 Wrapper identity: identity
 Event NodeInserted: H2
 Event NodeInserted: P
+Event NodeInserted: UL
+Event NodeInserted: UL
 Event NodeRemoved: H2
 Event NodeRemoved: P
+Event NodeRemoved: UL
+Event NodeRemoved: UL
 ==========8<==========
 <div id="container" style="display:none">
 <p>WebKit is used by <a href="http://www.apple.com/safari/">Safari</a>, Dashboard, etc..</p>
@@ -175,6 +179,8 @@ Replacing '<h2>Getting involved</h2>' with '<h2>Getting involved</h2><h2>Getting
 
 Wrapper identity: identity
 Event NodeInserted: H2
+Event NodeInserted: H2
+Event NodeRemoved: H2
 ==========8<==========
 <div id="container" style="display:none">
 <p>WebKit is used by <a href="http://www.apple.com/safari/">Safari</a>, Dashboard, etc..</p>
index e1db1e3..22c375c 100644 (file)
@@ -44,8 +44,14 @@ InspectorTest.recordEvent = function(eventName, event)
 
 InspectorTest.patchOuterHTML = function(pattern, replacement, next)
 {
-   InspectorTest.addResult("Replacing '" + pattern + "' with '" + replacement + "'\n");
-   InspectorTest.setOuterHTML(InspectorTest.containerText.replace(pattern, replacement), next);
+    InspectorTest.addResult("Replacing '" + pattern + "' with '" + replacement + "'\n");
+    InspectorTest.setOuterHTML(InspectorTest.containerText.replace(pattern, replacement), next);
+}
+
+InspectorTest.patchOuterHTMLUseUndo = function(pattern, replacement, next)
+{
+    InspectorTest.addResult("Replacing '" + pattern + "' with '" + replacement + "'\n");
+    InspectorTest.setOuterHTMLUseUndo(InspectorTest.containerText.replace(pattern, replacement), next);
 }
 
 InspectorTest.setOuterHTML = function(newText, next)
@@ -59,33 +65,44 @@ InspectorTest.setOuterHTML = function(newText, next)
     }
 }
 
+InspectorTest.setOuterHTMLUseUndo = function(newText, next)
+{
+    InspectorTest.innerSetOuterHTML(newText, false, bringBack);
+
+    function bringBack()
+    {
+        InspectorTest.addResult("\nBringing things back\n");
+        DOMAgent.undo(InspectorTest._dumpOuterHTML.bind(InspectorTest, true, next));
+    }
+}
+
 InspectorTest.innerSetOuterHTML = function(newText, last, next)
 {
-    DOMAgent.setOuterHTML(InspectorTest.containerId, newText, dumpOuterHTML);
+    DOMAgent.setOuterHTML(InspectorTest.containerId, newText, InspectorTest._dumpOuterHTML.bind(InspectorTest, last, next));
+}
 
-    function dumpOuterHTML()
+InspectorTest._dumpOuterHTML = function(last, next)
+{
+    RuntimeAgent.evaluate("document.getElementById(\"identity\").wrapperIdentity", dumpIdentity);
+    function dumpIdentity(error, result)
     {
-        RuntimeAgent.evaluate("document.getElementById(\"identity\").wrapperIdentity", dumpIdentity);
-        function dumpIdentity(error, result)
-        {
-            InspectorTest.addResult("Wrapper identity: " + result.value);
-            InspectorTest.events.sort();
-            for (var i = 0; i < InspectorTest.events.length; ++i)
-                InspectorTest.addResult(InspectorTest.events[i]);
-            InspectorTest.events = [];
-        }
+        InspectorTest.addResult("Wrapper identity: " + result.value);
+        InspectorTest.events.sort();
+        for (var i = 0; i < InspectorTest.events.length; ++i)
+            InspectorTest.addResult(InspectorTest.events[i]);
+        InspectorTest.events = [];
+    }
 
-        DOMAgent.getOuterHTML(InspectorTest.containerId, callback);
+    DOMAgent.getOuterHTML(InspectorTest.containerId, callback);
 
-        function callback(error, text)
-        {
-            InspectorTest.addResult("==========8<==========");
-            InspectorTest.addResult(text);
-            InspectorTest.addResult("==========>8==========");
-            if (last)
-                InspectorTest.addResult("\n\n\n");
-            next();
-        }
+    function callback(error, text)
+    {
+        InspectorTest.addResult("==========8<==========");
+        InspectorTest.addResult(text);
+        InspectorTest.addResult("==========>8==========");
+        if (last)
+            InspectorTest.addResult("\n\n\n");
+        next();
     }
 }
 
index f67fb3c..fa8337f 100644 (file)
@@ -58,6 +58,6 @@ Post-action:
   </div>
 Post-undo (initial):
 - <div id="testEditAsHTML">
-    + <div id="node-to-edit-as-html"></div>
+    + <div id="node-to-edit-as-html"></div>
   </div>
 
diff --git a/LayoutTests/inspector/elements/undo-set-outer-html-2-expected.txt b/LayoutTests/inspector/elements/undo-set-outer-html-2-expected.txt
new file mode 100644 (file)
index 0000000..b646a80
--- /dev/null
@@ -0,0 +1,214 @@
+Tests undo for the DOMAgent.setOuterHTML protocol method (part 2).
+
+
+Running: testSetUp
+
+Running: testChangeMultipleThings
+Wrapper identity: identity
+Event AttrModified: H2
+Event AttrModified: H2
+Event NodeInserted: UL
+Event NodeRemoved: UL
+==========8<==========
+<div id="container" style="display:none">
+<p>WebKit is used by <a href="http://www.apple.com/safari/">Safari</a>, Dashboard, etc..</p>
+<h2 foo="bar" bar="baz">Getting involved</h2>
+<p id="identity">There are many ways to get involved. You can:</p>
+<ul>
+   
+</ul>
+<ul>
+   <li></li>
+</ul>
+</div>
+==========>8==========
+
+Bringing things back
+
+Wrapper identity: identity
+Event AttrRemoved: H2
+Event AttrRemoved: H2
+Event NodeInserted: UL
+Event NodeRemoved: UL
+==========8<==========
+<div id="container" style="display:none">
+<p>WebKit is used by <a href="http://www.apple.com/safari/">Safari</a>, Dashboard, etc..</p>
+<h2>Getting involved</h2>
+<p id="identity">There are many ways to get involved. You can:</p>
+<ul>
+   <li></li>
+</ul>
+<ul>
+   <li></li>
+</ul>
+</div>
+==========>8==========
+
+
+
+
+
+Running: testChangeNestingLevel
+Wrapper identity: identity
+Event NodeInserted: DIV
+Event NodeRemoved: UL
+==========8<==========
+<div id="container" style="display:none">
+<p>WebKit is used by <a href="http://www.apple.com/safari/">Safari</a>, Dashboard, etc..</p>
+<h2>Getting involved</h2>
+<p id="identity">There are many ways to get involved. You can:</p>
+<div><ul>
+   <li></li>
+</ul></div>
+<ul>
+   <li></li>
+</ul>
+</div>
+==========>8==========
+
+Bringing things back
+
+Wrapper identity: identity
+Event NodeInserted: UL
+Event NodeRemoved: DIV
+==========8<==========
+<div id="container" style="display:none">
+<p>WebKit is used by <a href="http://www.apple.com/safari/">Safari</a>, Dashboard, etc..</p>
+<h2>Getting involved</h2>
+<p id="identity">There are many ways to get involved. You can:</p>
+<ul>
+   <li></li>
+</ul>
+<ul>
+   <li></li>
+</ul>
+</div>
+==========>8==========
+
+
+
+
+
+Running: testSwapNodes
+Wrapper identity: identity
+Event NodeInserted: H2
+Event NodeRemoved: H2
+==========8<==========
+<div id="container" style="display:none">
+<p>WebKit is used by <a href="http://www.apple.com/safari/">Safari</a>, Dashboard, etc..</p>
+
+<p id="identity">There are many ways to get involved. You can:</p>
+<ul>
+   <li></li>
+</ul>
+<ul>
+   <li></li>
+</ul>
+<h2>Getting involved</h2></div>
+==========>8==========
+
+Bringing things back
+
+Wrapper identity: identity
+Event NodeInserted: H2
+Event NodeRemoved: H2
+==========8<==========
+<div id="container" style="display:none">
+<p>WebKit is used by <a href="http://www.apple.com/safari/">Safari</a>, Dashboard, etc..</p>
+<h2>Getting involved</h2>
+<p id="identity">There are many ways to get involved. You can:</p>
+<ul>
+   <li></li>
+</ul>
+<ul>
+   <li></li>
+</ul>
+</div>
+==========>8==========
+
+
+
+
+
+Running: testEditTwoRoots
+Wrapper identity: identity
+Event NodeInserted: DIV
+==========8<==========
+<div id="container" style="display:none">
+<p>WebKit is used by <a href="http://www.apple.com/safari/">Safari</a>, Dashboard, etc..</p>
+<h2>Getting involved</h2>
+<p id="identity">There are many ways to get involved. You can:</p>
+<ul>
+   <li></li>
+</ul>
+<ul>
+   <li></li>
+</ul>
+</div>
+==========>8==========
+
+Bringing things back
+
+Wrapper identity: identity
+Event NodeRemoved: DIV
+==========8<==========
+<div id="container" style="display:none">
+<p>WebKit is used by <a href="http://www.apple.com/safari/">Safari</a>, Dashboard, etc..</p>
+<h2>Getting involved</h2>
+<p id="identity">There are many ways to get involved. You can:</p>
+<ul>
+   <li></li>
+</ul>
+<ul>
+   <li></li>
+</ul>
+</div>
+==========>8==========
+
+
+
+
+
+Running: testDupeNode
+Replacing '<h2>Getting involved</h2>' with '<h2>Getting involved</h2><h2>Getting involved</h2>'
+
+Wrapper identity: identity
+Event NodeInserted: H2
+Event NodeInserted: H2
+Event NodeRemoved: H2
+==========8<==========
+<div id="container" style="display:none">
+<p>WebKit is used by <a href="http://www.apple.com/safari/">Safari</a>, Dashboard, etc..</p>
+<h2>Getting involved</h2><h2>Getting involved</h2>
+<p id="identity">There are many ways to get involved. You can:</p>
+<ul>
+   <li></li>
+</ul>
+<ul>
+   <li></li>
+</ul>
+</div>
+==========>8==========
+
+Bringing things back
+
+Wrapper identity: identity
+Event NodeRemoved: H2
+==========8<==========
+<div id="container" style="display:none">
+<p>WebKit is used by <a href="http://www.apple.com/safari/">Safari</a>, Dashboard, etc..</p>
+<h2>Getting involved</h2>
+<p id="identity">There are many ways to get involved. You can:</p>
+<ul>
+   <li></li>
+</ul>
+<ul>
+   <li></li>
+</ul>
+</div>
+==========>8==========
+
+
+
+
+
diff --git a/LayoutTests/inspector/elements/undo-set-outer-html-2.html b/LayoutTests/inspector/elements/undo-set-outer-html-2.html
new file mode 100644 (file)
index 0000000..a17ba99
--- /dev/null
@@ -0,0 +1,77 @@
+<html>
+<head>
+
+<script src="../../http/tests/inspector/inspector-test.js"></script>
+<script src="../../http/tests/inspector/elements-test.js"></script>
+<script src="set-outer-html-test.js"></script>
+<script>
+
+function onload()
+{
+    document.getElementById("identity").wrapperIdentity = "identity";
+    runTest();
+}
+
+function test()
+{
+    InspectorTest.runTestSuite([
+        function testSetUp(next)
+        {
+            InspectorTest.setUpTestSuite(next);
+        },
+
+        function testChangeMultipleThings(next)
+        {
+            var text = InspectorTest.containerText.replace(/<li>.*<\/li>/, "");
+            text = text.replace("<h2>", "<h2 foo=\"bar\" bar=\"baz\">");
+            InspectorTest.setOuterHTMLUseUndo(text, next);
+        },
+
+        function testChangeNestingLevel(next)
+        {
+            var text = InspectorTest.containerText.replace("<ul>", "<div><ul>");
+            var text = text.replace("</ul>", "</ul></div>");
+            InspectorTest.setOuterHTMLUseUndo(text, next);
+        },
+
+        function testSwapNodes(next)
+        {
+            var text = InspectorTest.containerText.replace("<h2>Getting involved</h2>", "");
+            var text = text.replace("</div>", "<h2>Getting involved</h2></div>");
+            InspectorTest.setOuterHTMLUseUndo(text, next);
+        },
+
+        function testEditTwoRoots(next)
+        {
+            var text = InspectorTest.containerText + "<div>Additional node</div>";
+            InspectorTest.setOuterHTMLUseUndo(text, next);
+        },
+
+        function testDupeNode(next)
+        {
+            InspectorTest.patchOuterHTML("<h2>Getting involved</h2>", "<h2>Getting involved</h2><h2>Getting involved</h2>", next);
+        }
+    ]);
+}
+</script>
+</head>
+
+<body onload="onload()">
+<p>
+Tests undo for the DOMAgent.setOuterHTML protocol method (part 2).
+</p>
+
+<div id="container" style="display:none">
+<p>WebKit is used by <a href="http://www.apple.com/safari/">Safari</a>, Dashboard, etc..</p>
+<h2>Getting involved</h2>
+<p id="identity">There are many ways to get involved. You can:</p>
+<ul>
+   <li></li>
+</ul>
+<ul>
+   <li></li>
+</ul>
+</div>
+
+</body>
+</html>
diff --git a/LayoutTests/inspector/elements/undo-set-outer-html-expected.txt b/LayoutTests/inspector/elements/undo-set-outer-html-expected.txt
new file mode 100644 (file)
index 0000000..c9f60f9
--- /dev/null
@@ -0,0 +1,160 @@
+Tests undo for the DOMAgent.setOuterHTML protocol method.
+
+
+Running: testSetUp
+
+Running: testChangeCharacterData
+Replacing 'Getting involved' with 'Getting not involved'
+
+Wrapper identity: identity
+Event CharacterDataModified: 
+==========8<==========
+<div id="container" style="display:none">
+<p>WebKit is used by <a href="http://www.apple.com/safari/">Safari</a>, Dashboard, etc..</p>
+<h2>Getting not involved</h2>
+<p id="identity">There are many ways to get involved. You can:</p>
+</div>
+==========>8==========
+
+Bringing things back
+
+Wrapper identity: identity
+Event CharacterDataModified: 
+==========8<==========
+<div id="container" style="display:none">
+<p>WebKit is used by <a href="http://www.apple.com/safari/">Safari</a>, Dashboard, etc..</p>
+<h2>Getting involved</h2>
+<p id="identity">There are many ways to get involved. You can:</p>
+</div>
+==========>8==========
+
+
+
+
+
+Running: testChangeAttributes
+Replacing '<a href' with '<a foo="bar" href'
+
+Wrapper identity: identity
+Event AttrModified: A
+Event AttrModified: A
+Event AttrRemoved: A
+==========8<==========
+<div id="container" style="display:none">
+<p>WebKit is used by <a foo="bar" href="http://www.apple.com/safari/">Safari</a>, Dashboard, etc..</p>
+<h2>Getting involved</h2>
+<p id="identity">There are many ways to get involved. You can:</p>
+</div>
+==========>8==========
+
+Bringing things back
+
+Wrapper identity: identity
+Event AttrModified: A
+Event AttrRemoved: A
+Event AttrRemoved: A
+==========8<==========
+<div id="container" style="display:none">
+<p>WebKit is used by <a href="http://www.apple.com/safari/">Safari</a>, Dashboard, etc..</p>
+<h2>Getting involved</h2>
+<p id="identity">There are many ways to get involved. You can:</p>
+</div>
+==========>8==========
+
+
+
+
+
+Running: testRemoveLastChild
+Replacing 'Getting involved' with ''
+
+Wrapper identity: identity
+Event NodeRemoved: 
+==========8<==========
+<div id="container" style="display:none">
+<p>WebKit is used by <a href="http://www.apple.com/safari/">Safari</a>, Dashboard, etc..</p>
+<h2></h2>
+<p id="identity">There are many ways to get involved. You can:</p>
+</div>
+==========>8==========
+
+Bringing things back
+
+Wrapper identity: identity
+Event NodeInserted: 
+==========8<==========
+<div id="container" style="display:none">
+<p>WebKit is used by <a href="http://www.apple.com/safari/">Safari</a>, Dashboard, etc..</p>
+<h2>Getting involved</h2>
+<p id="identity">There are many ways to get involved. You can:</p>
+</div>
+==========>8==========
+
+
+
+
+
+Running: testSplitNode
+Replacing 'Getting involved' with 'Getting</h2><h2>involved'
+
+Wrapper identity: identity
+Event NodeInserted: H2
+Event NodeInserted: H2
+Event NodeRemoved: H2
+==========8<==========
+<div id="container" style="display:none">
+<p>WebKit is used by <a href="http://www.apple.com/safari/">Safari</a>, Dashboard, etc..</p>
+<h2>Getting</h2><h2>involved</h2>
+<p id="identity">There are many ways to get involved. You can:</p>
+</div>
+==========>8==========
+
+Bringing things back
+
+Wrapper identity: identity
+Event NodeInserted: H2
+Event NodeRemoved: H2
+Event NodeRemoved: H2
+==========8<==========
+<div id="container" style="display:none">
+<p>WebKit is used by <a href="http://www.apple.com/safari/">Safari</a>, Dashboard, etc..</p>
+<h2>Getting involved</h2>
+<p id="identity">There are many ways to get involved. You can:</p>
+</div>
+==========>8==========
+
+
+
+
+
+Running: testChangeNodeName
+Replacing '<h2>Getting involved</h2>' with '<h3>Getting involved</h3>'
+
+Wrapper identity: identity
+Event NodeInserted: H3
+Event NodeRemoved: H2
+==========8<==========
+<div id="container" style="display:none">
+<p>WebKit is used by <a href="http://www.apple.com/safari/">Safari</a>, Dashboard, etc..</p>
+<h3>Getting involved</h3>
+<p id="identity">There are many ways to get involved. You can:</p>
+</div>
+==========>8==========
+
+Bringing things back
+
+Wrapper identity: identity
+Event NodeInserted: H2
+Event NodeRemoved: H3
+==========8<==========
+<div id="container" style="display:none">
+<p>WebKit is used by <a href="http://www.apple.com/safari/">Safari</a>, Dashboard, etc..</p>
+<h2>Getting involved</h2>
+<p id="identity">There are many ways to get involved. You can:</p>
+</div>
+==========>8==========
+
+
+
+
+
diff --git a/LayoutTests/inspector/elements/undo-set-outer-html.html b/LayoutTests/inspector/elements/undo-set-outer-html.html
new file mode 100644 (file)
index 0000000..30a52e4
--- /dev/null
@@ -0,0 +1,64 @@
+<html>
+<head>
+
+<script src="../../http/tests/inspector/inspector-test.js"></script>
+<script src="../../http/tests/inspector/elements-test.js"></script>
+<script src="set-outer-html-test.js"></script>
+<script>
+
+function onload()
+{
+    document.getElementById("identity").wrapperIdentity = "identity";
+    runTest();
+}
+
+function test()
+{
+    InspectorTest.runTestSuite([
+        function testSetUp(next)
+        {
+            InspectorTest.setUpTestSuite(next);
+        },
+
+        function testChangeCharacterData(next)
+        {
+            InspectorTest.patchOuterHTMLUseUndo("Getting involved", "Getting not involved", next);
+        },
+
+        function testChangeAttributes(next)
+        {
+            InspectorTest.patchOuterHTMLUseUndo("<a href", "<a foo=\"bar\" href", next);
+        },
+
+        function testRemoveLastChild(next)
+        {
+            InspectorTest.patchOuterHTMLUseUndo("Getting involved", "", next);
+        },
+
+        function testSplitNode(next)
+        {
+            InspectorTest.patchOuterHTMLUseUndo("Getting involved", "Getting</h2><h2>involved", next);
+        },
+
+        function testChangeNodeName(next)
+        {
+            InspectorTest.patchOuterHTMLUseUndo("<h2>Getting involved</h2>", "<h3>Getting involved</h3>", next);
+        }
+    ]);
+}
+</script>
+</head>
+
+<body onload="onload()">
+<p>
+Tests undo for the DOMAgent.setOuterHTML protocol method.
+</p>
+
+<div id="container" style="display:none">
+<p>WebKit is used by <a href="http://www.apple.com/safari/">Safari</a>, Dashboard, etc.</a>.</p>
+<h2>Getting involved</h2>
+<p id="identity">There are many ways to get involved. You can:</p>
+</div>
+
+</body>
+</html>
index ef11638..f864153 100644 (file)
@@ -1,3 +1,96 @@
+2012-02-10  Pavel Feldman  <pfeldman@google.com>
+
+        Web Inspector: implement undo for setOuterHTML via undo-ing nested primitive commands.
+        https://bugs.webkit.org/show_bug.cgi?id=78346
+
+        Reviewed by Yury Semikhatsky.
+
+        Tests: inspector/elements/undo-set-outer-html-2.html
+               inspector/elements/undo-set-outer-html.html
+
+        * inspector/DOMEditor.cpp:
+        (WebCore::DOMEditor::RemoveChildAction::RemoveChildAction):
+        (WebCore::DOMEditor::InsertBeforeAction::InsertBeforeAction):
+        (WebCore::DOMEditor::InsertBeforeAction::undo):
+        (WebCore::DOMEditor::RemoveAttributeAction::RemoveAttributeAction):
+        (WebCore::DOMEditor::SetAttributeAction::SetAttributeAction):
+        (WebCore::DOMEditor::SetOuterHTMLAction::SetOuterHTMLAction):
+        (WebCore::DOMEditor::SetOuterHTMLAction::perform):
+        (WebCore::DOMEditor::SetOuterHTMLAction::undo):
+        (DOMEditor::SetOuterHTMLAction):
+        (WebCore::DOMEditor::ReplaceWholeTextAction::ReplaceWholeTextAction):
+        (DOMEditor::ReplaceChildNodeAction):
+        (WebCore::DOMEditor::ReplaceChildNodeAction::ReplaceChildNodeAction):
+        (WebCore::DOMEditor::ReplaceChildNodeAction::perform):
+        (WebCore::DOMEditor::ReplaceChildNodeAction::undo):
+        (WebCore):
+        (DOMEditor::SetNodeValueAction):
+        (WebCore::DOMEditor::SetNodeValueAction::SetNodeValueAction):
+        (WebCore::DOMEditor::SetNodeValueAction::perform):
+        (WebCore::DOMEditor::SetNodeValueAction::undo):
+        (WebCore::DOMEditor::insertBefore):
+        (WebCore::DOMEditor::removeChild):
+        (WebCore::DOMEditor::setAttribute):
+        (WebCore::DOMEditor::removeAttribute):
+        (WebCore::DOMEditor::setOuterHTML):
+        (WebCore::DOMEditor::replaceWholeText):
+        (WebCore::DOMEditor::replaceChild):
+        (WebCore::DOMEditor::setNodeValue):
+        (WebCore::populateErrorString):
+        * inspector/DOMEditor.h:
+        (DOMEditor):
+        * inspector/DOMPatchSupport.cpp:
+        (WebCore::DOMPatchSupport::patchDocument):
+        (WebCore):
+        (WebCore::DOMPatchSupport::DOMPatchSupport):
+        (WebCore::DOMPatchSupport::patchNode):
+        (WebCore::DOMPatchSupport::innerPatchNode):
+        (WebCore::DOMPatchSupport::innerPatchChildren):
+        (WebCore::DOMPatchSupport::insertBeforeAndMarkAsUsed):
+        (WebCore::DOMPatchSupport::removeChildAndMoveToNew):
+        * inspector/DOMPatchSupport.h:
+        (WebCore):
+        (DOMPatchSupport):
+        * inspector/InspectorCSSAgent.cpp:
+        (WebCore::InspectorCSSAgent::StyleSheetAction::perform):
+        (WebCore::InspectorCSSAgent::StyleSheetAction::undo):
+        (InspectorCSSAgent::StyleSheetAction):
+        (WebCore::InspectorCSSAgent::SetStyleSheetTextAction::perform):
+        (WebCore::InspectorCSSAgent::SetStyleSheetTextAction::undo):
+        (WebCore::InspectorCSSAgent::SetPropertyTextAction::perform):
+        (WebCore::InspectorCSSAgent::SetPropertyTextAction::undo):
+        (WebCore::InspectorCSSAgent::TogglePropertyAction::perform):
+        (WebCore::InspectorCSSAgent::TogglePropertyAction::undo):
+        (WebCore::InspectorCSSAgent::setStyleSheetText):
+        (WebCore::InspectorCSSAgent::setPropertyText):
+        (WebCore::InspectorCSSAgent::toggleProperty):
+        (WebCore::InspectorCSSAgent::assertStyleSheetForId):
+        * inspector/InspectorDOMAgent.cpp:
+        (WebCore::InspectorDOMAgent::toErrorString):
+        (WebCore):
+        (WebCore::InspectorDOMAgent::setAttributesAsText):
+        (WebCore::InspectorDOMAgent::setOuterHTML):
+        (WebCore::InspectorDOMAgent::undo):
+        * inspector/InspectorDOMAgent.h:
+        (InspectorDOMAgent):
+        * inspector/InspectorHistory.cpp:
+        (WebCore::InspectorHistory::perform):
+        (WebCore::InspectorHistory::undo):
+        * inspector/InspectorHistory.h:
+        (WebCore):
+        (Action):
+        (InspectorHistory):
+        * inspector/InspectorPageAgent.cpp:
+        (WebCore::InspectorPageAgent::setDocumentContent):
+        * inspector/InspectorStyleSheet.cpp:
+        (WebCore::InspectorStyle::setPropertyText):
+        (WebCore::InspectorStyle::toggleProperty):
+        (WebCore::InspectorStyleSheet::setPropertyText):
+        (WebCore::InspectorStyleSheet::toggleProperty):
+        * inspector/InspectorStyleSheet.h:
+        (InspectorStyle):
+        (InspectorStyleSheet):
+
 2012-02-10  Kentaro Hara  <haraken@chromium.org>
 
         Replace [CustomArgumentHandling] with [CallWith=ScriptArguments|CallStack]
index f153c90..f0a3140 100644 (file)
@@ -49,47 +49,11 @@ using namespace std;
 
 namespace WebCore {
 
-class DOMEditor::DOMAction : public InspectorHistory::Action {
-public:
-    DOMAction(const String& name) : InspectorHistory::Action(name) { }
-
-    virtual bool perform(ErrorString* errorString)
-    {
-        ExceptionCode ec = 0;
-        bool result = perform(ec);
-        if (ec) {
-            ExceptionCodeDescription description(ec);
-            *errorString = description.name;
-        }
-        return result && !ec;
-    }
-
-    virtual bool undo(ErrorString* errorString)
-    {
-        ExceptionCode ec = 0;
-        bool result = undo(ec);
-        if (ec) {
-            ExceptionCodeDescription description(ec);
-            *errorString = description.name;
-        }
-        return result && !ec;
-    }
-
-    virtual bool perform(ExceptionCode&) = 0;
-
-    virtual bool undo(ExceptionCode&) = 0;
-
-private:
-    RefPtr<Node> m_parentNode;
-    RefPtr<Node> m_node;
-    RefPtr<Node> m_anchorNode;
-};
-
-class DOMEditor::RemoveChildAction : public DOMEditor::DOMAction {
+class DOMEditor::RemoveChildAction : public InspectorHistory::Action {
     WTF_MAKE_NONCOPYABLE(RemoveChildAction);
 public:
     RemoveChildAction(Node* parentNode, Node* node)
-        : DOMEditor::DOMAction("RemoveChild")
+        : InspectorHistory::Action("RemoveChild")
         , m_parentNode(parentNode)
         , m_node(node)
     {
@@ -112,11 +76,11 @@ private:
     RefPtr<Node> m_anchorNode;
 };
 
-class DOMEditor::InsertBeforeAction : public DOMEditor::DOMAction {
+class DOMEditor::InsertBeforeAction : public InspectorHistory::Action {
     WTF_MAKE_NONCOPYABLE(InsertBeforeAction);
 public:
-    InsertBeforeAction(Node* parentNode, Node* node, Node* anchorNode)
-        : DOMEditor::DOMAction("InsertBefore")
+    InsertBeforeAction(Node* parentNode, PassRefPtr<Node> node, Node* anchorNode)
+        : InspectorHistory::Action("InsertBefore")
         , m_parentNode(parentNode)
         , m_node(node)
         , m_anchorNode(anchorNode)
@@ -135,10 +99,11 @@ public:
 
     virtual bool undo(ExceptionCode& ec)
     {
+        if (!m_parentNode->removeChild(m_node.get(), ec))
+            return false;
         if (m_removeChildAction)
             return m_removeChildAction->undo(ec);
-
-        return m_parentNode->removeChild(m_node.get(), ec);
+        return true;
     }
 
 private:
@@ -148,11 +113,11 @@ private:
     OwnPtr<RemoveChildAction> m_removeChildAction;
 };
 
-class DOMEditor::RemoveAttributeAction : public DOMEditor::DOMAction {
+class DOMEditor::RemoveAttributeAction : public InspectorHistory::Action {
     WTF_MAKE_NONCOPYABLE(RemoveAttributeAction);
 public:
     RemoveAttributeAction(Element* element, const String& name)
-        : DOMEditor::DOMAction("RemoveAttribute")
+        : InspectorHistory::Action("RemoveAttribute")
         , m_element(element)
         , m_name(name)
     {
@@ -177,11 +142,11 @@ private:
     String m_value;
 };
 
-class DOMEditor::SetAttributeAction : public DOMEditor::DOMAction {
+class DOMEditor::SetAttributeAction : public InspectorHistory::Action {
     WTF_MAKE_NONCOPYABLE(SetAttributeAction);
 public:
     SetAttributeAction(Element* element, const String& name, const String& value)
-        : DOMEditor::DOMAction("SetAttribute")
+        : InspectorHistory::Action("SetAttribute")
         , m_element(element)
         , m_name(name)
         , m_value(value)
@@ -215,41 +180,31 @@ private:
     String m_oldValue;
 };
 
-class DOMEditor::SetOuterHTMLAction : public DOMEditor::DOMAction {
+class DOMEditor::SetOuterHTMLAction : public InspectorHistory::Action {
     WTF_MAKE_NONCOPYABLE(SetOuterHTMLAction);
 public:
     SetOuterHTMLAction(Node* node, const String& html)
-        : DOMEditor::DOMAction("SetOuterHTML")
+        : InspectorHistory::Action("SetOuterHTML")
         , m_node(node)
         , m_nextSibling(node->nextSibling())
         , m_html(html)
         , m_newNode(0)
+        , m_history(adoptPtr(new InspectorHistory()))
+        , m_domEditor(adoptPtr(new DOMEditor(m_history.get())))
     {
     }
 
     virtual bool perform(ExceptionCode& ec)
     {
         m_oldHTML = createMarkup(m_node.get());
-        DOMPatchSupport domPatchSupport(m_node->ownerDocument());
+        DOMPatchSupport domPatchSupport(m_domEditor.get(), m_node->ownerDocument());
         m_newNode = domPatchSupport.patchNode(m_node.get(), m_html, ec);
         return !ec;
     }
 
     virtual bool undo(ExceptionCode& ec)
     {
-        DOMPatchSupport domPatchSupport(m_newNode->ownerDocument());
-        Node* node = domPatchSupport.patchNode(m_newNode, m_oldHTML, ec);
-        if (ec || !node)
-            return false;
-        // HTML editing could have produced extra nodes. Remove them if necessary.
-        node = node->nextSibling();
-
-        while (!ec && node && node != m_nextSibling.get()) {
-            Node* nodeToRemove = node;
-            node = node->nextSibling();
-            nodeToRemove->remove(ec);
-        }
-        return !ec;
+        return m_history->undo(ec);
     }
 
     Node* newNode()
@@ -263,13 +218,15 @@ private:
     String m_html;
     String m_oldHTML;
     Node* m_newNode;
+    OwnPtr<InspectorHistory> m_history;
+    OwnPtr<DOMEditor> m_domEditor;
 };
 
-class DOMEditor::ReplaceWholeTextAction : public DOMEditor::DOMAction {
+class DOMEditor::ReplaceWholeTextAction : public InspectorHistory::Action {
     WTF_MAKE_NONCOPYABLE(ReplaceWholeTextAction);
 public:
     ReplaceWholeTextAction(Text* textNode, const String& text)
-        : DOMAction("ReplaceWholeText")
+        : InspectorHistory::Action("ReplaceWholeText")
         , m_textNode(textNode)
         , m_text(text)
     {
@@ -294,43 +251,165 @@ private:
     String m_oldText;
 };
 
+class DOMEditor::ReplaceChildNodeAction : public InspectorHistory::Action {
+    WTF_MAKE_NONCOPYABLE(ReplaceChildNodeAction);
+public:
+    ReplaceChildNodeAction(Node* parentNode, PassRefPtr<Node> newNode, Node* oldNode)
+        : InspectorHistory::Action("ReplaceChildNode")
+        , m_parentNode(parentNode)
+        , m_newNode(newNode)
+        , m_oldNode(oldNode)
+    {
+    }
+
+    virtual bool perform(ExceptionCode& ec)
+    {
+        return m_parentNode->replaceChild(m_newNode, m_oldNode.get(), ec);
+    }
+
+    virtual bool undo(ExceptionCode& ec)
+    {
+        return m_parentNode->replaceChild(m_oldNode, m_newNode.get(), ec);
+    }
+
+private:
+    RefPtr<Node> m_parentNode;
+    RefPtr<Node> m_newNode;
+    RefPtr<Node> m_oldNode;
+};
+
+class DOMEditor::SetNodeValueAction : public InspectorHistory::Action {
+    WTF_MAKE_NONCOPYABLE(SetNodeValueAction);
+public:
+    SetNodeValueAction(Node* node, const String& value)
+        : InspectorHistory::Action("SetNodeValue")
+        , m_node(node)
+        , m_value(value)
+    {
+    }
+
+    virtual bool perform(ExceptionCode& ec)
+    {
+        m_oldValue = m_node->nodeValue();
+        m_node->setNodeValue(m_value, ec);
+        return !ec;
+    }
+
+    virtual bool undo(ExceptionCode& ec)
+    {
+        m_node->setNodeValue(m_oldValue, ec);
+        return !ec;
+    }
+
+private:
+    RefPtr<Node> m_node;
+    String m_value;
+    String m_oldValue;
+};
+
 DOMEditor::DOMEditor(InspectorHistory* history) : m_history(history) { }
 
 DOMEditor::~DOMEditor() { }
 
-bool DOMEditor::insertBefore(Node* parentNode, Node* node, Node* anchorNode, ErrorString* errorString)
+bool DOMEditor::insertBefore(Node* parentNode, PassRefPtr<Node> node, Node* anchorNode, ExceptionCode& ec)
 {
-    return m_history->perform(adoptPtr(new InsertBeforeAction(parentNode, node, anchorNode)), errorString);
+    return m_history->perform(adoptPtr(new InsertBeforeAction(parentNode, node, anchorNode)), ec);
 }
 
-bool DOMEditor::removeChild(Node* parentNode, Node* node, ErrorString* errorString)
+bool DOMEditor::removeChild(Node* parentNode, Node* node, ExceptionCode& ec)
 {
-    return m_history->perform(adoptPtr(new RemoveChildAction(parentNode, node)), errorString);
+    return m_history->perform(adoptPtr(new RemoveChildAction(parentNode, node)), ec);
 }
 
-bool DOMEditor::setAttribute(Element* element, const String& name, const String& value, ErrorString* errorString)
+bool DOMEditor::setAttribute(Element* element, const String& name, const String& value, ExceptionCode& ec)
 {
-    return m_history->perform(adoptPtr(new SetAttributeAction(element, name, value)), errorString);
+    return m_history->perform(adoptPtr(new SetAttributeAction(element, name, value)), ec);
 }
 
-bool DOMEditor::removeAttribute(Element* element, const String& name, ErrorString* errorString)
+bool DOMEditor::removeAttribute(Element* element, const String& name, ExceptionCode& ec)
 {
-    return m_history->perform(adoptPtr(new RemoveAttributeAction(element, name)), errorString);
+    return m_history->perform(adoptPtr(new RemoveAttributeAction(element, name)), ec);
 }
 
-bool DOMEditor::setOuterHTML(Node* node, const String& html, Node** newNode, ErrorString* errorString)
+bool DOMEditor::setOuterHTML(Node* node, const String& html, Node** newNode, ExceptionCode& ec)
 {
     OwnPtr<SetOuterHTMLAction> action = adoptPtr(new SetOuterHTMLAction(node, html));
     SetOuterHTMLAction* rawAction = action.get();
-    bool result = m_history->perform(action.release(), errorString);
+    bool result = m_history->perform(action.release(), ec);
     if (result)
         *newNode = rawAction->newNode();
     return result;
 }
 
+bool DOMEditor::replaceWholeText(Text* textNode, const String& text, ExceptionCode& ec)
+{
+    return m_history->perform(adoptPtr(new ReplaceWholeTextAction(textNode, text)), ec);
+}
+
+bool DOMEditor::replaceChild(Node* parentNode, PassRefPtr<Node> newNode, Node* oldNode, ExceptionCode& ec)
+{
+    return m_history->perform(adoptPtr(new ReplaceChildNodeAction(parentNode, newNode, oldNode)), ec);
+}
+
+bool DOMEditor::setNodeValue(Node* node, const String& value, ExceptionCode& ec)
+{
+    return m_history->perform(adoptPtr(new SetNodeValueAction(node, value)), ec);
+}
+
+static void populateErrorString(const ExceptionCode& ec, ErrorString* errorString)
+{
+    if (ec) {
+        ExceptionCodeDescription description(ec);
+        *errorString = description.name;
+    }
+}
+
+bool DOMEditor::insertBefore(Node* parentNode, PassRefPtr<Node> node, Node* anchorNode, ErrorString* errorString)
+{
+    ExceptionCode ec = 0;
+    bool result = insertBefore(parentNode, node, anchorNode, ec);
+    populateErrorString(ec, errorString);
+    return result;
+}
+
+bool DOMEditor::removeChild(Node* parentNode, Node* node, ErrorString* errorString)
+{
+    ExceptionCode ec = 0;
+    bool result = removeChild(parentNode, node, ec);
+    populateErrorString(ec, errorString);
+    return result;
+}
+
+bool DOMEditor::setAttribute(Element* element, const String& name, const String& value, ErrorString* errorString)
+{
+    ExceptionCode ec = 0;
+    bool result = setAttribute(element, name, value, ec);
+    populateErrorString(ec, errorString);
+    return result;
+}
+
+bool DOMEditor::removeAttribute(Element* element, const String& name, ErrorString* errorString)
+{
+    ExceptionCode ec = 0;
+    bool result = removeAttribute(element, name, ec);
+    populateErrorString(ec, errorString);
+    return result;
+}
+
+bool DOMEditor::setOuterHTML(Node* node, const String& html, Node** newNode, ErrorString* errorString)
+{
+    ExceptionCode ec = 0;
+    bool result = setOuterHTML(node, html, newNode, ec);
+    populateErrorString(ec, errorString);
+    return result;
+}
+
 bool DOMEditor::replaceWholeText(Text* textNode, const String& text, ErrorString* errorString)
 {
-    return m_history->perform(adoptPtr(new ReplaceWholeTextAction(textNode, text)), errorString);
+    ExceptionCode ec = 0;
+    bool result = replaceWholeText(textNode, text, ec);
+    populateErrorString(ec, errorString);
+    return result;
 }
 
 } // namespace WebCore
index bd10b2a..2649132 100644 (file)
@@ -31,6 +31,8 @@
 #ifndef DOMEditor_h
 #define DOMEditor_h
 
+#include "ExceptionCode.h"
+
 #include <wtf/text/WTFString.h>
 
 namespace WebCore {
@@ -50,7 +52,16 @@ public:
     explicit DOMEditor(InspectorHistory*);
     ~DOMEditor();
 
-    bool insertBefore(Node* parentNode, Node*, Node* anchorNode, ErrorString*);
+    bool insertBefore(Node* parentNode, PassRefPtr<Node>, Node* anchorNode, ExceptionCode&);
+    bool removeChild(Node* parentNode, Node*, ExceptionCode&);
+    bool setAttribute(Element*, const String& name, const String& value, ExceptionCode&);
+    bool removeAttribute(Element*, const String& name, ExceptionCode&);
+    bool setOuterHTML(Node*, const String& html, Node** newNode, ExceptionCode&);
+    bool replaceWholeText(Text*, const String& text, ExceptionCode&);
+    bool replaceChild(Node* parentNode, PassRefPtr<Node> newNode, Node* oldNode, ExceptionCode&);
+    bool setNodeValue(Node* parentNode, const String& value, ExceptionCode&);
+
+    bool insertBefore(Node* parentNode, PassRefPtr<Node>, Node* anchorNode, ErrorString*);
     bool removeChild(Node* parentNode, Node*, ErrorString*);
     bool setAttribute(Element*, const String& name, const String& value, ErrorString*);
     bool removeAttribute(Element*, const String& name, ErrorString*);
@@ -65,6 +76,8 @@ private:
     class SetAttributeAction;
     class SetOuterHTMLAction;
     class ReplaceWholeTextAction;
+    class ReplaceChildNodeAction;
+    class SetNodeValueAction;
 
     InspectorHistory* m_history;
 };
index 4113b3d..9ed89a3 100644 (file)
@@ -35,6 +35,7 @@
 
 #include "Attribute.h"
 #include "Base64.h"
+#include "DOMEditor.h"
 #include "Document.h"
 #include "DocumentFragment.h"
 #include "HTMLDocument.h"
@@ -42,6 +43,7 @@
 #include "HTMLElement.h"
 #include "HTMLHeadElement.h"
 #include "HTMLNames.h"
+#include "InspectorHistory.h"
 #include "Node.h"
 
 #include <wtf/Deque.h>
@@ -67,7 +69,19 @@ struct DOMPatchSupport::Digest {
     Vector<OwnPtr<Digest> > m_children;
 };
 
-DOMPatchSupport::DOMPatchSupport(Document* document) : m_document(document) { }
+void DOMPatchSupport::patchDocument(Document* document, const String& markup)
+{
+    InspectorHistory history;
+    DOMEditor domEditor(&history);
+    DOMPatchSupport patchSupport(&domEditor, document);
+    patchSupport.patchDocument(markup);
+}
+
+DOMPatchSupport::DOMPatchSupport(DOMEditor* domEditor, Document* document)
+    : m_domEditor(domEditor)
+    , m_document(document)
+{
+}
 
 DOMPatchSupport::~DOMPatchSupport() { }
 
@@ -79,12 +93,11 @@ void DOMPatchSupport::patchDocument(const String& markup)
     parser->finish();
     parser->detach();
 
-    ExceptionCode ec = 0;
     OwnPtr<Digest> oldInfo = createDigest(m_document->documentElement(), 0);
     OwnPtr<Digest> newInfo = createDigest(newDocument->documentElement(), &m_unusedNodesMap);
-    innerPatchNode(oldInfo.get(), newInfo.get(), ec);
 
-    if (ec) {
+    ExceptionCode ec = 0;
+    if (!innerPatchNode(oldInfo.get(), newInfo.get(), ec)) {
         // Fall back to rewrite.
         m_document->write(markup);
         m_document->close();
@@ -125,37 +138,33 @@ Node* DOMPatchSupport::patchNode(Node* node, const String& markup, ExceptionCode
     for (Node* child = node->nextSibling(); child; child = child->nextSibling())
         newList.append(createDigest(child, 0));
 
-    innerPatchChildren(parentNode, oldList, newList, ec);
-    if (ec) {
+    if (!innerPatchChildren(parentNode, oldList, newList, ec)) {
         // Fall back to total replace.
         ec = 0;
-        parentNode->replaceChild(fragment.release(), node, ec);
-        if (ec)
+        if (!m_domEditor->replaceChild(parentNode, fragment.release(), node, ec))
             return 0;
     }
     return previousSibling ? previousSibling->nextSibling() : parentNode->firstChild();
 }
 
-void DOMPatchSupport::innerPatchNode(Digest* oldDigest, Digest* newDigest, ExceptionCode& ec)
+bool DOMPatchSupport::innerPatchNode(Digest* oldDigest, Digest* newDigest, ExceptionCode& ec)
 {
     if (oldDigest->m_sha1 == newDigest->m_sha1)
-        return;
+        return true;
 
     Node* oldNode = oldDigest->m_node;
     Node* newNode = newDigest->m_node;
 
-    if (newNode->nodeType() != oldNode->nodeType() || newNode->nodeName() != oldNode->nodeName()) {
-        oldNode->parentNode()->replaceChild(newNode, oldNode, ec);
-        return;
-    }
+    if (newNode->nodeType() != oldNode->nodeType() || newNode->nodeName() != oldNode->nodeName())
+        return m_domEditor->replaceChild(oldNode->parentNode(), newNode, oldNode, ec);
 
-    if (oldNode->nodeValue() != newNode->nodeValue())
-        oldNode->setNodeValue(newNode->nodeValue(), ec);
-    if (ec)
-        return;
+    if (oldNode->nodeValue() != newNode->nodeValue()) {
+        if (!m_domEditor->setNodeValue(oldNode, newNode->nodeValue(), ec))
+            return false;
+    }
 
     if (oldNode->nodeType() != Node::ELEMENT_NODE)
-        return;
+        return true;
 
     // Patch attributes
     Element* oldElement = static_cast<Element*>(oldNode);
@@ -163,8 +172,11 @@ void DOMPatchSupport::innerPatchNode(Digest* oldDigest, Digest* newDigest, Excep
     if (oldDigest->m_attrsSHA1 != newDigest->m_attrsSHA1) {
         // FIXME: Create a function in Element for removing all properties. Take in account whether did/willModifyAttribute are important.
         if (oldElement->hasAttributesWithoutUpdate()) {
-            while (oldElement->attributeCount())
-                oldElement->removeAttribute(0);
+            while (oldElement->attributeCount()) {
+                Attribute* attr = oldElement->attributeItem(0);
+                if (!m_domEditor->removeAttribute(oldElement, attr->localName(), ec))
+                    return false;
+            }
         }
 
         // FIXME: Create a function in Element for copying properties. setAttributesFromElement() is close but not enough for this case.
@@ -172,13 +184,15 @@ void DOMPatchSupport::innerPatchNode(Digest* oldDigest, Digest* newDigest, Excep
             size_t numAttrs = newElement->attributeCount();
             for (size_t i = 0; i < numAttrs; ++i) {
                 const Attribute* attribute = newElement->attributeItem(i);
-                oldElement->setAttribute(attribute->name(), attribute->value());
+                if (!m_domEditor->setAttribute(oldElement, attribute->name().localName(), attribute->value(), ec))
+                    return false;
             }
         }
     }
 
-    innerPatchChildren(oldElement, oldDigest->m_children, newDigest->m_children, ec);
+    bool result = innerPatchChildren(oldElement, oldDigest->m_children, newDigest->m_children, ec);
     m_unusedNodesMap.remove(newDigest->m_sha1);
+    return result;
 }
 
 pair<DOMPatchSupport::ResultMap, DOMPatchSupport::ResultMap>
@@ -269,7 +283,7 @@ DOMPatchSupport::diff(const Vector<OwnPtr<Digest> >& oldList, const Vector<OwnPt
     return make_pair(oldMap, newMap);
 }
 
-void DOMPatchSupport::innerPatchChildren(ContainerNode* parentNode, const Vector<OwnPtr<Digest> >& oldList, const Vector<OwnPtr<Digest> >& newList, ExceptionCode& ec)
+bool DOMPatchSupport::innerPatchChildren(ContainerNode* parentNode, const Vector<OwnPtr<Digest> >& oldList, const Vector<OwnPtr<Digest> >& newList, ExceptionCode& ec)
 {
     pair<ResultMap, ResultMap> resultMaps = diff(oldList, newList);
     ResultMap& oldMap = resultMaps.first;
@@ -309,14 +323,12 @@ void DOMPatchSupport::innerPatchChildren(ContainerNode* parentNode, const Vector
             if (anchorAfter - anchorCandidate == 1 && anchorCandidate < newList.size())
                 merges.set(newList[anchorCandidate].get(), oldList[i].get());
             else {
-                removeChild(oldList[i].get(), ec);
-                if (ec)
-                    return;
+                if (!removeChildAndMoveToNew(oldList[i].get(), ec))
+                    return false;
             }
         } else {
-            removeChild(oldList[i].get(), ec);
-            if (ec)
-                return;
+            if (!removeChildAndMoveToNew(oldList[i].get(), ec))
+                return false;
         }
     }
 
@@ -348,20 +360,16 @@ void DOMPatchSupport::innerPatchChildren(ContainerNode* parentNode, const Vector
 
     // 2. Patch nodes marked for merge.
     for (HashMap<Digest*, Digest*>::iterator it = merges.begin(); it != merges.end(); ++it) {
-        innerPatchNode(it->second, it->first, ec);
-        if (ec)
-            return;
+        if (!innerPatchNode(it->second, it->first, ec))
+            return false;
     }
 
     // 3. Insert missing nodes.
     for (size_t i = 0; i < newMap.size(); ++i) {
         if (newMap[i].first || merges.contains(newList[i].get()))
             continue;
-
-        ExceptionCode ec = 0;
-        insertBefore(parentNode, newList[i].get(), parentNode->childNode(i), ec);
-        if (ec)
-            return;
+        if (!insertBeforeAndMarkAsUsed(parentNode, newList[i].get(), parentNode->childNode(i), ec))
+            return false;
     }
 
     // 4. Then put all nodes that retained into their slots (sort by new index).
@@ -375,10 +383,10 @@ void DOMPatchSupport::innerPatchChildren(ContainerNode* parentNode, const Vector
         if (node->hasTagName(bodyTag) || node->hasTagName(headTag))
             continue; // Never move head or body, move the rest of the nodes around them.
 
-        parentNode->insertBefore(node, anchorNode, ec);
-        if (ec)
-            return;
+        if (!m_domEditor->insertBefore(parentNode, node.release(), anchorNode, ec))
+            return false;
     }
+    return true;
 }
 
 static void addStringToSHA1(SHA1& sha1, const String& string)
@@ -431,35 +439,40 @@ PassOwnPtr<DOMPatchSupport::Digest> DOMPatchSupport::createDigest(Node* node, Un
     return adoptPtr(digest);
 }
 
-void DOMPatchSupport::insertBefore(ContainerNode* parentNode, Digest* digest, Node* anchor, ExceptionCode& ec)
+bool DOMPatchSupport::insertBeforeAndMarkAsUsed(ContainerNode* parentNode, Digest* digest, Node* anchor, ExceptionCode& ec)
 {
-    parentNode->insertBefore(digest->m_node, anchor, ec);
+    bool result = m_domEditor->insertBefore(parentNode, digest->m_node, anchor, ec);
     markNodeAsUsed(digest);
+    return result;
 }
 
-void DOMPatchSupport::removeChild(Digest* oldDigest, ExceptionCode& ec)
+bool DOMPatchSupport::removeChildAndMoveToNew(Digest* oldDigest, ExceptionCode& ec)
 {
     RefPtr<Node> oldNode = oldDigest->m_node;
-    oldNode->parentNode()->removeChild(oldNode.get(), ec);
+    if (!m_domEditor->removeChild(oldNode->parentNode(), oldNode.get(), ec))
+        return false;
 
     // Diff works within levels. In order not to lose the node identity when user
     // prepends his HTML with "<div>" (i.e. all nodes are shifted to the next nested level),
     // prior to dropping the original node on the floor, check whether new DOM has a digest
     // with matching sha1. If it does, replace it with the original DOM chunk. Chances are
     // high that it will get merged back into the original DOM during the further patching.
-
     UnusedNodesMap::iterator it = m_unusedNodesMap.find(oldDigest->m_sha1);
     if (it != m_unusedNodesMap.end()) {
         Digest* newDigest = it->second;
         Node* newNode = newDigest->m_node;
-        newNode->parentNode()->replaceChild(oldNode, newNode, ec);
+        if (!m_domEditor->replaceChild(newNode->parentNode(), oldNode, newNode, ec))
+            return false;
         newDigest->m_node = oldNode.get();
         markNodeAsUsed(newDigest);
-        return;
+        return true;
     }
 
-    for (size_t i = 0; i < oldDigest->m_children.size(); ++i)
-        removeChild(oldDigest->m_children[i].get(), ec);
+    for (size_t i = 0; i < oldDigest->m_children.size(); ++i) {
+        if (!removeChildAndMoveToNew(oldDigest->m_children[i].get(), ec))
+            return false;
+    }
+    return true;
 }
 
 void DOMPatchSupport::markNodeAsUsed(Digest* digest)
index 4a07192..4d040f0 100644 (file)
@@ -42,6 +42,7 @@
 namespace WebCore {
 
 class ContainerNode;
+class DOMEditor;
 class Document;
 class NamedNodeMap;
 class Node;
@@ -51,7 +52,9 @@ class Node;
 class DOMPatchSupport {
     WTF_MAKE_NONCOPYABLE(DOMPatchSupport);
 public:
-    explicit DOMPatchSupport(Document*);
+    static void patchDocument(Document*, const String& markup);
+
+    DOMPatchSupport(DOMEditor*, Document*);
     virtual ~DOMPatchSupport();
 
     void patchDocument(const String& markup);
@@ -62,17 +65,18 @@ private:
     typedef Vector<pair<Digest*, size_t> > ResultMap;
     typedef HashMap<String, Digest*> UnusedNodesMap;
 
-    void innerPatchNode(Digest* oldNode, Digest* newNode, ExceptionCode&);
+    bool innerPatchNode(Digest* oldNode, Digest* newNode, ExceptionCode&);
     std::pair<ResultMap, ResultMap> diff(const Vector<OwnPtr<Digest> >& oldChildren, const Vector<OwnPtr<Digest> >& newChildren);
-    void innerPatchChildren(ContainerNode*, const Vector<OwnPtr<Digest> >& oldChildren, const Vector<OwnPtr<Digest> >& newChildren, ExceptionCode&);
+    bool innerPatchChildren(ContainerNode*, const Vector<OwnPtr<Digest> >& oldChildren, const Vector<OwnPtr<Digest> >& newChildren, ExceptionCode&);
     PassOwnPtr<Digest> createDigest(Node*, UnusedNodesMap*);
-    void insertBefore(ContainerNode*, Digest*, Node* anchor, ExceptionCode&);
-    void removeChild(Digest*, ExceptionCode&);
+    bool insertBeforeAndMarkAsUsed(ContainerNode*, Digest*, Node* anchor, ExceptionCode&);
+    bool removeChildAndMoveToNew(Digest*, ExceptionCode&);
     void markNodeAsUsed(Digest*);
 #ifdef DEBUG_DOM_PATCH_SUPPORT
     void dumpMap(const ResultMap&, const String& name);
 #endif
 
+    DOMEditor* m_domEditor;
     Document* m_document;
 
     UnusedNodesMap m_unusedNodesMap;
index 05d22bd..a1c7e9b 100644 (file)
@@ -228,25 +228,26 @@ public:
     {
     }
 
-    virtual bool perform(ErrorString* errorString)
+    virtual bool perform(ExceptionCode& ec)
     {
-        InspectorStyleSheet* styleSheet = m_cssAgent->assertStyleSheetForId(errorString, m_styleSheetId);
+        ErrorString errorString;
+        InspectorStyleSheet* styleSheet = m_cssAgent->assertStyleSheetForId(&errorString, m_styleSheetId);
         if (!styleSheet)
             return false;
-        return perform(styleSheet, errorString);
+        return perform(styleSheet, ec);
     }
 
-    virtual bool undo(ErrorString* errorString)
+    virtual bool undo(ExceptionCode& ec)
     {
-        InspectorStyleSheet* styleSheet = m_cssAgent->assertStyleSheetForId(errorString, m_styleSheetId);
+        InspectorStyleSheet* styleSheet = m_cssAgent->assertStyleSheetForId(0, m_styleSheetId);
         if (!styleSheet)
             return false;
-        return undo(styleSheet, errorString);
+        return undo(styleSheet, ec);
     }
 
-    virtual bool perform(InspectorStyleSheet*, ErrorString*) = 0;
+    virtual bool perform(InspectorStyleSheet*, ExceptionCode&) = 0;
 
-    virtual bool undo(InspectorStyleSheet*, ErrorString*) = 0;
+    virtual bool undo(InspectorStyleSheet*, ExceptionCode&) = 0;
 
 protected:
     InspectorCSSAgent* m_cssAgent;
@@ -262,7 +263,7 @@ public:
     {
     }
 
-    virtual bool perform(InspectorStyleSheet* inspectorStyleSheet, ErrorString*)
+    virtual bool perform(InspectorStyleSheet* inspectorStyleSheet, ExceptionCode&)
     {
         if (!inspectorStyleSheet->getText(&m_oldText))
             return false;
@@ -274,7 +275,7 @@ public:
         return false;
     }
 
-    virtual bool undo(InspectorStyleSheet* inspectorStyleSheet, ErrorString*)
+    virtual bool undo(InspectorStyleSheet* inspectorStyleSheet, ExceptionCode&)
     {
         if (inspectorStyleSheet->setText(m_oldText)) {
             inspectorStyleSheet->reparseStyleSheet(m_oldText);
@@ -305,10 +306,10 @@ public:
         return mergeId() + ": " + m_oldText + " -> " + m_text;
     }
 
-    virtual bool perform(InspectorStyleSheet* inspectorStyleSheet, ErrorString* errorString)
+    virtual bool perform(InspectorStyleSheet* inspectorStyleSheet, ExceptionCode& ec)
     {
         String oldText;
-        bool result = inspectorStyleSheet->setPropertyText(errorString, m_cssId, m_propertyIndex, m_text, m_overwrite, &oldText);
+        bool result = inspectorStyleSheet->setPropertyText(m_cssId, m_propertyIndex, m_text, m_overwrite, &oldText, ec);
         m_oldText = oldText.stripWhiteSpace();
         // FIXME: remove this once the model handles this case.
         if (!m_oldText.endsWith(";"))
@@ -316,10 +317,10 @@ public:
         return result;
     }
 
-    virtual bool undo(InspectorStyleSheet* inspectorStyleSheet, ErrorString* errorString)
+    virtual bool undo(InspectorStyleSheet* inspectorStyleSheet, ExceptionCode& ec)
     {
         String placeholder;
-        return inspectorStyleSheet->setPropertyText(errorString, m_cssId, m_propertyIndex, m_overwrite ? m_oldText : "", true, &placeholder);
+        return inspectorStyleSheet->setPropertyText(m_cssId, m_propertyIndex, m_overwrite ? m_oldText : "", true, &placeholder, ec);
     }
 
     virtual String mergeId()
@@ -354,14 +355,14 @@ public:
     {
     }
 
-    virtual bool perform(InspectorStyleSheet* inspectorStyleSheet, ErrorString* errorString)
+    virtual bool perform(InspectorStyleSheet* inspectorStyleSheet, ExceptionCode& ec)
     {
-        return inspectorStyleSheet->toggleProperty(errorString, m_cssId, m_propertyIndex, m_disable);
+        return inspectorStyleSheet->toggleProperty(m_cssId, m_propertyIndex, m_disable, ec);
     }
 
-    virtual bool undo(InspectorStyleSheet* inspectorStyleSheet, ErrorString* errorString)
+    virtual bool undo(InspectorStyleSheet* inspectorStyleSheet, ExceptionCode& ec)
     {
-      return inspectorStyleSheet->toggleProperty(errorString, m_cssId, m_propertyIndex, !m_disable);
+        return inspectorStyleSheet->toggleProperty(m_cssId, m_propertyIndex, !m_disable, ec);
     }
 
 private:
@@ -597,7 +598,9 @@ void InspectorCSSAgent::getStyleSheetText(ErrorString* errorString, const String
 
 void InspectorCSSAgent::setStyleSheetText(ErrorString* errorString, const String& styleSheetId, const String& text)
 {
-    m_domAgent->history()->perform(adoptPtr(new SetStyleSheetTextAction(this, styleSheetId, text)), errorString);
+    ExceptionCode ec = 0;
+    m_domAgent->history()->perform(adoptPtr(new SetStyleSheetTextAction(this, styleSheetId, text)), ec);
+    *errorString = InspectorDOMAgent::toErrorString(ec);
     m_domAgent->history()->markUndoableState();
 }
 
@@ -610,9 +613,11 @@ void InspectorCSSAgent::setPropertyText(ErrorString* errorString, const RefPtr<I
     if (!inspectorStyleSheet)
         return;
 
-    bool success = m_domAgent->history()->perform(adoptPtr(new SetPropertyTextAction(this, compoundId.styleSheetId(), compoundId, propertyIndex, text, overwrite)), errorString);
+    ExceptionCode ec = 0;
+    bool success = m_domAgent->history()->perform(adoptPtr(new SetPropertyTextAction(this, compoundId.styleSheetId(), compoundId, propertyIndex, text, overwrite)), ec);
     if (success)
         result = inspectorStyleSheet->buildObjectForStyle(inspectorStyleSheet->styleForId(compoundId));
+    *errorString = InspectorDOMAgent::toErrorString(ec);
 }
 
 void InspectorCSSAgent::toggleProperty(ErrorString* errorString, const RefPtr<InspectorObject>& fullStyleId, int propertyIndex, bool disable, RefPtr<InspectorObject>& result)
@@ -624,9 +629,11 @@ void InspectorCSSAgent::toggleProperty(ErrorString* errorString, const RefPtr<In
     if (!inspectorStyleSheet)
         return;
 
-    bool success = m_domAgent->history()->perform(adoptPtr(new TogglePropertyAction(this, compoundId.styleSheetId(), compoundId, propertyIndex, disable)), errorString);
+    ExceptionCode ec = 0;
+    bool success = m_domAgent->history()->perform(adoptPtr(new TogglePropertyAction(this, compoundId.styleSheetId(), compoundId, propertyIndex, disable)), ec);
     if (success)
         result = inspectorStyleSheet->buildObjectForStyle(inspectorStyleSheet->styleForId(compoundId));
+    *errorString = InspectorDOMAgent::toErrorString(ec);
     m_domAgent->history()->markUndoableState();
 }
 
index d253525..4ddf250 100644 (file)
@@ -179,6 +179,15 @@ void RevalidateStyleAttributeTask::onTimer(Timer<RevalidateStyleAttributeTask>*)
     m_elements.clear();
 }
 
+String InspectorDOMAgent::toErrorString(const ExceptionCode& ec)
+{
+    if (ec) {
+        ExceptionCodeDescription description(ec);
+        return description.name;
+    }
+    return "";
+}
+
 InspectorDOMAgent::InspectorDOMAgent(InstrumentingAgents* instrumentingAgents, InspectorPageAgent* pageAgent, InspectorClient* client, InspectorState* inspectorState, InjectedScriptManager* injectedScriptManager)
     : InspectorBaseAgent<InspectorDOMAgent>("DOM", instrumentingAgents, inspectorState)
     , m_pageAgent(pageAgent)
@@ -541,13 +550,13 @@ void InspectorDOMAgent::setAttributesAsText(ErrorString* errorString, int elemen
     ExceptionCode ec = 0;
     RefPtr<Element> parsedElement = element->document()->createElement("span", ec);
     if (ec) {
-        *errorString = "Internal error: could not set attribute value";
+        *errorString = InspectorDOMAgent::toErrorString(ec);
         return;
     }
 
     toHTMLElement(parsedElement.get())->setInnerHTML("<span " + text + "></span>", ec);
     if (ec) {
-        *errorString = "Could not parse value as attributes";
+        *errorString = InspectorDOMAgent::toErrorString(ec);
         return;
     }
 
@@ -654,7 +663,7 @@ void InspectorDOMAgent::getOuterHTML(ErrorString* errorString, int nodeId, WTF::
 void InspectorDOMAgent::setOuterHTML(ErrorString* errorString, int nodeId, const String& outerHTML)
 {
     if (!nodeId) {
-        DOMPatchSupport domPatchSupport(m_document.get());
+        DOMPatchSupport domPatchSupport(m_domEditor.get(), m_document.get());
         domPatchSupport.patchDocument(outerHTML);
         return;
     }
@@ -1077,7 +1086,9 @@ void InspectorDOMAgent::setTouchEmulationEnabled(ErrorString* error, bool enable
 
 void InspectorDOMAgent::undo(ErrorString* errorString)
 {
-    m_history->undo(errorString);
+    ExceptionCode ec = 0;
+    m_history->undo(ec);
+    *errorString = InspectorDOMAgent::toErrorString(ec);
 }
 
 void InspectorDOMAgent::markUndoableState(ErrorString*)
index 0c8849f..28aabe9 100644 (file)
@@ -107,6 +107,8 @@ public:
         return adoptPtr(new InspectorDOMAgent(instrumentingAgents, pageAgent, client, inspectorState, injectedScriptManager));
     }
 
+    static String toErrorString(const ExceptionCode&);
+
     ~InspectorDOMAgent();
 
     virtual void setFrontend(InspectorFrontend*);
index bf68c1f..8324897 100644 (file)
@@ -43,9 +43,9 @@ class UndoableStateMark : public InspectorHistory::Action {
 public:
     UndoableStateMark() : InspectorHistory::Action("[UndoableState]") { }
 
-    virtual bool perform(ErrorString*) { return true; }
+    virtual bool perform(ExceptionCode&) { return true; }
 
-    virtual bool undo(ErrorString*) { return true; }
+    virtual bool undo(ExceptionCode&) { return true; }
 
     virtual bool isUndoableStateMark() { return true; }
 };
@@ -83,9 +83,9 @@ InspectorHistory::InspectorHistory() { }
 
 InspectorHistory::~InspectorHistory() { }
 
-bool InspectorHistory::perform(PassOwnPtr<Action> action, ErrorString* errorString)
+bool InspectorHistory::perform(PassOwnPtr<Action> action, ExceptionCode& ec)
 {
-    if (!action->perform(errorString))
+    if (!action->perform(ec))
         return false;
 
     if (!m_history.isEmpty() && !action->mergeId().isEmpty() && action->mergeId() == m_history.first()->mergeId())
@@ -101,14 +101,14 @@ void InspectorHistory::markUndoableState()
     m_history.prepend(adoptPtr(new UndoableStateMark()));
 }
 
-bool InspectorHistory::undo(ErrorString* errorString)
+bool InspectorHistory::undo(ExceptionCode& ec)
 {
     while (!m_history.isEmpty() && m_history.first()->isUndoableStateMark())
         m_history.removeFirst();
 
     while (!m_history.isEmpty()) {
         OwnPtr<Action> first = m_history.takeFirst();
-        if (!first->undo(errorString)) {
+        if (!first->undo(ec)) {
             m_history.clear();
             return false;
         }
index e506e05..a488338 100644 (file)
@@ -43,8 +43,6 @@ class ContainerNode;
 class Element;
 class Node;
 
-typedef String ErrorString;
-
 #if ENABLE(INSPECTOR)
 
 class InspectorHistory {
@@ -61,8 +59,8 @@ public:
         virtual String mergeId();
         virtual void merge(PassOwnPtr<Action>);
 
-        virtual bool perform(ErrorString*) = 0;
-        virtual bool undo(ErrorString*) = 0;
+        virtual bool perform(ExceptionCode&) = 0;
+        virtual bool undo(ExceptionCode&) = 0;
     private:
         String m_name;
     };
@@ -70,10 +68,10 @@ public:
     InspectorHistory();
     virtual ~InspectorHistory();
 
-    bool perform(PassOwnPtr<Action>, ErrorString*);
+    bool perform(PassOwnPtr<Action>, ExceptionCode&);
     void markUndoableState();
 
-    bool undo(ErrorString*);
+    bool undo(ExceptionCode&);
     void reset();
 
 private:
index 3bcb3ab..66f70b1 100644 (file)
@@ -571,8 +571,7 @@ void InspectorPageAgent::setDocumentContent(ErrorString* errorString, const Stri
         *errorString = "No Document instance to set HTML for";
         return;
     }
-    DOMPatchSupport patcher(document);
-    patcher.patchDocument(html);
+    DOMPatchSupport::patchDocument(document, html);
 }
 
 void InspectorPageAgent::setScreenSizeOverride(ErrorString* errorString, const int width, const int height)
index c7c4edb..b75971f 100644 (file)
@@ -280,13 +280,13 @@ PassRefPtr<InspectorArray> InspectorStyle::buildArrayForComputedStyle() const
 //
 // The propertyText (if not empty) is checked to be a valid style declaration (containing at least one property). If not,
 // the method returns false (denoting an error).
-bool InspectorStyle::setPropertyText(ErrorString* errorString, unsigned index, const String& propertyText, bool overwrite, String* oldText)
+bool InspectorStyle::setPropertyText(unsigned index, const String& propertyText, bool overwrite, String* oldText, ExceptionCode& ec)
 {
     ASSERT(m_parentStyleSheet);
     DEFINE_STATIC_LOCAL(String, bogusPropertyName, ("-webkit-boguz-propertee"));
 
     if (!m_parentStyleSheet->ensureParsedDataReady()) {
-        *errorString = "Internal error: no stylesheet parsed data available";
+        ec = NOT_FOUND_ERR;
         return false;
     }
 
@@ -303,27 +303,27 @@ bool InspectorStyle::setPropertyText(ErrorString* errorString, unsigned index, c
 
         // At least one property + the bogus property added just above should be present.
         if (propertyCount < 2) {
-            *errorString = "Invalid property value";
+            ec = SYNTAX_ERR;
             return false;
         }
 
         // Check for a proper propertyText termination (the parser could at least restore to the PROPERTY_NAME state).
         if (propertyData.at(propertyCount - 1).name != bogusPropertyName) {
-            *errorString = "Invalid property value";
+            ec = SYNTAX_ERR;
             return false;
         }
     }
 
     RefPtr<CSSRuleSourceData> sourceData = m_parentStyleSheet->ruleSourceDataFor(m_style.get());
     if (!sourceData) {
-        *errorString = "Internal error: no CSS rule source found";
+        ec = NOT_FOUND_ERR;
         return false;
     }
 
     String text;
     bool success = styleText(&text);
     if (!success) {
-        *errorString = "Internal error: could not fetch style text";
+        ec = NOT_FOUND_ERR;
         return false;
     }
 
@@ -337,31 +337,31 @@ bool InspectorStyle::setPropertyText(ErrorString* errorString, unsigned index, c
     return applyStyleText(editor.styleText());
 }
 
-bool InspectorStyle::toggleProperty(ErrorString* errorString, unsigned index, bool disable)
+bool InspectorStyle::toggleProperty(unsigned index, bool disable, ExceptionCode& ec)
 {
     ASSERT(m_parentStyleSheet);
     if (!m_parentStyleSheet->ensureParsedDataReady()) {
-        *errorString = "Can toggle only source-based properties";
+        ec = NO_MODIFICATION_ALLOWED_ERR;
         return false;
     }
 
     RefPtr<CSSRuleSourceData> sourceData = m_parentStyleSheet->ruleSourceDataFor(m_style.get());
     if (!sourceData) {
-        *errorString = "Internal error: No source data for the style found";
+        ec = NOT_FOUND_ERR;
         return false;
     }
 
     String text;
     bool success = styleText(&text);
     if (!success) {
-        *errorString = "Internal error: could not fetch style text";
+        ec = NOT_FOUND_ERR;
         return false;
     }
 
     Vector<InspectorStyleProperty> allProperties;
     populateAllProperties(&allProperties);
     if (index >= allProperties.size()) {
-        *errorString = "Property index is outside of property range";
+        ec = INDEX_SIZE_ERR;
         return false;
     }
 
@@ -868,26 +868,26 @@ PassRefPtr<InspectorObject> InspectorStyleSheet::buildObjectForStyle(CSSStyleDec
     return result.release();
 }
 
-bool InspectorStyleSheet::setPropertyText(ErrorString* errorString, const InspectorCSSId& id, unsigned propertyIndex, const String& text, bool overwrite, String* oldText)
+bool InspectorStyleSheet::setPropertyText(const InspectorCSSId& id, unsigned propertyIndex, const String& text, bool overwrite, String* oldText, ExceptionCode& ec)
 {
     RefPtr<InspectorStyle> inspectorStyle = inspectorStyleForId(id);
     if (!inspectorStyle) {
-        *errorString = "No style found for given id";
+        ec = NOT_FOUND_ERR;
         return false;
     }
 
-    return inspectorStyle->setPropertyText(errorString, propertyIndex, text, overwrite, oldText);
+    return inspectorStyle->setPropertyText(propertyIndex, text, overwrite, oldText, ec);
 }
 
-bool InspectorStyleSheet::toggleProperty(ErrorString* errorString, const InspectorCSSId& id, unsigned propertyIndex, bool disable)
+bool InspectorStyleSheet::toggleProperty(const InspectorCSSId& id, unsigned propertyIndex, bool disable, ExceptionCode& ec)
 {
     RefPtr<InspectorStyle> inspectorStyle = inspectorStyleForId(id);
     if (!inspectorStyle) {
-        *errorString = "No style found for given id";
+        ec = NOT_FOUND_ERR;
         return false;
     }
 
-    bool success = inspectorStyle->toggleProperty(errorString, propertyIndex, disable);
+    bool success = inspectorStyle->toggleProperty(propertyIndex, disable, ec);
     if (success) {
         if (disable)
             rememberInspectorStyle(inspectorStyle);
index d627b1d..5fe9aa2 100644 (file)
@@ -26,6 +26,7 @@
 #define InspectorStyleSheet_h
 
 #include "CSSPropertySourceData.h"
+#include "ExceptionCode.h"
 #include "InspectorStyleTextEditor.h"
 #include "InspectorValues.h"
 #include "PlatformString.h"
@@ -131,8 +132,8 @@ public:
     PassRefPtr<InspectorObject> buildObjectForStyle() const;
     PassRefPtr<InspectorArray> buildArrayForComputedStyle() const;
     bool hasDisabledProperties() const { return !m_disabledProperties.isEmpty(); }
-    bool setPropertyText(ErrorString*, unsigned index, const String& text, bool overwrite, String* oldText);
-    bool toggleProperty(ErrorString*, unsigned index, bool disable);
+    bool setPropertyText(unsigned index, const String& text, bool overwrite, String* oldText, ExceptionCode&);
+    bool toggleProperty(unsigned index, bool disable, ExceptionCode&);
 
 private:
     InspectorStyle(const InspectorCSSId& styleId, PassRefPtr<CSSStyleDeclaration> style, InspectorStyleSheet* parentStyleSheet);
@@ -174,8 +175,8 @@ public:
     PassRefPtr<InspectorObject> buildObjectForStyleSheetInfo();
     PassRefPtr<InspectorObject> buildObjectForRule(CSSStyleRule*);
     PassRefPtr<InspectorObject> buildObjectForStyle(CSSStyleDeclaration*);
-    bool setPropertyText(ErrorString*, const InspectorCSSId&, unsigned propertyIndex, const String& text, bool overwrite, String* oldPropertyText);
-    bool toggleProperty(ErrorString*, const InspectorCSSId&, unsigned propertyIndex, bool disable);
+    bool setPropertyText(const InspectorCSSId&, unsigned propertyIndex, const String& text, bool overwrite, String* oldPropertyText, ExceptionCode&);
+    bool toggleProperty(const InspectorCSSId&, unsigned propertyIndex, bool disable, ExceptionCode&);
 
     virtual bool getText(String* result) const;
     virtual CSSStyleDeclaration* styleForId(const InspectorCSSId&) const;