diff --git a/layout/xul/base/src/nsImageBoxFrame.cpp b/layout/xul/base/src/nsImageBoxFrame.cpp index 278d0fb1b55..71eb7a20232 100644 --- a/layout/xul/base/src/nsImageBoxFrame.cpp +++ b/layout/xul/base/src/nsImageBoxFrame.cpp @@ -144,7 +144,8 @@ nsImageBoxFrame::nsImageBoxFrame(nsIPresShell* aShell, nsStyleContext* aContext) mRequestRegistered(false), mLoadFlags(nsIRequest::LOAD_NORMAL), mUseSrcAttr(false), - mSuppressStyleCheck(false) + mSuppressStyleCheck(false), + mFireEventOnDecode(false) { MarkIntrinsicWidthsDirty(); } @@ -630,6 +631,22 @@ nsresult nsImageBoxFrame::OnStartContainer(imgIRequest *request, nsresult nsImageBoxFrame::OnStopDecode(imgIRequest *request) { + if (mFireEventOnDecode) { + mFireEventOnDecode = false; + + uint32_t reqStatus; + request->GetImageStatus(&reqStatus); + if (!(reqStatus & imgIRequest::STATUS_ERROR)) { + FireImageDOMEvent(mContent, NS_LOAD); + } else { + // Fire an onerror DOM event. + mIntrinsicSize.SizeTo(0, 0); + PresContext()->PresShell()-> + FrameNeedsReflow(this, nsIPresShell::eStyleChange, NS_FRAME_IS_DIRTY); + FireImageDOMEvent(mContent, NS_LOAD_ERROR); + } + } + nsBoxLayoutState state(PresContext()); this->Redraw(state); @@ -639,15 +656,26 @@ nsresult nsImageBoxFrame::OnStopDecode(imgIRequest *request) nsresult nsImageBoxFrame::OnStopRequest(imgIRequest *request, nsresult aStatus) { - if (NS_SUCCEEDED(aStatus)) - // Fire an onload DOM event. - FireImageDOMEvent(mContent, NS_LOAD); - else { - // Fire an onerror DOM event. - mIntrinsicSize.SizeTo(0, 0); - PresContext()->PresShell()-> - FrameNeedsReflow(this, nsIPresShell::eStyleChange, NS_FRAME_IS_DIRTY); - FireImageDOMEvent(mContent, NS_LOAD_ERROR); + uint32_t reqStatus; + request->GetImageStatus(&reqStatus); + + // We want to give the decoder a chance to find errors. If we haven't found + // an error yet and we've already started decoding, we must only fire these + // events after we finish decoding. + if (NS_SUCCEEDED(aStatus) && !(reqStatus & imgIRequest::STATUS_ERROR) && + reqStatus & imgIRequest::STATUS_DECODE_STARTED) { + mFireEventOnDecode = true; + } else { + if (NS_SUCCEEDED(aStatus)) { + // Fire an onload DOM event. + FireImageDOMEvent(mContent, NS_LOAD); + } else { + // Fire an onerror DOM event. + mIntrinsicSize.SizeTo(0, 0); + PresContext()->PresShell()-> + FrameNeedsReflow(this, nsIPresShell::eStyleChange, NS_FRAME_IS_DIRTY); + FireImageDOMEvent(mContent, NS_LOAD_ERROR); + } } return NS_OK; @@ -673,7 +701,7 @@ nsresult nsImageBoxFrame::FrameChanged(imgIRequest *aRequest) return NS_OK; } -NS_IMPL_ISUPPORTS1(nsImageBoxListener, imgINotificationObserver) +NS_IMPL_ISUPPORTS2(nsImageBoxListener, imgINotificationObserver, imgIOnloadBlocker) nsImageBoxListener::nsImageBoxListener() { @@ -691,3 +719,25 @@ nsImageBoxListener::Notify(imgIRequest *request, int32_t aType, const nsIntRect* return mFrame->Notify(request, aType, aData); } + +/* void blockOnload (in imgIRequest aRequest); */ +NS_IMETHODIMP +nsImageBoxListener::BlockOnload(imgIRequest *aRequest) +{ + if (mFrame && mFrame->GetContent() && mFrame->GetContent()->GetCurrentDoc()) { + mFrame->GetContent()->GetCurrentDoc()->BlockOnload(); + } + + return NS_OK; +} + +/* void unblockOnload (in imgIRequest aRequest); */ +NS_IMETHODIMP +nsImageBoxListener::UnblockOnload(imgIRequest *aRequest) +{ + if (mFrame && mFrame->GetContent() && mFrame->GetContent()->GetCurrentDoc()) { + mFrame->GetContent()->GetCurrentDoc()->UnblockOnload(false); + } + + return NS_OK; +} diff --git a/layout/xul/base/src/nsImageBoxFrame.h b/layout/xul/base/src/nsImageBoxFrame.h index 6a3cfb7a082..4cf3388face 100644 --- a/layout/xul/base/src/nsImageBoxFrame.h +++ b/layout/xul/base/src/nsImageBoxFrame.h @@ -12,13 +12,15 @@ #include "imgIRequest.h" #include "imgIContainer.h" #include "imgINotificationObserver.h" +#include "imgIOnloadBlocker.h" class imgRequestProxy; class nsImageBoxFrame; class nsDisplayXULImage; -class nsImageBoxListener : public imgINotificationObserver +class nsImageBoxListener : public imgINotificationObserver, + public imgIOnloadBlocker { public: nsImageBoxListener(); @@ -26,6 +28,7 @@ public: NS_DECL_ISUPPORTS NS_DECL_IMGINOTIFICATIONOBSERVER + NS_DECL_IMGIONLOADBLOCKER void SetFrame(nsImageBoxFrame *frame) { mFrame = frame; } @@ -118,6 +121,7 @@ private: bool mUseSrcAttr; ///< Whether or not the image src comes from an attribute. bool mSuppressStyleCheck; + bool mFireEventOnDecode; }; // class nsImageBoxFrame class nsDisplayXULImage : public nsDisplayImageContainer {