<html>
<head>
<script src="../../http/tests/inspector/resources/protocol-test.js"></script>
<script>

function test()
{

    var nodes = [];
 
    InspectorProtocol.eventHandler["DOM.setChildNodes"] = setChildNodes;

    enableLayerTreeAgent();
    
    function enableLayerTreeAgent(result)
    {
        step({
            name: "Enable the LayerTree agent",
            command: "LayerTree.enable",
            parameters: {},
            callback: getDocument
        });
    };

    function getDocument()
    {
        // We must first get the document so that later on we may get sensible nodeIds.
        step({
            name: "Get the Document",
            command: "DOM.getDocument",
            parameters: {},
            callback: getLayerTree
        });
    };

    function getLayerTree(result)
    {
        step({
            name: "Get the layer tree",
            command: "LayerTree.layersForNode",
            parameters: {"nodeId": result.root.nodeId},
            callback: gotLayerTree
        });
    };

    function gotLayerTree(result)
    {
        logTestName("Check layers' reasons for compositing")
        
        var layers = result.layers;

        var nodesById = {};
        nodes.forEach(function(node) {
            nodesById[node.nodeId] = node;
        });

        var count = 0;
        
        function hasId(node, id) {
            return node && node.attributes && node.attributes[0] === "id" && node.attributes[1] === id;
        }
        
        function dumpReasons(layer, compositingReasons) {
            var node = nodesById[layer.nodeId];

            if (hasId(node, "opacity-container")) {
                assert(
                    "<div id=\"opacity-container\"> is composited due to having an opacity style and a composited child",
                    compositingReasons.opacityWithCompositedDescendants,
                    true);
            } else if (hasId(node, "child")) {
                assert(
                    "<div id=\"child\"> is composited due to having \"backface-visibility: hidden\" and a 3D transform",
                    compositingReasons.transform3D && compositingReasons.backfaceVisibilityHidden,
                    true);
            } else if (hasId(node, "canvas")) {
                assert(
                    "<canvas id=\"canvas\"> is composited due to having a 3D transform",
                    compositingReasons.transform3D,
                    true);
            }

            if (++count === layers.length)
                ProtocolTest.completeTest();
        };

        layers.forEach(function (layer) {
            runCommand({
                command: "LayerTree.reasonsForCompositingLayer",
                parameters: {"layerId": layer.layerId},
                callback: function(result) {
                    dumpReasons(layer, result.compositingReasons);
                }
            });
        });
    };

    function setChildNodes (messageObject) {
        messageObject.params.nodes.forEach(function (node) {
            nodes.push(node);
        })
    };

    function step(test)
    {
        if (test.callback)
            logTestName(test.name);
        runCommand(test);
    };

    function logTestName(name)
    {
        ProtocolTest.log("\n=== " + name + " ===\n");
    };

    function runCommand(command)
    {
        InspectorProtocol.sendCommand(command.command, command.parameters, function(messageObject) {
            if (messageObject.hasOwnProperty("error")) {
                ProtocolTest.log("FAIL: " + messageObject.error.message + " (" + messageObject.error.code + ")");
                ProtocolTest.completeTest();
                return;
            }

            if (command.name)
                ProtocolTest.log("PASS");

            if (command.callback)
                command.callback(messageObject.result);
        });
    };

    function assert(name, actual, expected)
    {
        if (expected === actual)
            ProtocolTest.log("PASS: " + name + ".");
        else
            ProtocolTest.log("FAIL: " + name + ". Expected " + expected + " but got " + actual);
    };

};

window.addEventListener("DOMContentLoaded", function()
{
    runTest();
}, false);

</script>
<style type="text/css">
      
    #opacity-container {
        opacity: 0.5;
    }

    #child {
        -webkit-backface-visibility: hidden;
        -webkit-transform: translateZ(0);
    }

    #canvas {
        transform: translate3D(0,0,0);
    }

</style>
</head>
<body>

    <div id="fixed"></div>

    <div id="opacity-container">
        <div id="child"></div>
    </div>

    <canvas id="canvas" width="65537" height="65537"></canvas>

</body>
</html>
