Bug 854799: Make image.src='' discard the image immediately even if the image is not in the document. r=jlebar

This commit is contained in:
Kyle Huey 2013-04-09 09:50:35 -07:00
parent dea9da1095
commit 2e0f028222
2 changed files with 36 additions and 22 deletions

View File

@ -99,8 +99,9 @@ void
nsImageLoadingContent::DestroyImageLoadingContent()
{
// Cancel our requests so they won't hold stale refs to us
ClearCurrentRequest(NS_BINDING_ABORTED);
ClearPendingRequest(NS_BINDING_ABORTED);
// NB: Don't ask to discard the images here.
ClearCurrentRequest(NS_BINDING_ABORTED, 0);
ClearPendingRequest(NS_BINDING_ABORTED, 0);
}
nsImageLoadingContent::~nsImageLoadingContent()
@ -944,8 +945,8 @@ void
nsImageLoadingContent::CancelImageRequests(bool aNotify)
{
AutoStateChanger changer(this, aNotify);
ClearPendingRequest(NS_BINDING_ABORTED);
ClearCurrentRequest(NS_BINDING_ABORTED);
ClearPendingRequest(NS_BINDING_ABORTED, REQUEST_DISCARD);
ClearCurrentRequest(NS_BINDING_ABORTED, REQUEST_DISCARD);
}
nsresult
@ -956,8 +957,8 @@ nsImageLoadingContent::UseAsPrimaryRequest(imgRequestProxy* aRequest,
AutoStateChanger changer(this, aNotify);
// Get rid if our existing images
ClearPendingRequest(NS_BINDING_ABORTED);
ClearCurrentRequest(NS_BINDING_ABORTED);
ClearPendingRequest(NS_BINDING_ABORTED, REQUEST_DISCARD);
ClearCurrentRequest(NS_BINDING_ABORTED, REQUEST_DISCARD);
// Clone the request we were given.
nsRefPtr<imgRequestProxy>& req = PrepareNextRequest();
@ -1074,14 +1075,14 @@ nsImageLoadingContent::SetBlockedRequest(nsIURI* aURI, int16_t aContentDecision)
// reason "image source changed". However, apparently there's some abuse
// over in nsImageFrame where the displaying of the "broken" icon for the
// next image depends on the cancel reason of the previous image. ugh.
ClearPendingRequest(NS_ERROR_IMAGE_BLOCKED);
ClearPendingRequest(NS_ERROR_IMAGE_BLOCKED, REQUEST_DISCARD);
// For the blocked case, we only want to cancel the existing current request
// if size is not available. bz says the web depends on this behavior.
if (!HaveSize(mCurrentRequest)) {
mImageBlockingStatus = aContentDecision;
ClearCurrentRequest(NS_ERROR_IMAGE_BLOCKED);
ClearCurrentRequest(NS_ERROR_IMAGE_BLOCKED, REQUEST_DISCARD);
// We still want to remember what URI we were despite not having an actual
// request.
@ -1097,7 +1098,7 @@ nsImageLoadingContent::PrepareCurrentRequest()
mImageBlockingStatus = nsIContentPolicy::ACCEPT;
// Get rid of anything that was there previously.
ClearCurrentRequest(NS_ERROR_IMAGE_SRC_CHANGED);
ClearCurrentRequest(NS_ERROR_IMAGE_SRC_CHANGED, REQUEST_DISCARD);
if (mNewRequestsWillNeedAnimationReset) {
mCurrentRequestFlags |= REQUEST_NEEDS_ANIMATION_RESET;
@ -1111,7 +1112,7 @@ nsRefPtr<imgRequestProxy>&
nsImageLoadingContent::PreparePendingRequest()
{
// Get rid of anything that was there previously.
ClearPendingRequest(NS_ERROR_IMAGE_SRC_CHANGED);
ClearPendingRequest(NS_ERROR_IMAGE_SRC_CHANGED, REQUEST_DISCARD);
if (mNewRequestsWillNeedAnimationReset) {
mPendingRequestFlags |= REQUEST_NEEDS_ANIMATION_RESET;
@ -1167,7 +1168,8 @@ nsImageLoadingContent::MakePendingRequestCurrent()
}
void
nsImageLoadingContent::ClearCurrentRequest(nsresult aReason)
nsImageLoadingContent::ClearCurrentRequest(nsresult aReason,
uint32_t aFlags)
{
if (!mCurrentRequest) {
// Even if we didn't have a current request, we might have been keeping
@ -1184,14 +1186,15 @@ nsImageLoadingContent::ClearCurrentRequest(nsresult aReason)
&mCurrentRequestRegistered);
// Clean up the request.
UntrackImage(mCurrentRequest, REQUEST_DISCARD);
UntrackImage(mCurrentRequest, aFlags);
mCurrentRequest->CancelAndForgetObserver(aReason);
mCurrentRequest = nullptr;
mCurrentRequestFlags = 0;
}
void
nsImageLoadingContent::ClearPendingRequest(nsresult aReason)
nsImageLoadingContent::ClearPendingRequest(nsresult aReason,
uint32_t aFlags)
{
if (!mPendingRequest)
return;
@ -1207,7 +1210,7 @@ nsImageLoadingContent::ClearPendingRequest(nsresult aReason)
nsLayoutUtils::DeregisterImageRequest(GetFramePresContext(), mPendingRequest,
&mPendingRequestRegistered);
UntrackImage(mPendingRequest, REQUEST_DISCARD);
UntrackImage(mPendingRequest, aFlags);
mPendingRequest->CancelAndForgetObserver(aReason);
mPendingRequest = nullptr;
mPendingRequestFlags = 0;
@ -1326,21 +1329,32 @@ nsImageLoadingContent::UntrackImage(imgIRequest* aImage, uint32_t aFlags /* = 0
MOZ_ASSERT(aImage == mCurrentRequest || aImage == mPendingRequest,
"Why haven't we heard of this request?");
// If GetOurDocument() returns null here, we've outlived our document.
// That's fine, because the document empties out the tracker and unlocks
// all locked images on destruction.
// We may not be in the document. If we outlived our document that's fine,
// because the document empties out the tracker and unlocks all locked images
// on destruction. But if we were never in the document we may need to force
// discarding the image here, since this is the only chance we have.
nsIDocument* doc = GetOurCurrentDoc();
if (doc) {
if (aImage == mCurrentRequest && (mCurrentRequestFlags & REQUEST_IS_TRACKED)) {
if (aImage == mCurrentRequest) {
if (doc && (mCurrentRequestFlags & REQUEST_IS_TRACKED)) {
mCurrentRequestFlags &= ~REQUEST_IS_TRACKED;
doc->RemoveImage(mCurrentRequest,
(aFlags & REQUEST_DISCARD) ? nsIDocument::REQUEST_DISCARD : 0);
}
if (aImage == mPendingRequest && (mPendingRequestFlags & REQUEST_IS_TRACKED)) {
else if (aFlags & REQUEST_DISCARD) {
// If we're not in the document we may still need to be discarded.
aImage->RequestDiscard();
}
}
if (aImage == mPendingRequest) {
if (doc && (mPendingRequestFlags & REQUEST_IS_TRACKED)) {
mPendingRequestFlags &= ~REQUEST_IS_TRACKED;
doc->RemoveImage(mPendingRequest,
(aFlags & REQUEST_DISCARD) ? nsIDocument::REQUEST_DISCARD : 0);
}
else if (aFlags & REQUEST_DISCARD) {
// If we're not in the document we may still need to be discarded.
aImage->RequestDiscard();
}
}
return NS_OK;
}

View File

@ -298,8 +298,8 @@ protected:
/**
* Cancels and nulls-out the "current" and "pending" requests if they exist.
*/
void ClearCurrentRequest(nsresult aReason);
void ClearPendingRequest(nsresult aReason);
void ClearCurrentRequest(nsresult aReason, uint32_t aFlags);
void ClearPendingRequest(nsresult aReason, uint32_t aFlags);
/**
* Retrieve a pointer to the 'registered with the refresh driver' flag for