Make nsRefreshDriver hold a reference to its observers while notifying them. (Bug 531585) r=bzbarsky

This commit is contained in:
L. David Baron 2009-12-23 06:35:45 -05:00
parent 521bd402f6
commit d8b2dda1b6
2 changed files with 26 additions and 1 deletions

View File

@ -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<nsARefreshObserver> obs = etor.GetNext();
obs->WillRefresh(mMostRecentRefresh);
if (!mPresContext || !mPresContext->GetPresShell()) {
StopTimer();
return NS_OK;
}
}
if (i == 0) {
// This is the Flush_Style case.

View File

@ -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);