mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-23 02:05:42 +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");
|
yield addTab(TEST_URL_ROOT + "doc_simple_animation.html");
|
||||||
let {controller, inspector} = yield openAnimationInspector();
|
let {controller, inspector} = yield openAnimationInspector();
|
||||||
|
|
||||||
is(controller.animationPlayers.length, 0,
|
|
||||||
"There are no AnimationPlayerFront objects at first");
|
|
||||||
|
|
||||||
info("Selecting an animated node");
|
info("Selecting an animated node");
|
||||||
// selectNode waits for the inspector-updated event before resolving, which
|
// selectNode waits for the inspector-updated event before resolving, which
|
||||||
// means the controller.PLAYERS_UPDATED_EVENT event has been emitted before
|
// 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");
|
yield addTab(TEST_URL_ROOT + "doc_simple_animation.html");
|
||||||
let {inspector, panel, controller} = yield openAnimationInspector();
|
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", {
|
yield executeInContent("devtools:test:setAttribute", {
|
||||||
selector: ".still",
|
selector: ".still",
|
||||||
attributeName: "class",
|
attributeName: "class",
|
||||||
attributeValue: "ball still multi-finite"
|
attributeValue: "ball still multi-finite"
|
||||||
});
|
});
|
||||||
|
yield onUiUpdated;
|
||||||
info("Select the test node");
|
|
||||||
yield selectNode(".still", inspector);
|
|
||||||
|
|
||||||
is(controller.animationPlayers.length, 2, "2 animation players exist");
|
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");
|
yield addTab(TEST_URL_ROOT + "doc_simple_animation.html");
|
||||||
let {inspector, panel} = yield openAnimationInspector();
|
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", {
|
yield executeInContent("devtools:test:setAttribute", {
|
||||||
selector: ".still",
|
selector: ".still",
|
||||||
attributeName: "class",
|
attributeName: "class",
|
||||||
attributeValue: "ball still short"
|
attributeValue: "ball still short"
|
||||||
});
|
});
|
||||||
|
yield onUiUpdated;
|
||||||
info("Select the node");
|
|
||||||
yield selectNode(".still", inspector);
|
|
||||||
|
|
||||||
info("Wait until the animation ends");
|
info("Wait until the animation ends");
|
||||||
let widget = panel.playerWidgets[0];
|
let widget = panel.playerWidgets[0];
|
||||||
|
@ -31,7 +31,8 @@ add_task(function*() {
|
|||||||
info("Faking an older server version by setting " +
|
info("Faking an older server version by setting " +
|
||||||
"AnimationsController.hasSetCurrentTime to false");
|
"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;
|
controller.hasSetCurrentTime = false;
|
||||||
|
|
||||||
info("Selecting the animated node again");
|
info("Selecting the animated node again");
|
||||||
@ -46,13 +47,12 @@ add_task(function*() {
|
|||||||
ok(container.children[0].classList.contains("toggle"),
|
ok(container.children[0].classList.contains("toggle"),
|
||||||
"The first button is the play/pause button");
|
"The first button is the play/pause button");
|
||||||
|
|
||||||
yield selectNode("body", inspector);
|
yield selectNode(".still", inspector);
|
||||||
controller.hasSetCurrentTime = true;
|
controller.hasSetCurrentTime = true;
|
||||||
|
|
||||||
info("Faking an older server version by setting " +
|
info("Faking an older server version by setting " +
|
||||||
"AnimationsController.hasSetPlaybackRate to false");
|
"AnimationsController.hasSetPlaybackRate to false");
|
||||||
|
|
||||||
yield selectNode("body", inspector);
|
|
||||||
controller.hasSetPlaybackRate = false;
|
controller.hasSetPlaybackRate = false;
|
||||||
|
|
||||||
info("Selecting the animated node again");
|
info("Selecting the animated node again");
|
||||||
@ -65,6 +65,6 @@ add_task(function*() {
|
|||||||
ok(!container.querySelector("select"),
|
ok(!container.querySelector("select"),
|
||||||
"The playback rate select does not exist");
|
"The playback rate select does not exist");
|
||||||
|
|
||||||
yield selectNode("body", inspector);
|
yield selectNode(".still", inspector);
|
||||||
controller.hasSetPlaybackRate = true;
|
controller.hasSetPlaybackRate = true;
|
||||||
});
|
});
|
||||||
|
@ -10,6 +10,9 @@ add_task(function*() {
|
|||||||
yield addTab(TEST_URL_ROOT + "doc_simple_animation.html");
|
yield addTab(TEST_URL_ROOT + "doc_simple_animation.html");
|
||||||
let {inspector, panel} = yield openAnimationInspector();
|
let {inspector, panel} = yield openAnimationInspector();
|
||||||
|
|
||||||
|
info("Select the non-animated test node");
|
||||||
|
yield selectNode(".still", inspector);
|
||||||
|
|
||||||
ok(!panel.toggleAllButtonEl.classList.contains("paused"),
|
ok(!panel.toggleAllButtonEl.classList.contains("paused"),
|
||||||
"The toggle button is in its running state by default");
|
"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
|
* Retrieve the list of AnimationPlayerActor actors for currently running
|
||||||
* currently running animations for a given node.
|
* animations on a node and its descendants.
|
||||||
* @param {NodeActor} nodeActor The NodeActor type is defined in
|
* @param {NodeActor} nodeActor The NodeActor as defined in
|
||||||
* /toolkit/devtools/server/actors/inspector
|
* /toolkit/devtools/server/actors/inspector
|
||||||
*/
|
*/
|
||||||
getAnimationPlayersForNode: method(function(nodeActor) {
|
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
|
// No care is taken here to destroy the previously stored actors because it
|
||||||
// is assumed that the client is responsible for lifetimes of actors.
|
// is assumed that the client is responsible for lifetimes of actors.
|
||||||
@ -511,7 +514,10 @@ let AnimationsActor = exports.AnimationsActor = ActorClass({
|
|||||||
this.stopAnimationPlayerUpdates();
|
this.stopAnimationPlayerUpdates();
|
||||||
let win = nodeActor.rawNode.ownerDocument.defaultView;
|
let win = nodeActor.rawNode.ownerDocument.defaultView;
|
||||||
this.observer = new win.MutationObserver(this.onAnimationMutation);
|
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;
|
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
|
* Iterates through all nodes below a given rootNode (optionally also in
|
||||||
* finds all existing animation players.
|
* nested frames) and finds all existing animation players.
|
||||||
* This is currently used to allow playing/pausing all animations at once
|
* @param {DOMNode} rootNode The root node to start iterating at. Animation
|
||||||
* until the WebAnimations API provides a way to play/pause via the document
|
* players will *not* be reported for this node.
|
||||||
* timeline (alternatively, when bug 1123524 is fixed, we will be able to
|
* @param {Boolean} traverseFrames Whether we should iterate through nested
|
||||||
* only iterate once and then listen for changes).
|
* frames too.
|
||||||
|
* @return {Array} An array of AnimationPlayer objects.
|
||||||
*/
|
*/
|
||||||
getAllAnimationPlayers: function() {
|
getAllAnimations: function(rootNode, traverseFrames) {
|
||||||
let animations = [];
|
let animations = [];
|
||||||
|
|
||||||
// These loops shouldn't be as bad as they look.
|
// These loops shouldn't be as bad as they look.
|
||||||
// Typically, there will be very few windows, and getElementsByTagName is
|
// Typically, there will be very few nested frames, and getElementsByTagName
|
||||||
// really fast even on large DOM trees.
|
// is really fast even on large DOM trees.
|
||||||
for (let window of this.tabActor.windows) {
|
for (let element of rootNode.getElementsByTagNameNS("*", "*")) {
|
||||||
let root = window.document.body || window.document;
|
if (traverseFrames && element.contentWindow) {
|
||||||
for (let element of root.getElementsByTagNameNS("*", "*")) {
|
animations = [
|
||||||
animations = [...animations, ...element.getAnimations()];
|
...animations,
|
||||||
|
...this.getAllAnimations(element.contentWindow.document, traverseFrames)
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
animations = [
|
||||||
|
...animations,
|
||||||
|
...element.getAnimations()
|
||||||
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -636,7 +650,10 @@ let AnimationsActor = exports.AnimationsActor = ActorClass({
|
|||||||
*/
|
*/
|
||||||
pauseAll: method(function() {
|
pauseAll: method(function() {
|
||||||
let readyPromises = [];
|
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();
|
player.pause();
|
||||||
readyPromises.push(player.ready);
|
readyPromises.push(player.ready);
|
||||||
}
|
}
|
||||||
@ -653,7 +670,10 @@ let AnimationsActor = exports.AnimationsActor = ActorClass({
|
|||||||
*/
|
*/
|
||||||
playAll: method(function() {
|
playAll: method(function() {
|
||||||
let readyPromises = [];
|
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();
|
player.play();
|
||||||
readyPromises.push(player.ready);
|
readyPromises.push(player.ready);
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,7 @@ support-files =
|
|||||||
[browser_animation_actors_13.js]
|
[browser_animation_actors_13.js]
|
||||||
[browser_animation_actors_14.js]
|
[browser_animation_actors_14.js]
|
||||||
[browser_animation_actors_15.js]
|
[browser_animation_actors_15.js]
|
||||||
|
[browser_animation_actors_16.js]
|
||||||
[browser_canvasframe_helper_01.js]
|
[browser_canvasframe_helper_01.js]
|
||||||
[browser_canvasframe_helper_02.js]
|
[browser_canvasframe_helper_02.js]
|
||||||
[browser_canvasframe_helper_03.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