Bug 1196114 - Part 2: Add AnimationPropertyStatus interface and KeyframeEffectReadOnly.runningStatus(). r?birtles,smaug draft
authorHiroyuki Ikezoe <hiikezoe@mozilla-japan.org>
Fri, 04 Mar 2016 06:36:41 +0900
changeset 336794 29f2ddc6cc2d15871d4071b07f4e632ccedf2942
parent 336793 64fec231dbcb268bc5a65ed53cad0eddcf842483
child 336795 4cf8ee93ff08804396c28c82c3510534c14faf27
child 336800 6536260cf7f7e2c532336e930ea0759a0237c20b
push id12183
push userhiikezoe@mozilla-japan.org
push dateFri, 04 Mar 2016 06:04:41 +0000
reviewersbirtles, smaug
bugs1196114
milestone47.0a1
Bug 1196114 - Part 2: Add AnimationPropertyStatus interface and KeyframeEffectReadOnly.runningStatus(). r?birtles,smaug MozReview-Commit-ID: CPz3DtWxKll
dom/animation/KeyframeEffect.cpp
dom/animation/KeyframeEffect.h
dom/animation/test/chrome.ini
dom/animation/test/chrome/test_animation_property_state.html
dom/webidl/KeyframeEffect.webidl
--- a/dom/animation/KeyframeEffect.cpp
+++ b/dom/animation/KeyframeEffect.cpp
@@ -1872,16 +1872,40 @@ KeyframeEffectReadOnly::GetFrames(JSCont
       previousEntry = entry;
       entry = &entries[i];
     } while (entry->SameKeyframe(*previousEntry));
 
     aResult.AppendElement(keyframe);
   }
 }
 
+
+void
+KeyframeEffectReadOnly::GetPropertyState(
+    nsTArray<AnimationPropertyState>& aStates) const
+{
+  for (const AnimationProperty& property : mProperties) {
+    // Bug 1252730: We should also expose this winsInCascade as well.
+    if (!property.mWinsInCascade) {
+      continue;
+    }
+
+    AnimationPropertyState state;
+    state.mProperty.Construct(
+      NS_ConvertASCIItoUTF16(nsCSSProps::GetStringValue(property.mProperty)));
+    state.mRunningOnCompositor.Construct(property.mIsRunningOnCompositor);
+
+    if (property.mPerformanceWarning.isSome()) {
+      state.mWarning.Construct(property.mPerformanceWarning.value());
+    }
+
+    aStates.AppendElement(state);
+  }
+}
+
 /* static */ const TimeDuration
 KeyframeEffectReadOnly::OverflowRegionRefreshInterval()
 {
   // The amount of time we can wait between updating throttled animations
   // on the main thread that influence the overflow region.
   static const TimeDuration kOverflowRegionRefreshInterval =
     TimeDuration::FromMilliseconds(200);
 
--- a/dom/animation/KeyframeEffect.h
+++ b/dom/animation/KeyframeEffect.h
@@ -38,16 +38,17 @@ class AnimValuesStyleRule;
 enum class CSSPseudoElementType : uint8_t;
 
 namespace dom {
 class ElementOrCSSPseudoElement;
 class OwningElementOrCSSPseudoElement;
 class UnrestrictedDoubleOrKeyframeEffectOptions;
 enum class IterationCompositeOperation : uint32_t;
 enum class CompositeOperation : uint32_t;
+struct AnimationPropertyState;
 }
 
 /**
  * Stores the results of calculating the timing properties of an animation
  * at a given sample time.
  */
 struct ComputedTiming
 {
@@ -302,16 +303,18 @@ public:
   // contained in |aSetProperties|.
   // Any updated properties are added to |aSetProperties|.
   void ComposeStyle(RefPtr<AnimValuesStyleRule>& aStyleRule,
                     nsCSSPropertySet& aSetProperties);
   // Returns true if at least one property is being animated on compositor.
   bool IsRunningOnCompositor() const;
   void SetIsRunningOnCompositor(nsCSSProperty aProperty, bool aIsRunning);
 
+  void GetPropertyState(nsTArray<AnimationPropertyState>& aStates) const;
+
   // Returns true if this effect, applied to |aFrame|, contains
   // properties that mean we shouldn't run *any* compositor animations on this
   // element.
   //
   // For example, if we have an animation of geometric properties like 'left'
   // and 'top' on an element, we force all 'transform' and 'opacity' animations
   // running at the same time on the same element to run on the main thread.
   //
--- a/dom/animation/test/chrome.ini
+++ b/dom/animation/test/chrome.ini
@@ -2,11 +2,12 @@
 support-files =
   testcommon.js
   ../../imptests/testharness.js
   ../../imptests/testharnessreport.js
 [chrome/test_animate_xrays.html]
 # file_animate_xrays.html needs to go in mochitest.ini since it is served
 # over HTTP
 [chrome/test_animation_observers.html]
+[chrome/test_animation_property_state.html]
 [chrome/test_restyles.html]
 [chrome/test_running_on_compositor.html]
 skip-if = buildapp == 'b2g'
new file mode 100644
--- /dev/null
+++ b/dom/animation/test/chrome/test_animation_property_state.html
@@ -0,0 +1,127 @@
+<!doctype html>
+<head>
+<meta charset=utf-8>
+<title>Bug 1196114 - Animation property which indicates
+       running on the compositor or not</title>
+<script type="application/javascript" src="../testharness.js"></script>
+<script type="application/javascript" src="../testharnessreport.js"></script>
+<script type="application/javascript" src="../testcommon.js"></script>
+<style>
+div {
+  /* Element needs geometry to be eligible for layerization */
+  width: 100px;
+  height: 100px;
+  background-color: white;
+}
+</style>
+</head>
+<body>
+<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1196114"
+  target="_blank">Mozilla Bug 1196114</a>
+<div id="log"></div>
+<script>
+'use strict';
+
+function compare_property_state(a, b) {
+  if (a.property > b.property) {
+    return -1;
+  } else if (a.property < b.property) {
+    return 1;
+  }
+  if (a.runningOnCompositor != b.runningOnCompositor) {
+    return a.runningOnCompositor ? 1 : -1;
+  }
+  return a.warning > b.warning ? -1 : 1;
+}
+
+function assert_animation_property_state_equals(actual, expected) {
+  assert_equals(actual.length, expected.length);
+
+  var sortedActual = actual.sort(compare_property_state);
+  var sortedExpected = expected.sort(compare_property_state);
+
+  for (var i = 0; i < sortedActual.length; i++) {
+    assert_equals(sortedActual[i].property,
+                  sortedExpected[i].property,
+                  'CSS property name should match');
+    assert_equals(sortedActual[i].runningOnCompositor,
+                  sortedExpected[i].runningOnCompositor,
+                  'runningOnCompositor property should match');
+  }
+}
+
+var gAnimationsTests = [
+  {
+    desc: 'animations on compositor',
+    frames: {
+      opacity: [0, 1]
+    },
+    expected: [
+      {
+        property: 'opacity',
+        runningOnCompositor: true
+      }
+    ]
+  },
+  {
+    desc: 'animations on main thread',
+    frames: {
+      backgroundColor: ['white', 'red']
+    },
+    expected: [
+      {
+        property: 'background-color',
+        runningOnCompositor: false
+      }
+    ]
+  },
+  {
+    desc: 'animations on both threads',
+    frames: {
+      backgroundColor: ['white', 'red'],
+      transform: ['translate(0px)', 'translate(100px)']
+    },
+    expected: [
+      {
+        property: 'background-color',
+        runningOnCompositor: false
+      },
+      {
+        property: 'transform',
+        runningOnCompositor: true
+      }
+    ]
+  },
+  {
+    desc: 'two animation properties on compositor thread',
+    frames: {
+      opacity: [0, 1],
+      transform: ['translate(0px)', 'translate(100px)']
+    },
+    expected: [
+      {
+        property: 'opacity',
+        runningOnCompositor: true
+      },
+      {
+        property: 'transform',
+        runningOnCompositor: true
+      }
+    ]
+  }
+];
+
+gAnimationsTests.forEach(function(subtest) {
+  promise_test(function(t) {
+    var div = addDiv(t);
+    var animation = div.animate(subtest.frames, 100000);
+    return animation.ready.then(t.step_func(function() {
+      assert_animation_property_state_equals(
+        animation.effect.getPropertyState(),
+        subtest.expected);
+    }));
+  }, subtest.desc);
+});
+
+</script>
+</body>
--- a/dom/webidl/KeyframeEffect.webidl
+++ b/dom/webidl/KeyframeEffect.webidl
@@ -40,16 +40,26 @@ interface KeyframeEffectReadOnly : Anima
   // Not yet implemented:
   // KeyframeEffect             clone();
 
   // We use object instead of ComputedKeyframe so that we can put the
   // property-value pairs on the object.
   [Throws] sequence<object> getFrames();
 };
 
+// Non-standard extensions
+dictionary AnimationPropertyState {
+  DOMString property;
+  boolean runningOnCompositor;
+  DOMString? warning;
+};
+
+partial interface KeyframeEffectReadOnly {
+  [ChromeOnly] sequence<AnimationPropertyState> getPropertyState();
+};
 
 [Func="nsDocument::IsWebAnimationsEnabled",
  Constructor ((Element or CSSPseudoElement)? target,
               object? frames,
               optional (unrestricted double or KeyframeEffectOptions) options)]
 interface KeyframeEffect : KeyframeEffectReadOnly {
   // Bug 1067769 - Allow setting KeyframeEffect.target
   // inherit attribute Animatable?                 target;