Title: [145057] trunk
Revision
145057
Author
grao...@apple.com
Date
2013-03-07 02:39:15 -0800 (Thu, 07 Mar 2013)

Log Message

Web Inspector: identify layers for CSS generated content in LayerTreeAgent
https://bugs.webkit.org/show_bug.cgi?id=111551

Source/WebCore:

Layers can be associated with pseudo elements, elements that are generated
when ::before or ::after pseudo-classes are used to style an element and
provide additional rendering using the CSS "content" property. In order to
identify that a layer is associated to a pseudo element, we add a new set of
optional properties on the Layer object: "isGeneratedContent", "pseudoElementId"
and "pseudoClass".

We need to provide the "pseudoElementId" for the same reason we provide a
"nodeId" for the Layer. This is so that the front-end can identify that a
layer whose "layerId" may have changed between two layer tree updates is
used to render content for the same pseudo element.

In the instance that a layer is rendering generated content, we also set
the "nodeId" to be the generating node's id. The generating node is the
node in the DOM that the user styled using ::before or ::after pseudo-classes.
We also add the pseudo-class used as the "pseudoClass" property such that the
front-end may provide useful information to the user about what type of
pseudo-class yielded the generation of this layer. We also deal with the
possibility that the layer is a reflection for a pseudo element.

Since pseudo elements are not part of the user-visible DOM, and thus can't be
pushed to the front-end, we maintain a special ID hash map in the LayerTreeAgent.
In order to be able to unbind a pseudo element id and a pseudo element, we add a
destructor method to PseudoElement and provide a new instrumentation call so that
the LayerTreeAgent may be notified of a PseudoElement being destroyed. This
reflects the principle we use to update the RenderLayer bindings when a
RenderLayer is destroyed, as notified by the RenderLayerCompositor.

Reviewed by Simon Fraser.

Test: inspector-protocol/layers/layers-generated-content.html

* dom/PseudoElement.cpp:
(WebCore::PseudoElement::~PseudoElement): New destructor used to notify
InspectorInstrumentation of a PseudoElement being destroyed, such that
it can eventually be relayed to the InspectorLayerTreeAgent.
(WebCore):
* dom/PseudoElement.h:
(PseudoElement):
* inspector/Inspector.json: Add the new PseudoElementId type used for
the new "pseudoElementId" property on Layer, to which we also add the
"isGeneratedContent" and "pseudoClass" properties.
* inspector/InspectorInstrumentation.cpp:
(WebCore):
(WebCore::InspectorInstrumentation::pseudoElementDestroyedImpl):
* inspector/InspectorInstrumentation.h:
(WebCore):
(InspectorInstrumentation):
(WebCore::InspectorInstrumentation::pseudoElementDestroyed): New method
called in the PseudoElement destructor used to relay the fact that a
PseudoElement was destroyed to the InspectorLayerTreeAgent.
* inspector/InspectorLayerTreeAgent.cpp:
(WebCore::InspectorLayerTreeAgent::reset): Clear the new PseudoElement
identifier maps.
(WebCore::InspectorLayerTreeAgent::pseudoElementDestroyed): Remove any
identifier binding for the provided PseudoElement being destroyed.
(WebCore):
(WebCore::InspectorLayerTreeAgent::buildObjectForLayer): Set the new
"isGeneratedContent", "pseudoElementId" and "pseudoClass" properties on
the Layer object for layers associated with a pseudo element.
(WebCore::InspectorLayerTreeAgent::bind): Use emptyString() instead of "".
(WebCore::InspectorLayerTreeAgent::unbind): Use an iterator instead of a
get() and remove() combination in order to reduce lookups and mimick the
code written for unbindPseudoElement().
(WebCore::InspectorLayerTreeAgent::bindPseudoElement): Binds the provided
PseudoElement to a unique identifier.
(WebCore::InspectorLayerTreeAgent::unbindPseudoElement): Unbinds the
provided PseudoElement from its unique identifier.
* inspector/InspectorLayerTreeAgent.h:
(InspectorLayerTreeAgent):

LayoutTests:

New tests for layers associated with pseudo elements.

Reviewed by Simon Fraser.

* inspector-protocol/layers/layers-generated-content-expected.txt: Added.
* inspector-protocol/layers/layers-generated-content.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (145056 => 145057)


--- trunk/LayoutTests/ChangeLog	2013-03-07 10:08:03 UTC (rev 145056)
+++ trunk/LayoutTests/ChangeLog	2013-03-07 10:39:15 UTC (rev 145057)
@@ -1,3 +1,15 @@
+2013-03-07  Antoine Quint  <grao...@apple.com>
+
+        Web Inspector: identify layers for CSS generated content in LayerTreeAgent
+        https://bugs.webkit.org/show_bug.cgi?id=111551
+
+        New tests for layers associated with pseudo elements.
+
+        Reviewed by Simon Fraser.
+
+        * inspector-protocol/layers/layers-generated-content-expected.txt: Added.
+        * inspector-protocol/layers/layers-generated-content.html: Added.
+
 2013-03-07  Ádám Kallai  <ka...@inf.u-szeged.hu>
 
         [Qt] Unreviewed gardneing. Skipped some failing tests.

Added: trunk/LayoutTests/inspector-protocol/layers/layers-generated-content-expected.txt (0 => 145057)


--- trunk/LayoutTests/inspector-protocol/layers/layers-generated-content-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/inspector-protocol/layers/layers-generated-content-expected.txt	2013-03-07 10:39:15 UTC (rev 145057)
@@ -0,0 +1,33 @@
+
+=== Enable the LayerTree agent ===
+
+PASS
+
+=== Get the Document ===
+
+PASS
+
+=== Get the layer tree ===
+
+PASS
+
+=== Check layers ===
+
+PASS: Expected number of ::before layers.
+PASS: The sole ::before layer has a pseudo element.
+PASS: Expected number of ::after layers.
+PASS: The first ::after layer has a pseudo element.
+PASS: The second ::after layer has a pseudo element.
+PASS: The second ::after layer is a reflection.
+PASS: The two ::after layers have the same node id.
+PASS: The two ::after layers have the same pseudo element id.
+PASS: The non-reflection generated generated layers have the same node id.
+PASS: The non-reflection generated layers have different pseudo element ids.
+
+=== Check generating node ===
+
+PASS: Generating node was found.
+PASS: Generating node has expected localName.
+PASS: Generating node has id.
+PASS: Generating node has expected id.
+

Added: trunk/LayoutTests/inspector-protocol/layers/layers-generated-content.html (0 => 145057)


--- trunk/LayoutTests/inspector-protocol/layers/layers-generated-content.html	                        (rev 0)
+++ trunk/LayoutTests/inspector-protocol/layers/layers-generated-content.html	2013-03-07 10:39:15 UTC (rev 145057)
@@ -0,0 +1,166 @@
+<html>
+<head>
+<script type="text/_javascript_" src=""
+<script type="text/_javascript_">
+
+function test()
+{
+
+    var nodes;
+ 
+    InspectorTest.eventHandler["DOM.setChildNodes"] = setChildNodes;
+
+    enableLayerTreeAgent();
+    
+    function enableLayerTreeAgent(result)
+    {
+        step({
+            name: "Enable the LayerTree agent",
+            command: "LayerTree.enable",
+            parameters: {},
+            callback: getDocument
+        });
+    };
+
+    function getDocument()
+    {
+        // We must first get the document so that later on we may get sensible nodeIds.
+        step({
+            name: "Get the Document",
+            command: "DOM.getDocument",
+            parameters: {},
+            callback: getLayerTree
+        });
+    };
+
+    function getLayerTree(result)
+    {
+        step({
+            name: "Get the layer tree",
+            command: "LayerTree.layersForNode",
+            parameters: {"nodeId": result.root.nodeId},
+            callback: gotLayerTree
+        });
+    };
+
+    function gotLayerTree(result)
+    {
+        var beforeLayers = [];
+        var afterLayers = [];
+        result.layers.forEach(function (layer) {
+            if (!layer.isGeneratedContent)
+                return;
+
+            if (layer.pseudoClass === "before")
+                beforeLayers.push(layer);
+            if (layer.pseudoClass === "after")
+                afterLayers.push(layer);
+        });
+
+        logTestName("Check layers");
+
+        assert("Expected number of ::before layers", beforeLayers.length, 1);
+        assert("The sole ::before layer has a pseudo element", beforeLayers[0].pseudoElementId !== "", true);
+
+        assert("Expected number of ::after layers", afterLayers.length, 2);
+        assert("The first ::after layer has a pseudo element", afterLayers[0].pseudoElementId !== "", true);
+        assert("The second ::after layer has a pseudo element", afterLayers[1].pseudoElementId !== "", true);
+        assert("The second ::after layer is a reflection", afterLayers[1].isReflection, true);
+        assert("The two ::after layers have the same node id", afterLayers[0].nodeId, afterLayers[1].nodeId);
+        assert("The two ::after layers have the same pseudo element id", afterLayers[0].pseudoElementId, afterLayers[1].pseudoElementId);
+
+        assert("The non-reflection generated generated layers have the same node id", beforeLayers[0].nodeId, afterLayers[0].nodeId);
+        assert("The non-reflection generated layers have different pseudo element ids", beforeLayers[0].pseudoElementId !== afterLayers[0].pseudoElementId, true);
+
+        var node;
+        var nodeId = beforeLayers[0].nodeId;
+        for (var i = 0, count = nodes.length; i < count; ++i) {
+            if (nodes[i].nodeId === nodeId) {
+                node = nodes[i];
+                break;
+            }
+        }
+
+        logTestName("Check generating node");
+        
+        assert("Generating node was found", !!node, true);
+        assert("Generating node has expected localName", node.localName, "div");
+        assert("Generating node has id", node.attributes[0], "id");
+        assert("Generating node has expected id", node.attributes[1], "generator");
+        
+        InspectorTest.completeTest();
+    };
+
+    function setChildNodes (messageObject) {
+        nodes = messageObject.params.nodes;
+    };
+
+    function step(test)
+    {
+        if (test.callback)
+            logTestName(test.name);
+        runCommand(test);
+    };
+
+    function logTestName(name)
+    {
+        InspectorTest.log("\n=== " + name + " ===\n");
+    };
+
+    function runCommand(command)
+    {
+        InspectorTest.sendCommand(command.command, command.parameters, function(messageObject) {
+            if (messageObject.hasOwnProperty("error")) {
+                InspectorTest.log("FAIL: " + messageObject.error.message + " (" + messageObject.error.code + ")");
+                InspectorTest.completeTest();
+                return;
+            }
+
+            if (command.name)
+                InspectorTest.log("PASS");
+
+            if (command.callback)
+                command.callback(messageObject.result);
+        });
+    };
+
+    function assert(name, actual, expected)
+    {
+        if (expected === actual)
+            InspectorTest.log("PASS: " + name + ".");
+        else
+            InspectorTest.log("FAIL: " + name + ". Expected " + expected + " but got " + actual);
+    };
+
+};
+
+window.addEventListener("DOMContentLoaded", function()
+{
+    runTest();
+}, false);
+
+</script>
+<style type="text/css">
+      
+    #generator::before,
+    #generator::after {
+        position: absolute;
+        width: 100px;
+        height: 100px;
+        background-color: black;
+        -webkit-transform: translateZ(0);
+        content: "";
+    }
+
+    #generator::after {
+        -webkit-box-reflect:below 1px -webkit-gradient(linear, left top, left bottom, from(transparent), color-stop(0.5, transparent), to(white));
+    }
+
+</style>
+</head>
+<body>
+
+    <div id="generator"></div>
+
+</body>
+</html>

Modified: trunk/Source/WebCore/ChangeLog (145056 => 145057)


--- trunk/Source/WebCore/ChangeLog	2013-03-07 10:08:03 UTC (rev 145056)
+++ trunk/Source/WebCore/ChangeLog	2013-03-07 10:39:15 UTC (rev 145057)
@@ -1,3 +1,79 @@
+2013-03-07  Antoine Quint  <grao...@apple.com>
+
+        Web Inspector: identify layers for CSS generated content in LayerTreeAgent
+        https://bugs.webkit.org/show_bug.cgi?id=111551
+
+        Layers can be associated with pseudo elements, elements that are generated
+        when ::before or ::after pseudo-classes are used to style an element and
+        provide additional rendering using the CSS "content" property. In order to
+        identify that a layer is associated to a pseudo element, we add a new set of
+        optional properties on the Layer object: "isGeneratedContent", "pseudoElementId"
+        and "pseudoClass".
+
+        We need to provide the "pseudoElementId" for the same reason we provide a
+        "nodeId" for the Layer. This is so that the front-end can identify that a
+        layer whose "layerId" may have changed between two layer tree updates is
+        used to render content for the same pseudo element.
+
+        In the instance that a layer is rendering generated content, we also set
+        the "nodeId" to be the generating node's id. The generating node is the
+        node in the DOM that the user styled using ::before or ::after pseudo-classes.
+        We also add the pseudo-class used as the "pseudoClass" property such that the
+        front-end may provide useful information to the user about what type of
+        pseudo-class yielded the generation of this layer. We also deal with the
+        possibility that the layer is a reflection for a pseudo element.
+    
+        Since pseudo elements are not part of the user-visible DOM, and thus can't be
+        pushed to the front-end, we maintain a special ID hash map in the LayerTreeAgent.
+        In order to be able to unbind a pseudo element id and a pseudo element, we add a
+        destructor method to PseudoElement and provide a new instrumentation call so that
+        the LayerTreeAgent may be notified of a PseudoElement being destroyed. This
+        reflects the principle we use to update the RenderLayer bindings when a
+        RenderLayer is destroyed, as notified by the RenderLayerCompositor.
+
+        Reviewed by Simon Fraser.
+
+        Test: inspector-protocol/layers/layers-generated-content.html
+
+        * dom/PseudoElement.cpp:
+        (WebCore::PseudoElement::~PseudoElement): New destructor used to notify
+        InspectorInstrumentation of a PseudoElement being destroyed, such that
+        it can eventually be relayed to the InspectorLayerTreeAgent.
+        (WebCore):
+        * dom/PseudoElement.h:
+        (PseudoElement):
+        * inspector/Inspector.json: Add the new PseudoElementId type used for
+        the new "pseudoElementId" property on Layer, to which we also add the
+        "isGeneratedContent" and "pseudoClass" properties.
+        * inspector/InspectorInstrumentation.cpp:
+        (WebCore):
+        (WebCore::InspectorInstrumentation::pseudoElementDestroyedImpl):
+        * inspector/InspectorInstrumentation.h:
+        (WebCore):
+        (InspectorInstrumentation):
+        (WebCore::InspectorInstrumentation::pseudoElementDestroyed): New method
+        called in the PseudoElement destructor used to relay the fact that a
+        PseudoElement was destroyed to the InspectorLayerTreeAgent.
+        * inspector/InspectorLayerTreeAgent.cpp:
+        (WebCore::InspectorLayerTreeAgent::reset): Clear the new PseudoElement
+        identifier maps.
+        (WebCore::InspectorLayerTreeAgent::pseudoElementDestroyed): Remove any
+        identifier binding for the provided PseudoElement being destroyed.
+        (WebCore):
+        (WebCore::InspectorLayerTreeAgent::buildObjectForLayer): Set the new
+        "isGeneratedContent", "pseudoElementId" and "pseudoClass" properties on
+        the Layer object for layers associated with a pseudo element.
+        (WebCore::InspectorLayerTreeAgent::bind): Use emptyString() instead of "".
+        (WebCore::InspectorLayerTreeAgent::unbind): Use an iterator instead of a
+        get() and remove() combination in order to reduce lookups and mimick the
+        code written for unbindPseudoElement().
+        (WebCore::InspectorLayerTreeAgent::bindPseudoElement): Binds the provided
+        PseudoElement to a unique identifier.
+        (WebCore::InspectorLayerTreeAgent::unbindPseudoElement): Unbinds the
+        provided PseudoElement from its unique identifier.
+        * inspector/InspectorLayerTreeAgent.h:
+        (InspectorLayerTreeAgent):
+
 2013-03-07  Keishi Hattori  <kei...@webkit.org>
 
         Add clear button to date/time input types

Modified: trunk/Source/WebCore/dom/PseudoElement.cpp (145056 => 145057)


--- trunk/Source/WebCore/dom/PseudoElement.cpp	2013-03-07 10:08:03 UTC (rev 145056)
+++ trunk/Source/WebCore/dom/PseudoElement.cpp	2013-03-07 10:39:15 UTC (rev 145057)
@@ -28,6 +28,7 @@
 #include "PseudoElement.h"
 
 #include "ContentData.h"
+#include "InspectorInstrumentation.h"
 #include "NodeRenderingContext.h"
 #include "RenderObject.h"
 #include "RenderQuote.h"
@@ -63,6 +64,11 @@
     setHasCustomStyleCallbacks();
 }
 
+PseudoElement::~PseudoElement()
+{
+    InspectorInstrumentation::pseudoElementDestroyed(document()->page(), this);
+}
+
 PassRefPtr<RenderStyle> PseudoElement::customStyleForRenderer()
 {
     return parentOrShadowHostElement()->renderer()->getCachedPseudoStyle(m_pseudoId);

Modified: trunk/Source/WebCore/dom/PseudoElement.h (145056 => 145057)


--- trunk/Source/WebCore/dom/PseudoElement.h	2013-03-07 10:08:03 UTC (rev 145056)
+++ trunk/Source/WebCore/dom/PseudoElement.h	2013-03-07 10:39:15 UTC (rev 145057)
@@ -40,6 +40,7 @@
     {
         return adoptRef(new PseudoElement(parent, pseudoId));
     }
+    ~PseudoElement();
 
     virtual PassRefPtr<RenderStyle> customStyleForRenderer() OVERRIDE;
     virtual void attach() OVERRIDE;

Modified: trunk/Source/WebCore/inspector/Inspector.json (145056 => 145057)


--- trunk/Source/WebCore/inspector/Inspector.json	2013-03-07 10:08:03 UTC (rev 145056)
+++ trunk/Source/WebCore/inspector/Inspector.json	2013-03-07 10:39:15 UTC (rev 145057)
@@ -3646,6 +3646,11 @@
                 "description": "Unique RenderLayer identifier."
             },
             {
+                "id": "PseudoElementId",
+                "type": "string",
+                "description": "Unique PseudoElement identifier."
+            },
+            {
                 "id": "IntRect",
                 "type": "object",
                 "description": "A rectangle.",
@@ -3668,7 +3673,10 @@
                     { "name": "memory", "type": "integer", "description": "Estimated memory used by this layer." },
                     { "name": "compositedBounds", "$ref": "IntRect", "description": "The bounds of the composited layer." },
                     { "name": "isInShadowTree", "type": "boolean", "optional": true, "description": "Indicates whether this layer is associated with an element hosted in a shadow tree." },
-                    { "name": "isReflection", "type": "boolean", "optional": true, "description": "Indicates whether this layer was used to provide a reflection for the element." }
+                    { "name": "isReflection", "type": "boolean", "optional": true, "description": "Indicates whether this layer was used to provide a reflection for the element." },
+                    { "name": "isGeneratedContent", "type": "boolean", "optional": true, "description": "Indicates whether the layer is attached to a pseudo element that is CSS generated content." },
+                    { "name": "pseudoElementId", "$ref": "PseudoElementId", "optional": true, "description": "The id for the pseudo element associated with this layer." },
+                    { "name": "pseudoClass", "type": "string", "optional": true, "description": "The name of the CSS pseudo-class that prompted the layer's content to be generated." }
                 ]
             }
         ],

Modified: trunk/Source/WebCore/inspector/InspectorInstrumentation.cpp (145056 => 145057)


--- trunk/Source/WebCore/inspector/InspectorInstrumentation.cpp	2013-03-07 10:08:03 UTC (rev 145056)
+++ trunk/Source/WebCore/inspector/InspectorInstrumentation.cpp	2013-03-07 10:39:15 UTC (rev 145057)
@@ -1367,6 +1367,12 @@
     if (InspectorLayerTreeAgent* layerTreeAgent = instrumentingAgents->inspectorLayerTreeAgent())
         layerTreeAgent->renderLayerDestroyed(renderLayer);
 }
+
+void InspectorInstrumentation::pseudoElementDestroyedImpl(InstrumentingAgents* instrumentingAgents, PseudoElement* pseudoElement)
+{
+    if (InspectorLayerTreeAgent* layerTreeAgent = instrumentingAgents->inspectorLayerTreeAgent())
+        layerTreeAgent->pseudoElementDestroyed(pseudoElement);
+}
 #endif
 
 namespace InstrumentationEvents {

Modified: trunk/Source/WebCore/inspector/InspectorInstrumentation.h (145056 => 145057)


--- trunk/Source/WebCore/inspector/InspectorInstrumentation.h	2013-03-07 10:08:03 UTC (rev 145056)
+++ trunk/Source/WebCore/inspector/InspectorInstrumentation.h	2013-03-07 10:39:15 UTC (rev 145057)
@@ -70,6 +70,7 @@
 class InstrumentingAgents;
 class KURL;
 class Node;
+class PseudoElement;
 class RenderLayer;
 class RenderObject;
 class ResourceRequest;
@@ -310,6 +311,7 @@
 #if USE(ACCELERATED_COMPOSITING)
     static void layerTreeDidChange(Page*);
     static void renderLayerDestroyed(Page*, const RenderLayer*);
+    static void pseudoElementDestroyed(Page*, PseudoElement*);
 #endif
 
 private:
@@ -496,6 +498,7 @@
 #if USE(ACCELERATED_COMPOSITING)
     static void layerTreeDidChangeImpl(InstrumentingAgents*);
     static void renderLayerDestroyedImpl(InstrumentingAgents*, const RenderLayer*);
+    static void pseudoElementDestroyedImpl(InstrumentingAgents*, PseudoElement*);
 #endif
 
     static int s_frontendCounter;
@@ -2015,7 +2018,18 @@
     UNUSED_PARAM(renderLayer);
 #endif
 }
+
+inline void InspectorInstrumentation::pseudoElementDestroyed(Page* page, PseudoElement* pseudoElement)
+{
+#if ENABLE(INSPECTOR)
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForPage(page))
+        pseudoElementDestroyedImpl(instrumentingAgents, pseudoElement);
+#else
+    UNUSED_PARAM(page);
+    UNUSED_PARAM(pseudoElement);
 #endif
+}
+#endif
 
 #if ENABLE(INSPECTOR)
 inline bool InspectorInstrumentation::collectingHTMLParseErrors(Page* page)

Modified: trunk/Source/WebCore/inspector/InspectorLayerTreeAgent.cpp (145056 => 145057)


--- trunk/Source/WebCore/inspector/InspectorLayerTreeAgent.cpp	2013-03-07 10:08:03 UTC (rev 145056)
+++ trunk/Source/WebCore/inspector/InspectorLayerTreeAgent.cpp	2013-03-07 10:39:15 UTC (rev 145057)
@@ -41,6 +41,7 @@
 #include "InspectorState.h"
 #include "InstrumentingAgents.h"
 #include "IntRect.h"
+#include "PseudoElement.h"
 #include "RenderLayer.h"
 #include "RenderLayerBacking.h"
 #include "RenderView.h"
@@ -83,6 +84,8 @@
 {
     m_documentLayerToIdMap.clear();
     m_idToLayer.clear();
+    m_pseudoElementToIdMap.clear();
+    m_idToPseudoElement.clear();
 }
 
 void InspectorLayerTreeAgent::enable(ErrorString*)
@@ -109,6 +112,11 @@
     unbind(renderLayer);
 }
 
+void InspectorLayerTreeAgent::pseudoElementDestroyed(PseudoElement* pseudoElement)
+{
+    unbindPseudoElement(pseudoElement);
+}
+
 void InspectorLayerTreeAgent::layersForNode(ErrorString* errorString, int nodeId, RefPtr<TypeBuilder::Array<TypeBuilder::LayerTree::Layer> >& layers)
 {
     layers = TypeBuilder::Array<TypeBuilder::LayerTree::Layer>::create();
@@ -150,12 +158,20 @@
 
 PassRefPtr<TypeBuilder::LayerTree::Layer> InspectorLayerTreeAgent::buildObjectForLayer(ErrorString* errorString, RenderLayer* renderLayer)
 {
-    bool isReflection = renderLayer->isReflection();
-
     RenderObject* renderer = renderLayer->renderer();
     RenderLayerBacking* backing = renderLayer->backing();
-    Node* node = isReflection ? renderer->parent()->node() : renderer->node();
+    Node* node = renderer->node();
 
+    bool isReflection = renderLayer->isReflection();
+    bool isGenerated = (isReflection ? renderer->parent() : renderer)->isBeforeOrAfterContent();
+
+    if (isReflection && isGenerated)
+        node = renderer->parent()->generatingNode();
+    else if (isGenerated)
+        node = renderer->generatingNode();
+    else if (isReflection)
+        node = renderer->parent()->node();
+
     // Basic set of properties.
     RefPtr<TypeBuilder::LayerTree::Layer> layerObject = TypeBuilder::LayerTree::Layer::create()
         .setLayerId(bind(renderLayer))
@@ -171,6 +187,17 @@
     if (isReflection)
         layerObject->setIsReflection(true);
 
+    if (isGenerated) {
+        if (isReflection)
+            renderer = renderer->parent();
+        layerObject->setIsGeneratedContent(true);
+        layerObject->setPseudoElementId(bindPseudoElement(static_cast<PseudoElement*>(renderer->node())));
+        if (renderer->isBeforeContent())
+            layerObject->setPseudoClass("before");
+        else if (renderer->isAfterContent())
+            layerObject->setPseudoClass("after");
+    }
+
     return layerObject;
 }
 
@@ -197,7 +224,7 @@
 String InspectorLayerTreeAgent::bind(const RenderLayer* layer)
 {
     if (!layer)
-        return "";
+        return emptyString();
     String identifier = m_documentLayerToIdMap.get(layer);
     if (identifier.isNull()) {
         identifier = IdentifiersFactory::createIdentifier();
@@ -209,14 +236,35 @@
 
 void InspectorLayerTreeAgent::unbind(const RenderLayer* layer)
 {
-    String identifier = m_documentLayerToIdMap.get(layer);
-    if (identifier.isNull())
+    HashMap<const RenderLayer*, String>::iterator iterator = m_documentLayerToIdMap.find(layer);
+    if (iterator == m_documentLayerToIdMap.end())
         return;
+    m_idToLayer.remove(iterator->value);
+    m_documentLayerToIdMap.remove(iterator);
+}
 
-    m_documentLayerToIdMap.remove(layer);
-    m_idToLayer.remove(identifier);
+String InspectorLayerTreeAgent::bindPseudoElement(PseudoElement* pseudoElement)
+{
+    if (!pseudoElement)
+        return emptyString();
+    String identifier = m_pseudoElementToIdMap.get(pseudoElement);
+    if (identifier.isNull()) {
+        identifier = IdentifiersFactory::createIdentifier();
+        m_pseudoElementToIdMap.set(pseudoElement, identifier);
+        m_idToPseudoElement.set(identifier, pseudoElement);
+    }
+    return identifier;
 }
 
+void InspectorLayerTreeAgent::unbindPseudoElement(PseudoElement* pseudoElement)
+{
+    HashMap<PseudoElement*, String>::iterator iterator = m_pseudoElementToIdMap.find(pseudoElement);
+    if (iterator == m_pseudoElementToIdMap.end())
+        return;
+    m_idToPseudoElement.remove(iterator->value);
+    m_pseudoElementToIdMap.remove(iterator);
+}
+
 } // namespace WebCore
 
 #endif // ENABLE(INSPECTOR)

Modified: trunk/Source/WebCore/inspector/InspectorLayerTreeAgent.h (145056 => 145057)


--- trunk/Source/WebCore/inspector/InspectorLayerTreeAgent.h	2013-03-07 10:08:03 UTC (rev 145056)
+++ trunk/Source/WebCore/inspector/InspectorLayerTreeAgent.h	2013-03-07 10:39:15 UTC (rev 145057)
@@ -62,6 +62,7 @@
 
     void layerTreeDidChange();
     void renderLayerDestroyed(const RenderLayer*);
+    void pseudoElementDestroyed(PseudoElement*);
 
     // Called from the front-end.
     virtual void enable(ErrorString*);
@@ -82,11 +83,17 @@
     PassRefPtr<TypeBuilder::LayerTree::IntRect> buildObjectForIntRect(const IntRect&);
 
     int idForNode(ErrorString*, Node*);
-        
+
+    String bindPseudoElement(PseudoElement*);
+    void unbindPseudoElement(PseudoElement*);
+
     InspectorFrontend::LayerTree* m_frontend;
 
     HashMap<const RenderLayer*, String> m_documentLayerToIdMap;
     HashMap<String, const RenderLayer*> m_idToLayer;
+
+    HashMap<PseudoElement*, String> m_pseudoElementToIdMap;
+    HashMap<String, PseudoElement*> m_idToPseudoElement;
 };
 
 } // namespace WebCore
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to