Bug 1105825 - Add auto state refresh to AnimationPlayerActors; r=bgrins

This commit is contained in:
Patrick Brosset 2014-12-22 17:56:41 +01:00
Родитель cc33239ad9
Коммит 440967c333
3 изменённых файлов: 140 добавлений и 1 удалений

Просмотреть файл

@ -24,10 +24,16 @@
* /dom/webidl/Animation*.webidl
*/
const {Cu} = require("chrome");
const {Task} = Cu.import("resource://gre/modules/Task.jsm", {});
const {setInterval, clearInterval} = require("sdk/timers");
const {ActorClass, Actor,
FrontClass, Front,
Arg, method, RetVal} = require("devtools/server/protocol");
const {NodeActor} = require("devtools/server/actors/inspector");
const EventEmitter = require("devtools/toolkit/event-emitter");
const PLAYER_DEFAULT_AUTO_REFRESH_TIMEOUT = 500; // ms
/**
* The AnimationPlayerActor provides information about a given animation: its
@ -179,8 +185,13 @@ let AnimationPlayerActor = ActorClass({
});
let AnimationPlayerFront = FrontClass(AnimationPlayerActor, {
AUTO_REFRESH_EVENT: "updated-state",
initialize: function(conn, form, detail, ctx) {
EventEmitter.decorate(this);
Front.prototype.initialize.call(this, conn, form, detail, ctx);
this.state = {};
},
form: function(form, detail) {
@ -189,9 +200,11 @@ let AnimationPlayerFront = FrontClass(AnimationPlayerActor, {
return;
}
this._form = form;
this.state = this.initialState;
},
destroy: function() {
this.stopAutoRefresh();
Front.prototype.destroy.call(this);
},
@ -209,7 +222,75 @@ let AnimationPlayerFront = FrontClass(AnimationPlayerActor, {
iterationCount: this._form.iterationCount,
isRunningOnCompositor: this._form.isRunningOnCompositor
}
}
},
// About auto-refresh:
//
// The AnimationPlayerFront is capable of automatically refreshing its state
// by calling the getCurrentState method at regular intervals. This allows
// consumers to update their knowledge of the player's currentTime, playState,
// ... dynamically.
//
// Calling startAutoRefresh will start the automatic refreshing of the state,
// and calling stopAutoRefresh will stop it.
// Once the automatic refresh has been started, the AnimationPlayerFront emits
// "updated-state" events everytime the state changes.
//
// Note that given the time-related nature of animations, the actual state
// changes a lot more often than "updated-state" events are emitted. This is
// to avoid making many protocol requests.
/**
* Start auto-refreshing this player's state.
* @param {Number} interval Optional auto-refresh timer interval to override
* the default value.
*/
startAutoRefresh: function(interval=PLAYER_DEFAULT_AUTO_REFRESH_TIMEOUT) {
if (this.autoRefreshTimer) {
return;
}
this.autoRefreshTimer = setInterval(this.refreshState.bind(this), interval);
},
/**
* Stop auto-refreshing this player's state.
*/
stopAutoRefresh: function() {
if (!this.autoRefreshTimer) {
return;
}
clearInterval(this.autoRefreshTimer);
this.autoRefreshTimer = null;
},
/**
* Called automatically when auto-refresh is on. Doesn't return anything, but
* emits the "updated-state" event.
*/
refreshState: Task.async(function*() {
let data = yield this.getCurrentState();
// By the time the new state is received, auto-refresh might be stopped.
if (!this.autoRefreshTimer) {
return;
}
// Check if something has changed
let hasChanged = false;
for (let key in data) {
if (this.state[key] !== data[key]) {
hasChanged = true;
break;
}
}
if (hasChanged) {
this.state = data;
this.emit(this.AUTO_REFRESH_EVENT, this.state);
}
})
});
/**

Просмотреть файл

@ -18,6 +18,7 @@ support-files =
[browser_animation_actors_02.js]
[browser_animation_actors_03.js]
[browser_animation_actors_04.js]
[browser_animation_actors_05.js]
[browser_navigateEvents.js]
[browser_storage_dynamic_windows.js]
[browser_storage_listings.js]

Просмотреть файл

@ -0,0 +1,57 @@
/* 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 AnimationPlayers can auto-refresh their states.
const {AnimationsFront} = require("devtools/server/actors/animation");
const {InspectorFront} = require("devtools/server/actors/inspector");
add_task(function*() {
let doc = yield addTab(MAIN_DOMAIN + "animation.html");
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);
let node = yield walker.querySelector(walker.rootNode, ".simple-animation");
let [player] = yield front.getAnimationPlayersForNode(node);
ok(player.startAutoRefresh, "The startAutoRefresh function is available");
ok(player.stopAutoRefresh, "The stopAutoRefresh function is available");
ok(player.state, "The current state is stored on the player");
info("Subscribe to the refresh event, start the auto-refresh and wait for " +
"a few events to be received");
player.startAutoRefresh();
let onAllEventsReceived = new Promise(resolve => {
let expected = 5;
let previousState = player.initialState;
let onNewState = (e, state) => {
ok(state.currentTime !== previousState.currentTime,
"The time has changed since the last update");
expected --;
previousState = state;
if (expected === 0) {
player.off(player.AUTO_REFRESH_EVENT, onNewState);
resolve();
}
};
player.on(player.AUTO_REFRESH_EVENT, onNewState);
});
yield onAllEventsReceived;
info("Stop the auto-refresh");
player.stopAutoRefresh();
yield closeDebuggerClient(client);
gBrowser.removeCurrentTab();
});