Make the transition manager reference-counted. (Bug 531585) r=bzbarsky
☠☠ backed out by f32e7f33b015 ☠ ☠
authorL. David Baron <dbaron@dbaron.org>
Mon, 21 Dec 2009 16:46:25 -0500
changeset 36522 8b22441911b036039ea3927cb2859ac4d67ae8b5
parent 36521 fa5326c011b8d22f132d59d191b8f3316be5dda9
child 36523 cfa10b01b1f657b7ac20ccaef5a666ffc334881c
push idunknown
push userunknown
push dateunknown
reviewersbzbarsky
bugs531585
milestone1.9.3a1pre
Make the transition manager reference-counted. (Bug 531585) r=bzbarsky
layout/base/nsPresContext.cpp
layout/base/nsPresContext.h
layout/style/nsTransitionManager.cpp
layout/style/nsTransitionManager.h
--- a/layout/base/nsPresContext.cpp
+++ b/layout/base/nsPresContext.cpp
@@ -258,17 +258,19 @@ nsPresContext::~nsPresContext()
 
   NS_PRECONDITION(!mShell, "Presshell forgot to clear our mShell pointer");
   SetShell(nsnull);
 
   if (mRefreshDriver) {
     mRefreshDriver->Disconnect();
   }
 
-  delete mTransitionManager;
+  if (mTransitionManager) {
+    mTransitionManager->Disconnect();
+  }
 
   if (mEventManager) {
     // unclear if these are needed, but can't hurt
     mEventManager->NotifyDestroyPresContext(this);
     mEventManager->SetPresContext(nsnull);
 
     NS_RELEASE(mEventManager);
   }
--- a/layout/base/nsPresContext.h
+++ b/layout/base/nsPresContext.h
@@ -947,17 +947,17 @@ protected:
   nsIDeviceContext*     mDeviceContext; // [STRONG] could be weak, but
                                         // better safe than sorry.
                                         // Cannot reintroduce cycles
                                         // since there is no dependency
                                         // from gfx back to layout.
   nsIEventStateManager* mEventManager;  // [STRONG]
   nsILookAndFeel*       mLookAndFeel;   // [STRONG]
   nsRefPtr<nsRefreshDriver> mRefreshDriver;
-  nsTransitionManager*  mTransitionManager; // owns; it aggregates our refcount
+  nsRefPtr<nsTransitionManager> mTransitionManager;
   nsIAtom*              mMedium;        // initialized by subclass ctors;
                                         // weak pointer to static atom
 
   nsILinkHandler*       mLinkHandler;   // [WEAK]
   nsIAtom*              mLangGroup;     // [STRONG]
 
   nsRefPtrHashtable<nsVoidPtrHashKey, nsImageLoader>
                         mImageLoaders[IMAGE_LOAD_TYPE_COUNT];
--- a/layout/style/nsTransitionManager.cpp
+++ b/layout/style/nsTransitionManager.cpp
@@ -742,19 +742,17 @@ nsTransitionManager::AddElementTransitio
 
   PR_INSERT_BEFORE(aElementTransitions, &mElementTransitions);
 }
 
 /*
  * nsISupports implementation
  */
 
-NS_IMPL_ADDREF_USING_AGGREGATOR(nsTransitionManager, mPresContext)
-NS_IMPL_RELEASE_USING_AGGREGATOR(nsTransitionManager, mPresContext)
-NS_IMPL_QUERY_INTERFACE1(nsTransitionManager, nsIStyleRuleProcessor)
+NS_IMPL_ISUPPORTS1(nsTransitionManager, nsIStyleRuleProcessor)
 
 /*
  * nsIStyleRuleProcessor implementation
  */
 
 nsresult
 nsTransitionManager::WalkTransitionRule(RuleProcessorData* aData,
                                         nsCSSPseudoElements::Type aPseudoType)
@@ -846,16 +844,20 @@ nsTransitionManager::MediumFeaturesChang
 {
   *aRulesChanged = PR_FALSE;
   return NS_OK;
 }
 
 /* virtual */ void
 nsTransitionManager::WillRefresh(mozilla::TimeStamp aTime)
 {
+  NS_ABORT_IF_FALSE(mPresContext,
+                    "refresh driver should not notify additional observers "
+                    "after pres context has been destroyed");
+
   // Trim transitions that have completed, and post restyle events for
   // frames that are still transitioning.
   {
     PRCList *next = PR_LIST_HEAD(&mElementTransitions);
     while (next != &mElementTransitions) {
       ElementTransitions *et = static_cast<ElementTransitions*>(next);
       next = PR_NEXT_LINK(next);
 
--- a/layout/style/nsTransitionManager.h
+++ b/layout/style/nsTransitionManager.h
@@ -47,27 +47,30 @@
 #include "nsCSSPseudoElements.h"
 
 class nsStyleContext;
 class nsPresContext;
 class nsCSSPropertySet;
 struct nsTransition;
 struct ElementTransitions;
 
-/**
- * Must be created only as a sub-object of an nsPresContext (since its
- * reference counting methods assume that).
- */
 class nsTransitionManager : public nsIStyleRuleProcessor,
                             public nsARefreshObserver {
 public:
   nsTransitionManager(nsPresContext *aPresContext);
   ~nsTransitionManager();
 
   /**
+   * Notify the transition manager that the pres context is going away.
+   */
+  void Disconnect() {
+    mPresContext = nsnull;
+  }
+
+  /**
    * StyleContextChanged 
    *
    * To be called from nsFrameManager::ReResolveStyleContext when the
    * style of an element has changed, to initiate transitions from that
    * style change.
    *
    * It may return a "cover rule" (see CoverTransitionStartStyleRule) to
    * cover up some of the changes for the duration of the restyling of
@@ -77,17 +80,17 @@ public:
    * returned cover rule as the most specific rule.
    */
   already_AddRefed<nsIStyleRule>
     StyleContextChanged(nsIContent *aElement,
                         nsStyleContext *aOldStyleContext,
                         nsStyleContext *aNewStyleContext);
 
   // nsISupports
-  NS_DECL_ISUPPORTS_INHERITED
+  NS_DECL_ISUPPORTS
 
   // nsIStyleRuleProcessor
   NS_IMETHOD RulesMatching(ElementRuleProcessorData* aData);
   NS_IMETHOD RulesMatching(PseudoElementRuleProcessorData* aData);
   NS_IMETHOD RulesMatching(AnonBoxRuleProcessorData* aData);
 #ifdef MOZ_XUL
   NS_IMETHOD RulesMatching(XULTreeRuleProcessorData* aData);
 #endif
@@ -115,12 +118,12 @@ private:
                                             nsCSSPseudoElements::Type aPseudoType,
                                             PRBool aCreateIfNeeded);
   void AddElementTransitions(ElementTransitions* aElementTransitions);
   void TransitionsRemoved();
   nsresult WalkTransitionRule(RuleProcessorData* aData,
 			      nsCSSPseudoElements::Type aPseudoType);
 
   PRCList mElementTransitions;
-  nsPresContext *mPresContext;
+  nsPresContext *mPresContext; // weak (non-null from ctor to Disconnect)
 };
 
 #endif /* !defined(nsTransitionManager_h_) */