Bug 1033679. When we clear frames from the image loader make sure that we also remove the images from the refresh driver. r=khuey

Normally a frame being destroyed would do this via PresShell::NotifyDestroyingFrame -> ImageLoader::DropRequestsForFrame but when we are tearing down the whole frame tree we skip per frame notifications like that for perf reasons. So we now make sure to do it when clearing out frames wholesale.

We also need to pass a prescontext pointer to ClearFrames because the ImageLoader only has a document pointer, and by that point in the presshell destruction sequence the presshell pointer on the document has been cleared.
This commit is contained in:
Timothy Nikkel 2014-09-04 23:27:16 -05:00
parent c8afb910e7
commit b45467f328
3 changed files with 39 additions and 5 deletions

View File

@ -2134,7 +2134,7 @@ PresShell::SetIgnoreFrameDestruction(bool aIgnore)
if (mDocument) {
// We need to tell the ImageLoader to drop all its references to frames
// because they're about to go away and it won't get notifications of that.
mDocument->StyleImageLoader()->ClearFrames();
mDocument->StyleImageLoader()->ClearFrames(mPresContext);
}
mIgnoreFrameDestruction = aIgnore;
}

View File

@ -64,7 +64,10 @@ ClearImageHashSet(nsPtrHashKey<ImageLoader::Image>* aKey, void* aClosure)
void
ImageLoader::DropDocumentReference()
{
ClearFrames();
// It's okay if GetPresContext returns null here (due to the presshell pointer
// on the document being null) as that means the presshell has already
// been destroyed, and it also calls ClearFrames when it is destroyed.
ClearFrames(GetPresContext());
mImages.EnumerateEntries(&ClearImageHashSet, mDocument);
mDocument = nullptr;
}
@ -232,9 +235,33 @@ ImageLoader::SetAnimationMode(uint16_t aMode)
mRequestToFrameMap.EnumerateRead(SetAnimationModeEnumerator, &aMode);
}
void
ImageLoader::ClearFrames()
/* static */ PLDHashOperator
ImageLoader::DeregisterRequestEnumerator(nsISupports* aKey, FrameSet* aValue,
void* aClosure)
{
imgIRequest* request = static_cast<imgIRequest*>(aKey);
#ifdef DEBUG
{
nsCOMPtr<imgIRequest> debugRequest = do_QueryInterface(aKey);
NS_ASSERTION(debugRequest == request, "This is bad");
}
#endif
nsPresContext* presContext = static_cast<nsPresContext*>(aClosure);
if (presContext) {
nsLayoutUtils::DeregisterImageRequest(presContext,
request,
nullptr);
}
return PL_DHASH_NEXT;
}
void
ImageLoader::ClearFrames(nsPresContext* aPresContext)
{
mRequestToFrameMap.EnumerateRead(DeregisterRequestEnumerator, aPresContext);
mRequestToFrameMap.Clear();
mFrameToRequestMap.Clear();
}

View File

@ -59,7 +59,10 @@ public:
void SetAnimationMode(uint16_t aMode);
void ClearFrames();
// The prescontext for this ImageLoader's document. We need it to be passed
// in because this can be called during presentation destruction after the
// presshell pointer on the document has been cleared.
void ClearFrames(nsPresContext* aPresContext);
void LoadImage(nsIURI* aURI, nsIPrincipal* aPrincipal, nsIURI* aReferrer,
Image* aCSSValue);
@ -93,6 +96,10 @@ private:
SetAnimationModeEnumerator(nsISupports* aKey, FrameSet* aValue,
void* aClosure);
static PLDHashOperator
DeregisterRequestEnumerator(nsISupports* aKey, FrameSet* aValue,
void* aClosure);
nsresult OnStartContainer(imgIRequest *aRequest, imgIContainer* aImage);
nsresult OnStopFrame(imgIRequest *aRequest);
nsresult OnImageIsAnimated(imgIRequest *aRequest);