Bug 1449532 - Part III, Polyfill Web Animation API features
The Animation and KeyframeEffect constructors and the finshed promise are not
enabled on release channel currently. The polyfill is added to make sure
we don't break on release.
When the feature ships, removing the polyfill should be as easy as
reverting this changeset.
MozReview-Commit-ID: 2EWN7hBN5tj
--- a/toolkit/content/widgets/videocontrols.xml
+++ b/toolkit/content/widgets/videocontrols.xml
@@ -1018,16 +1018,42 @@
{ opacity: 1 }
],
options: {
duration: 1050
}
}
},
+ // Polyfill animation.finished promise, also invalidate
+ // the previous promise.
+ // Remove when the platform implementation ships.
+ // (currently behind dom.animations-api.core.enabled)
+ installFinishedPromisePolyfill(animation) {
+ let handler = {
+ handleEvent(evt) {
+ animation.removeEventListener("finish", this);
+ animation.removeEventListener("cancel", this);
+ if (evt.type == "finish" &&
+ this === animation.finished) {
+ this.fn();
+ }
+ },
+ then(fn) {
+ this.fn = fn;
+ }
+ };
+ // Note that handler is not a real Promise.
+ // All it offered is a then() method to register a callback
+ // to be triggered at the right time.
+ animation.finished = handler;
+ animation.addEventListener("finish", handler);
+ animation.addEventListener("cancel", handler);
+ },
+
startFade(element, fadeIn, immediate = false) {
// Bug 493523, the scrubber doesn't call valueChanged while hidden,
// so our dependent state (eg, timestamp in the thumb) will be stale.
// As a workaround, update it manually when it first becomes unhidden.
if (element == this.controlBar && fadeIn && element.hidden) {
this.scrubber.value = this.video.currentTime * 1000;
}
@@ -1035,18 +1061,25 @@
this.animationProps[element.getAttribute("anonid")];
if (!animationProp) {
throw new Error("Element " + element.getAttribute("anonid") +
" has no transition. Toggle the hidden property directly.");
}
let animation = this.animationMap.get(element);
if (!animation) {
+ // Create the animation object but don't start it.
+ // To be replaced with the following when the constructors ship
+ // (currently behind dom.animations-api.core.enabled)
+ /*
animation = new Animation(new KeyframeEffect(
element, animationProp.keyframes, animationProp.options));
+ */
+ animation = element.animate(animationProp.keyframes, animationProp.options);
+ animation.cancel();
this.animationMap.set(element, animation);
}
if (fadeIn) {
// hidden state should be controlled by adjustControlSize
if (element.isAdjustableControl && element.hiddenByAdjustment) {
return;
@@ -1072,16 +1105,17 @@
}
element.classList.toggle("fadeout", !fadeIn);
element.classList.toggle("fadein", fadeIn);
let finishedPromise;
if (!immediate) {
animation.playbackRate = fadeIn ? 1 : -1;
animation.play();
+ this.installFinishedPromisePolyfill(animation);
finishedPromise = animation.finished;
} else {
animation.cancel();
finishedPromise = Promise.resolve();
}
finishedPromise.then(() => {
if (element == this.controlBar) {
this.onControlBarAnimationFinished();
--- a/toolkit/themes/shared/media/videocontrols.css
+++ b/toolkit/themes/shared/media/videocontrols.css
@@ -60,16 +60,26 @@ audio > xul|videocontrols {
.touch .controlBar {
/* Do not delete: these variables are accessed by JavaScript directly.
see videocontrols.xml and search for |-width|. */
--scrubberStack-width: 84px;
--volumeStack-width: 64px;
}
+/*
+ XXX this is needed because of bug 1354501.
+ Can be removed when the bug is fixed, or when we move away from
+ the finish event to the finished promise.
+ (currently behind dom.animations-api.core.enabled)
+*/
+.fadeout {
+ opacity: 0;
+}
+
.controlsContainer [hidden],
.controlBar[hidden] {
display: none;
}
.controlBar[size="hidden"] {
display: none;
}