Bug 1379582 - Disable frames() timing function using a pref on release/beta channels; r=hiro
authorBrian Birtles <birtles@gmail.com>
Wed, 12 Jul 2017 08:41:58 +0900
changeset 607430 a1772d538281397995d64f83e591c4cde8732af0
parent 607429 1535861c7f58caf7abdc101d47e46cd711210bab
child 607431 45910b8e37deaf5f6593d3c7e582954652093555
child 607502 2ea915a5c474da35b3ab6cf828d6816d53e1347f
push id67985
push userbmo:emilio+bugs@crisal.io
push dateWed, 12 Jul 2017 08:36:44 +0000
reviewershiro
bugs1379582
milestone56.0a1
Bug 1379582 - Disable frames() timing function using a pref on release/beta channels; r=hiro MozReview-Commit-ID: 4B8NwMAfyrS
devtools/client/animationinspector/test/head.js
layout/style/ServoBindings.cpp
layout/style/ServoBindings.h
layout/style/nsCSSParser.cpp
layout/style/test/property_database.js
modules/libpref/init/all.js
testing/web-platform/meta/css-timing/__dir__.ini
testing/web-platform/meta/web-animations/__dir__.ini
--- a/devtools/client/animationinspector/test/head.js
+++ b/devtools/client/animationinspector/test/head.js
@@ -27,34 +27,37 @@ registerCleanupFunction(function* () {
 });
 
 // Clean-up all prefs that might have been changed during a test run
 // (safer here because if the test fails, then the pref is never reverted)
 registerCleanupFunction(() => {
   Services.prefs.clearUserPref("devtools.debugger.log");
 });
 
-// WebAnimations API is not enabled by default in all release channels yet, see
-// Bug 1264101.
-function enableWebAnimationsAPI() {
+// Some animation features are not enabled by default in release/beta channels
+// yet including:
+// * parts of the Web Animations API (Bug 1264101), and
+// * the frames() timing function (Bug 1379582).
+function enableAnimationFeatures() {
   return new Promise(resolve => {
     SpecialPowers.pushPrefEnv({"set": [
-      ["dom.animations-api.core.enabled", true]
+      ["dom.animations-api.core.enabled", true],
+      ["layout.css.frames-timing.enabled", true],
     ]}, resolve);
   });
 }
 
 /**
  * Add a new test tab in the browser and load the given url.
  * @param {String} url The url to be loaded in the new tab
  * @return a promise that resolves to the tab object when the url is loaded
  */
 var _addTab = addTab;
 addTab = function (url) {
-  return enableWebAnimationsAPI().then(() => _addTab(url)).then(tab => {
+  return enableAnimationFeatures().then(() => _addTab(url)).then(tab => {
     let browser = tab.linkedBrowser;
     info("Loading the helper frame script " + FRAME_SCRIPT_URL);
     browser.messageManager.loadFrameScript(FRAME_SCRIPT_URL, false);
     info("Loading the helper frame script " + COMMON_FRAME_SCRIPT_URL);
     browser.messageManager.loadFrameScript(COMMON_FRAME_SCRIPT_URL, false);
     return tab;
   });
 };
--- a/layout/style/ServoBindings.cpp
+++ b/layout/style/ServoBindings.cpp
@@ -48,16 +48,17 @@
 
 #include "mozilla/DeclarationBlockInlines.h"
 #include "mozilla/EffectCompositor.h"
 #include "mozilla/EffectSet.h"
 #include "mozilla/EventStates.h"
 #include "mozilla/GeckoStyleContext.h"
 #include "mozilla/Keyframe.h"
 #include "mozilla/Mutex.h"
+#include "mozilla/Preferences.h"
 #include "mozilla/ServoElementSnapshot.h"
 #include "mozilla/ServoRestyleManager.h"
 #include "mozilla/StyleAnimationValue.h"
 #include "mozilla/SystemGroup.h"
 #include "mozilla/ServoMediaList.h"
 #include "mozilla/RWLock.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/ElementInlines.h"
@@ -83,16 +84,17 @@ using namespace mozilla::dom;
   }
 #include "mozilla/ServoArcTypeList.h"
 #undef SERVO_ARC_TYPE
 
 
 static Mutex* sServoFontMetricsLock = nullptr;
 static RWLock* sServoLangFontPrefsLock = nullptr;
 
+static bool sFramesTimingFunctionEnabled;
 
 static
 const nsFont*
 ThreadSafeGetDefaultFontHelper(const nsPresContext* aPresContext,
                                nsIAtom* aLanguage, uint8_t aGenericId)
 {
   bool needsCache = false;
   const nsFont* retval;
@@ -759,16 +761,21 @@ Gecko_GetPositionInSegment(RawGeckoAnima
   double positionInSegment =
     (aProgress - aSegment->mFromKey) / (aSegment->mToKey - aSegment->mFromKey);
 
   return ComputedTimingFunction::GetPortion(aSegment->mTimingFunction,
                                             positionInSegment,
                                             aBeforeFlag);
 }
 
+bool
+Gecko_IsFramesTimingEnabled() {
+  return sFramesTimingFunctionEnabled;
+}
+
 RawServoAnimationValueBorrowedOrNull
 Gecko_AnimationGetBaseStyle(void* aBaseStyles, nsCSSPropertyID aProperty)
 {
   auto base =
     static_cast<nsRefPtrHashtable<nsUint32HashKey, RawServoAnimationValue>*>
       (aBaseStyles);
   return base->GetWeak(aProperty);
 }
@@ -2334,16 +2341,19 @@ Gecko_XBLBinding_InheritsStyle(RawGeckoX
 void
 InitializeServo()
 {
   URLExtraData::InitDummy();
   Servo_Initialize(URLExtraData::Dummy());
 
   sServoFontMetricsLock = new Mutex("Gecko_GetFontMetrics");
   sServoLangFontPrefsLock = new RWLock("nsPresContext::GetDefaultFont");
+
+  Preferences::AddBoolVarCache(&sFramesTimingFunctionEnabled,
+                               "layout.css.frames-timing.enabled");
 }
 
 void
 ShutdownServo()
 {
   delete sServoFontMetricsLock;
   delete sServoLangFontPrefsLock;
   Servo_Shutdown();
--- a/layout/style/ServoBindings.h
+++ b/layout/style/ServoBindings.h
@@ -232,16 +232,17 @@ nsCSSPropertyID Gecko_ElementTransitions
 RawServoAnimationValueBorrowedOrNull Gecko_ElementTransitions_EndValueAt(
   RawGeckoElementBorrowed aElementOrPseudo,
   size_t aIndex);
 double Gecko_GetProgressFromComputedTiming(RawGeckoComputedTimingBorrowed aComputedTiming);
 double Gecko_GetPositionInSegment(
   RawGeckoAnimationPropertySegmentBorrowed aSegment,
   double aProgress,
   mozilla::ComputedTimingFunction::BeforeFlag aBeforeFlag);
+bool Gecko_IsFramesTimingEnabled();
 // Get servo's AnimationValue for |aProperty| from the cached base style
 // |aBaseStyles|.
 // |aBaseStyles| is nsRefPtrHashtable<nsUint32HashKey, RawServoAnimationValue>.
 // We use void* to avoid exposing nsRefPtrHashtable in FFI.
 RawServoAnimationValueBorrowedOrNull Gecko_AnimationGetBaseStyle(
   void* aBaseStyles,
   nsCSSPropertyID aProperty);
 void Gecko_StyleTransition_SetUnsupportedProperty(
--- a/layout/style/nsCSSParser.cpp
+++ b/layout/style/nsCSSParser.cpp
@@ -71,16 +71,17 @@ using namespace mozilla::css;
 typedef nsCSSProps::KTableEntry KTableEntry;
 
 // pref-backed bool values (hooked up in nsCSSParser::Startup)
 static bool sOpentypeSVGEnabled;
 static bool sWebkitPrefixedAliasesEnabled;
 static bool sWebkitDevicePixelRatioEnabled;
 static bool sMozGradientsEnabled;
 static bool sControlCharVisibility;
+static bool sFramesTimingFunctionEnabled;
 
 const uint32_t
 nsCSSProps::kParserVariantTable[eCSSProperty_COUNT_no_shorthands] = {
 #define CSS_PROP(name_, id_, method_, flags_, pref_, parsevariant_, kwtable_, \
                  stylestruct_, stylestructoffset_, animtype_)                 \
   parsevariant_,
 #define CSS_PROP_LIST_INCLUDE_LOGICAL
 #include "nsCSSPropList.h"
@@ -7852,17 +7853,18 @@ CSSParserImpl::ParseVariant(nsCSSValue& 
     }
     if (tk->mIdent.LowerCaseEqualsLiteral("steps")) {
       if (!ParseTransitionStepTimingFunctionValues(aValue)) {
         SkipUntil(')');
         return CSSParseResult::Error;
       }
       return CSSParseResult::Ok;
     }
-    if (tk->mIdent.LowerCaseEqualsLiteral("frames")) {
+    if (sFramesTimingFunctionEnabled &&
+        tk->mIdent.LowerCaseEqualsLiteral("frames")) {
       if (!ParseTransitionFramesTimingFunctionValues(aValue)) {
         SkipUntil(')');
         return CSSParseResult::Error;
       }
       return CSSParseResult::Ok;
     }
   }
   if ((aVariantMask & VARIANT_CALC) &&
@@ -17833,16 +17835,18 @@ nsCSSParser::Startup()
   Preferences::AddBoolVarCache(&sWebkitPrefixedAliasesEnabled,
                                "layout.css.prefixes.webkit");
   Preferences::AddBoolVarCache(&sWebkitDevicePixelRatioEnabled,
                                "layout.css.prefixes.device-pixel-ratio-webkit");
   Preferences::AddBoolVarCache(&sMozGradientsEnabled,
                                "layout.css.prefixes.gradients");
   Preferences::AddBoolVarCache(&sControlCharVisibility,
                                "layout.css.control-characters.visible");
+  Preferences::AddBoolVarCache(&sFramesTimingFunctionEnabled,
+                               "layout.css.frames-timing.enabled");
 }
 
 nsCSSParser::nsCSSParser(mozilla::css::Loader* aLoader,
                          CSSStyleSheet* aSheet)
 {
   CSSParserImpl *impl = gFreeList;
   if (impl) {
     gFreeList = impl->mNextFree;
--- a/layout/style/test/property_database.js
+++ b/layout/style/test/property_database.js
@@ -1023,18 +1023,18 @@ var gCSSProperties = {
     other_values: [ "paused", "running, running", "paused, running", "paused, paused", "running, paused", "paused, running, running, running, paused, running" ],
     invalid_values: [ "0" ]
   },
   "animation-timing-function": {
     domProp: "animationTimingFunction",
     inherited: false,
     type: CSS_TYPE_LONGHAND,
     initial_values: [ "ease" ],
-    other_values: [ "cubic-bezier(0.25, 0.1, 0.25, 1.0)", "linear", "ease-in", "ease-out", "ease-in-out", "linear, ease-in, cubic-bezier(0.1, 0.2, 0.8, 0.9)", "cubic-bezier(0.5, 0.5, 0.5, 0.5)", "cubic-bezier(0.25, 1.5, 0.75, -0.5)", "step-start", "step-end", "steps(1)", "steps(2, start)", "steps(386)", "steps(3, end)", "frames(2)", "frames(1000)", "frames( 2 )" ],
-    invalid_values: [ "none", "auto", "cubic-bezier(0.25, 0.1, 0.25)", "cubic-bezier(0.25, 0.1, 0.25, 0.25, 1.0)", "cubic-bezier(-0.5, 0.5, 0.5, 0.5)", "cubic-bezier(1.5, 0.5, 0.5, 0.5)", "cubic-bezier(0.5, 0.5, -0.5, 0.5)", "cubic-bezier(0.5, 0.5, 1.5, 0.5)", "steps(2, step-end)", "steps(0)", "steps(-2)", "steps(0, step-end, 1)", "frames(1)", "frames(-2)", "frames", "frames()", "frames(,)", "frames(a)", "frames(2.0)", "frames(2.5)", "frames(2 3)" ]
+    other_values: [ "cubic-bezier(0.25, 0.1, 0.25, 1.0)", "linear", "ease-in", "ease-out", "ease-in-out", "linear, ease-in, cubic-bezier(0.1, 0.2, 0.8, 0.9)", "cubic-bezier(0.5, 0.5, 0.5, 0.5)", "cubic-bezier(0.25, 1.5, 0.75, -0.5)", "step-start", "step-end", "steps(1)", "steps(2, start)", "steps(386)", "steps(3, end)" ],
+    invalid_values: [ "none", "auto", "cubic-bezier(0.25, 0.1, 0.25)", "cubic-bezier(0.25, 0.1, 0.25, 0.25, 1.0)", "cubic-bezier(-0.5, 0.5, 0.5, 0.5)", "cubic-bezier(1.5, 0.5, 0.5, 0.5)", "cubic-bezier(0.5, 0.5, -0.5, 0.5)", "cubic-bezier(0.5, 0.5, 1.5, 0.5)", "steps(2, step-end)", "steps(0)", "steps(-2)", "steps(0, step-end, 1)" ]
   },
   "-moz-appearance": {
     domProp: "MozAppearance",
     inherited: false,
     type: CSS_TYPE_LONGHAND,
     initial_values: [ "none" ],
     other_values: [ "radio", "menulist" ],
     invalid_values: []
@@ -5698,16 +5698,24 @@ if (IsCSSPropertyPrefEnabled("layout.css
       "'wdth', 1" // comma within pair
     ],
     unbalanced_values: [
       "'wdth\" 1", "\"wdth' 1" // mismatched quotes
     ]
   }
 }
 
+if (IsCSSPropertyPrefEnabled("layout.css.frames-timing.enabled")) {
+  gCSSProperties["animation-timing-function"].other_values.push(
+    "frames(2)", "frames(1000)", "frames( 2 )");
+  gCSSProperties["animation-timing-function"].invalid_values.push(
+    "frames(1)", "frames(-2)", "frames", "frames()", "frames(,)",
+    "frames(a)", "frames(2.0)", "frames(2.5)", "frames(2 3)");
+}
+
 if (IsCSSPropertyPrefEnabled("svg.paint-order.enabled")) {
   gCSSProperties["paint-order"] = {
     domProp: "paintOrder",
     inherited: true,
     type: CSS_TYPE_LONGHAND,
     initial_values: [ "normal" ],
     other_values: [ "fill", "fill stroke", "fill stroke markers", "stroke markers fill" ],
     invalid_values: [ "fill stroke markers fill", "fill normal" ]
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -2855,16 +2855,23 @@ pref("layout.css.float-logical-values.en
 pref("layout.css.image-orientation.enabled", true);
 
 // Is support for the font-display @font-face descriptor enabled?
 pref("layout.css.font-display.enabled", false);
 
 // Is support for variation fonts enabled?
 pref("layout.css.font-variations.enabled", false);
 
+// Is support for the frames() timing function enabled?
+#ifdef RELEASE_OR_BETA
+pref("layout.css.frames-timing.enabled", false);
+#else
+pref("layout.css.frames-timing.enabled", true);
+#endif
+
 // Are sets of prefixed properties supported?
 pref("layout.css.prefixes.border-image", true);
 pref("layout.css.prefixes.transforms", true);
 pref("layout.css.prefixes.transitions", true);
 pref("layout.css.prefixes.animations", true);
 pref("layout.css.prefixes.box-sizing", true);
 pref("layout.css.prefixes.font-features", true);
 
--- a/testing/web-platform/meta/css-timing/__dir__.ini
+++ b/testing/web-platform/meta/css-timing/__dir__.ini
@@ -1,1 +1,2 @@
-prefs: [dom.animations-api.core.enabled:true]
\ No newline at end of file
+prefs: [dom.animations-api.core.enabled:true,
+        layout.css.frames-timing.enabled:true]
--- a/testing/web-platform/meta/web-animations/__dir__.ini
+++ b/testing/web-platform/meta/web-animations/__dir__.ini
@@ -1,1 +1,2 @@
-prefs: [dom.animations-api.core.enabled:true]
\ No newline at end of file
+prefs: [dom.animations-api.core.enabled:true,
+        layout.css.frames-timing.enabled:true]