Bug 540090: Add method nsIDocument::HasAnimationController, to let us check for active SMIL animation without triggering lazy construction. r=roc
authorDaniel Holbert <dholbert@cs.stanford.edu>
Tue, 02 Mar 2010 23:09:51 -0800
changeset 38869 65d602fba99fa2936b59f48ae9eee40949f6376f
parent 38868 68c8b1a015bab855ec2c407dfb7b711c361b12ac
child 38870 d6dbb4231c11b824a0cac08455f6f908bcd2de75
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)
reviewersroc
bugs540090
milestone1.9.3a3pre
Bug 540090: Add method nsIDocument::HasAnimationController, to let us check for active SMIL animation without triggering lazy construction. r=roc
content/base/public/nsIDocument.h
content/base/src/nsDocument.h
content/smil/nsISMILAnimationElement.h
content/svg/content/src/nsSVGAnimationElement.cpp
content/svg/content/src/nsSVGAnimationElement.h
content/svg/content/src/nsSVGElement.cpp
layout/base/nsPresContext.cpp
--- a/content/base/public/nsIDocument.h
+++ b/content/base/public/nsIDocument.h
@@ -54,17 +54,17 @@
 #include "nsTHashtable.h"
 #include "nsHashKeys.h"
 #include "nsNodeInfoManager.h"
 #include "nsIStreamListener.h"
 #include "nsIObserver.h"
 #include "nsGkAtoms.h"
 #include "nsAutoPtr.h"
 #ifdef MOZ_SMIL
-class nsSMILAnimationController;
+#include "nsSMILAnimationController.h"
 #endif // MOZ_SMIL
 
 class nsIContent;
 class nsPresContext;
 class nsIPresShell;
 class nsIDocShell;
 class nsStyleSet;
 class nsIStyleSheet;
@@ -109,20 +109,19 @@ namespace css {
 class Loader;
 } // namespace css
 
 namespace dom {
 class Link;
 } // namespace dom
 } // namespace mozilla
 
-// 0bce8f8b-8e27-44e6-92bc-65d0805b7fb4
 #define NS_IDOCUMENT_IID      \
-{ 0x0bce8f8b, 0x8e27, 0x44e6, \
-  { 0x92, 0xbc, 0x65, 0xd0, 0x80, 0x5b, 0x7f, 0xb4 } }
+{ 0x36f0a42c, 0x089b, 0x4909, \
+  { 0xb3, 0xee, 0xc5, 0xa4, 0x00, 0x90, 0x30, 0x02 } }
 
 // Flag for AddStyleSheet().
 #define NS_STYLESHEET_FROM_CATALOG                (1 << 0)
 
 //----------------------------------------------------------------------
 
 // Document interface.  This is implemented by all document objects in
 // Gecko.
@@ -1160,17 +1159,24 @@ public:
 
   void RegisterFreezableElement(nsIContent* aContent);
   PRBool UnregisterFreezableElement(nsIContent* aContent);
   typedef void (* FreezableElementEnumerator)(nsIContent*, void*);
   void EnumerateFreezableElements(FreezableElementEnumerator aEnumerator,
                                   void* aData);
 
 #ifdef MOZ_SMIL
-  // Getter for this document's SMIL Animation Controller
+  // Indicates whether mAnimationController has been (lazily) initialized.
+  // If this returns PR_TRUE, we're promising that GetAnimationController()
+  // will have a non-null return value.
+  PRBool HasAnimationController()  { return !!mAnimationController; }
+
+  // Getter for this document's SMIL Animation Controller. Performs lazy
+  // initialization, if this document supports animation and if
+  // mAnimationController isn't yet initialized.
   virtual nsSMILAnimationController* GetAnimationController() = 0;
 #endif // MOZ_SMIL
 
   /**
    * Prevents user initiated events from being dispatched to the document and
    * subdocuments.
    */
   virtual void SuppressEventHandling(PRUint32 aIncrease = 1) = 0;
@@ -1339,16 +1345,21 @@ protected:
   mozilla::css::Loader* mCSSLoader; // [STRONG]
 
   // The set of all object, embed, applet, video and audio elements for
   // which this is the owner document. (They might not be in the document.)
   // These are non-owning pointers, the elements are responsible for removing
   // themselves when they go away.
   nsAutoPtr<nsTHashtable<nsPtrHashKey<nsIContent> > > mFreezableElements;
 
+#ifdef MOZ_SMIL
+  // SMIL Animation Controller, lazily-initialized in GetAnimationController
+  nsAutoPtr<nsSMILAnimationController> mAnimationController;
+#endif // MOZ_SMIL
+
   // Table of element properties for this document.
   nsPropertyTable mPropertyTable;
 
   // Compatibility mode
   nsCompatibility mCompatMode;
 
   // True if BIDI is enabled.
   PRPackedBool mBidiEnabled;
--- a/content/base/src/nsDocument.h
+++ b/content/base/src/nsDocument.h
@@ -130,20 +130,16 @@ class nsIOutputStream;
 class nsDocument;
 class nsIDTD;
 class nsIRadioVisitor;
 class nsIFormControl;
 struct nsRadioGroupStruct;
 class nsOnloadBlocker;
 class nsUnblockOnloadEvent;
 class nsChildContentList;
-#ifdef MOZ_SMIL
-class nsSMILAnimationController;
-#endif // MOZ_SMIL
-
 
 /**
  * Right now our identifier map entries contain information for 'name'
  * and 'id' mappings of a given string. This is so that
  * nsHTMLDocument::ResolveName only has to do one hash lookup instead
  * of two. It's not clear whether this still matters for performance.
  * 
  * We also store the document.all result list here. This is mainly so that
@@ -890,16 +886,18 @@ public:
   virtual NS_HIDDEN_(nsIDocument*)
     RequestExternalResource(nsIURI* aURI,
                             nsINode* aRequestingNode,
                             ExternalResourceLoad** aPendingLoad);
   virtual NS_HIDDEN_(void)
     EnumerateExternalResources(nsSubDocEnumFunc aCallback, void* aData);
 
 #ifdef MOZ_SMIL
+  // Returns our (lazily-initialized) animation controller.
+  // If HasAnimationController is true, this is guaranteed to return non-null.
   nsSMILAnimationController* GetAnimationController();
 #endif // MOZ_SMIL
 
   virtual void SuppressEventHandling(PRUint32 aIncrease);
 
   virtual void UnsuppressEventHandlingAndFireEvents(PRBool aFireEvents);
   
   void DecreaseEventSuppression() { --mEventsSuppressed; }
@@ -1190,20 +1188,16 @@ private:
 
   nsExternalResourceMap mExternalResourceMap;
 
   // All images in process of being preloaded
   nsCOMArray<imgIRequest> mPreloadingImages;
 
   nsCOMPtr<nsIDOMDOMImplementation> mDOMImplementation;
 
-#ifdef MOZ_SMIL
-  nsAutoPtr<nsSMILAnimationController> mAnimationController;
-#endif // MOZ_SMIL
-
 #ifdef DEBUG
 protected:
   PRBool mWillReparent;
 #endif
 };
 
 #define NS_DOCUMENT_INTERFACE_TABLE_BEGIN(_class)                             \
   NS_NODE_OFFSET_AND_INTERFACE_TABLE_BEGIN(_class)                            \
--- a/content/smil/nsISMILAnimationElement.h
+++ b/content/smil/nsISMILAnimationElement.h
@@ -35,30 +35,32 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef NS_ISMILANIMATIONELEMENT_H_
 #define NS_ISMILANIMATIONELEMENT_H_
 
 #include "nsISupports.h"
-#include "nsIContent.h"
-
-class nsISMILAttr;
 
 //////////////////////////////////////////////////////////////////////////////
 // nsISMILAnimationElement: Interface for elements that control the animation of
 // some property of another element, e.g. <animate>, <set>.
 
 #define NS_ISMILANIMATIONELEMENT_IID \
-{ 0x70ac6eed, 0x0dba, 0x4c11, { 0xa6, 0xc5, 0x15, 0x73, 0xbc, 0x2f, 0x1a, 0xd8 } }
+{ 0x5c891601, 0x47aa, 0x4230,        \
+  { 0xb8, 0xdc, 0xb9, 0x26, 0xd1, 0xe7, 0xd7, 0xf4 } }
 
+class nsISMILAttr;
 class nsSMILAnimationFunction;
 class nsSMILTimeContainer;
 class nsSMILTimedElement;
+class nsIContent;
+class nsIAtom;
+class nsAttrValue;
 
 enum nsSMILTargetAttrType {
   eSMILTargetAttrType_auto,
   eSMILTargetAttrType_CSS,
   eSMILTargetAttrType_XML
 };
 
 class nsISMILAnimationElement : public nsISupports
@@ -93,28 +95,22 @@ public:
    * Get the current value of an attribute as a string. The global namespace
    * will be used.
    *
    * @param aName the name of the attr
    * @param aResult the value (may legitimately be the empty string) [OUT]
    * @returns PR_TRUE if the attribute was set (even when set to empty string)
    *          PR_FALSE when not set.
    */
-  PRBool GetAnimAttr(nsIAtom* aAttName, nsAString &aResult) const
-  {
-    return Content().GetAttr(kNameSpaceID_None, aAttName, aResult);
-  }
+  virtual PRBool GetAnimAttr(nsIAtom* aAttName, nsAString& aResult) const = 0;
 
   /*
    * Check for the presence of an attribute in the global namespace.
    */
-  PRBool HasAnimAttr(nsIAtom* aAttName) const
-  {
-    return Content().HasAttr(kNameSpaceID_None, aAttName);
-  }
+  virtual PRBool HasAnimAttr(nsIAtom* aAttName) const = 0;
 
   /*
    * Returns the target (animated) element.
    */
   virtual nsIContent* GetTargetElementContent() = 0;
 
   /*
    * Returns the name of the target (animated) attribute or property.
--- a/content/svg/content/src/nsSVGAnimationElement.cpp
+++ b/content/svg/content/src/nsSVGAnimationElement.cpp
@@ -117,16 +117,29 @@ nsSVGAnimationElement::Content()
 }
 
 const nsAttrValue*
 nsSVGAnimationElement::GetAnimAttr(nsIAtom* aName) const
 {
   return mAttrsAndChildren.GetAttr(aName, kNameSpaceID_None);
 }
 
+PRBool
+nsSVGAnimationElement::GetAnimAttr(nsIAtom* aAttName,
+                                   nsAString& aResult) const
+{
+  return GetAttr(kNameSpaceID_None, aAttName, aResult);
+}
+
+PRBool
+nsSVGAnimationElement::HasAnimAttr(nsIAtom* aAttName) const
+{
+  return HasAttr(kNameSpaceID_None, aAttName);
+}
+
 nsIContent*
 nsSVGAnimationElement::GetTargetElementContent()
 {
   if (HasAttr(kNameSpaceID_XLink, nsGkAtoms::href)) {
     return mHrefTarget.get();
   }
   NS_ABORT_IF_FALSE(!mHrefTarget.get(),
                     "We shouldn't have an xlink:href target "
--- a/content/svg/content/src/nsSVGAnimationElement.h
+++ b/content/svg/content/src/nsSVGAnimationElement.h
@@ -83,16 +83,18 @@ public:
                                 nsIAtom* aAttribute,
                                 const nsAString& aValue,
                                 nsAttrValue& aResult);
 
   // nsISMILAnimationElement interface
   virtual const nsIContent& Content() const;
   virtual nsIContent& Content();
   virtual const nsAttrValue* GetAnimAttr(nsIAtom* aName) const;
+  virtual PRBool GetAnimAttr(nsIAtom* aAttName, nsAString& aResult) const;
+  virtual PRBool HasAnimAttr(nsIAtom* aAttName) const;
   virtual nsIContent* GetTargetElementContent();
   virtual nsIAtom* GetTargetAttributeName() const;
   virtual nsSMILTargetAttrType GetTargetAttributeType() const;
   virtual nsSMILTimedElement& TimedElement();
   virtual nsSMILTimeContainer* GetTimeContainer();
 
 protected:
   void UpdateHrefTarget(nsIContent* aNodeForContext,
--- a/content/svg/content/src/nsSVGElement.cpp
+++ b/content/svg/content/src/nsSVGElement.cpp
@@ -1872,28 +1872,22 @@ nsSVGElement::GetAnimatedAttr(const nsIA
 
   return nsnull;
 }
 
 void
 nsSVGElement::AnimationNeedsResample()
 {
   nsIDocument* doc = GetCurrentDoc();
-  if (doc) {
-    nsSMILAnimationController* smilController = doc->GetAnimationController();
-    if (smilController) {
-      smilController->SetResampleNeeded();
-    }
+  if (doc && doc->HasAnimationController()) {
+    doc->GetAnimationController()->SetResampleNeeded();
   }
 }
 
 void
 nsSVGElement::FlushAnimations()
 {
   nsIDocument* doc = GetCurrentDoc();
-  if (doc) {
-    nsSMILAnimationController* smilController = doc->GetAnimationController();
-    if (smilController) {
-      smilController->FlushResampleRequests();
-    }
+  if (doc && doc->HasAnimationController()) {
+    doc->GetAnimationController()->FlushResampleRequests();
   }
 }
 #endif // MOZ_SMIL
--- a/layout/base/nsPresContext.cpp
+++ b/layout/base/nsPresContext.cpp
@@ -1123,18 +1123,18 @@ void nsPresContext::SetImgAnimations(nsI
   }
 }
 
 #ifdef MOZ_SMIL
 void
 nsPresContext::SetSMILAnimations(nsIDocument *aDoc, PRUint16 aNewMode,
                                  PRUint16 aOldMode)
 {
-  nsSMILAnimationController *controller = aDoc->GetAnimationController();
-  if (controller) {
+  if (aDoc->HasAnimationController()) {
+    nsSMILAnimationController* controller = aDoc->GetAnimationController();
     switch (aNewMode)
     {
       case imgIContainer::kNormalAnimMode:
       case imgIContainer::kLoopOnceAnimMode:
         if (aOldMode == imgIContainer::kDontAnimMode)
           controller->Resume(nsSMILTimeContainer::PAUSE_USERPREF);
         break;