diff --git a/layout/base/nsPresContext.cpp b/layout/base/nsPresContext.cpp index 94cbfb6e1c1..adbcb8d40df 100644 --- a/layout/base/nsPresContext.cpp +++ b/layout/base/nsPresContext.cpp @@ -259,7 +259,9 @@ nsPresContext::~nsPresContext() NS_PRECONDITION(!mShell, "Presshell forgot to clear our mShell pointer"); SetShell(nsnull); - delete mTransitionManager; + if (mTransitionManager) { + mTransitionManager->Disconnect(); + } // Disconnect the refresh driver *after* the transition manager, which // needs it. diff --git a/layout/base/nsPresContext.h b/layout/base/nsPresContext.h index 407dd37084a..564fca5c5f5 100644 --- a/layout/base/nsPresContext.h +++ b/layout/base/nsPresContext.h @@ -952,7 +952,7 @@ protected: nsIEventStateManager* mEventManager; // [STRONG] nsILookAndFeel* mLookAndFeel; // [STRONG] nsRefPtr mRefreshDriver; - nsTransitionManager* mTransitionManager; // owns; it aggregates our refcount + nsRefPtr mTransitionManager; nsIAtom* mMedium; // initialized by subclass ctors; // weak pointer to static atom diff --git a/layout/style/nsTransitionManager.cpp b/layout/style/nsTransitionManager.cpp index 51a38edd648..0d070385102 100644 --- a/layout/style/nsTransitionManager.cpp +++ b/layout/style/nsTransitionManager.cpp @@ -333,6 +333,12 @@ nsTransitionManager::nsTransitionManager(nsPresContext *aPresContext) } nsTransitionManager::~nsTransitionManager() +{ + NS_ABORT_IF_FALSE(!mPresContext, "Disconnect should have been called"); +} + +void +nsTransitionManager::Disconnect() { // Content nodes might outlive the transition manager. while (!PR_CLIST_IS_EMPTY(&mElementTransitions)) { @@ -340,6 +346,8 @@ nsTransitionManager::~nsTransitionManager() PR_LIST_HEAD(&mElementTransitions)); head->Destroy(); } + + mPresContext = nsnull; } static PRBool @@ -781,9 +789,7 @@ nsTransitionManager::AddElementTransitions(ElementTransitions* aElementTransitio * 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 @@ -885,6 +891,10 @@ nsTransitionManager::MediumFeaturesChanged(nsPresContext* aPresContext, /* 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. { diff --git a/layout/style/nsTransitionManager.h b/layout/style/nsTransitionManager.h index c91bb81efc6..f9761c38152 100644 --- a/layout/style/nsTransitionManager.h +++ b/layout/style/nsTransitionManager.h @@ -52,16 +52,17 @@ 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(); + /** * StyleContextChanged * @@ -82,7 +83,7 @@ public: nsStyleContext *aNewStyleContext); // nsISupports - NS_DECL_ISUPPORTS_INHERITED + NS_DECL_ISUPPORTS // nsIStyleRuleProcessor NS_IMETHOD RulesMatching(ElementRuleProcessorData* aData); @@ -120,7 +121,7 @@ private: nsCSSPseudoElements::Type aPseudoType); PRCList mElementTransitions; - nsPresContext *mPresContext; + nsPresContext *mPresContext; // weak (non-null from ctor to Disconnect) }; #endif /* !defined(nsTransitionManager_h_) */