Bug 473904 - Add an about:config option (defaulting to 'false' right now) for toggling SVG animation (SMIL) support. r+sr=roc
authorDaniel Holbert <dholbert@cs.stanford.edu>
Mon, 09 Mar 2009 18:20:17 -0700
changeset 25961 ba3ad61aa365dc6bbc8abcdb7e6ceb0c5b9140c9
parent 25960 e1545d194a52d0e6e3c6b816a2197b68721a5c09
child 25962 a17853b08a6cb0dfe0ded639b4475711e3b1af9c
push id1
push userroot
push dateTue, 26 Apr 2011 22:38:44 +0000
treeherdermozilla-beta@bfdb6e623a36 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs473904
milestone1.9.2a1pre
Bug 473904 - Add an about:config option (defaulting to 'false' right now) for toggling SVG animation (SMIL) support. r+sr=roc
content/base/src/nsDocument.cpp
content/base/src/nsGenericElement.cpp
content/svg/content/src/nsSVGElementFactory.cpp
content/svg/content/src/nsSVGSVGElement.cpp
layout/svg/base/src/nsSVGUtils.cpp
layout/svg/base/src/nsSVGUtils.h
modules/libpref/src/init/all.js
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -169,16 +169,17 @@ static NS_DEFINE_CID(kDOMEventGroupCID, 
 
 #include "nsFrameLoader.h"
 
 #include "mozAutoDocUpdate.h"
 
 #ifdef MOZ_SMIL
 #include "nsSMILAnimationController.h"
 #include "imgIContainer.h"
+#include "nsSVGUtils.h"
 #endif // MOZ_SMIL
 
 
 #ifdef MOZ_LOGGING
 // so we can get logging even in release builds
 #define FORCE_PR_LOG 1
 #endif
 #include "prlog.h"
@@ -5296,16 +5297,19 @@ nsDocument::EnumerateExternalResources(n
 #ifdef MOZ_SMIL
 nsSMILAnimationController*
 nsDocument::GetAnimationController()
 {
   // We create the animation controller lazily because most documents won't want
   // one and only SVG documents and the like will call this
   if (mAnimationController)
     return mAnimationController;
+  // Refuse to create an Animation Controller if SMIL is disabled
+  if (!NS_SMILEnabled())
+    return nsnull;
 
   mAnimationController = NS_NewSMILAnimationController(this);
   
   // If there's a presContext then check the animation mode and pause if
   // necessary.
   nsIPresShell *shell = GetPrimaryShell();
   if (mAnimationController && shell) {
     nsPresContext *context = shell->GetPresContext();
--- a/content/base/src/nsGenericElement.cpp
+++ b/content/base/src/nsGenericElement.cpp
@@ -1901,17 +1901,17 @@ nsGenericElement::InternalIsSupported(ns
     if (aVersion.IsEmpty() ||
         PL_strcmp(v, "1.0") == 0 ||
         PL_strcmp(v, "1.1") == 0) {
       *aReturn = PR_TRUE;
     }
   }
 #endif /* MOZ_SVG */
 #ifdef MOZ_SMIL
-  else if (PL_strcasecmp(f, "TimeControl") == 0) {
+  else if (NS_SMILEnabled() && PL_strcasecmp(f, "TimeControl") == 0) {
     if (aVersion.IsEmpty() || PL_strcmp(v, "1.0") == 0) {
       *aReturn = PR_TRUE;
     }
   }
 #endif /* MOZ_SMIL */
   else {
     nsCOMPtr<nsIDOMNSFeatureFactory> factory =
       GetDOMFeatureFactory(aFeature, aVersion);
--- a/content/svg/content/src/nsSVGElementFactory.cpp
+++ b/content/svg/content/src/nsSVGElementFactory.cpp
@@ -294,20 +294,22 @@ NS_NewSVGElement(nsIContent** aResult, n
     return NS_NewSVGFEDisplacementMapElement(aResult, aNodeInfo);
   if (name == nsGkAtoms::pattern)
     return NS_NewSVGPatternElement(aResult, aNodeInfo);
   if (name == nsGkAtoms::mask)
     return NS_NewSVGMaskElement(aResult, aNodeInfo);
   if (name == nsGkAtoms::svgSwitch)
     return NS_NewSVGSwitchElement(aResult, aNodeInfo);
 #ifdef MOZ_SMIL
-  if (name == nsGkAtoms::animate)
-    return NS_NewSVGAnimateElement(aResult, aNodeInfo);
-  if (name == nsGkAtoms::animateTransform)
-    return NS_NewSVGAnimateTransformElement(aResult, aNodeInfo);
-  if (name == nsGkAtoms::set)
-    return NS_NewSVGSetElement(aResult, aNodeInfo);
+  if (NS_SMILEnabled()) {
+    if (name == nsGkAtoms::animate)
+      return NS_NewSVGAnimateElement(aResult, aNodeInfo);
+    if (name == nsGkAtoms::animateTransform)
+      return NS_NewSVGAnimateTransformElement(aResult, aNodeInfo);
+    if (name == nsGkAtoms::set)
+      return NS_NewSVGSetElement(aResult, aNodeInfo);
+  }
 #endif // MOZ_SMIL
 
   // if we don't know what to create, just create a standard xml element:
   return NS_NewXMLElement(aResult, aNodeInfo);
 }
 
--- a/content/svg/content/src/nsSVGSVGElement.cpp
+++ b/content/svg/content/src/nsSVGSVGElement.cpp
@@ -454,109 +454,114 @@ nsSVGSVGElement::ForceRedraw()
   return NS_OK;
 }
 
 /* void pauseAnimations (); */
 NS_IMETHODIMP
 nsSVGSVGElement::PauseAnimations()
 {
 #ifdef MOZ_SMIL
-  if (mTimedDocumentRoot) {
-    mTimedDocumentRoot->Pause(nsSMILTimeContainer::PAUSE_SCRIPT);
+  if (NS_SMILEnabled()) {
+    if (mTimedDocumentRoot) {
+      mTimedDocumentRoot->Pause(nsSMILTimeContainer::PAUSE_SCRIPT);
+    }
+    // else we're not the outermost <svg> or not bound to a tree, so silently fail
+    return NS_OK;
   }
-  // else we're not the outermost <svg> or not bound to a tree, so silently fail
-  return NS_OK;
-#else
+#endif // MOZ_SMIL
   NS_NOTYETIMPLEMENTED("nsSVGSVGElement::PauseAnimations");
   return NS_ERROR_NOT_IMPLEMENTED;
-#endif
 }
 
 /* void unpauseAnimations (); */
 NS_IMETHODIMP
 nsSVGSVGElement::UnpauseAnimations()
 {
 #ifdef MOZ_SMIL
-  if (mTimedDocumentRoot) {
-    mTimedDocumentRoot->Resume(nsSMILTimeContainer::PAUSE_SCRIPT);
+  if (NS_SMILEnabled()) {
+    if (mTimedDocumentRoot) {
+      mTimedDocumentRoot->Resume(nsSMILTimeContainer::PAUSE_SCRIPT);
+    }
+    // else we're not the outermost <svg> or not bound to a tree, so silently fail
+    return NS_OK;
   }
-  // else we're not the outermost <svg> or not bound to a tree, so silently fail
-  return NS_OK;
-#else
+#endif // MOZ_SMIL
   NS_NOTYETIMPLEMENTED("nsSVGSVGElement::UnpauseAnimations");
   return NS_ERROR_NOT_IMPLEMENTED;
-#endif
 }
 
 /* boolean animationsPaused (); */
 NS_IMETHODIMP
 nsSVGSVGElement::AnimationsPaused(PRBool *_retval)
 {
 #ifdef MOZ_SMIL
-  nsSMILTimeContainer* root = GetTimedDocumentRoot();
-  *_retval = root && root->IsPausedByType(nsSMILTimeContainer::PAUSE_SCRIPT);
-  return NS_OK;
-#else
+  if (NS_SMILEnabled()) {
+    nsSMILTimeContainer* root = GetTimedDocumentRoot();
+    *_retval = root && root->IsPausedByType(nsSMILTimeContainer::PAUSE_SCRIPT);
+    return NS_OK;
+  }
+#endif // MOZ_SMIL
   NS_NOTYETIMPLEMENTED("nsSVGSVGElement::AnimationsPaused");
   return NS_ERROR_NOT_IMPLEMENTED;
-#endif
 }
 
 /* float getCurrentTime (); */
 NS_IMETHODIMP
 nsSVGSVGElement::GetCurrentTime(float *_retval)
 {
 #ifdef MOZ_SMIL
-  nsSMILTimeContainer* root = GetTimedDocumentRoot();
-  if (root) {
-    double fCurrentTimeMs = double(root->GetCurrentTime());
-    *_retval = (float)(fCurrentTimeMs / PR_MSEC_PER_SEC);
-  } else {
-    *_retval = 0.f;
+  if (NS_SMILEnabled()) {
+    nsSMILTimeContainer* root = GetTimedDocumentRoot();
+    if (root) {
+      double fCurrentTimeMs = double(root->GetCurrentTime());
+      *_retval = (float)(fCurrentTimeMs / PR_MSEC_PER_SEC);
+    } else {
+      *_retval = 0.f;
+    }
+    return NS_OK;
   }
-  return NS_OK;
-#else
+#endif // MOZ_SMIL
   NS_NOTYETIMPLEMENTED("nsSVGSVGElement::GetCurrentTime");
   return NS_ERROR_NOT_IMPLEMENTED;
-#endif
 }
 
 /* void setCurrentTime (in float seconds); */
 NS_IMETHODIMP
 nsSVGSVGElement::SetCurrentTime(float seconds)
 {
   NS_ENSURE_FINITE(seconds, NS_ERROR_ILLEGAL_VALUE);
 #ifdef MOZ_SMIL
-  if (mTimedDocumentRoot) {
-    double fMilliseconds = double(seconds) * PR_MSEC_PER_SEC;
-    // Round to nearest whole number before converting, to avoid precision
-    // errors
-    nsSMILTime lMilliseconds = PRInt64(NS_round(fMilliseconds));
-    mTimedDocumentRoot->SetCurrentTime(lMilliseconds);
-    // Force a resample now
-    //
-    // It's not sufficient to just request a resample here because calls to
-    // BeginElement etc. expect to operate on an up-to-date timegraph or else
-    // instance times may be incorrectly discarded.
-    //
-    // See the mochitest: test_smilSync.xhtml:testSetCurrentTime()
-    nsIDocument* doc = GetCurrentDoc();
-    if (doc) {
-      nsSMILAnimationController* smilController = doc->GetAnimationController();
-      if (smilController) {
-        smilController->Resample();
+  if (NS_SMILEnabled()) {
+    if (mTimedDocumentRoot) {
+      double fMilliseconds = double(seconds) * PR_MSEC_PER_SEC;
+      // Round to nearest whole number before converting, to avoid precision
+      // errors
+      nsSMILTime lMilliseconds = PRInt64(NS_round(fMilliseconds));
+      mTimedDocumentRoot->SetCurrentTime(lMilliseconds);
+      // Force a resample now
+      //
+      // It's not sufficient to just request a resample here because calls to
+      // BeginElement etc. expect to operate on an up-to-date timegraph or else
+      // instance times may be incorrectly discarded.
+      //
+      // See the mochitest: test_smilSync.xhtml:testSetCurrentTime()
+      nsIDocument* doc = GetCurrentDoc();
+      if (doc) {
+        nsSMILAnimationController* smilController = doc->GetAnimationController();
+        if (smilController) {
+          smilController->Resample();
+        }
       }
-    }
-  } // else we're not the outermost <svg> or not bound to a tree, so silently
-    // fail
-  return NS_OK;
-#else
+    } // else we're not the outermost <svg> or not bound to a tree, so silently
+      // fail
+    return NS_OK;
+  }
+#endif // MOZ_SMIL
   NS_NOTYETIMPLEMENTED("nsSVGSVGElement::SetCurrentTime");
   return NS_ERROR_NOT_IMPLEMENTED;
-#endif
 }
 
 /* nsIDOMNodeList getIntersectionList (in nsIDOMSVGRect rect, in nsIDOMSVGElement referenceElement); */
 NS_IMETHODIMP
 nsSVGSVGElement::GetIntersectionList(nsIDOMSVGRect *rect,
                                      nsIDOMSVGElement *referenceElement,
                                      nsIDOMNodeList **_retval)
 {
--- a/layout/svg/base/src/nsSVGUtils.cpp
+++ b/layout/svg/base/src/nsSVGUtils.cpp
@@ -158,16 +158,21 @@ 190, 192, 194, 196, 198, 200, 202, 204,
 206, 208, 210, 212, 214, 216, 218, 220,
 222, 224, 226, 229, 231, 233, 235, 237,
 239, 242, 244, 246, 248, 250, 253, 255
 };
 
 static PRBool gSVGEnabled;
 static const char SVG_PREF_STR[] = "svg.enabled";
 
+#ifdef MOZ_SMIL
+static PRBool gSMILEnabled;
+static const char SMIL_PREF_STR[] = "svg.smil.enabled";
+#endif // MOZ_SMIL
+
 static int
 SVGPrefChanged(const char *aPref, void *aClosure)
 {
   PRBool prefVal = nsContentUtils::GetBoolPref(SVG_PREF_STR);
   if (prefVal == gSVGEnabled)
     return 0;
 
   gSVGEnabled = prefVal;
@@ -190,16 +195,42 @@ NS_SVGEnabled()
     nsContentUtils::RegisterPrefCallback(SVG_PREF_STR, SVGPrefChanged, nsnull);
 
     sInitialized = PR_TRUE;
   }
 
   return gSVGEnabled;
 }
 
+#ifdef MOZ_SMIL
+static int
+SMILPrefChanged(const char *aPref, void *aClosure)
+{
+  PRBool prefVal = nsContentUtils::GetBoolPref(SMIL_PREF_STR);
+  gSMILEnabled = prefVal;
+  return 0;
+}
+
+PRBool
+NS_SMILEnabled()
+{
+  static PRBool sInitialized = PR_FALSE;
+  
+  if (!sInitialized) {
+    /* check and register ourselves with the pref */
+    gSMILEnabled = nsContentUtils::GetBoolPref(SMIL_PREF_STR);
+    nsContentUtils::RegisterPrefCallback(SMIL_PREF_STR, SMILPrefChanged, nsnull);
+
+    sInitialized = PR_TRUE;
+  }
+
+  return gSMILEnabled;
+}
+#endif // MOZ_SMIL
+
 static nsIFrame*
 GetFrameForContent(nsIContent* aContent)
 {
   if (!aContent)
     return nsnull;
 
   nsIDocument *doc = aContent->GetCurrentDoc();
   if (!doc)
--- a/layout/svg/base/src/nsSVGUtils.h
+++ b/layout/svg/base/src/nsSVGUtils.h
@@ -119,16 +119,24 @@ class nsISVGChildFrame;
 /*
  * Checks the svg enable preference and if a renderer could
  * successfully be created.  Declared as a function instead of a
  * nsSVGUtil method so that files that can't pull in nsSVGUtils.h (due
  * to cairo.h usage) can still query this information.
  */
 PRBool NS_SVGEnabled();
 
+#ifdef MOZ_SMIL
+/*
+ * Checks the smil enabled preference.  Declared as a function to match
+ * NS_SVGEnabled().
+ */
+PRBool NS_SMILEnabled();
+#endif // MOZ_SMIL
+
 // GRRR WINDOWS HATE HATE HATE
 #undef CLIP_MASK
 
 class nsSVGRenderState
 {
 public:
   enum RenderMode { NORMAL, CLIP, CLIP_MASK };
 
--- a/modules/libpref/src/init/all.js
+++ b/modules/libpref/src/init/all.js
@@ -1139,16 +1139,17 @@ pref("config.use_system_prefs.accessibil
 
 pref("editor.resizing.preserve_ratio",       true);
 pref("editor.positioning.offset",            0);
 
 pref("dom.max_chrome_script_run_time", 20);
 pref("dom.max_script_run_time", 10);
 
 pref("svg.enabled", true);
+pref("svg.smil.enabled", false);
 
 pref("font.minimum-size.ar", 0);
 pref("font.minimum-size.x-armn", 0);
 pref("font.minimum-size.x-beng", 0);
 pref("font.minimum-size.x-baltic", 0);
 pref("font.minimum-size.x-central-euro", 0);
 pref("font.minimum-size.zh-CN", 0);
 pref("font.minimum-size.zh-HK", 0);