Bug 1196114 - Part 5: Store performce warning information as enum type. r=birtles
authorHiroyuki Ikezoe <hiikezoe@mozilla-japan.org>
Fri, 04 Mar 2016 17:54:25 +0900
changeset 323194 605c2c5d1ab07663c86ff9aba39be2759520dd86
parent 323193 ad0b2eb05697db2f9ba31e25f8d1b5eabd9ce9aa
child 323195 5be4e5b20d33bf626f4c83bf7253f64f666d7e46
push id5913
push userjlund@mozilla.com
push dateMon, 25 Apr 2016 16:57:49 +0000
treeherdermozilla-beta@dcaf0a6fa115 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbirtles
bugs1196114
milestone47.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1196114 - Part 5: Store performce warning information as enum type. r=birtles Each warning message is generated only when getPropertyState() is called. MozReview-Commit-ID: C03ZSvPv9ff
dom/animation/AnimationPerformanceWarning.cpp
dom/animation/AnimationPerformanceWarning.h
dom/animation/EffectCompositor.cpp
dom/animation/EffectCompositor.h
dom/animation/KeyframeEffect.cpp
dom/animation/KeyframeEffect.h
dom/animation/moz.build
layout/base/nsDisplayList.cpp
new file mode 100644
--- /dev/null
+++ b/dom/animation/AnimationPerformanceWarning.cpp
@@ -0,0 +1,72 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "AnimationPerformanceWarning.h"
+
+#include "nsContentUtils.h"
+
+namespace mozilla {
+
+bool
+AnimationPerformanceWarning::ToLocalizedString(
+  nsXPIDLString& aLocalizedString) const
+{
+  const char* key = nullptr;
+
+  switch (mType) {
+    case Type::ContentTooLarge:
+    {
+      MOZ_ASSERT(mParams && mParams->Length() == 7,
+                 "Parameter's length should be 7 for ContentTooLarge");
+
+      MOZ_ASSERT(mParams->Length() <= kMaxParamsForLocalization,
+                 "Parameter's length should be less than "
+                 "kMaxParamsForLocalization");
+      // We can pass an array of parameters whose length is greater than 7 to
+      // nsContentUtils::FormatLocalizedString because
+      // nsTextFormatter drops those extra parameters in the end.
+      nsAutoString strings[kMaxParamsForLocalization];
+      const char16_t* charParams[kMaxParamsForLocalization];
+
+      for (size_t i = 0, n = mParams->Length(); i < n; i++) {
+        strings[i].AppendInt((*mParams)[i]);
+        charParams[i] = strings[i].get();
+      }
+
+      nsresult rv = nsContentUtils::FormatLocalizedString(
+        nsContentUtils::eLAYOUT_PROPERTIES,
+        "AnimationWarningContentTooLarge",
+        charParams,
+        aLocalizedString);
+      return NS_SUCCEEDED(rv);
+    }
+    case Type::TransformBackfaceVisibilityHidden:
+      key = "AnimationWarningTransformBackfaceVisibilityHidden";
+      break;
+    case Type::TransformPreserve3D:
+      key = "AnimationWarningTransformPreserve3D";
+      break;
+    case Type::TransformSVG:
+      key = "AnimationWarningTransformSVG";
+      break;
+    case Type::TransformFrameInactive:
+      key = "AnimationWarningTransformFrameInactive";
+      break;
+    case Type::OpacityFrameInactive:
+      key = "AnimationWarningOpacityFrameInactive";
+      break;
+    case Type::WithGeometricProperties:
+      key = "AnimationWarningWithGeometricProperties";
+      break;
+  }
+
+  nsresult rv =
+    nsContentUtils::GetLocalizedString(nsContentUtils::eLAYOUT_PROPERTIES,
+                                       key, aLocalizedString);
+  return NS_SUCCEEDED(rv);
+}
+
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/animation/AnimationPerformanceWarning.h
@@ -0,0 +1,74 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_dom_AnimationPerformanceWarning_h
+#define mozilla_dom_AnimationPerformanceWarning_h
+
+#include "mozilla/InitializerList.h"
+
+class nsXPIDLString;
+
+namespace mozilla {
+
+// Represents the reason why we can't run the CSS property on the compositor.
+struct AnimationPerformanceWarning
+{
+  enum class Type : uint8_t {
+    ContentTooLarge,
+    TransformBackfaceVisibilityHidden,
+    TransformPreserve3D,
+    TransformSVG,
+    TransformFrameInactive,
+    OpacityFrameInactive,
+    WithGeometricProperties
+  };
+
+  explicit AnimationPerformanceWarning(Type aType)
+    : mType(aType) { }
+
+  AnimationPerformanceWarning(Type aType,
+                              std::initializer_list<int32_t> aParams)
+    : mType(aType)
+  {
+    // FIXME:  Once std::initializer_list::size() become a constexpr function,
+    // we should use static_assert here.
+    MOZ_ASSERT(aParams.size() <= kMaxParamsForLocalization,
+      "The length of parameters should be less than "
+      "kMaxParamsForLocalization");
+    mParams.emplace(aParams);
+  }
+
+  // Maximum number of parameters passed to
+  // nsContentUtils::FormatLocalizedString to localize warning messages.
+  //
+  // NOTE: This constexpr can't be forward declared, so if you want to use
+  // this variable, please include this header file directly.
+  // This value is the same as the limit of nsStringBundle::FormatString.
+  // See the implementation of nsStringBundle::FormatString.
+  static MOZ_CONSTEXPR_VAR uint8_t kMaxParamsForLocalization = 10;
+
+  // Indicates why this property could not be animated on the compositor.
+  Type mType;
+
+  // Optional parameters that may be used for localization.
+  Maybe<nsTArray<int32_t>> mParams;
+
+  bool ToLocalizedString(nsXPIDLString& aLocalizedString) const;
+
+  bool operator==(const AnimationPerformanceWarning& aOther) const
+  {
+    return mType == aOther.mType &&
+           mParams == aOther.mParams;
+  }
+  bool operator!=(const AnimationPerformanceWarning& aOther) const
+  {
+    return !(*this == aOther);
+  }
+};
+
+} // namespace mozilla
+
+#endif // mozilla_dom_AnimationPerformanceWarning_h
--- a/dom/animation/EffectCompositor.cpp
+++ b/dom/animation/EffectCompositor.cpp
@@ -5,16 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "EffectCompositor.h"
 
 #include "mozilla/dom/Animation.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/KeyframeEffect.h" // For KeyframeEffectReadOnly
 #include "mozilla/AnimationUtils.h"
+#include "mozilla/AnimationPerformanceWarning.h"
 #include "mozilla/EffectSet.h"
 #include "mozilla/InitializerList.h"
 #include "mozilla/LayerAnimationInfo.h"
 #include "mozilla/RestyleManagerHandle.h"
 #include "mozilla/RestyleManagerHandleInlines.h"
 #include "nsComputedDOMStyle.h" // nsComputedDOMStyle::GetPresShellForContent
 #include "nsCSSPropertySet.h"
 #include "nsCSSProps.h"
@@ -104,24 +105,24 @@ FindAnimationsForCompositor(const nsIFra
   for (KeyframeEffectReadOnly* effect : *effects) {
     MOZ_ASSERT(effect && effect->GetAnimation());
     Animation* animation = effect->GetAnimation();
 
     if (!animation->IsPlaying()) {
       continue;
     }
 
-    nsAutoString performanceWarning;
+    AnimationPerformanceWarning::Type warningType;
     if (effect->ShouldBlockCompositorAnimations(aFrame,
-                                                performanceWarning)) {
+                                                warningType)) {
       if (aMatches) {
         aMatches->Clear();
       }
-      effect->SetPerformanceWarning(aProperty,
-                                    performanceWarning);
+      effect->SetPerformanceWarning(
+        aProperty, AnimationPerformanceWarning(warningType));
       return false;
     }
 
     if (!effect->HasAnimationOfProperty(aProperty)) {
       continue;
     }
 
     if (aMatches) {
@@ -716,27 +717,28 @@ EffectCompositor::GetPresContext(Element
   nsIPresShell* shell = nsComputedDOMStyle::GetPresShellForContent(aElement);
   if (!shell) {
     return nullptr;
   }
   return shell->GetPresContext();
 }
 
 /* static */ void
-EffectCompositor::SetPerformanceWarning(const nsIFrame *aFrame,
-                                        nsCSSProperty aProperty,
-                                        const nsAString& aMessage)
+EffectCompositor::SetPerformanceWarning(
+  const nsIFrame *aFrame,
+  nsCSSProperty aProperty,
+  const AnimationPerformanceWarning& aWarning)
 {
   EffectSet* effects = EffectSet::GetEffectSet(aFrame);
   if (!effects) {
     return;
   }
 
   for (KeyframeEffectReadOnly* effect : *effects) {
-    effect->SetPerformanceWarning(aProperty, aMessage);
+    effect->SetPerformanceWarning(aProperty, aWarning);
   }
 }
 
 // ---------------------------------------------------------
 //
 // Nested class: AnimationStyleRuleProcessor
 //
 // ---------------------------------------------------------
--- a/dom/animation/EffectCompositor.h
+++ b/dom/animation/EffectCompositor.h
@@ -25,16 +25,17 @@ class nsIStyleRule;
 class nsPresContext;
 class nsStyleContext;
 
 namespace mozilla {
 
 class EffectSet;
 class RestyleTracker;
 enum class CSSPseudoElementType : uint8_t;
+struct AnimationPerformanceWarning;
 
 namespace dom {
 class Animation;
 class Element;
 }
 
 class EffectCompositor
 {
@@ -182,21 +183,22 @@ public:
   // AnimationCollection), *not* the generated content.
   //
   // Returns an empty result when a suitable element cannot be found including
   // when the frame represents a pseudo-element on which we do not support
   // animations.
   static Maybe<Pair<dom::Element*, CSSPseudoElementType>>
   GetAnimationElementAndPseudoForFrame(const nsIFrame* aFrame);
 
-  // Associates a warning message with effects on |aFrame| if the effect
-  // has |aProperty|.
-  static void SetPerformanceWarning(const nsIFrame* aFrame,
-                                    nsCSSProperty aProperty,
-                                    const nsAString& aMessage);
+  // Associates a performance warning with effects on |aFrame| that animates
+  // |aProperty|.
+  static void SetPerformanceWarning(
+    const nsIFrame* aFrame,
+    nsCSSProperty aProperty,
+    const AnimationPerformanceWarning& aWarning);
 
 private:
   ~EffectCompositor() = default;
 
   // Rebuilds the animation rule corresponding to |aCascadeLevel| on the
   // EffectSet associated with the specified (pseudo-)element.
   static void ComposeAnimationRule(dom::Element* aElement,
                                    CSSPseudoElementType aPseudoType,
--- a/dom/animation/KeyframeEffect.cpp
+++ b/dom/animation/KeyframeEffect.cpp
@@ -1888,18 +1888,20 @@ KeyframeEffectReadOnly::GetPropertyState
       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());
+    nsXPIDLString localizedString;
+    if (property.mPerformanceWarning &&
+        property.mPerformanceWarning->ToLocalizedString(localizedString)) {
+      state.mWarning.Construct(localizedString);
     }
 
     aStates.AppendElement(state);
   }
 }
 
 /* static */ const TimeDuration
 KeyframeEffectReadOnly::OverflowRegionRefreshInterval()
@@ -2094,111 +2096,97 @@ KeyframeEffectReadOnly::IsGeometricPrope
     default:
       return false;
   }
 }
 
 /* static */ bool
 KeyframeEffectReadOnly::CanAnimateTransformOnCompositor(
   const nsIFrame* aFrame,
-  nsAString& aPerformanceWarning)
+  AnimationPerformanceWarning::Type& aPerformanceWarning)
 {
   // Disallow OMTA for preserve-3d transform. Note that we check the style property
   // rather than Extend3DContext() since that can recurse back into this function
   // via HasOpacity(). See bug 779598.
   if (aFrame->Combines3DTransformWithAncestors() ||
       aFrame->StyleDisplay()->mTransformStyle == NS_STYLE_TRANSFORM_STYLE_PRESERVE_3D) {
-    nsXPIDLString localizedMessage;
-    nsContentUtils::GetLocalizedString(
-      nsContentUtils::eLAYOUT_PROPERTIES,
-      "AnimationWarningTransformPreserve3D",
-      localizedMessage);
-    aPerformanceWarning = localizedMessage;
+    aPerformanceWarning = AnimationPerformanceWarning::Type::TransformPreserve3D;
     return false;
   }
   // Note that testing BackfaceIsHidden() is not a sufficient test for
   // what we need for animating backface-visibility correctly if we
   // remove the above test for Extend3DContext(); that would require
   // looking at backface-visibility on descendants as well. See bug 1186204.
   if (aFrame->StyleDisplay()->BackfaceIsHidden()) {
-    nsXPIDLString localizedMessage;
-    nsContentUtils::GetLocalizedString(
-      nsContentUtils::eLAYOUT_PROPERTIES,
-      "AnimationWarningTransformBackfaceVisibilityHidden",
-      localizedMessage);
-    aPerformanceWarning = localizedMessage;
+    aPerformanceWarning =
+      AnimationPerformanceWarning::Type::TransformBackfaceVisibilityHidden;
     return false;
   }
   // Async 'transform' animations of aFrames with SVG transforms is not
   // supported.  See bug 779599.
   if (aFrame->IsSVGTransformed()) {
-    nsXPIDLString localizedMessage;
-    nsContentUtils::GetLocalizedString(
-      nsContentUtils::eLAYOUT_PROPERTIES,
-      "AnimationWarningTransformSVG",
-      localizedMessage);
-    aPerformanceWarning = localizedMessage;
+    aPerformanceWarning = AnimationPerformanceWarning::Type::TransformSVG;
     return false;
   }
 
   return true;
 }
 
 bool
 KeyframeEffectReadOnly::ShouldBlockCompositorAnimations(
   const nsIFrame* aFrame,
-  nsAString& aPerformanceWarning) const
+  AnimationPerformanceWarning::Type& aPerformanceWarning) const
 {
   // We currently only expect this method to be called when this effect
   // is attached to a playing Animation. If that ever changes we'll need
   // to update this to only return true when that is the case since paused,
   // filling, cancelled Animations etc. shouldn't stop other Animations from
   // running on the compositor.
   MOZ_ASSERT(mAnimation && mAnimation->IsPlaying());
 
   for (const AnimationProperty& property : mProperties) {
     // If a property is overridden in the CSS cascade, it should not block other
     // animations from running on the compositor.
     if (!property.mWinsInCascade) {
       continue;
     }
     // Check for geometric properties
     if (IsGeometricProperty(property.mProperty)) {
-      nsXPIDLString localizedMessage;
-      nsContentUtils::GetLocalizedString(
-        nsContentUtils::eLAYOUT_PROPERTIES,
-        "AnimationWarningWithGeometricProperties",
-        localizedMessage);
-      aPerformanceWarning = localizedMessage;
+      aPerformanceWarning =
+        AnimationPerformanceWarning::Type::WithGeometricProperties;
       return true;
     }
 
     // Check for unsupported transform animations
     if (property.mProperty == eCSSProperty_transform) {
       if (!CanAnimateTransformOnCompositor(aFrame,
                                            aPerformanceWarning)) {
         return true;
       }
     }
   }
 
   return false;
 }
 
 void
-KeyframeEffectReadOnly::SetPerformanceWarning(nsCSSProperty aProperty,
-                                              const nsAString &aMessage)
+KeyframeEffectReadOnly::SetPerformanceWarning(
+  nsCSSProperty aProperty,
+  const AnimationPerformanceWarning& aWarning)
 {
   for (AnimationProperty& property : mProperties) {
-    if (property.mProperty == aProperty) {
-      property.mPerformanceWarning.reset();
-      property.mPerformanceWarning.emplace(aMessage);
+    if (property.mProperty == aProperty &&
+        (!property.mPerformanceWarning ||
+         *property.mPerformanceWarning != aWarning)) {
+      property.mPerformanceWarning = Some(aWarning);
 
-      if (nsLayoutUtils::IsAnimationLoggingEnabled()) {
-        nsAutoCString logMessage = NS_ConvertUTF16toUTF8(aMessage);
+      nsXPIDLString localizedString;
+      if (nsLayoutUtils::IsAnimationLoggingEnabled() &&
+          property.mPerformanceWarning->ToLocalizedString(localizedString)) {
+        nsAutoCString logMessage = NS_ConvertUTF16toUTF8(localizedString);
         AnimationUtils::LogAsyncAnimationFailure(logMessage, mTarget);
       }
       return;
     }
   }
 }
 
 //---------------------------------------------------------------------
--- a/dom/animation/KeyframeEffect.h
+++ b/dom/animation/KeyframeEffect.h
@@ -6,16 +6,17 @@
 
 #ifndef mozilla_dom_KeyframeEffect_h
 #define mozilla_dom_KeyframeEffect_h
 
 #include "nsAutoPtr.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsIDocument.h"
 #include "nsWrapperCache.h"
+#include "mozilla/AnimationPerformanceWarning.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/ComputedTimingFunction.h" // ComputedTimingFunction
 #include "mozilla/LayerAnimationInfo.h"     // LayerAnimations::kRecords
 #include "mozilla/OwningNonNull.h"          // OwningNonNull<...>
 #include "mozilla/StickyTimeDuration.h"
 #include "mozilla/StyleAnimationValue.h"
 #include "mozilla/TimeStamp.h"
 #include "mozilla/dom/AnimationEffectReadOnly.h"
@@ -141,19 +142,17 @@ struct AnimationProperty
   // between calling RequestRestyle on its EffectCompositor and when the
   // restyle is performed, this member may temporarily become false even if
   // the animation remains on the layer after the restyle.
   //
   // **NOTE**: This member is not included when comparing AnimationProperty
   // objects for equality.
   bool mIsRunningOnCompositor = false;
 
-  // A warning string indicating why this property could not be animated
-  // on the compositor.
-  Maybe<nsString> mPerformanceWarning;
+  Maybe<AnimationPerformanceWarning> mPerformanceWarning;
 
   InfallibleTArray<AnimationPropertySegment> mSegments;
 
   // NOTE: This operator does *not* compare the mWinsInCascade member *or* the
   // mIsRunningOnCompositor member.
   // This is because AnimationProperty objects are compared when recreating
   // CSS animations to determine if mutation observer change records need to
   // be created or not. However, at the point when these objects are compared
@@ -322,27 +321,30 @@ public:
   // when that is the case we simply disable all compositor animations
   // on the same element.
   //
   // Bug 1218620 - It seems like we don't need to be this restrictive. Wouldn't
   // it be ok to do 'opacity' animations on the compositor in either case?
   //
   // When returning true, |aOutPerformanceWarning| stores the reason why
   // we shouldn't run the compositor animations.
-  bool ShouldBlockCompositorAnimations(const nsIFrame* aFrame,
-                                       nsAString& aPerformanceWarning) const;
+  bool ShouldBlockCompositorAnimations(
+    const nsIFrame* aFrame,
+    AnimationPerformanceWarning::Type& aPerformanceWarning) const;
 
   nsIDocument* GetRenderedDocument() const;
   nsPresContext* GetPresContext() const;
 
-  // Associates a warning string with the animated property on the specified
-  // frame indicating why, for example, the property could not be animated
-  // on the compositor.
-  void SetPerformanceWarning(nsCSSProperty aProperty,
-                             const nsAString& aMessage);
+  // Associates a warning with the animated property on the specified frame
+  // indicating why, for example, the property could not be animated on the
+  // compositor. |aParams| and |aParamsLength| are optional parameters which
+  // will be used to generate a localized message for devtools.
+  void SetPerformanceWarning(
+    nsCSSProperty aProperty,
+    const AnimationPerformanceWarning& aWarning);
 
 protected:
   KeyframeEffectReadOnly(nsIDocument* aDocument,
                          Element* aTarget,
                          CSSPseudoElementType aPseudoType,
                          AnimationEffectTimingReadOnly* aTiming);
 
   virtual ~KeyframeEffectReadOnly();
@@ -397,18 +399,19 @@ private:
   nsIFrame* GetAnimationFrame() const;
 
   bool CanThrottle() const;
   bool CanThrottleTransformChanges(nsIFrame& aFrame) const;
 
   // Returns true unless Gecko limitations prevent performing transform
   // animations for |aFrame|. When returning true, the reason for the
   // limitation is stored in |aOutPerformanceWarning|.
-  static bool CanAnimateTransformOnCompositor(const nsIFrame* aFrame,
-                                              nsAString& aPerformanceWarning);
+  static bool CanAnimateTransformOnCompositor(
+    const nsIFrame* aFrame,
+    AnimationPerformanceWarning::Type& aPerformanceWarning);
   static bool IsGeometricProperty(const nsCSSProperty aProperty);
 
   static const TimeDuration OverflowRegionRefreshInterval();
 };
 
 class KeyframeEffect : public KeyframeEffectReadOnly
 {
 public:
--- a/dom/animation/moz.build
+++ b/dom/animation/moz.build
@@ -15,30 +15,32 @@ EXPORTS.mozilla.dom += [
     'AnimationTimeline.h',
     'CSSPseudoElement.h',
     'DocumentTimeline.h',
     'KeyframeEffect.h',
 ]
 
 EXPORTS.mozilla += [
     'AnimationComparator.h',
+    'AnimationPerformanceWarning.h',
     'AnimationUtils.h',
     'AnimValuesStyleRule.h',
     'ComputedTimingFunction.h',
     'EffectCompositor.h',
     'EffectSet.h',
     'PendingAnimationTracker.h',
     'PseudoElementHashEntry.h',
 ]
 
 UNIFIED_SOURCES += [
     'Animation.cpp',
     'AnimationEffectReadOnly.cpp',
     'AnimationEffectTiming.cpp',
     'AnimationEffectTimingReadOnly.cpp',
+    'AnimationPerformanceWarning.cpp',
     'AnimationTimeline.cpp',
     'AnimationUtils.cpp',
     'AnimValuesStyleRule.cpp',
     'ComputedTimingFunction.cpp',
     'CSSPseudoElement.cpp',
     'DocumentTimeline.cpp',
     'EffectCompositor.cpp',
     'EffectSet.cpp',
--- a/layout/base/nsDisplayList.cpp
+++ b/layout/base/nsDisplayList.cpp
@@ -47,16 +47,17 @@
 #include "nsSVGElement.h"
 #include "nsSVGClipPathFrame.h"
 #include "GeckoProfiler.h"
 #include "nsViewManager.h"
 #include "ImageLayers.h"
 #include "ImageContainer.h"
 #include "nsCanvasFrame.h"
 #include "StickyScrollContainer.h"
+#include "mozilla/AnimationPerformanceWarning.h"
 #include "mozilla/AnimationUtils.h"
 #include "mozilla/EffectCompositor.h"
 #include "mozilla/EventStates.h"
 #include "mozilla/LookAndFeel.h"
 #include "mozilla/PendingAnimationTracker.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/UniquePtr.h"
 #include "mozilla/unused.h"
@@ -5580,24 +5581,20 @@ nsDisplayTransform::GetResultingTransfor
 
 bool
 nsDisplayOpacity::CanUseAsyncAnimations(nsDisplayListBuilder* aBuilder)
 {
   if (ActiveLayerTracker::IsStyleAnimated(aBuilder, mFrame, eCSSProperty_opacity)) {
     return true;
   }
 
-  nsXPIDLString localizedMessage;
-  nsContentUtils::GetLocalizedString(
-    nsContentUtils::eLAYOUT_PROPERTIES,
-    "AnimationWarningOpacityFrameInactive",
-    localizedMessage);
-  EffectCompositor::SetPerformanceWarning(mFrame,
-                                          eCSSProperty_opacity,
-                                          localizedMessage);
+  EffectCompositor::SetPerformanceWarning(
+    mFrame, eCSSProperty_transform,
+    AnimationPerformanceWarning(
+      AnimationPerformanceWarning::Type::OpacityFrameInactive));
 
   return false;
 }
 
 bool
 nsDisplayTransform::ShouldPrerender(nsDisplayListBuilder* aBuilder) {
   if (!mMaybePrerender) {
     return false;
@@ -5635,24 +5632,21 @@ nsDisplayTransform::ShouldPrerenderTrans
 {
   // Elements whose transform has been modified recently, or which
   // have a compositor-animated transform, can be prerendered. An element
   // might have only just had its transform animated in which case
   // the ActiveLayerManager may not have been notified yet.
   if (!ActiveLayerTracker::IsStyleMaybeAnimated(aFrame, eCSSProperty_transform) &&
       !EffectCompositor::HasAnimationsForCompositor(aFrame,
                                                     eCSSProperty_transform)) {
-    nsXPIDLString localizedMessage;
-    nsContentUtils::GetLocalizedString(
-      nsContentUtils::eLAYOUT_PROPERTIES,
-      "AnimationWarningTransformFrameInactive",
-      localizedMessage);
-    EffectCompositor::SetPerformanceWarning(aFrame,
-                                            eCSSProperty_transform,
-                                            localizedMessage);
+    EffectCompositor::SetPerformanceWarning(
+      aFrame, eCSSProperty_transform,
+      AnimationPerformanceWarning(
+        AnimationPerformanceWarning::Type::TransformFrameInactive));
+
     return false;
   }
 
   nsSize refSize = aBuilder->RootReferenceFrame()->GetSize();
   // Only prerender if the transformed frame's size is <= the
   // reference frame size (~viewport), allowing a 1/8th fuzz factor
   // for shadows, borders, etc.
   refSize += nsSize(refSize.width / 8, refSize.height / 8);
@@ -5663,46 +5657,30 @@ nsDisplayTransform::ShouldPrerenderTrans
     nsRect visual = aFrame->GetVisualOverflowRect();
     if (visual.width <= maxInAppUnits && visual.height <= maxInAppUnits) {
       return true;
     }
   }
 
   nsRect visual = aFrame->GetVisualOverflowRect();
 
-  nsAutoString frameWidth, frameHeight,
-               refWidth, refHeight,
-               visualWidth, visualHeight,
-               maxInAppUnitsString;
-  frameWidth.AppendInt(nsPresContext::AppUnitsToIntCSSPixels(frameSize.width));
-  frameHeight.AppendInt(nsPresContext::AppUnitsToIntCSSPixels(frameSize.height));
-  refWidth.AppendInt(nsPresContext::AppUnitsToIntCSSPixels(refSize.width));
-  refHeight.AppendInt(nsPresContext::AppUnitsToIntCSSPixels(refSize.height));
-  visualWidth.AppendInt(nsPresContext::AppUnitsToIntCSSPixels(visual.width));
-  visualHeight.AppendInt(nsPresContext::AppUnitsToIntCSSPixels(visual.height));
-  maxInAppUnitsString.AppendInt(nsPresContext::AppUnitsToIntCSSPixels(maxInAppUnits));
-
-  const char16_t* params[7]  = {
-    frameWidth.get(),
-    frameHeight.get(),
-    refWidth.get(),
-    refHeight.get(),
-    visualWidth.get(),
-    visualHeight.get(),
-    maxInAppUnitsString.get()
-  };
-
-  nsXPIDLString message;
-  nsContentUtils::FormatLocalizedString(nsContentUtils::eLAYOUT_PROPERTIES,
-                                        "AnimationWarningContentTooLarge",
-                                        params,
-                                        message);
-  EffectCompositor::SetPerformanceWarning(aFrame,
-                                          eCSSProperty_transform,
-                                          message);
+
+  EffectCompositor::SetPerformanceWarning(
+    aFrame, eCSSProperty_transform,
+    AnimationPerformanceWarning(
+      AnimationPerformanceWarning::Type::ContentTooLarge,
+      {
+        nsPresContext::AppUnitsToIntCSSPixels(frameSize.width),
+        nsPresContext::AppUnitsToIntCSSPixels(frameSize.height),
+        nsPresContext::AppUnitsToIntCSSPixels(refSize.width),
+        nsPresContext::AppUnitsToIntCSSPixels(refSize.height),
+        nsPresContext::AppUnitsToIntCSSPixels(visual.width),
+        nsPresContext::AppUnitsToIntCSSPixels(visual.height),
+        nsPresContext::AppUnitsToIntCSSPixels(maxInAppUnits)
+      }));
   return false;
 }
 
 /* If the matrix is singular, or a hidden backface is shown, the frame won't be visible or hit. */
 static bool IsFrameVisible(nsIFrame* aFrame, const Matrix4x4& aMatrix)
 {
   if (aMatrix.IsSingular()) {
     return false;