Web Inspector: Make InspectorState instances per-agent, corresponding to JSON map...
[WebKit-https.git] / Source / WebCore / inspector / InspectorLayerTreeAgent.cpp
1 /*
2  * Copyright (C) 2012 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  *     * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *     * Redistributions in binary form must reproduce the above
11  * copyright notice, this list of conditions and the following disclaimer
12  * in the documentation and/or other materials provided with the
13  * distribution.
14  *     * Neither the name of Google Inc. nor the names of its
15  * contributors may be used to endorse or promote products derived from
16  * this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30
31 #include "config.h"
32
33 #if USE(ACCELERATED_COMPOSITING)
34 #if ENABLE(INSPECTOR)
35
36 #include "InspectorLayerTreeAgent.h"
37
38 #include "IdentifiersFactory.h"
39 #include "InspectorDOMAgent.h"
40 #include "InspectorFrontend.h"
41 #include "InspectorState.h"
42 #include "InstrumentingAgents.h"
43 #include "IntRect.h"
44 #include "Page.h"
45 #include "RenderLayer.h"
46 #include "RenderLayerBacking.h"
47 #include "RenderLayerCompositor.h"
48 #include "RenderView.h"
49
50 namespace WebCore {
51
52 namespace LayerTreeAgentState {
53 static const char layerTreeAgentEnabled[] = "layerTreeAgentEnabled";
54 };
55
56 InspectorLayerTreeAgent::InspectorLayerTreeAgent(InstrumentingAgents* instrumentingAgents, InspectorCompositeState* state, Page* page)
57     : InspectorBaseAgent<InspectorLayerTreeAgent>("LayerTree", instrumentingAgents, state)
58     , m_inspectedPage(page)
59     , m_frontend(0)
60 {
61 }
62
63 InspectorLayerTreeAgent::~InspectorLayerTreeAgent()
64 {
65     reset();
66 }
67
68 void InspectorLayerTreeAgent::setFrontend(InspectorFrontend* frontend)
69 {
70     m_frontend = frontend->layertree();
71 }
72
73 void InspectorLayerTreeAgent::clearFrontend()
74 {
75     m_frontend = 0;
76     disable(0);
77 }
78
79 void InspectorLayerTreeAgent::restore()
80 {
81     if (m_state->getBoolean(LayerTreeAgentState::layerTreeAgentEnabled))
82         enable(0);
83 }
84
85 void InspectorLayerTreeAgent::reset()
86 {
87     m_documentLayerToIdMap.clear();
88     m_idToLayer.clear();
89 }
90
91 void InspectorLayerTreeAgent::enable(ErrorString*)
92 {
93     m_state->setBoolean(LayerTreeAgentState::layerTreeAgentEnabled, true);
94     m_instrumentingAgents->setInspectorLayerTreeAgent(this);
95 }
96
97 void InspectorLayerTreeAgent::disable(ErrorString*)
98 {
99     if (!m_state->getBoolean(LayerTreeAgentState::layerTreeAgentEnabled))
100         return;
101     m_state->setBoolean(LayerTreeAgentState::layerTreeAgentEnabled, false);
102     m_instrumentingAgents->setInspectorLayerTreeAgent(0);
103 }
104
105 void InspectorLayerTreeAgent::layerTreeDidChange()
106 {
107     m_frontend->layerTreeDidChange();
108 }
109
110 void InspectorLayerTreeAgent::renderLayerDestroyed(const RenderLayer* renderLayer)
111 {
112     unbind(renderLayer);
113 }
114
115 void InspectorLayerTreeAgent::getLayerTree(ErrorString*, RefPtr<TypeBuilder::LayerTree::Layer>& object)
116 {
117     object = buildObjectForRootLayer();
118 }
119
120 PassRefPtr<TypeBuilder::LayerTree::Layer> InspectorLayerTreeAgent::buildObjectForRootLayer()
121 {
122     return buildObjectForLayer(m_inspectedPage->mainFrame()->contentRenderer()->compositor()->rootRenderLayer());
123 }
124
125 PassRefPtr<TypeBuilder::LayerTree::Layer> InspectorLayerTreeAgent::buildObjectForLayer(RenderLayer* renderLayer)
126 {
127     bool isComposited = renderLayer->isComposited();
128
129     // Basic set of properties.
130     RefPtr<TypeBuilder::LayerTree::Layer> layerObject = TypeBuilder::LayerTree::Layer::create()
131         .setLayerId(bind(renderLayer))
132         .setBounds(buildObjectForIntRect(enclosingIntRect(renderLayer->localBoundingBox())))
133         .setIsComposited(isComposited);
134
135     // Optional properties for composited layers only.
136     if (isComposited) {
137         RenderLayerBacking* backing = renderLayer->backing();
138         layerObject->setMemory(backing->backingStoreMemoryEstimate());
139         layerObject->setCompositedBounds(buildObjectForIntRect(backing->compositedBounds()));
140         layerObject->setPaintCount(backing->graphicsLayer()->repaintCount());
141     }
142
143     // Process children layers.
144     RefPtr<TypeBuilder::Array<TypeBuilder::LayerTree::Layer> > childrenArray = TypeBuilder::Array<TypeBuilder::LayerTree::Layer>::create();
145
146     renderLayer->updateLayerListsIfNeeded();
147
148     // Check if we have a reflection layer.
149     if (renderLayer->reflectionLayer())
150         childrenArray->addItem(buildObjectForLayer(renderLayer->reflectionLayer()));
151
152     if (renderLayer->isStackingContext()) {
153         if (Vector<RenderLayer*>* negZOrderList = renderLayer->negZOrderList()) {
154             size_t listSize = negZOrderList->size();
155             for (size_t i = 0; i < listSize; ++i)
156                 childrenArray->addItem(buildObjectForLayer(negZOrderList->at(i)));
157         }
158     }
159
160     if (Vector<RenderLayer*>* normalFlowList = renderLayer->normalFlowList()) {
161         size_t listSize = normalFlowList->size();
162         for (size_t i = 0; i < listSize; ++i)
163             childrenArray->addItem(buildObjectForLayer(normalFlowList->at(i)));
164     }
165     
166     if (renderLayer->isStackingContext()) {
167         if (Vector<RenderLayer*>* posZOrderList = renderLayer->posZOrderList()) {
168             size_t listSize = posZOrderList->size();
169             for (size_t i = 0; i < listSize; ++i)
170                 childrenArray->addItem(buildObjectForLayer(posZOrderList->at(i)));
171         }
172     }
173
174     layerObject->setChildLayers(childrenArray);
175     
176     return layerObject;
177 }
178
179 PassRefPtr<TypeBuilder::LayerTree::IntRect> InspectorLayerTreeAgent::buildObjectForIntRect(const IntRect& rect)
180 {
181     return TypeBuilder::LayerTree::IntRect::create()
182         .setX(rect.x())
183         .setY(rect.y())
184         .setWidth(rect.width())
185         .setHeight(rect.height()).release();
186 }
187
188 String InspectorLayerTreeAgent::bind(const RenderLayer* layer)
189 {
190     if (!layer)
191         return "";
192     String identifier = m_documentLayerToIdMap.get(layer);
193     if (identifier.isNull()) {
194         identifier = IdentifiersFactory::createIdentifier();
195         m_documentLayerToIdMap.set(layer, identifier);
196         m_idToLayer.set(identifier, layer);
197     }
198     return identifier;
199 }
200
201 void InspectorLayerTreeAgent::unbind(const RenderLayer* layer)
202 {
203     String identifier = m_documentLayerToIdMap.get(layer);
204     if (identifier.isNull())
205         return;
206
207     m_documentLayerToIdMap.remove(layer);
208     m_idToLayer.remove(identifier);
209 }
210
211 void InspectorLayerTreeAgent::nodeIdForLayerId(ErrorString* errorString, const String& layerId, int* resultNodeId)
212 {
213     // Obtain the RenderLayer from the identifier provided.
214     const RenderLayer* renderLayer = m_idToLayer.get(layerId);
215     
216     // Send an error if there is no such registered layer id.
217     if (!renderLayer) {
218         *errorString = "Could not find a bound layer for the provided id";
219         return;
220     }
221     
222     // Get the node id from the DOM agent and return it to the front-end.
223     InspectorDOMAgent* inspectorDOMAgent = m_instrumentingAgents->inspectorDOMAgent();
224     *resultNodeId = inspectorDOMAgent->pushNodePathForRenderLayerToFrontend(renderLayer);
225 }
226
227 } // namespace WebCore
228
229 #endif // ENABLE(INSPECTOR)
230 #endif // USE(ACCELERATED_COMPOSITING)