Diff
Modified: trunk/LayoutTests/ChangeLog (105261 => 105262)
--- trunk/LayoutTests/ChangeLog 2012-01-18 12:46:55 UTC (rev 105261)
+++ trunk/LayoutTests/ChangeLog 2012-01-18 12:52:46 UTC (rev 105262)
@@ -1,3 +1,14 @@
+2012-01-17 Pavel Feldman <[email protected]>
+
+ Web Inspector: track HTML revisions when editing DOM and / or upon free flow edits.
+ https://bugs.webkit.org/show_bug.cgi?id=76457
+
+ Reviewed by Yury Semikhatsky.
+
+ * inspector/elements/resources/set-outer-html-body-iframe.html:
+ * inspector/elements/set-html-via-resource-expected.txt: Added.
+ * inspector/elements/set-html-via-resource.html: Added.
+
2012-01-18 Philippe Normand <[email protected]>
Unreviewed, GTK rebaseline after r105247 and r105253.
Modified: trunk/LayoutTests/http/tests/inspector/inspector-test.js (105261 => 105262)
--- trunk/LayoutTests/http/tests/inspector/inspector-test.js 2012-01-18 12:46:55 UTC (rev 105261)
+++ trunk/LayoutTests/http/tests/inspector/inspector-test.js 2012-01-18 12:52:46 UTC (rev 105262)
@@ -490,6 +490,7 @@
outputElement = document.createElement("div");
outputElement.className = "output";
+ outputElement.id = "output";
outputElement.style.whiteSpace = "pre";
intermediate2.appendChild(outputElement);
}
Modified: trunk/LayoutTests/inspector/elements/edit-dom-actions-expected.txt (105261 => 105262)
--- trunk/LayoutTests/inspector/elements/edit-dom-actions-expected.txt 2012-01-18 12:46:55 UTC (rev 105261)
+++ trunk/LayoutTests/inspector/elements/edit-dom-actions-expected.txt 2012-01-18 12:52:46 UTC (rev 105262)
@@ -23,7 +23,7 @@
</div>
==== after ====
- <div id="testSetNodeName">
- <span id="node-to-set-name" ></span>
+ <span id="node-to-set-name"></span>
</div>
Running: testSetNodeNameInput
@@ -33,7 +33,7 @@
</div>
==== after ====
- <div id="testSetNodeNameInput">
- <input id="node-to-set-name-input" >
+ <input id="node-to-set-name-input">
</div>
Running: testSetNodeValue
Added: trunk/LayoutTests/inspector/elements/set-html-via-resource-expected.txt (0 => 105262)
--- trunk/LayoutTests/inspector/elements/set-html-via-resource-expected.txt (rev 0)
+++ trunk/LayoutTests/inspector/elements/set-html-via-resource-expected.txt 2012-01-18 12:52:46 UTC (rev 105262)
@@ -0,0 +1,5 @@
+Tests that the DOM content can be set via editing resource content.
+
+
+<html><head></head><body>New iframe content</body></html>
+
Property changes on: trunk/LayoutTests/inspector/elements/set-html-via-resource-expected.txt
___________________________________________________________________
Added: svn:eol-style
Added: trunk/LayoutTests/inspector/elements/set-html-via-resource.html (0 => 105262)
--- trunk/LayoutTests/inspector/elements/set-html-via-resource.html (rev 0)
+++ trunk/LayoutTests/inspector/elements/set-html-via-resource.html 2012-01-18 12:52:46 UTC (rev 105262)
@@ -0,0 +1,51 @@
+<html>
+<head>
+
+<script src=""
+<script src=""
+<script src=""
+
+<script>
+
+function test()
+{
+ WebInspector.experimentsSettings.freeFlowDOMEditing.enableForTest();
+ new WebInspector.DOMModelResourceBinding(WebInspector.domAgent);
+
+ InspectorTest.runAfterResourcesAreFinished(["set-html-via-resource.html", "set-html-via-resource-iframe.html"], step1);
+
+ function step1()
+ {
+ WebInspector.resourceTreeModel.forAllResources(formatter);
+
+ function formatter(resource)
+ {
+ if (resource.url.indexOf("set-html-via-resource-iframe.html") !== -1)
+ resource.setContent("<body>New iframe content</body>", false, step2.bind(this, resource.url));
+ }
+ }
+
+ function step2(url)
+ {
+ var doc = WebInspector.domAgent._documentURLToDocument[url];
+ DOMAgent.getOuterHTML(doc.id, step3);
+ }
+
+ function step3(error, text)
+ {
+ InspectorTest.addResult(text);
+ InspectorTest.completeTest();
+ }
+}
+</script>
+</head>
+
+<body>
+<p>
+Tests that the DOM content can be set via editing resource content.
+</p>
+
+<iframe src="" _onload_="runTest()"></iframe>
+
+</body>
+</html>
Property changes on: trunk/LayoutTests/inspector/elements/set-html-via-resource.html
___________________________________________________________________
Added: svn:eol-style
Modified: trunk/LayoutTests/inspector/elements/set-outer-html-test.js (105261 => 105262)
--- trunk/LayoutTests/inspector/elements/set-outer-html-test.js 2012-01-18 12:46:55 UTC (rev 105261)
+++ trunk/LayoutTests/inspector/elements/set-outer-html-test.js 2012-01-18 12:52:46 UTC (rev 105262)
@@ -1,6 +1,7 @@
var initialize_SetOuterHTMLTest = function() {
InspectorTest.events = [];
+InspectorTest.containerId;
InspectorTest.setUpTestSuite = function(next)
{
@@ -33,6 +34,11 @@
InspectorTest.recordEvent = function(eventName, event)
{
var node = event.data.node || event.data;
+ var parent = event.data.parent;
+ for (var currentNode = parent || node; currentNode; currentNode = currentNode.parentNode) {
+ if (currentNode.getAttribute("id") === "output")
+ return;
+ }
InspectorTest.events.push("Event " + eventName + ": " + node.nodeName());
}
Modified: trunk/Source/WebCore/ChangeLog (105261 => 105262)
--- trunk/Source/WebCore/ChangeLog 2012-01-18 12:46:55 UTC (rev 105261)
+++ trunk/Source/WebCore/ChangeLog 2012-01-18 12:52:46 UTC (rev 105262)
@@ -1,3 +1,43 @@
+2012-01-17 Pavel Feldman <[email protected]>
+
+ Web Inspector: track HTML revisions when editing DOM and / or upon free flow edits.
+ https://bugs.webkit.org/show_bug.cgi?id=76457
+
+ Reviewed by Yury Semikhatsky.
+
+ Test: inspector/elements/set-html-via-resource.html
+
+ * inspector/DOMEditor.cpp:
+ (WebCore::DOMEditor::patchNode):
+ * inspector/InspectorDOMAgent.cpp:
+ (WebCore::InspectorDOMAgent::getOuterHTML):
+ (WebCore::InspectorDOMAgent::setOuterHTML):
+ (WebCore::InspectorDOMAgent::buildObjectForNode):
+ * inspector/front-end/DOMAgent.js:
+ (WebInspector.DOMNode):
+ (WebInspector.DOMNode.prototype.setNodeName):
+ (WebInspector.DOMNode.prototype.setNodeValue):
+ (WebInspector.DOMNode.prototype.setAttribute):
+ (WebInspector.DOMNode.prototype.setAttributeValue):
+ (WebInspector.DOMNode.prototype.removeAttribute):
+ (WebInspector.DOMNode.prototype.getChildNodes.mycallback):
+ (WebInspector.DOMNode.prototype.getChildNodes):
+ (WebInspector.DOMNode.prototype.setOuterHTML):
+ (WebInspector.DOMNode.prototype.removeNode):
+ (WebInspector.DOMNode.prototype.moveTo):
+ (WebInspector.DOMDocument):
+ (WebInspector.DOMAgent):
+ (WebInspector.DOMAgent.prototype._setDocument):
+ (WebInspector.DOMAgent.prototype._buildHighlightConfig):
+ (WebInspector.DOMAgent.prototype._markRevision):
+ (WebInspector.DOMAgent.prototype._captureDOM.callback):
+ (WebInspector.DOMAgent.prototype._captureDOM):
+ (WebInspector.DOMModelResourceBinding.prototype.setContent):
+ (WebInspector.DOMModelResourceBinding.prototype.setContent.setOuterHTML):
+ (WebInspector.DOMModelResourceBinding.prototype.setContent.withDocument):
+ * inspector/front-end/ElementsTreeOutline.js:
+ (WebInspector.ElementsTreeElement.prototype._attributeEditingCommitted):
+
2012-01-18 Andrey Kosyakov <[email protected]>
Web Inspector: Popover does not disappear, causes debugger failure.
Modified: trunk/Source/WebCore/inspector/DOMEditor.cpp (105261 => 105262)
--- trunk/Source/WebCore/inspector/DOMEditor.cpp 2012-01-18 12:46:55 UTC (rev 105261)
+++ trunk/Source/WebCore/inspector/DOMEditor.cpp 2012-01-18 12:52:46 UTC (rev 105262)
@@ -93,7 +93,7 @@
Node* DOMEditor::patchNode(Node* node, const String& markup, ExceptionCode& ec)
{
// Don't parse <html> as a fragment.
- if (node == node->ownerDocument()->documentElement()) {
+ if (node->isDocumentNode() || (node->parentNode() && node->parentNode()->isDocumentNode())) {
patchDocument(markup);
return 0;
}
Modified: trunk/Source/WebCore/inspector/InspectorDOMAgent.cpp (105261 => 105262)
--- trunk/Source/WebCore/inspector/InspectorDOMAgent.cpp 2012-01-18 12:46:55 UTC (rev 105261)
+++ trunk/Source/WebCore/inspector/InspectorDOMAgent.cpp 2012-01-18 12:52:46 UTC (rev 105262)
@@ -616,22 +616,7 @@
if (!node)
return;
- if (node->isHTMLElement()) {
- *outerHTML = static_cast<HTMLElement*>(node)->outerHTML();
- return;
- }
-
- if (node->isCommentNode()) {
- *outerHTML = "<!--" + node->nodeValue() + "-->";
- return;
- }
-
- if (node->isTextNode()) {
- *outerHTML = node->nodeValue();
- return;
- }
-
- *errorString = "Only HTMLElements, Comments, and Text nodes are supported";
+ *outerHTML = createMarkup(node);
}
void InspectorDOMAgent::setOuterHTML(ErrorString* errorString, int nodeId, const String& outerHTML)
@@ -646,8 +631,8 @@
if (!node)
return;
- Document* document = node->ownerDocument();
- if (!document->isHTMLDocument()) {
+ Document* document = node->isDocumentNode() ? static_cast<Document*>(node) : node->ownerDocument();
+ if (!document || !document->isHTMLDocument()) {
*errorString = "Not an HTML document";
return;
}
@@ -1136,33 +1121,33 @@
.setLocalName(localName)
.setNodeValue(nodeValue);
- if (node->nodeType() == Node::ELEMENT_NODE || node->nodeType() == Node::DOCUMENT_NODE || node->nodeType() == Node::DOCUMENT_FRAGMENT_NODE) {
+ if (node->isContainerNode()) {
int nodeCount = innerChildNodeCount(node);
value->setChildNodeCount(nodeCount);
RefPtr<InspectorArray> children = buildArrayForContainerChildren(node, depth, nodesMap);
if (children->length() > 0)
value->setArray("children", children.release());
+ }
- if (node->nodeType() == Node::ELEMENT_NODE) {
- Element* element = static_cast<Element*>(node);
- value->setArray("attributes", buildArrayForElementAttributes(element));
- if (node->isFrameOwnerElement()) {
- HTMLFrameOwnerElement* frameOwner = static_cast<HTMLFrameOwnerElement*>(node);
- Document* doc = frameOwner->contentDocument();
- if (doc)
- value->setContentDocument(buildObjectForNode(doc, 0, nodesMap));
- }
- } else if (node->nodeType() == Node::DOCUMENT_NODE) {
- Document* document = static_cast<Document*>(node);
- value->setDocumentURL(documentURLString(document));
- value->setXmlVersion(document->xmlVersion());
+ if (node->isElementNode()) {
+ Element* element = static_cast<Element*>(node);
+ value->setArray("attributes", buildArrayForElementAttributes(element));
+ if (node->isFrameOwnerElement()) {
+ HTMLFrameOwnerElement* frameOwner = static_cast<HTMLFrameOwnerElement*>(node);
+ Document* doc = frameOwner->contentDocument();
+ if (doc)
+ value->setContentDocument(buildObjectForNode(doc, 0, nodesMap));
}
+ } else if (node->isDocumentNode()) {
+ Document* document = static_cast<Document*>(node);
+ value->setDocumentURL(documentURLString(document));
+ value->setXmlVersion(document->xmlVersion());
} else if (node->nodeType() == Node::DOCUMENT_TYPE_NODE) {
DocumentType* docType = static_cast<DocumentType*>(node);
value->setPublicId(docType->publicId());
value->setSystemId(docType->systemId());
value->setInternalSubset(docType->internalSubset());
- } else if (node->nodeType() == Node::ATTRIBUTE_NODE) {
+ } else if (node->isAttributeNode()) {
Attr* attribute = static_cast<Attr*>(node);
value->setName(attribute->name());
value->setValue(attribute->value());
Modified: trunk/Source/WebCore/inspector/front-end/DOMAgent.js (105261 => 105262)
--- trunk/Source/WebCore/inspector/front-end/DOMAgent.js 2012-01-18 12:46:55 UTC (rev 105261)
+++ trunk/Source/WebCore/inspector/front-end/DOMAgent.js 2012-01-18 12:52:46 UTC (rev 105262)
@@ -64,9 +64,13 @@
if (payload.contentDocument) {
this._contentDocument = new WebInspector.DOMDocument(domAgent, payload.contentDocument);
+ for (var i = 0; i < this._attributes.length; ++i) {
+ // Only bind document to URL when src attribute is set.
+ if (this._attributes[i].name.toLowerCase() === "src")
+ this._domAgent._documentURLToDocument[this._contentDocument.documentURL] = this._contentDocument;
+ }
this.children = [this._contentDocument];
this._renumber();
- this._domAgent._idToDOMNode[this._contentDocument.id] = this._contentDocument;
}
if (this._nodeType === Node.ELEMENT_NODE) {
@@ -75,15 +79,10 @@
this.ownerDocument.documentElement = this;
if (this.ownerDocument && !this.ownerDocument.body && this._nodeName === "BODY")
this.ownerDocument.body = this;
- if (payload.documentURL)
- this.documentURL = payload.documentURL;
} else if (this._nodeType === Node.DOCUMENT_TYPE_NODE) {
this.publicId = payload.publicId;
this.systemId = payload.systemId;
this.internalSubset = payload.internalSubset;
- } else if (this._nodeType === Node.DOCUMENT_NODE) {
- this.documentURL = payload.documentURL;
- this.xmlVersion = payload.xmlVersion;
} else if (this._nodeType === Node.ATTRIBUTE_NODE) {
this.name = payload.name;
this.value = payload.value;
@@ -133,11 +132,11 @@
/**
* @param {string} name
- * @param {function()=} callback
+ * @param {function(?Protocol.Error)=} callback
*/
setNodeName: function(name, callback)
{
- DOMAgent.setNodeName(this.id, name, callback);
+ DOMAgent.setNodeName(this.id, name, WebInspector.domAgent._markRevision(this, callback));
},
/**
@@ -162,7 +161,7 @@
*/
setNodeValue: function(value, callback)
{
- DOMAgent.setNodeValue(this.id, value, callback);
+ DOMAgent.setNodeValue(this.id, value, WebInspector.domAgent._markRevision(this, callback));
},
/**
@@ -178,21 +177,21 @@
/**
* @param {string} name
* @param {string} text
- * @param {function()=} callback
+ * @param {function(?Protocol.Error)=} callback
*/
setAttribute: function(name, text, callback)
{
- DOMAgent.setAttributesAsText(this.id, text, name, callback);
+ DOMAgent.setAttributesAsText(this.id, text, name, WebInspector.domAgent._markRevision(this, callback));
},
/**
* @param {string} name
* @param {string} value
- * @param {function()=} callback
+ * @param {function(?Protocol.Error)=} callback
*/
setAttributeValue: function(name, value, callback)
{
- DOMAgent.setAttributeValue(this.id, name, value, callback);
+ DOMAgent.setAttributeValue(this.id, name, value, WebInspector.domAgent._markRevision(this, callback));
},
/**
@@ -205,7 +204,7 @@
/**
* @param {string} name
- * @param {function()=} callback
+ * @param {function(?Protocol.Error)=} callback
*/
removeAttribute: function(name, callback)
{
@@ -221,8 +220,7 @@
}
}
- if (callback)
- callback();
+ WebInspector.domAgent._markRevision(this, callback)(error);
}
DOMAgent.removeAttribute(this.id, name, mycallback.bind(this));
},
@@ -242,7 +240,8 @@
* @this {WebInspector.DOMNode}
* @param {?Protocol.Error} error
*/
- function mycallback(error) {
+ function mycallback(error)
+ {
if (!error && callback)
callback(this.children);
}
@@ -264,7 +263,7 @@
*/
setOuterHTML: function(html, callback)
{
- DOMAgent.setOuterHTML(this.id, html, callback);
+ DOMAgent.setOuterHTML(this.id, html, WebInspector.domAgent._markRevision(this, callback));
},
/**
@@ -272,7 +271,7 @@
*/
removeNode: function(callback)
{
- DOMAgent.removeNode(this.id, callback);
+ DOMAgent.removeNode(this.id, WebInspector.domAgent._markRevision(this, callback));
},
/**
@@ -480,7 +479,7 @@
*/
moveTo: function(targetNode, anchorNode, callback)
{
- DOMAgent.moveTo(this.id, targetNode.id, anchorNode ? anchorNode.id : undefined, callback);
+ DOMAgent.moveTo(this.id, targetNode.id, anchorNode ? anchorNode.id : undefined, WebInspector.domAgent._markRevision(this, callback));
},
/**
@@ -501,6 +500,9 @@
WebInspector.DOMDocument = function(domAgent, payload)
{
WebInspector.DOMNode.call(this, domAgent, this, payload);
+ this.documentURL = payload.documentURL;
+ this.xmlVersion = payload.xmlVersion;
+ domAgent._idToDOMNode[this.id] = this;
/**
* @type {string} Document nodes always have documentURL
@@ -518,6 +520,7 @@
WebInspector.DOMAgent = function() {
/** @type {Object|undefined} */
this._idToDOMNode = {};
+ this._documentURLToDocument = {};
this._document = null;
this._attributeLoadNodeIds = {};
InspectorBackend.registerDOMDispatcher(new WebInspector.DOMDispatcher(this));
@@ -733,9 +736,10 @@
_setDocument: function(payload)
{
this._idToDOMNode = {};
+ this._documentURLToDocument = {};
if (payload && "nodeId" in payload) {
this._document = new WebInspector.DOMDocument(this, payload);
- this._idToDOMNode[payload.nodeId] = this._document;
+ this._documentURLToDocument[this._document.documentURL] = this._document;
if (this._document.children)
this._bindNodes(this._document.children);
} else
@@ -969,6 +973,56 @@
highlightConfig.marginColor = WebInspector.Color.PageHighlight.Margin.toProtocolRGBA();
return highlightConfig;
+ },
+
+ /**
+ * @param {WebInspector.DOMNode} node
+ * @param {function(?Protocol.Error)=} callback
+ * @return {function(?Protocol.Error)}
+ */
+ _markRevision: function(node, callback)
+ {
+ function wrapperFunction(error)
+ {
+ if (callback)
+ callback(error);
+ if (error || !WebInspector.experimentsSettings.freeFlowDOMEditing.isEnabled())
+ return;
+ if (this._captureDOMTimer)
+ clearTimeout(this._captureDOMTimer);
+ this._captureDOMTimer = setTimeout(this._captureDOM.bind(this, node), 500);
+ }
+ return wrapperFunction.bind(this);
+ },
+
+ /**
+ * @param {WebInspector.DOMNode} node
+ */
+ _captureDOM: function(node)
+ {
+ delete this._captureDOMTimer;
+ if (!node.ownerDocument)
+ return;
+
+ function callback(error, text)
+ {
+ if (error) {
+ console.error(error);
+ return;
+ }
+
+ var url = ""
+ if (!url)
+ return;
+
+ var resource = WebInspector.resourceForURL(url);
+ if (!resource)
+ return;
+
+ resource.addRevision(text);
+ }
+ DOMAgent.getOuterHTML(node.ownerDocument.id, callback);
+
}
}
@@ -1082,7 +1136,37 @@
WebInspector.DOMModelResourceBinding.prototype = {
setContent: function(resource, content, majorChange, userCallback)
{
- DOMAgent.setOuterHTML(0, content, userCallback);
+ function callbackWrapper(error)
+ {
+ if (majorChange)
+ resource.addRevision(content);
+ if (userCallback)
+ userCallback(error);
+ }
+
+ function setOuterHTML(reportError)
+ {
+ var doc = this._domAgent._documentURLToDocument[resource.url];
+ if (doc) {
+ DOMAgent.setOuterHTML(doc.id, content, callbackWrapper.bind(this));
+ return true;
+ }
+ if (reportError)
+ callback("No document with given URL found");
+ return false;
+ }
+
+ this._domAgent.requestDocument(withDocument.bind(this));
+
+ function withDocument(doc)
+ {
+ if (setOuterHTML.call(this, false))
+ return;
+
+ // We are editing one of the iframes, but it has not yet been loaded in the DOM tree.
+ // Load all iframe nodes here.
+ DOMAgent.querySelectorAll(doc.id, "iframe[src]", setOuterHTML.bind(this, true));
+ }
},
canSetContent: function()
Modified: trunk/Source/WebCore/inspector/front-end/ElementsTreeOutline.js (105261 => 105262)
--- trunk/Source/WebCore/inspector/front-end/ElementsTreeOutline.js 2012-01-18 12:46:55 UTC (rev 105261)
+++ trunk/Source/WebCore/inspector/front-end/ElementsTreeOutline.js 2012-01-18 12:52:46 UTC (rev 105262)
@@ -1320,7 +1320,10 @@
}
}
- this.representedObject.setAttribute(attributeName, newText, moveToNextAttributeIfNeeded.bind(this));
+ if (oldText !== newText)
+ this.representedObject.setAttribute(attributeName, newText, moveToNextAttributeIfNeeded.bind(this));
+ else
+ moveToNextAttributeIfNeeded.call(this);
},
_tagNameEditingCommitted: function(element, newText, oldText, tagName, moveDirection)
Modified: trunk/Source/WebCore/inspector/front-end/Settings.js (105261 => 105262)
--- trunk/Source/WebCore/inspector/front-end/Settings.js 2012-01-18 12:46:55 UTC (rev 105261)
+++ trunk/Source/WebCore/inspector/front-end/Settings.js 2012-01-18 12:52:46 UTC (rev 105262)
@@ -164,6 +164,7 @@
{
this._setting = WebInspector.settings.createSetting("experiments", {});
this._experiments = [];
+ this._enabledForTest = {};
// Add currently running experiments here.
// FIXME: Move out from experiments once navigator is production-ready.
@@ -209,6 +210,9 @@
*/
isEnabled: function(experimentName)
{
+ if (this._enabledForTest[experimentName])
+ return true;
+
if (!this.experimentsEnabled)
return false;
@@ -226,7 +230,15 @@
experimentsSetting[experimentName] = enabled;
this._setting.set(experimentsSetting);
},
-
+
+ /**
+ * @param {string} experimentName
+ */
+ _enableForTest: function(experimentName)
+ {
+ this._enabledForTest[experimentName] = true;
+ },
+
_cleanUpSetting: function()
{
var experimentsSetting = this._setting.get();
@@ -284,6 +296,11 @@
setEnabled: function(enabled)
{
return this._experimentsSettings.setEnabled(this._name, enabled);
+ },
+
+ enableForTest: function()
+ {
+ this._experimentsSettings._enableForTest(this._name);
}
}