Misc Inspector backend cleanup
[WebKit-https.git] / Source / WebCore / inspector / InspectorLayerTreeAgent.cpp
1 /*
2  * Copyright (C) 2012, 2015 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 #include "InspectorLayerTreeAgent.h"
33
34 #include "InspectorDOMAgent.h"
35 #include "InstrumentingAgents.h"
36 #include "IntRect.h"
37 #include "PseudoElement.h"
38 #include "RenderChildIterator.h"
39 #include "RenderLayer.h"
40 #include "RenderLayerBacking.h"
41 #include "RenderLayerCompositor.h"
42 #include "RenderView.h"
43 #include <inspector/IdentifiersFactory.h>
44
45 using namespace Inspector;
46
47 namespace WebCore {
48
49 InspectorLayerTreeAgent::InspectorLayerTreeAgent(WebAgentContext& context)
50     : InspectorAgentBase(ASCIILiteral("LayerTree"), context)
51     , m_frontendDispatcher(std::make_unique<Inspector::LayerTreeFrontendDispatcher>(context.frontendRouter))
52     , m_backendDispatcher(Inspector::LayerTreeBackendDispatcher::create(context.backendDispatcher, this))
53 {
54 }
55
56 InspectorLayerTreeAgent::~InspectorLayerTreeAgent()
57 {
58     reset();
59 }
60
61 void InspectorLayerTreeAgent::didCreateFrontendAndBackend(Inspector::FrontendRouter*, Inspector::BackendDispatcher*)
62 {
63 }
64
65 void InspectorLayerTreeAgent::willDestroyFrontendAndBackend(Inspector::DisconnectReason)
66 {
67     ErrorString unused;
68     disable(unused);
69 }
70
71 void InspectorLayerTreeAgent::reset()
72 {
73     m_documentLayerToIdMap.clear();
74     m_idToLayer.clear();
75     m_pseudoElementToIdMap.clear();
76     m_idToPseudoElement.clear();
77 }
78
79 void InspectorLayerTreeAgent::enable(ErrorString&)
80 {
81     m_instrumentingAgents.setInspectorLayerTreeAgent(this);
82 }
83
84 void InspectorLayerTreeAgent::disable(ErrorString&)
85 {
86     m_instrumentingAgents.setInspectorLayerTreeAgent(nullptr);
87 }
88
89 void InspectorLayerTreeAgent::layerTreeDidChange()
90 {
91     m_frontendDispatcher->layerTreeDidChange();
92 }
93
94 void InspectorLayerTreeAgent::renderLayerDestroyed(const RenderLayer& renderLayer)
95 {
96     unbind(&renderLayer);
97 }
98
99 void InspectorLayerTreeAgent::pseudoElementDestroyed(PseudoElement& pseudoElement)
100 {
101     unbindPseudoElement(&pseudoElement);
102 }
103
104 void InspectorLayerTreeAgent::layersForNode(ErrorString& errorString, int nodeId, RefPtr<Inspector::Protocol::Array<Inspector::Protocol::LayerTree::Layer>>& layers)
105 {
106     layers = Inspector::Protocol::Array<Inspector::Protocol::LayerTree::Layer>::create();
107
108     auto* node = m_instrumentingAgents.inspectorDOMAgent()->nodeForId(nodeId);
109     if (!node) {
110         errorString = ASCIILiteral("Provided node id doesn't match any known node");
111         return;
112     }
113
114     auto* renderer = node->renderer();
115     if (!renderer) {
116         errorString = ASCIILiteral("Node for provided node id doesn't have a renderer");
117         return;
118     }
119
120     if (is<RenderElement>(*renderer))
121         gatherLayersUsingRenderObjectHierarchy(errorString, downcast<RenderElement>(*renderer), layers);
122 }
123
124 void InspectorLayerTreeAgent::gatherLayersUsingRenderObjectHierarchy(ErrorString& errorString, RenderElement& renderer, RefPtr<Inspector::Protocol::Array<Inspector::Protocol::LayerTree::Layer>>& layers)
125 {
126     if (renderer.hasLayer()) {
127         gatherLayersUsingRenderLayerHierarchy(errorString, downcast<RenderLayerModelObject>(renderer).layer(), layers);
128         return;
129     }
130
131     for (auto& child : childrenOfType<RenderElement>(renderer))
132         gatherLayersUsingRenderObjectHierarchy(errorString, child, layers);
133 }
134
135 void InspectorLayerTreeAgent::gatherLayersUsingRenderLayerHierarchy(ErrorString& errorString, RenderLayer* renderLayer, RefPtr<Inspector::Protocol::Array<Inspector::Protocol::LayerTree::Layer>>& layers)
136 {
137     if (renderLayer->isComposited())
138         layers->addItem(buildObjectForLayer(errorString, renderLayer));
139
140     for (renderLayer = renderLayer->firstChild(); renderLayer; renderLayer = renderLayer->nextSibling())
141         gatherLayersUsingRenderLayerHierarchy(errorString, renderLayer, layers);
142 }
143
144 Ref<Inspector::Protocol::LayerTree::Layer> InspectorLayerTreeAgent::buildObjectForLayer(ErrorString& errorString, RenderLayer* renderLayer)
145 {
146     RenderObject* renderer = &renderLayer->renderer();
147     RenderLayerBacking* backing = renderLayer->backing();
148     Node* node = renderer->node();
149
150     bool isReflection = renderLayer->isReflection();
151     bool isGenerated = (isReflection ? renderer->parent() : renderer)->isBeforeOrAfterContent();
152     bool isAnonymous = renderer->isAnonymous();
153
154     if (renderer->isRenderView())
155         node = &renderer->document();
156     else if (isReflection && isGenerated)
157         node = renderer->parent()->generatingElement();
158     else if (isGenerated)
159         node = renderer->generatingNode();
160     else if (isReflection || isAnonymous)
161         node = renderer->parent()->element();
162
163     // Basic set of properties.
164     auto layerObject = Inspector::Protocol::LayerTree::Layer::create()
165         .setLayerId(bind(renderLayer))
166         .setNodeId(idForNode(errorString, node))
167         .setBounds(buildObjectForIntRect(renderer->absoluteBoundingBoxRect()))
168         .setMemory(backing->backingStoreMemoryEstimate())
169         .setCompositedBounds(buildObjectForIntRect(enclosingIntRect(backing->compositedBounds())))
170         .setPaintCount(backing->graphicsLayer()->repaintCount())
171         .release();
172
173     if (node && node->shadowHost())
174         layerObject->setIsInShadowTree(true);
175
176     if (isReflection)
177         layerObject->setIsReflection(true);
178
179     if (isGenerated) {
180         if (isReflection)
181             renderer = renderer->parent();
182         layerObject->setIsGeneratedContent(true);
183         layerObject->setPseudoElementId(bindPseudoElement(downcast<PseudoElement>(renderer->node())));
184         if (renderer->isBeforeContent())
185             layerObject->setPseudoElement("before");
186         else if (renderer->isAfterContent())
187             layerObject->setPseudoElement("after");
188     }
189
190     // FIXME: RenderView is now really anonymous but don't tell about it to the frontend before making sure it can handle it.
191     if (isAnonymous && !renderer->isRenderView()) {
192         layerObject->setIsAnonymous(true);
193         const RenderStyle& style = renderer->style();
194         if (style.styleType() == FIRST_LETTER)
195             layerObject->setPseudoElement("first-letter");
196         else if (style.styleType() == FIRST_LINE)
197             layerObject->setPseudoElement("first-line");
198     }
199
200     return layerObject;
201 }
202
203 int InspectorLayerTreeAgent::idForNode(ErrorString& errorString, Node* node)
204 {
205     if (!node)
206         return 0;
207
208     InspectorDOMAgent* domAgent = m_instrumentingAgents.inspectorDOMAgent();
209     
210     int nodeId = domAgent->boundNodeId(node);
211     if (!nodeId)
212         nodeId = domAgent->pushNodeToFrontend(errorString, domAgent->boundNodeId(&node->document()), node);
213
214     return nodeId;
215 }
216
217 Ref<Inspector::Protocol::LayerTree::IntRect> InspectorLayerTreeAgent::buildObjectForIntRect(const IntRect& rect)
218 {
219     return Inspector::Protocol::LayerTree::IntRect::create()
220         .setX(rect.x())
221         .setY(rect.y())
222         .setWidth(rect.width())
223         .setHeight(rect.height())
224         .release();
225 }
226
227 void InspectorLayerTreeAgent::reasonsForCompositingLayer(ErrorString& errorString, const String& layerId, RefPtr<Inspector::Protocol::LayerTree::CompositingReasons>& compositingReasonsResult)
228 {
229     const RenderLayer* renderLayer = m_idToLayer.get(layerId);
230
231     if (!renderLayer) {
232         errorString = ASCIILiteral("Could not find a bound layer for the provided id");
233         return;
234     }
235
236     CompositingReasons reasonsBitmask = renderLayer->compositor().reasonsForCompositing(*renderLayer);
237     auto compositingReasons = Inspector::Protocol::LayerTree::CompositingReasons::create().release();
238
239     if (reasonsBitmask & CompositingReason3DTransform)
240         compositingReasons->setTransform3D(true);
241
242     if (reasonsBitmask & CompositingReasonVideo)
243         compositingReasons->setVideo(true);
244     else if (reasonsBitmask & CompositingReasonCanvas)
245         compositingReasons->setCanvas(true);
246     else if (reasonsBitmask & CompositingReasonPlugin)
247         compositingReasons->setPlugin(true);
248     else if (reasonsBitmask & CompositingReasonIFrame)
249         compositingReasons->setIFrame(true);
250     
251     if (reasonsBitmask & CompositingReasonBackfaceVisibilityHidden)
252         compositingReasons->setBackfaceVisibilityHidden(true);
253
254     if (reasonsBitmask & CompositingReasonClipsCompositingDescendants)
255         compositingReasons->setClipsCompositingDescendants(true);
256
257     if (reasonsBitmask & CompositingReasonAnimation)
258         compositingReasons->setAnimation(true);
259
260     if (reasonsBitmask & CompositingReasonFilters)
261         compositingReasons->setFilters(true);
262
263     if (reasonsBitmask & CompositingReasonPositionFixed)
264         compositingReasons->setPositionFixed(true);
265
266     if (reasonsBitmask & CompositingReasonPositionSticky)
267         compositingReasons->setPositionSticky(true);
268
269     if (reasonsBitmask & CompositingReasonOverflowScrollingTouch)
270         compositingReasons->setOverflowScrollingTouch(true);
271
272     if (reasonsBitmask & CompositingReasonStacking)
273         compositingReasons->setStacking(true);
274
275     if (reasonsBitmask & CompositingReasonOverlap)
276         compositingReasons->setOverlap(true);
277
278     if (reasonsBitmask & CompositingReasonNegativeZIndexChildren)
279         compositingReasons->setNegativeZIndexChildren(true);
280
281     if (reasonsBitmask & CompositingReasonTransformWithCompositedDescendants)
282         compositingReasons->setTransformWithCompositedDescendants(true);
283
284     if (reasonsBitmask & CompositingReasonOpacityWithCompositedDescendants)
285         compositingReasons->setOpacityWithCompositedDescendants(true);
286
287     if (reasonsBitmask & CompositingReasonMaskWithCompositedDescendants)
288         compositingReasons->setMaskWithCompositedDescendants(true);
289
290     if (reasonsBitmask & CompositingReasonReflectionWithCompositedDescendants)
291         compositingReasons->setReflectionWithCompositedDescendants(true);
292
293     if (reasonsBitmask & CompositingReasonFilterWithCompositedDescendants)
294         compositingReasons->setFilterWithCompositedDescendants(true);
295
296     if (reasonsBitmask & CompositingReasonBlendingWithCompositedDescendants)
297         compositingReasons->setBlendingWithCompositedDescendants(true);
298
299     if (reasonsBitmask & CompositingReasonIsolatesCompositedBlendingDescendants)
300         compositingReasons->setIsolatesCompositedBlendingDescendants(true);
301
302     if (reasonsBitmask & CompositingReasonPerspective)
303         compositingReasons->setPerspective(true);
304
305     if (reasonsBitmask & CompositingReasonPreserve3D)
306         compositingReasons->setPreserve3D(true);
307
308     if (reasonsBitmask & CompositingReasonWillChange)
309         compositingReasons->setWillChange(true);
310
311     if (reasonsBitmask & CompositingReasonRoot)
312         compositingReasons->setRoot(true);
313     
314     compositingReasonsResult = WTFMove(compositingReasons);
315 }
316
317 String InspectorLayerTreeAgent::bind(const RenderLayer* layer)
318 {
319     if (!layer)
320         return emptyString();
321     String identifier = m_documentLayerToIdMap.get(layer);
322     if (identifier.isNull()) {
323         identifier = IdentifiersFactory::createIdentifier();
324         m_documentLayerToIdMap.set(layer, identifier);
325         m_idToLayer.set(identifier, layer);
326     }
327     return identifier;
328 }
329
330 void InspectorLayerTreeAgent::unbind(const RenderLayer* layer)
331 {
332     HashMap<const RenderLayer*, String>::iterator iterator = m_documentLayerToIdMap.find(layer);
333     if (iterator == m_documentLayerToIdMap.end())
334         return;
335     m_idToLayer.remove(iterator->value);
336     m_documentLayerToIdMap.remove(iterator);
337 }
338
339 String InspectorLayerTreeAgent::bindPseudoElement(PseudoElement* pseudoElement)
340 {
341     if (!pseudoElement)
342         return emptyString();
343     String identifier = m_pseudoElementToIdMap.get(pseudoElement);
344     if (identifier.isNull()) {
345         identifier = IdentifiersFactory::createIdentifier();
346         m_pseudoElementToIdMap.set(pseudoElement, identifier);
347         m_idToPseudoElement.set(identifier, pseudoElement);
348     }
349     return identifier;
350 }
351
352 void InspectorLayerTreeAgent::unbindPseudoElement(PseudoElement* pseudoElement)
353 {
354     HashMap<PseudoElement*, String>::iterator iterator = m_pseudoElementToIdMap.find(pseudoElement);
355     if (iterator == m_pseudoElementToIdMap.end())
356         return;
357     m_idToPseudoElement.remove(iterator->value);
358     m_pseudoElementToIdMap.remove(iterator);
359 }
360
361 } // namespace WebCore