| <html> |
| <head> |
| <script src="../../http/tests/inspector/resources/protocol-test.js"></script> |
| <script> |
| |
| function addCompositedLayer() |
| { |
| var element = document.createElement("div"); |
| element.className = "composited"; |
| element.id = "last-element"; |
| document.body.appendChild(element); |
| return new Promise(resolve => requestAnimationFrame(resolve)); |
| }; |
| |
| function test() |
| { |
| let documentNode; |
| let initialLayers; |
| |
| step({ |
| name: "Enable the LayerTree agent", |
| command: "LayerTree.enable", |
| parameters: {}, |
| callback: () => {} |
| }); |
| |
| InspectorProtocol.awaitEvent({event: "LayerTree.layerTreeDidChange"}).then(getDocument); |
| |
| function getDocument() |
| { |
| step({ |
| name: "Get the Document", |
| command: "DOM.getDocument", |
| parameters: {}, |
| callback: getInitialLayerTree |
| }); |
| }; |
| |
| function getInitialLayerTree(result) |
| { |
| documentNode = result.root; |
| step({ |
| name: "Get the initial layer tree", |
| command: "LayerTree.layersForNode", |
| parameters: {"nodeId": documentNode.nodeId}, |
| callback: gotInitialLayerTree |
| }); |
| }; |
| |
| function gotInitialLayerTree(result) |
| { |
| initialLayers = result.layers; |
| |
| dumpLayers(initialLayers); |
| |
| step({ |
| name: "Message the page to add a new composited layer", |
| command: "Runtime.evaluate", |
| parameters: {"expression": "addCompositedLayer()"}, |
| callback: awaitRequestAnimationFrame |
| }); |
| }; |
| |
| function awaitRequestAnimationFrame(result) |
| { |
| step({ |
| name: "Wait for requestAnimationFrame", |
| command: "Runtime.awaitPromise", |
| parameters: {"promiseObjectId": result.result.objectId}, |
| callback: getModifiedLayerTree |
| }); |
| }; |
| |
| function getModifiedLayerTree(result) |
| { |
| step({ |
| name: "Get the modified layer tree", |
| command: "LayerTree.layersForNode", |
| parameters: {"nodeId": documentNode.nodeId}, |
| callback: gotModifiedLayerTree |
| }); |
| }; |
| |
| var layerCount = 0; |
| |
| function gotModifiedLayerTree(result) |
| { |
| dumpLayers(result.layers); |
| |
| var mutations = layerMutations(initialLayers, result.layers); |
| var newLayer = mutations.additions[0]; |
| |
| step({ |
| name: "Get attributes for the newly inserted node", |
| command: "DOM.getAttributes", |
| parameters: {"nodeId": newLayer.nodeId}, |
| callback: gotNodeAttributes |
| }); |
| }; |
| |
| function gotNodeAttributes(result) |
| { |
| var attributes = attributesDictionaryFromArray(result.attributes); |
| if (attributes.id !== "last-element") |
| ProtocolTest.log("FAIL: Did not obtain the expected element for the last inserted layer."); |
| |
| finishTest(); |
| }; |
| |
| function finishTest() |
| { |
| ProtocolTest.log("\n=== Test complete, all expected conditions met ==="); |
| ProtocolTest.completeTest(); |
| }; |
| |
| function layerMutations(oldLayers, newLayers) |
| { |
| function layerIdMap(layer) { |
| return layer.layerId; |
| } |
| |
| var oldLayerIds = oldLayers.map(layerIdMap); |
| var newLayerIds = newLayers.map(layerIdMap); |
| |
| return { |
| additions: newLayers.filter(function (layer) { |
| return (oldLayerIds.indexOf(layer.layerId) === -1); |
| }), |
| removals: oldLayers.filter(function (layer) { |
| return (newLayerIds.indexOf(layer.layerId) === -1); |
| }) |
| }; |
| }; |
| |
| function attributesDictionaryFromArray(attributes) |
| { |
| var dictionary = {} |
| for (var i = 0, count = attributes.length; i < count; i += 2) { |
| dictionary[attributes[i]] = attributes[i + 1]; |
| } |
| return dictionary; |
| }; |
| |
| function dumpLayers(layers) |
| { |
| function replacer(key, value) |
| { |
| if (key === "layerId" || key === "nodeId" || key === "memory" || key === "paintCount") |
| return typeof(value); |
| |
| // some values differ based on port, but the ones we most |
| // care about will always be less or equal 100. |
| if ((key === "width" || key === "height") && value > 100) |
| return typeof(value); |
| |
| return value; |
| }; |
| |
| ProtocolTest.log("\n" + JSON.stringify(layers, replacer, " ")); |
| }; |
| |
| function step(test) |
| { |
| ProtocolTest.log("\n=== " + test.name + " ===\n") |
| InspectorProtocol.sendCommand(test.command, test.parameters, function(messageObject) { |
| if (messageObject.hasOwnProperty("error")) { |
| ProtocolTest.log("FAIL: " + messageObject.error.message + " (" + messageObject.error.code + ")"); |
| ProtocolTest.completeTest(); |
| return; |
| } |
| |
| ProtocolTest.log("PASS"); |
| test.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"> |
| |
| div { |
| position: absolute; |
| top: 0; |
| left: 0; |
| } |
| |
| .regular { |
| width: 100px; |
| height: 100px; |
| background-color: black; |
| } |
| |
| .composited { |
| top: 25px; |
| left: 25px; |
| width: 50px; |
| height: 50px; |
| background-color: blue; |
| -webkit-transform: translateZ(0); |
| } |
| |
| .offset { |
| left: 200px; |
| -webkit-transform: translateZ(0); |
| } |
| |
| </style> |
| </head> |
| <body> |
| |
| <div class="regular"></div> |
| |
| <div class="composited"> |
| <div class="composited"></div> |
| </div> |
| |
| <div class="regular offset"> |
| <div class="composited"></div> |
| </div> |
| |
| </body> |
| </html> |