Keyframe animation doesn't 't show up in the Animations timeline
[WebKit-https.git] / Source / WebCore / inspector / agents / InspectorLayerTreeAgent.cpp
1 /*
2  * Copyright (C) 2012-2017 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 <JavaScriptCore/IdentifiersFactory.h>
44
45 namespace WebCore {
46
47 using namespace Inspector;
48
49 InspectorLayerTreeAgent::InspectorLayerTreeAgent(WebAgentContext& context)
50     : InspectorAgentBase("LayerTree"_s, context)
51     , m_frontendDispatcher(makeUnique<Inspector::LayerTreeFrontendDispatcher>(context.frontendRouter))
52     , m_backendDispatcher(Inspector::LayerTreeBackendDispatcher::create(context.backendDispatcher, this))
53 {
54 }
55
56 InspectorLayerTreeAgent::~InspectorLayerTreeAgent() = default;
57
58 void InspectorLayerTreeAgent::didCreateFrontendAndBackend(Inspector::FrontendRouter*, Inspector::BackendDispatcher*)
59 {
60 }
61
62 void InspectorLayerTreeAgent::willDestroyFrontendAndBackend(Inspector::DisconnectReason)
63 {
64     ErrorString ignored;
65     disable(ignored);
66 }
67
68 void InspectorLayerTreeAgent::reset()
69 {
70     m_documentLayerToIdMap.clear();
71     m_idToLayer.clear();
72     m_pseudoElementToIdMap.clear();
73     m_idToPseudoElement.clear();
74     m_suppressLayerChangeEvents = false;
75 }
76
77 void InspectorLayerTreeAgent::enable(ErrorString&)
78 {
79     m_instrumentingAgents.setEnabledLayerTreeAgent(this);
80 }
81
82 void InspectorLayerTreeAgent::disable(ErrorString&)
83 {
84     m_instrumentingAgents.setEnabledLayerTreeAgent(nullptr);
85
86     reset();
87 }
88
89 void InspectorLayerTreeAgent::layerTreeDidChange()
90 {
91     if (m_suppressLayerChangeEvents)
92         return;
93
94     m_suppressLayerChangeEvents = true;
95
96     m_frontendDispatcher->layerTreeDidChange();
97 }
98
99 void InspectorLayerTreeAgent::renderLayerDestroyed(const RenderLayer& renderLayer)
100 {
101     unbind(&renderLayer);
102 }
103
104 void InspectorLayerTreeAgent::pseudoElementDestroyed(PseudoElement& pseudoElement)
105 {
106     unbindPseudoElement(&pseudoElement);
107 }
108
109 void InspectorLayerTreeAgent::layersForNode(ErrorString& errorString, int nodeId, RefPtr<JSON::ArrayOf<Inspector::Protocol::LayerTree::Layer>>& layers)
110 {
111     layers = JSON::ArrayOf<Inspector::Protocol::LayerTree::Layer>::create();
112
113     auto* node = m_instrumentingAgents.persistentDOMAgent()->nodeForId(nodeId);
114     if (!node) {
115         errorString = "Missing node for given nodeId"_s;
116         return;
117     }
118
119     auto* renderer = node->renderer();
120     if (!renderer) {
121         errorString = "Missing renderer of node for given nodeId"_s;
122         return;
123     }
124
125     if (!is<RenderElement>(*renderer))
126         return;
127
128     gatherLayersUsingRenderObjectHierarchy(errorString, downcast<RenderElement>(*renderer), layers);
129
130     m_suppressLayerChangeEvents = false;
131 }
132
133 void InspectorLayerTreeAgent::gatherLayersUsingRenderObjectHierarchy(ErrorString& errorString, RenderElement& renderer, RefPtr<JSON::ArrayOf<Inspector::Protocol::LayerTree::Layer>>& layers)
134 {
135     if (renderer.hasLayer()) {
136         gatherLayersUsingRenderLayerHierarchy(errorString, downcast<RenderLayerModelObject>(renderer).layer(), layers);
137         return;
138     }
139
140     for (auto& child : childrenOfType<RenderElement>(renderer))
141         gatherLayersUsingRenderObjectHierarchy(errorString, child, layers);
142 }
143
144 void InspectorLayerTreeAgent::gatherLayersUsingRenderLayerHierarchy(ErrorString& errorString, RenderLayer* renderLayer, RefPtr<JSON::ArrayOf<Inspector::Protocol::LayerTree::Layer>>& layers)
145 {
146     if (renderLayer->isComposited())
147         layers->addItem(buildObjectForLayer(errorString, renderLayer));
148
149     for (renderLayer = renderLayer->firstChild(); renderLayer; renderLayer = renderLayer->nextSibling())
150         gatherLayersUsingRenderLayerHierarchy(errorString, renderLayer, layers);
151 }
152
153 Ref<Inspector::Protocol::LayerTree::Layer> InspectorLayerTreeAgent::buildObjectForLayer(ErrorString& errorString, RenderLayer* renderLayer)
154 {
155     RenderObject* renderer = &renderLayer->renderer();
156     RenderLayerBacking* backing = renderLayer->backing();
157     Node* node = renderer->node();
158
159     bool isReflection = renderLayer->isReflection();
160     bool isGenerated = (isReflection ? renderer->parent() : renderer)->isBeforeOrAfterContent();
161     bool isAnonymous = renderer->isAnonymous();
162
163     if (renderer->isRenderView())
164         node = &renderer->document();
165     else if (isReflection && isGenerated)
166         node = renderer->parent()->generatingElement();
167     else if (isGenerated)
168         node = renderer->generatingNode();
169     else if (isReflection || isAnonymous)
170         node = renderer->parent()->element();
171
172     // Basic set of properties.
173     auto layerObject = Inspector::Protocol::LayerTree::Layer::create()
174         .setLayerId(bind(renderLayer))
175         .setNodeId(idForNode(errorString, node))
176         .setBounds(buildObjectForIntRect(renderer->absoluteBoundingBoxRect()))
177         .setMemory(backing->backingStoreMemoryEstimate())
178         .setCompositedBounds(buildObjectForIntRect(enclosingIntRect(backing->compositedBounds())))
179         .setPaintCount(backing->graphicsLayer()->repaintCount())
180         .release();
181
182     if (node && node->shadowHost())
183         layerObject->setIsInShadowTree(true);
184
185     if (isReflection)
186         layerObject->setIsReflection(true);
187
188     if (isGenerated) {
189         if (isReflection)
190             renderer = renderer->parent();
191         layerObject->setIsGeneratedContent(true);
192         layerObject->setPseudoElementId(bindPseudoElement(downcast<PseudoElement>(renderer->node())));
193         if (renderer->isBeforeContent())
194             layerObject->setPseudoElement("before");
195         else if (renderer->isAfterContent())
196             layerObject->setPseudoElement("after");
197     }
198
199     // FIXME: RenderView is now really anonymous but don't tell about it to the frontend before making sure it can handle it.
200     if (isAnonymous && !renderer->isRenderView()) {
201         layerObject->setIsAnonymous(true);
202         const RenderStyle& style = renderer->style();
203         if (style.styleType() == PseudoId::FirstLetter)
204             layerObject->setPseudoElement("first-letter");
205         else if (style.styleType() == PseudoId::FirstLine)
206             layerObject->setPseudoElement("first-line");
207     }
208
209     return layerObject;
210 }
211
212 int InspectorLayerTreeAgent::idForNode(ErrorString& errorString, Node* node)
213 {
214     if (!node)
215         return 0;
216
217     InspectorDOMAgent* domAgent = m_instrumentingAgents.persistentDOMAgent();
218     
219     int nodeId = domAgent->boundNodeId(node);
220     if (!nodeId) {
221         // FIXME: <https://webkit.org/b/213499> Web Inspector: allow DOM nodes to be instrumented at any point, regardless of whether the main document has also been instrumented
222         nodeId = domAgent->pushNodeToFrontend(errorString, domAgent->boundNodeId(&node->document()), node);
223     }
224
225     return nodeId;
226 }
227
228 Ref<Inspector::Protocol::LayerTree::IntRect> InspectorLayerTreeAgent::buildObjectForIntRect(const IntRect& rect)
229 {
230     return Inspector::Protocol::LayerTree::IntRect::create()
231         .setX(rect.x())
232         .setY(rect.y())
233         .setWidth(rect.width())
234         .setHeight(rect.height())
235         .release();
236 }
237
238 void InspectorLayerTreeAgent::reasonsForCompositingLayer(ErrorString& errorString, const String& layerId, RefPtr<Inspector::Protocol::LayerTree::CompositingReasons>& compositingReasonsResult)
239 {
240     const RenderLayer* renderLayer = m_idToLayer.get(layerId);
241
242     if (!renderLayer) {
243         errorString = "Missing render layer for given layerId"_s;
244         return;
245     }
246
247     OptionSet<CompositingReason> reasons = renderLayer->compositor().reasonsForCompositing(*renderLayer);
248     auto compositingReasons = Inspector::Protocol::LayerTree::CompositingReasons::create().release();
249
250     if (reasons.contains(CompositingReason::Transform3D))
251         compositingReasons->setTransform3D(true);
252
253     if (reasons.contains(CompositingReason::Video))
254         compositingReasons->setVideo(true);
255     else if (reasons.contains(CompositingReason::Canvas))
256         compositingReasons->setCanvas(true);
257     else if (reasons.contains(CompositingReason::Plugin))
258         compositingReasons->setPlugin(true);
259     else if (reasons.contains(CompositingReason::IFrame))
260         compositingReasons->setIFrame(true);
261
262     if (reasons.contains(CompositingReason::BackfaceVisibilityHidden))
263         compositingReasons->setBackfaceVisibilityHidden(true);
264
265     if (reasons.contains(CompositingReason::ClipsCompositingDescendants))
266         compositingReasons->setClipsCompositingDescendants(true);
267
268     if (reasons.contains(CompositingReason::Animation))
269         compositingReasons->setAnimation(true);
270
271     if (reasons.contains(CompositingReason::Filters))
272         compositingReasons->setFilters(true);
273
274     if (reasons.contains(CompositingReason::PositionFixed))
275         compositingReasons->setPositionFixed(true);
276
277     if (reasons.contains(CompositingReason::PositionSticky))
278         compositingReasons->setPositionSticky(true);
279
280     if (reasons.contains(CompositingReason::OverflowScrolling))
281         compositingReasons->setOverflowScrollingTouch(true);
282
283     // FIXME: handle OverflowScrollPositioning (webkit.org/b/195985).
284
285     if (reasons.contains(CompositingReason::Stacking))
286         compositingReasons->setStacking(true);
287
288     if (reasons.contains(CompositingReason::Overlap))
289         compositingReasons->setOverlap(true);
290
291     if (reasons.contains(CompositingReason::NegativeZIndexChildren))
292         compositingReasons->setNegativeZIndexChildren(true);
293
294     if (reasons.contains(CompositingReason::TransformWithCompositedDescendants))
295         compositingReasons->setTransformWithCompositedDescendants(true);
296
297     if (reasons.contains(CompositingReason::OpacityWithCompositedDescendants))
298         compositingReasons->setOpacityWithCompositedDescendants(true);
299
300     if (reasons.contains(CompositingReason::MaskWithCompositedDescendants))
301         compositingReasons->setMaskWithCompositedDescendants(true);
302
303     if (reasons.contains(CompositingReason::ReflectionWithCompositedDescendants))
304         compositingReasons->setReflectionWithCompositedDescendants(true);
305
306     if (reasons.contains(CompositingReason::FilterWithCompositedDescendants))
307         compositingReasons->setFilterWithCompositedDescendants(true);
308
309     if (reasons.contains(CompositingReason::BlendingWithCompositedDescendants))
310         compositingReasons->setBlendingWithCompositedDescendants(true);
311
312     if (reasons.contains(CompositingReason::IsolatesCompositedBlendingDescendants))
313         compositingReasons->setIsolatesCompositedBlendingDescendants(true);
314
315     if (reasons.contains(CompositingReason::Perspective))
316         compositingReasons->setPerspective(true);
317
318     if (reasons.contains(CompositingReason::Preserve3D))
319         compositingReasons->setPreserve3D(true);
320
321     if (reasons.contains(CompositingReason::WillChange))
322         compositingReasons->setWillChange(true);
323
324     if (reasons.contains(CompositingReason::Root))
325         compositingReasons->setRoot(true);
326
327     compositingReasonsResult = WTFMove(compositingReasons);
328 }
329
330 String InspectorLayerTreeAgent::bind(const RenderLayer* layer)
331 {
332     if (!layer)
333         return emptyString();
334     return m_documentLayerToIdMap.ensure(layer, [this, layer] {
335         auto identifier = IdentifiersFactory::createIdentifier();
336         m_idToLayer.set(identifier, layer);
337         return identifier;
338     }).iterator->value;
339 }
340
341 void InspectorLayerTreeAgent::unbind(const RenderLayer* layer)
342 {
343     auto identifier = m_documentLayerToIdMap.take(layer);
344     if (identifier.isNull())
345         return;
346     m_idToLayer.remove(identifier);
347 }
348
349 String InspectorLayerTreeAgent::bindPseudoElement(PseudoElement* pseudoElement)
350 {
351     if (!pseudoElement)
352         return emptyString();
353     return m_pseudoElementToIdMap.ensure(pseudoElement, [this, pseudoElement] {
354         auto identifier = IdentifiersFactory::createIdentifier();
355         m_idToPseudoElement.set(identifier, pseudoElement);
356         return identifier;
357     }).iterator->value;
358 }
359
360 void InspectorLayerTreeAgent::unbindPseudoElement(PseudoElement* pseudoElement)
361 {
362     auto identifier = m_pseudoElementToIdMap.take(pseudoElement);
363     if (identifier.isNull())
364         return;
365     m_idToPseudoElement.remove(identifier);
366 }
367
368 } // namespace WebCore