1 /* 2 * Copyright (C) 2012 Apple Inc. All rights reserved. 3 * Copyright (C) 2013 Google Inc. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: 8 * 9 * * Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * * Redistributions in binary form must reproduce the above 12 * copyright notice, this list of conditions and the following disclaimer 13 * in the documentation and/or other materials provided with the 14 * distribution. 15 * * Neither the name of Google Inc. nor the names of its 16 * contributors may be used to endorse or promote products derived from 17 * this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #include "config.h" 33 34 #include "core/inspector/InspectorLayerTreeAgent.h" 35 36 #include "InspectorFrontend.h" 37 #include "core/inspector/IdentifiersFactory.h" 38 #include "core/inspector/InspectorDOMAgent.h" 39 #include "core/inspector/InspectorState.h" 40 #include "core/inspector/InstrumentingAgents.h" 41 #include "core/loader/DocumentLoader.h" 42 #include "core/page/Page.h" 43 #include "core/platform/graphics/IntRect.h" 44 #include "core/rendering/RenderLayer.h" 45 #include "core/rendering/RenderLayerBacking.h" 46 #include "core/rendering/RenderLayerCompositor.h" 47 #include "core/rendering/RenderView.h" 48 #include "public/platform/WebLayer.h" 49 50 namespace WebCore { 51 52 namespace LayerTreeAgentState { 53 static const char layerTreeAgentEnabled[] = "layerTreeAgentEnabled"; 54 }; 55 56 static PassRefPtr<TypeBuilder::LayerTree::Layer> buildObjectForLayer(GraphicsLayer* graphicsLayer, int nodeId, bool forceRoot) 57 { 58 RefPtr<TypeBuilder::LayerTree::Layer> layerObject = TypeBuilder::LayerTree::Layer::create() 59 .setLayerId(String::number(graphicsLayer->platformLayer()->id())) 60 .setNodeId(nodeId) 61 .setOffsetX(graphicsLayer->position().x()) 62 .setOffsetY(graphicsLayer->position().y()) 63 .setWidth(graphicsLayer->size().width()) 64 .setHeight(graphicsLayer->size().height()) 65 .setPaintCount(graphicsLayer->repaintCount()); 66 67 // Artificially clip tree at root renger layer's graphic layer -- it might be not the real 68 // root of graphics layer hierarchy, as platform adds containing layers (e.g. for overflosw scroll). 69 if (graphicsLayer->parent() && !forceRoot) 70 layerObject->setParentLayerId(String::number(graphicsLayer->parent()->platformLayer()->id())); 71 72 return layerObject; 73 } 74 75 static void maybeAddGraphicsLayer(GraphicsLayer* graphicsLayer, int nodeId, RefPtr<TypeBuilder::Array<TypeBuilder::LayerTree::Layer> >& layers, bool forceRoot = false) 76 { 77 if (!graphicsLayer) 78 return; 79 layers->addItem(buildObjectForLayer(graphicsLayer, nodeId, forceRoot)); 80 } 81 82 InspectorLayerTreeAgent::InspectorLayerTreeAgent(InstrumentingAgents* instrumentingAgents, InspectorCompositeState* state, InspectorDOMAgent* domAgent, Page* page) 83 : InspectorBaseAgent<InspectorLayerTreeAgent>("LayerTree", instrumentingAgents, state) 84 , m_frontend(0) 85 , m_page(page) 86 , m_domAgent(domAgent) 87 { 88 } 89 90 InspectorLayerTreeAgent::~InspectorLayerTreeAgent() 91 { 92 } 93 94 void InspectorLayerTreeAgent::setFrontend(InspectorFrontend* frontend) 95 { 96 m_frontend = frontend->layertree(); 97 } 98 99 void InspectorLayerTreeAgent::clearFrontend() 100 { 101 m_frontend = 0; 102 disable(0); 103 } 104 105 void InspectorLayerTreeAgent::restore() 106 { 107 if (m_state->getBoolean(LayerTreeAgentState::layerTreeAgentEnabled)) 108 enable(0); 109 } 110 111 void InspectorLayerTreeAgent::enable(ErrorString*) 112 { 113 m_state->setBoolean(LayerTreeAgentState::layerTreeAgentEnabled, true); 114 m_instrumentingAgents->setInspectorLayerTreeAgent(this); 115 } 116 117 void InspectorLayerTreeAgent::disable(ErrorString*) 118 { 119 if (!m_state->getBoolean(LayerTreeAgentState::layerTreeAgentEnabled)) 120 return; 121 m_state->setBoolean(LayerTreeAgentState::layerTreeAgentEnabled, false); 122 m_instrumentingAgents->setInspectorLayerTreeAgent(0); 123 } 124 125 void InspectorLayerTreeAgent::didCommitLoad(Frame* frame, DocumentLoader* loader) 126 { 127 if (loader->frame() != frame->page()->mainFrame()) 128 return; 129 } 130 131 void InspectorLayerTreeAgent::layerTreeDidChange() 132 { 133 m_frontend->layerTreeDidChange(); 134 } 135 136 void InspectorLayerTreeAgent::getLayers(ErrorString* errorString, const int* nodeId, RefPtr<TypeBuilder::Array<TypeBuilder::LayerTree::Layer> >& layers) 137 { 138 layers = TypeBuilder::Array<TypeBuilder::LayerTree::Layer>::create(); 139 140 RenderView* renderView = m_page->mainFrame()->contentRenderer(); 141 RenderLayerCompositor* compositor = renderView ? renderView->compositor() : 0; 142 if (!compositor) { 143 *errorString = "Not in compositing mode"; 144 return; 145 } 146 if (!nodeId) { 147 gatherLayersUsingRenderLayerHierarchy(errorString, compositor->rootRenderLayer(), layers); 148 return; 149 } 150 Node* node = m_instrumentingAgents->inspectorDOMAgent()->nodeForId(*nodeId); 151 if (!node) { 152 *errorString = "Provided node id doesn't match any known node"; 153 return; 154 } 155 RenderObject* renderer = node->renderer(); 156 if (!renderer) { 157 *errorString = "Node for provided node id doesn't have a renderer"; 158 return; 159 } 160 gatherLayersUsingRenderObjectHierarchy(errorString, renderer, layers); 161 } 162 163 void InspectorLayerTreeAgent::addRenderLayerBacking(ErrorString* errorString, RenderLayerBacking* layerBacking, Node* node, RefPtr<TypeBuilder::Array<TypeBuilder::LayerTree::Layer> >& layers) 164 { 165 int nodeId = idForNode(errorString, node); 166 RenderLayerCompositor* compositor = layerBacking->owningLayer()->compositor(); 167 bool forceRoot = layerBacking->owningLayer()->isRootLayer(); 168 if (layerBacking->ancestorClippingLayer()) { 169 maybeAddGraphicsLayer(layerBacking->ancestorClippingLayer(), nodeId, layers, forceRoot); 170 forceRoot = false; 171 } 172 maybeAddGraphicsLayer(layerBacking->graphicsLayer(), nodeId, layers, forceRoot); 173 maybeAddGraphicsLayer(layerBacking->clippingLayer(), nodeId, layers); 174 maybeAddGraphicsLayer(layerBacking->foregroundLayer(), nodeId, layers); 175 maybeAddGraphicsLayer(layerBacking->backgroundLayer(), nodeId, layers); 176 maybeAddGraphicsLayer(layerBacking->scrollingLayer(), nodeId, layers); 177 maybeAddGraphicsLayer(layerBacking->scrollingContentsLayer(), nodeId, layers); 178 maybeAddGraphicsLayer(layerBacking->layerForHorizontalScrollbar(), nodeId, layers); 179 maybeAddGraphicsLayer(layerBacking->layerForVerticalScrollbar(), nodeId, layers); 180 } 181 182 void InspectorLayerTreeAgent::gatherLayersUsingRenderObjectHierarchy(ErrorString* errorString, RenderObject* renderer, RefPtr<TypeBuilder::Array<TypeBuilder::LayerTree::Layer> >& layers) 183 { 184 if (renderer->hasLayer()) { 185 gatherLayersUsingRenderLayerHierarchy(errorString, toRenderLayerModelObject(renderer)->layer(), layers); 186 return; 187 } 188 189 for (renderer = renderer->firstChild(); renderer; renderer = renderer->nextSibling()) 190 gatherLayersUsingRenderObjectHierarchy(errorString, renderer, layers); 191 } 192 193 void InspectorLayerTreeAgent::gatherLayersUsingRenderLayerHierarchy(ErrorString* errorString, RenderLayer* renderLayer, RefPtr<TypeBuilder::Array<TypeBuilder::LayerTree::Layer> >& layers) 194 { 195 if (renderLayer->isComposited()) { 196 Node* node = (renderLayer->isReflection() ? renderLayer->parent() : renderLayer)->renderer()->generatingNode(); 197 addRenderLayerBacking(errorString, renderLayer->backing(), node, layers); 198 } 199 for (renderLayer = renderLayer->firstChild(); renderLayer; renderLayer = renderLayer->nextSibling()) 200 gatherLayersUsingRenderLayerHierarchy(errorString, renderLayer, layers); 201 } 202 203 int InspectorLayerTreeAgent::idForNode(ErrorString* errorString, Node* node) 204 { 205 InspectorDOMAgent* domAgent = m_instrumentingAgents->inspectorDOMAgent(); 206 207 int nodeId = domAgent->boundNodeId(node); 208 if (!nodeId) 209 nodeId = domAgent->pushNodeToFrontend(errorString, domAgent->boundNodeId(node->document()), node); 210 211 return nodeId; 212 } 213 214 } // namespace WebCore 215