diff --git a/layout/base/nsRefreshDriver.cpp b/layout/base/nsRefreshDriver.cpp index 0cf9fab261d2..80bb2e033593 100644 --- a/layout/base/nsRefreshDriver.cpp +++ b/layout/base/nsRefreshDriver.cpp @@ -44,6 +44,7 @@ #include "nsPresContext.h" #include "nsComponentManagerUtils.h" #include "prlog.h" +#include "nsAutoPtr.h" /* * TODO: @@ -194,10 +195,22 @@ nsRefreshDriver::Notify(nsITimer *aTimer) return NS_OK; } + /* + * The timer holds a reference to |this| while calling |Notify|. + * However, implementations of |WillRefresh| are permitted to destroy + * the pres context, which will cause our |mPresContext| to become + * null. If this happens, we must stop notifying observers. + */ for (PRUint32 i = 0; i < NS_ARRAY_LENGTH(mObservers); ++i) { ObserverArray::EndLimitedIterator etor(mObservers[i]); while (etor.HasMore()) { - etor.GetNext()->WillRefresh(mMostRecentRefresh); + nsRefPtr obs = etor.GetNext(); + obs->WillRefresh(mMostRecentRefresh); + + if (!mPresContext || !mPresContext->GetPresShell()) { + StopTimer(); + return NS_OK; + } } if (i == 0) { // This is the Flush_Style case. diff --git a/layout/base/nsRefreshDriver.h b/layout/base/nsRefreshDriver.h index 41f535d24260..a65cd44cba08 100644 --- a/layout/base/nsRefreshDriver.h +++ b/layout/base/nsRefreshDriver.h @@ -58,6 +58,15 @@ class nsPresContext; */ class nsARefreshObserver { public: + // AddRef and Release signatures that match nsISupports. Implementors + // must implement reference counting, and those that do implement + // nsISupports will already have methods with the correct signature. + // + // The refresh driver does NOT hold references to refresh observers + // except while it is notifying them. + NS_IMETHOD_(nsrefcnt) AddRef(void) = 0; + NS_IMETHOD_(nsrefcnt) Release(void) = 0; + virtual void WillRefresh(mozilla::TimeStamp aTime) = 0; }; @@ -93,6 +102,9 @@ public: * painting, and, correspondingly, which get notified when there * is a flush during such suppression * and it must be either Flush_Style, Flush_Layout, or Flush_Display. + * + * The refresh driver does NOT own a reference to these observers; + * they must remove themselves before they are destroyed. */ PRBool AddRefreshObserver(nsARefreshObserver *aObserver, mozFlushType aFlushType);