From 0688000585a1b222221522173b67ced6ed53531c Mon Sep 17 00:00:00 2001 From: Fedor Date: Sun, 7 Feb 2021 17:33:04 +0200 Subject: [PATCH] Sort out the Web Animations API. --- dom/animation/KeyframeEffect.cpp | 5 ++-- dom/animation/KeyframeUtils.cpp | 30 ++++++++++++------- dom/animation/test/crashtests/crashtests.list | 14 ++++----- dom/animation/test/mochitest.ini | 6 ++++ dom/base/nsDocument.cpp | 27 +++++++++++++++++ dom/base/nsDocument.h | 4 +++ dom/webidl/Animatable.webidl | 2 +- dom/webidl/Animation.webidl | 2 +- dom/webidl/AnimationTimeline.webidl | 2 +- dom/webidl/CSSPseudoElement.webidl | 2 +- dom/webidl/Document.webidl | 4 +-- dom/webidl/DocumentTimeline.webidl | 2 +- dom/xslt/tests/mochitest/test_bug1135764.html | 2 +- layout/reftests/web-animations/reftest.list | 6 ++-- layout/style/test/mochitest.ini | 3 ++ modules/libpref/init/all.js | 12 ++++---- 16 files changed, 86 insertions(+), 37 deletions(-) diff --git a/dom/animation/KeyframeEffect.cpp b/dom/animation/KeyframeEffect.cpp index 90230a5b4..090c7019d 100644 --- a/dom/animation/KeyframeEffect.cpp +++ b/dom/animation/KeyframeEffect.cpp @@ -10,6 +10,7 @@ #include "mozilla/dom/AnimationEffectTiming.h" #include "mozilla/dom/KeyframeEffectBinding.h" #include "mozilla/KeyframeUtils.h" +#include "mozilla/Preferences.h" #include "nsContentUtils.h" #include "nsDOMMutationObserver.h" // For nsAutoAnimationMutationBatch #include "nsIScriptError.h" @@ -135,9 +136,9 @@ void KeyframeEffect::SetIterationComposite( const IterationCompositeOperation& aIterationComposite) { - // Ignore iterationComposite if the Web Animations API is not enabled, + // Ignore iterationComposite if the API is not enabled, // then the default value 'Replace' will be used. - if (!AnimationUtils::IsCoreAPIEnabledForCaller()) { + if (!Preferences::GetBool("dom.animations-api.compositing.enabled")) { return; } diff --git a/dom/animation/KeyframeUtils.cpp b/dom/animation/KeyframeUtils.cpp index 166f6728a..540f892d5 100644 --- a/dom/animation/KeyframeUtils.cpp +++ b/dom/animation/KeyframeUtils.cpp @@ -7,6 +7,7 @@ #include "mozilla/AnimationUtils.h" #include "mozilla/ErrorResult.h" #include "mozilla/Move.h" +#include "mozilla/Preferences.h" #include "mozilla/RangedArray.h" #include "mozilla/ServoBindings.h" #include "mozilla/StyleAnimationValue.h" @@ -21,6 +22,7 @@ #include "nsCSSPropertyIDSet.h" #include "nsCSSProps.h" #include "nsCSSPseudoElements.h" // For CSSPseudoElementType +#include "nsDocument.h" #include "nsTArray.h" #include // For std::stable_sort @@ -400,7 +402,7 @@ GetKeyframeListFromPropertyIndexedKeyframe(JSContext* aCx, ErrorResult& aRv); static bool -RequiresAdditiveAnimation(const nsTArray& aKeyframes, +HasImplicitKeyframeValues(const nsTArray& aKeyframes, nsIDocument* aDocument); static void @@ -467,11 +469,13 @@ KeyframeUtils::GetKeyframesFromObject(JSContext* aCx, // says that if you don't have a keyframe at offset 0 or 1, then you should // synthesize one using an additive zero value when you go to compose style. // Until we implement additive animations we just throw if we encounter any - // set of keyframes that would put us in that situation. + // set of keyframes that would put us in that situation and keyframes aren't + // explicitly force-enabled. - if (RequiresAdditiveAnimation(keyframes, aDocument)) { - aRv.Throw(NS_ERROR_DOM_ANIM_MISSING_PROPS_ERR); + if (!nsDocument::AreWebAnimationsImplicitKeyframesEnabled(aCx, nullptr) && + HasImplicitKeyframeValues(keyframes, aDocument)) { keyframes.Clear(); + aRv.Throw(NS_ERROR_DOM_ANIM_MISSING_PROPS_ERR); } return keyframes; @@ -1330,10 +1334,16 @@ GetKeyframeListFromPropertyIndexedKeyframe(JSContext* aCx, // No animation values for this property. continue; } - if (count == 1) { - // We don't support additive values and so can't support an - // animation that goes from the underlying value to this - // specified value. Throw an exception until we do support this. + if (!Preferences::GetBool("dom.animations-api.implicit-keyframes.enabled") && + count == 1) { + // We don't support implicit keyframes by preference. + aRv.Throw(NS_ERROR_DOM_ANIM_MISSING_PROPS_ERR); + return; + } else if (count == 1) { + // Implicit keyframes isn't implemented yet and so we can't + // support an animation that goes from the underlying value + // to this specified value. + // Throw an exception until we do support this. aRv.Throw(NS_ERROR_DOM_ANIM_MISSING_PROPS_ERR); return; } @@ -1374,7 +1384,7 @@ GetKeyframeListFromPropertyIndexedKeyframe(JSContext* aCx, * try to detect where we have an invalid value at 0%/100%. */ static bool -RequiresAdditiveAnimation(const nsTArray& aKeyframes, +HasImplicitKeyframeValues(const nsTArray& aKeyframes, nsIDocument* aDocument) { // We are looking to see if that every property referenced in |aKeyframes| @@ -1385,7 +1395,7 @@ RequiresAdditiveAnimation(const nsTArray& aKeyframes, // a document which we might not always have at the point where we want to // perform this check. // - // This is only a temporary measure until we implement additive animation. + // This is only a temporary measure until we implement implicit keyframes. // So as long as this check catches most cases, and we don't do anything // horrible in one of the cases we can't detect, it should be sufficient. diff --git a/dom/animation/test/crashtests/crashtests.list b/dom/animation/test/crashtests/crashtests.list index f61d7f876..29b18769a 100644 --- a/dom/animation/test/crashtests/crashtests.list +++ b/dom/animation/test/crashtests/crashtests.list @@ -1,13 +1,13 @@ pref(dom.animations-api.core.enabled,true) load 1239889-1.html pref(dom.animations-api.core.enabled,true) load 1244595-1.html -pref(dom.animations-api.core.enabled,true) load 1216842-1.html -pref(dom.animations-api.core.enabled,true) load 1216842-2.html -pref(dom.animations-api.core.enabled,true) load 1216842-3.html -pref(dom.animations-api.core.enabled,true) load 1216842-4.html -pref(dom.animations-api.core.enabled,true) load 1216842-5.html -pref(dom.animations-api.core.enabled,true) load 1216842-6.html +pref(dom.animations-api.core.enabled,true) pref(dom.animations-api.timelines.enabled,true) load 1216842-1.html +pref(dom.animations-api.core.enabled,true) pref(dom.animations-api.timelines.enabled,true) load 1216842-2.html +pref(dom.animations-api.core.enabled,true) pref(dom.animations-api.timelines.enabled,true) load 1216842-3.html +pref(dom.animations-api.core.enabled,true) pref(dom.animations-api.timelines.enabled,true) load 1216842-4.html +pref(dom.animations-api.core.enabled,true) pref(dom.animations-api.timelines.enabled,true) load 1216842-5.html +pref(dom.animations-api.core.enabled,true) pref(dom.animations-api.timelines.enabled,true) load 1216842-6.html pref(dom.animations-api.core.enabled,true) load 1272475-1.html pref(dom.animations-api.core.enabled,true) load 1272475-2.html pref(dom.animations-api.core.enabled,true) load 1278485-1.html -pref(dom.animations-api.core.enabled,true) load 1277272-1.html +pref(dom.animations-api.core.enabled,true) pref(dom.animations-api.timelines.enabled,true) load 1277272-1.html pref(dom.animations-api.core.enabled,true) load 1290535-1.html diff --git a/dom/animation/test/mochitest.ini b/dom/animation/test/mochitest.ini index db6dffada..ecdb674fe 100644 --- a/dom/animation/test/mochitest.ini +++ b/dom/animation/test/mochitest.ini @@ -1,4 +1,10 @@ [DEFAULT] +prefs = + dom.animations-api.compositing.enabled=true + dom.animations-api.core.enabled=true + dom.animations-api.getAnimations.enabled=true + dom.animations-api.implicit-keyframes.enabled=true + dom.animations-api.timelines.enabled=true # Support files for chrome tests that we want to load over HTTP need # to go in here, not chrome.ini. support-files = diff --git a/dom/base/nsDocument.cpp b/dom/base/nsDocument.cpp index 3d866ec42..1287335b9 100644 --- a/dom/base/nsDocument.cpp +++ b/dom/base/nsDocument.cpp @@ -2923,6 +2923,33 @@ nsDocument::IsWebAnimationsEnabled(JSContext* /*unused*/, JSObject* /*unused*/) Preferences::GetBool("dom.animations-api.core.enabled"); } +bool +nsDocument::AreWebAnimationsTimelinesEnabled(JSContext* /*unused*/, JSObject* /*unused*/) +{ + MOZ_ASSERT(NS_IsMainThread()); + + return nsContentUtils::IsCallerChrome() || + Preferences::GetBool("dom.animations-api.timelines.enabled"); +} + +bool +nsDocument::AreWebAnimationsImplicitKeyframesEnabled(JSContext* /*unused*/, JSObject* /*unused*/) +{ + MOZ_ASSERT(NS_IsMainThread()); + + return nsContentUtils::IsCallerChrome() || + Preferences::GetBool("dom.animations-api.implicit-keyframes.enabled"); +} + +bool +nsDocument::IsWebAnimationsGetAnimationsEnabled(JSContext* /*unused*/, JSObject* /*unused*/) +{ + MOZ_ASSERT(NS_IsMainThread()); + + return nsContentUtils::IsCallerChrome() || + Preferences::GetBool("dom.animations-api.getAnimations.enabled"); +} + DocumentTimeline* nsDocument::Timeline() { diff --git a/dom/base/nsDocument.h b/dom/base/nsDocument.h index 951ed2616..010f95ae2 100644 --- a/dom/base/nsDocument.h +++ b/dom/base/nsDocument.h @@ -433,6 +433,10 @@ public: static bool IsElementAnimateEnabled(JSContext* aCx, JSObject* aObject); static bool IsWebAnimationsEnabled(JSContext* aCx, JSObject* aObject); + static bool AreWebAnimationsImplicitKeyframesEnabled(JSContext* aCx, JSObject* aObject); + static bool AreWebAnimationsTimelinesEnabled(JSContext* aCx, JSObject* aObject); + static bool IsWebAnimationsGetAnimationsEnabled(JSContext* aCx, JSObject* aObject); + virtual mozilla::dom::DocumentTimeline* Timeline() override; virtual void GetAnimations( nsTArray>& aAnimations) override; diff --git a/dom/webidl/Animatable.webidl b/dom/webidl/Animatable.webidl index 4c1396c99..decc13960 100644 --- a/dom/webidl/Animatable.webidl +++ b/dom/webidl/Animatable.webidl @@ -23,6 +23,6 @@ interface Animatable { [Func="nsDocument::IsElementAnimateEnabled", Throws] Animation animate(object? keyframes, optional UnrestrictedDoubleOrKeyframeAnimationOptions options); - [Func="nsDocument::IsWebAnimationsEnabled"] + [Func="nsDocument::IsWebAnimationsGetAnimationsEnabled"] sequence getAnimations(optional AnimationFilter filter); }; diff --git a/dom/webidl/Animation.webidl b/dom/webidl/Animation.webidl index 615084f75..9fdea5ade 100644 --- a/dom/webidl/Animation.webidl +++ b/dom/webidl/Animation.webidl @@ -19,7 +19,7 @@ interface Animation : EventTarget { attribute DOMString id; [Func="nsDocument::IsWebAnimationsEnabled", Pure] attribute AnimationEffectReadOnly? effect; - [Func="nsDocument::IsWebAnimationsEnabled"] + [Func="nsDocument::AreWebAnimationsTimelinesEnabled"] attribute AnimationTimeline? timeline; [BinaryName="startTimeAsDouble"] attribute double? startTime; diff --git a/dom/webidl/AnimationTimeline.webidl b/dom/webidl/AnimationTimeline.webidl index fe3d0fb49..4cf5567ce 100644 --- a/dom/webidl/AnimationTimeline.webidl +++ b/dom/webidl/AnimationTimeline.webidl @@ -10,7 +10,7 @@ * liability, trademark and document use rules apply. */ -[Func="nsDocument::IsWebAnimationsEnabled"] +[Func="nsDocument::AreWebAnimationsTimelinesEnabled"] interface AnimationTimeline { [BinaryName="currentTimeAsDouble"] readonly attribute double? currentTime; diff --git a/dom/webidl/CSSPseudoElement.webidl b/dom/webidl/CSSPseudoElement.webidl index 96d191e3a..250bef03c 100644 --- a/dom/webidl/CSSPseudoElement.webidl +++ b/dom/webidl/CSSPseudoElement.webidl @@ -15,7 +15,7 @@ // this interface. // What we implement here is a minimal subset of the two definitions which we // ship behind a pref until the specification issues have been resolved. -[Func="nsDocument::IsWebAnimationsEnabled"] +[Func="nsDocument::IsWebAnimationsGetAnimationsEnabled"] interface CSSPseudoElement { readonly attribute DOMString type; readonly attribute Element parentElement; diff --git a/dom/webidl/Document.webidl b/dom/webidl/Document.webidl index 26985202b..2ade9a2c9 100644 --- a/dom/webidl/Document.webidl +++ b/dom/webidl/Document.webidl @@ -312,9 +312,9 @@ partial interface Document { // http://w3c.github.io/web-animations/#extensions-to-the-document-interface partial interface Document { - [Func="nsDocument::IsWebAnimationsEnabled"] + [Func="nsDocument::AreWebAnimationsTimelinesEnabled"] readonly attribute DocumentTimeline timeline; - [Func="nsDocument::IsWebAnimationsEnabled"] + [Func="nsDocument::IsWebAnimationsGetAnimationsEnabled"] sequence getAnimations(); }; diff --git a/dom/webidl/DocumentTimeline.webidl b/dom/webidl/DocumentTimeline.webidl index 916b1a491..f10e2b365 100644 --- a/dom/webidl/DocumentTimeline.webidl +++ b/dom/webidl/DocumentTimeline.webidl @@ -14,7 +14,7 @@ dictionary DocumentTimelineOptions { DOMHighResTimeStamp originTime = 0; }; -[Func="nsDocument::IsWebAnimationsEnabled", +[Func="nsDocument::AreWebAnimationsTimelinesEnabled", Constructor (optional DocumentTimelineOptions options)] interface DocumentTimeline : AnimationTimeline { }; diff --git a/dom/xslt/tests/mochitest/test_bug1135764.html b/dom/xslt/tests/mochitest/test_bug1135764.html index 5a7410e37..b1f627c87 100644 --- a/dom/xslt/tests/mochitest/test_bug1135764.html +++ b/dom/xslt/tests/mochitest/test_bug1135764.html @@ -27,7 +27,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1135764 } addLoadEvent(function() { SpecialPowers.pushPrefEnv( - { "set": [[ "dom.animations-api.core.enabled", true]] }, + { "set": [[ "dom.animations-api.timelines.enabled", true]] }, function() { var ifr = document.querySelector("iframe"); ifr.onload = function() { diff --git a/layout/reftests/web-animations/reftest.list b/layout/reftests/web-animations/reftest.list index eefd41f49..da1d07089 100644 --- a/layout/reftests/web-animations/reftest.list +++ b/layout/reftests/web-animations/reftest.list @@ -15,6 +15,6 @@ test-pref(dom.animations-api.core.enabled,true) == stacking-context-transform-ch test-pref(dom.animations-api.core.enabled,true) == stacking-context-transform-changing-effect.html stacking-context-animation-ref.html test-pref(dom.animations-api.core.enabled,true) == stacking-context-transform-changing-display-property.html stacking-context-animation-ref.html test-pref(dom.animations-api.core.enabled,true) == stacking-context-transform-losing-css-animation-in-delay.html stacking-context-animation-ref.html -test-pref(dom.animations-api.core.enabled,true) == style-updates-on-iteration-composition-changed-from-accumulate-to-replace.html style-updates-for-iteration-composite-ref.html -test-pref(dom.animations-api.core.enabled,true) == style-updates-on-iteration-composition-changed-from-replace-to-accumulate.html style-updates-for-iteration-composite-ref.html -test-pref(dom.animations-api.core.enabled,true) == style-updates-on-current-iteration-changed.html style-updates-for-iteration-composite-ref.html +test-pref(dom.animations-api.core.enabled,true) test-pref(dom.animations-api.compositing.enabled,true) == style-updates-on-iteration-composition-changed-from-accumulate-to-replace.html style-updates-for-iteration-composite-ref.html +test-pref(dom.animations-api.core.enabled,true) test-pref(dom.animations-api.compositing.enabled,true) == style-updates-on-iteration-composition-changed-from-replace-to-accumulate.html style-updates-for-iteration-composite-ref.html +test-pref(dom.animations-api.core.enabled,true) test-pref(dom.animations-api.compositing.enabled,true) == style-updates-on-current-iteration-changed.html style-updates-for-iteration-composite-ref.html diff --git a/layout/style/test/mochitest.ini b/layout/style/test/mochitest.ini index 8182691ca..358bda2fc 100644 --- a/layout/style/test/mochitest.ini +++ b/layout/style/test/mochitest.ini @@ -1,4 +1,7 @@ [DEFAULT] +prefs = + dom.animations-api.core.enabled=true + dom.animations-api.timelines.enabled=true support-files = animation_utils.js ccd-quirks.html diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index e924b0cbb..4a071af20 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -2710,14 +2710,12 @@ pref("layout.idle_period.required_quiescent_frames", 2); pref("layout.idle_period.time_limit", 1); // Is support for the Web Animations API enabled? -// Before enabling this by default, make sure also CSSPseudoElement interface -// has been spec'ed properly, or we should add a separate pref for -// CSSPseudoElement interface. See Bug 1174575 for further details. -#ifdef RELEASE_OR_BETA -pref("dom.animations-api.core.enabled", false); -#else pref("dom.animations-api.core.enabled", true); -#endif + +pref("dom.animations-api.timelines.enabled", false); +pref("dom.animations-api.implicit-keyframes.enabled", false); +pref("dom.animations-api.compositing.enabled", false); +pref("dom.animations-api.getAnimations.enabled", false); // Is support for the Element.animate() function (a subset of the Web Animations // API) enabled?