mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-22 17:55:50 +00:00
Bug 1155651 - Return all players below a node in getAnimationPlayersForNode; r=miker
Now when the front requests the list of AnimationPlayers for a node, all players for this node + the nodes in its subtree are returned. Also the mutationobserver starts observing all mutations in the node and its subtree. --HG-- extra : rebase_source : c419bd2f397617317fa9c9d0b7fd22f07abc12cf
This commit is contained in:
parent
b2a2f73211
commit
b2a9538957
@ -11,9 +11,6 @@ add_task(function*() {
|
||||
yield addTab(TEST_URL_ROOT + "doc_simple_animation.html");
|
||||
let {controller, inspector} = yield openAnimationInspector();
|
||||
|
||||
is(controller.animationPlayers.length, 0,
|
||||
"There are no AnimationPlayerFront objects at first");
|
||||
|
||||
info("Selecting an animated node");
|
||||
// selectNode waits for the inspector-updated event before resolving, which
|
||||
// means the controller.PLAYERS_UPDATED_EVENT event has been emitted before
|
||||
|
@ -10,15 +10,17 @@ add_task(function*() {
|
||||
yield addTab(TEST_URL_ROOT + "doc_simple_animation.html");
|
||||
let {inspector, panel, controller} = yield openAnimationInspector();
|
||||
|
||||
info("Apply 2 finite animations to the test node");
|
||||
info("Select the test node");
|
||||
yield selectNode(".still", inspector);
|
||||
|
||||
info("Apply 2 finite animations to the test node and wait for the widgets to appear");
|
||||
let onUiUpdated = panel.once(panel.UI_UPDATED_EVENT);
|
||||
yield executeInContent("devtools:test:setAttribute", {
|
||||
selector: ".still",
|
||||
attributeName: "class",
|
||||
attributeValue: "ball still multi-finite"
|
||||
});
|
||||
|
||||
info("Select the test node");
|
||||
yield selectNode(".still", inspector);
|
||||
yield onUiUpdated;
|
||||
|
||||
is(controller.animationPlayers.length, 2, "2 animation players exist");
|
||||
|
||||
|
@ -14,15 +14,17 @@ add_task(function*() {
|
||||
yield addTab(TEST_URL_ROOT + "doc_simple_animation.html");
|
||||
let {inspector, panel} = yield openAnimationInspector();
|
||||
|
||||
info("Start an animation on the test node");
|
||||
info("Select the test node");
|
||||
yield selectNode(".still", inspector);
|
||||
|
||||
info("Start an animation on the test node and wait for the widget to appear");
|
||||
let onUiUpdated = panel.once(panel.UI_UPDATED_EVENT);
|
||||
yield executeInContent("devtools:test:setAttribute", {
|
||||
selector: ".still",
|
||||
attributeName: "class",
|
||||
attributeValue: "ball still short"
|
||||
});
|
||||
|
||||
info("Select the node");
|
||||
yield selectNode(".still", inspector);
|
||||
yield onUiUpdated;
|
||||
|
||||
info("Wait until the animation ends");
|
||||
let widget = panel.playerWidgets[0];
|
||||
|
@ -31,7 +31,8 @@ add_task(function*() {
|
||||
info("Faking an older server version by setting " +
|
||||
"AnimationsController.hasSetCurrentTime to false");
|
||||
|
||||
yield selectNode("body", inspector);
|
||||
// Selecting <div.still> to make sure no widgets are displayed in the panel.
|
||||
yield selectNode(".still", inspector);
|
||||
controller.hasSetCurrentTime = false;
|
||||
|
||||
info("Selecting the animated node again");
|
||||
@ -46,13 +47,12 @@ add_task(function*() {
|
||||
ok(container.children[0].classList.contains("toggle"),
|
||||
"The first button is the play/pause button");
|
||||
|
||||
yield selectNode("body", inspector);
|
||||
yield selectNode(".still", inspector);
|
||||
controller.hasSetCurrentTime = true;
|
||||
|
||||
info("Faking an older server version by setting " +
|
||||
"AnimationsController.hasSetPlaybackRate to false");
|
||||
|
||||
yield selectNode("body", inspector);
|
||||
controller.hasSetPlaybackRate = false;
|
||||
|
||||
info("Selecting the animated node again");
|
||||
@ -65,6 +65,6 @@ add_task(function*() {
|
||||
ok(!container.querySelector("select"),
|
||||
"The playback rate select does not exist");
|
||||
|
||||
yield selectNode("body", inspector);
|
||||
yield selectNode(".still", inspector);
|
||||
controller.hasSetPlaybackRate = true;
|
||||
});
|
||||
|
@ -10,6 +10,9 @@ add_task(function*() {
|
||||
yield addTab(TEST_URL_ROOT + "doc_simple_animation.html");
|
||||
let {inspector, panel} = yield openAnimationInspector();
|
||||
|
||||
info("Select the non-animated test node");
|
||||
yield selectNode(".still", inspector);
|
||||
|
||||
ok(!panel.toggleAllButtonEl.classList.contains("paused"),
|
||||
"The toggle button is in its running state by default");
|
||||
|
||||
|
@ -486,13 +486,16 @@ let AnimationsActor = exports.AnimationsActor = ActorClass({
|
||||
},
|
||||
|
||||
/**
|
||||
* Retrieve the list of AnimationPlayerActor actors corresponding to
|
||||
* currently running animations for a given node.
|
||||
* @param {NodeActor} nodeActor The NodeActor type is defined in
|
||||
* Retrieve the list of AnimationPlayerActor actors for currently running
|
||||
* animations on a node and its descendants.
|
||||
* @param {NodeActor} nodeActor The NodeActor as defined in
|
||||
* /toolkit/devtools/server/actors/inspector
|
||||
*/
|
||||
getAnimationPlayersForNode: method(function(nodeActor) {
|
||||
let animations = nodeActor.rawNode.getAnimations();
|
||||
let animations = [
|
||||
...nodeActor.rawNode.getAnimations(),
|
||||
...this.getAllAnimations(nodeActor.rawNode)
|
||||
];
|
||||
|
||||
// No care is taken here to destroy the previously stored actors because it
|
||||
// is assumed that the client is responsible for lifetimes of actors.
|
||||
@ -511,7 +514,10 @@ let AnimationsActor = exports.AnimationsActor = ActorClass({
|
||||
this.stopAnimationPlayerUpdates();
|
||||
let win = nodeActor.rawNode.ownerDocument.defaultView;
|
||||
this.observer = new win.MutationObserver(this.onAnimationMutation);
|
||||
this.observer.observe(nodeActor.rawNode, {animations: true});
|
||||
this.observer.observe(nodeActor.rawNode, {
|
||||
animations: true,
|
||||
subtree: true
|
||||
});
|
||||
|
||||
return this.actors;
|
||||
}, {
|
||||
@ -596,23 +602,31 @@ let AnimationsActor = exports.AnimationsActor = ActorClass({
|
||||
}),
|
||||
|
||||
/**
|
||||
* Iterates through all nodes in all of the tabActor's window documents and
|
||||
* finds all existing animation players.
|
||||
* This is currently used to allow playing/pausing all animations at once
|
||||
* until the WebAnimations API provides a way to play/pause via the document
|
||||
* timeline (alternatively, when bug 1123524 is fixed, we will be able to
|
||||
* only iterate once and then listen for changes).
|
||||
* Iterates through all nodes below a given rootNode (optionally also in
|
||||
* nested frames) and finds all existing animation players.
|
||||
* @param {DOMNode} rootNode The root node to start iterating at. Animation
|
||||
* players will *not* be reported for this node.
|
||||
* @param {Boolean} traverseFrames Whether we should iterate through nested
|
||||
* frames too.
|
||||
* @return {Array} An array of AnimationPlayer objects.
|
||||
*/
|
||||
getAllAnimationPlayers: function() {
|
||||
getAllAnimations: function(rootNode, traverseFrames) {
|
||||
let animations = [];
|
||||
|
||||
// These loops shouldn't be as bad as they look.
|
||||
// Typically, there will be very few windows, and getElementsByTagName is
|
||||
// really fast even on large DOM trees.
|
||||
for (let window of this.tabActor.windows) {
|
||||
let root = window.document.body || window.document;
|
||||
for (let element of root.getElementsByTagNameNS("*", "*")) {
|
||||
animations = [...animations, ...element.getAnimations()];
|
||||
// Typically, there will be very few nested frames, and getElementsByTagName
|
||||
// is really fast even on large DOM trees.
|
||||
for (let element of rootNode.getElementsByTagNameNS("*", "*")) {
|
||||
if (traverseFrames && element.contentWindow) {
|
||||
animations = [
|
||||
...animations,
|
||||
...this.getAllAnimations(element.contentWindow.document, traverseFrames)
|
||||
];
|
||||
} else {
|
||||
animations = [
|
||||
...animations,
|
||||
...element.getAnimations()
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@ -636,7 +650,10 @@ let AnimationsActor = exports.AnimationsActor = ActorClass({
|
||||
*/
|
||||
pauseAll: method(function() {
|
||||
let readyPromises = [];
|
||||
for (let player of this.getAllAnimationPlayers()) {
|
||||
// Until the WebAnimations API provides a way to play/pause via the document
|
||||
// timeline, we have to iterate through the whole DOM to find all players.
|
||||
for (let player of
|
||||
this.getAllAnimations(this.tabActor.window.document, true)) {
|
||||
player.pause();
|
||||
readyPromises.push(player.ready);
|
||||
}
|
||||
@ -653,7 +670,10 @@ let AnimationsActor = exports.AnimationsActor = ActorClass({
|
||||
*/
|
||||
playAll: method(function() {
|
||||
let readyPromises = [];
|
||||
for (let player of this.getAllAnimationPlayers()) {
|
||||
// Until the WebAnimations API provides a way to play/pause via the document
|
||||
// timeline, we have to iterate through the whole DOM to find all players.
|
||||
for (let player of
|
||||
this.getAllAnimations(this.tabActor.window.document, true)) {
|
||||
player.play();
|
||||
readyPromises.push(player.ready);
|
||||
}
|
||||
|
@ -31,6 +31,7 @@ support-files =
|
||||
[browser_animation_actors_13.js]
|
||||
[browser_animation_actors_14.js]
|
||||
[browser_animation_actors_15.js]
|
||||
[browser_animation_actors_16.js]
|
||||
[browser_canvasframe_helper_01.js]
|
||||
[browser_canvasframe_helper_02.js]
|
||||
[browser_canvasframe_helper_03.js]
|
||||
|
@ -0,0 +1,46 @@
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Check that the AnimationsActor can retrieve all animations inside a node's
|
||||
// subtree (but not going into iframes).
|
||||
|
||||
const {AnimationsFront} = require("devtools/server/actors/animation");
|
||||
const {InspectorFront} = require("devtools/server/actors/inspector");
|
||||
|
||||
const URL = MAIN_DOMAIN + "animation.html";
|
||||
|
||||
add_task(function*() {
|
||||
info("Creating a test document with 2 iframes containing animated nodes");
|
||||
let doc = yield addTab("data:text/html;charset=utf-8," +
|
||||
"<iframe id='iframe' src='" + URL + "'></iframe>");
|
||||
|
||||
initDebuggerServer();
|
||||
let client = new DebuggerClient(DebuggerServer.connectPipe());
|
||||
let form = yield connectDebuggerClient(client);
|
||||
let inspector = InspectorFront(client, form);
|
||||
let walker = yield inspector.getWalker();
|
||||
let front = AnimationsFront(client, form);
|
||||
|
||||
info("Try retrieving all animations from the root doc's <body> node");
|
||||
let rootBody = yield walker.querySelector(walker.rootNode, "body");
|
||||
let players = yield front.getAnimationPlayersForNode(rootBody);
|
||||
is(players.length, 0, "The node has no animation players");
|
||||
|
||||
info("Retrieve all animations from the iframe's <body> node");
|
||||
let iframe = yield walker.querySelector(walker.rootNode, "#iframe");
|
||||
let {nodes} = yield walker.children(iframe);
|
||||
let frameBody = yield walker.querySelector(nodes[0], "body");
|
||||
players = yield front.getAnimationPlayersForNode(frameBody);
|
||||
|
||||
// Testing for a hard-coded number of animations here would intermittently
|
||||
// fail depending on how fast or slow the test is (indeed, the test page
|
||||
// contains short transitions, and delayed animations). So just make sure we
|
||||
// at least have the infinitely running animations.
|
||||
ok(players.length >= 4, "All subtree animations were retrieved");
|
||||
|
||||
yield closeDebuggerClient(client);
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
Loading…
Reference in New Issue
Block a user