Home | History | Annotate | Download | only in inspector
      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