Bug 514033 - Error recovery for imagelib - part 9 - Coalesce end-of-decode notifications into superclass.r=joe,a=blocker

This commit is contained in:
Bobby Holley 2010-09-12 08:22:30 -07:00
parent 6b88ca3f31
commit 4f052631cc
12 changed files with 60 additions and 138 deletions

View File

@ -89,11 +89,7 @@ nsBMPDecoder::FinishInternal()
// Send notifications if appropriate
if (!IsSizeDecode() && !IsError() && (GetFrameCount() == 1)) {
PostFrameStop();
mImage->DecodingComplete();
if (mObserver) {
mObserver->OnStopContainer(nsnull, mImage);
mObserver->OnStopDecode(nsnull, NS_OK, nsnull);
}
PostDecodeDone();
}
}

View File

@ -135,10 +135,11 @@ void
nsGIFDecoder2::FinishInternal()
{
// If the GIF got cut off, handle it anyway
if (!IsSizeDecode() && !IsError()) {
if (!IsSizeDecode() && !IsError() && mGIFOpen) {
if (mCurrentFrame == mGIFStruct.images_decoded)
EndImageFrame();
EndGIF(/* aSuccess = */ PR_TRUE);
PostDecodeDone();
mGIFOpen = PR_FALSE;
}
mImage->SetLoopCount(mGIFStruct.loop_count);
@ -192,24 +193,6 @@ void nsGIFDecoder2::BeginGIF()
return;
}
//******************************************************************************
void nsGIFDecoder2::EndGIF(PRBool aSuccess)
{
if (!mGIFOpen)
return;
if (aSuccess)
mImage->DecodingComplete();
if (mObserver) {
mObserver->OnStopContainer(nsnull, mImage);
mObserver->OnStopDecode(nsnull, aSuccess ? NS_OK : NS_ERROR_FAILURE,
nsnull);
}
mGIFOpen = PR_FALSE;
}
//******************************************************************************
nsresult nsGIFDecoder2::BeginImageFrame(gfx_depth aDepth)
{
@ -1067,18 +1050,17 @@ nsGIFDecoder2::WriteInternal(const char *aBuffer, PRUint32 aCount)
break;
case gif_done:
EndGIF(/* aSuccess = */ PR_TRUE);
PostDecodeDone();
mGIFOpen = PR_FALSE;
goto done;
case gif_error:
PostDataError();
EndGIF(/* aSuccess = */ PR_FALSE);
return;
// Handle out of memory errors
case gif_oom:
PostDecoderError(NS_ERROR_OUT_OF_MEMORY);
EndGIF(/* aSuccess = */ PR_FALSE);
return;
// We shouldn't ever get here.
@ -1090,7 +1072,6 @@ nsGIFDecoder2::WriteInternal(const char *aBuffer, PRUint32 aCount)
// if an error state is set but no data remains, code flow reaches here
if (mGIFStruct.state == gif_error) {
PostDataError();
EndGIF(/* aSuccess = */ PR_FALSE);
return;
}

View File

@ -69,7 +69,6 @@ private:
* frame size information, etc. */
void BeginGIF();
void EndGIF(PRBool aSuccess);
nsresult BeginImageFrame(gfx_depth aDepth);
void EndImageFrame();
void FlushImageData();

View File

@ -114,11 +114,7 @@ nsICODecoder::FinishInternal()
PostInvalidation(r);
PostFrameStop();
mImage->DecodingComplete();
if (mObserver) {
mObserver->OnStopContainer(nsnull, 0);
mObserver->OnStopDecode(nsnull, NS_OK, nsnull);
}
PostDecodeDone();
}
}

View File

@ -56,8 +56,7 @@ nsIconDecoder::nsIconDecoder() :
mPixBytesRead(0),
mPixBytesTotal(0),
mImageData(nsnull),
mState(iconStateStart),
mNotifiedDone(PR_FALSE)
mState(iconStateStart)
{
// Nothing to do
}
@ -65,15 +64,6 @@ nsIconDecoder::nsIconDecoder() :
nsIconDecoder::~nsIconDecoder()
{ }
void
nsIconDecoder::FinishInternal()
{
// If we haven't notified of completion yet for a full/success decode, we
// didn't finish. Notify in error mode
if (!IsSizeDecode() && !mNotifiedDone)
NotifyDone(/* aSuccess = */ PR_FALSE);
}
void
nsIconDecoder::WriteInternal(const char *aBuffer, PRUint32 aCount)
{
@ -154,7 +144,8 @@ nsIconDecoder::WriteInternal(const char *aBuffer, PRUint32 aCount)
// If we've got all the pixel bytes, we're finished
if (mPixBytesRead == mPixBytesTotal) {
NotifyDone(/* aSuccess = */ PR_TRUE);
PostFrameStop();
PostDecodeDone();
mState = iconStateFinished;
}
break;
@ -169,25 +160,5 @@ nsIconDecoder::WriteInternal(const char *aBuffer, PRUint32 aCount)
}
}
void
nsIconDecoder::NotifyDone(PRBool aSuccess)
{
// We should only call this once
NS_ABORT_IF_FALSE(!mNotifiedDone, "Calling NotifyDone twice");
// Notify
PostFrameStop();
if (aSuccess)
mImage->DecodingComplete();
if (mObserver) {
mObserver->OnStopContainer(nsnull, mImage);
mObserver->OnStopDecode(nsnull, aSuccess ? NS_OK : NS_ERROR_FAILURE,
nsnull);
}
// Flag that we've notified
mNotifiedDone = PR_TRUE;
}
} // namespace imagelib
} // namespace mozilla

View File

@ -78,7 +78,6 @@ public:
virtual ~nsIconDecoder();
virtual void WriteInternal(const char* aBuffer, PRUint32 aCount);
virtual void FinishInternal();
PRUint8 mWidth;
PRUint8 mHeight;
@ -86,9 +85,6 @@ public:
PRUint32 mPixBytesTotal;
PRUint8* mImageData;
PRUint32 mState;
PRBool mNotifiedDone;
void NotifyDone(PRBool aSuccess);
};
enum {

View File

@ -99,7 +99,6 @@ nsJPEGDecoder::nsJPEGDecoder()
{
mState = JPEG_HEADER;
mReading = PR_TRUE;
mNotifiedDone = PR_FALSE;
mImageData = nsnull;
mBytesToSkip = 0;
@ -187,16 +186,6 @@ nsJPEGDecoder::FinishInternal()
(mState != JPEG_ERROR) &&
!IsSizeDecode())
this->Write(nsnull, 0);
/* If we already know we're in an error state, don't
bother flagging another one here. */
if (mState == JPEG_ERROR)
return;
/* If we're doing a full decode and haven't notified of completion yet,
* we must not have got everything we wanted. Send error notifications. */
if (!IsSizeDecode() && !mNotifiedDone)
NotifyDone(/* aSuccess = */ PR_FALSE);
}
void
@ -554,23 +543,10 @@ nsJPEGDecoder::WriteInternal(const char *aBuffer, PRUint32 aCount)
}
void
nsJPEGDecoder::NotifyDone(PRBool aSuccess)
nsJPEGDecoder::NotifyDone()
{
// We should only be called once
NS_ABORT_IF_FALSE(!mNotifiedDone, "calling NotifyDone twice!");
// Notify
PostFrameStop();
if (aSuccess)
mImage->DecodingComplete();
if (mObserver) {
mObserver->OnStopContainer(nsnull, mImage);
mObserver->OnStopDecode(nsnull, aSuccess ? NS_OK : NS_ERROR_FAILURE,
nsnull);
}
// Mark that we've been called
mNotifiedDone = PR_TRUE;
PostDecodeDone();
}
void
@ -886,8 +862,8 @@ term_source (j_decompress_ptr jd)
NS_ABORT_IF_FALSE(decoder->mState != JPEG_ERROR,
"Calling term_source on a JPEG with mState == JPEG_ERROR!");
// Notify
decoder->NotifyDone(/* aSuccess = */ PR_TRUE);
// Notify using a helper method to get around protectedness issues.
decoder->NotifyDone();
}
} // namespace imagelib

View File

@ -93,7 +93,7 @@ public:
virtual void WriteInternal(const char* aBuffer, PRUint32 aCount);
virtual void FinishInternal();
void NotifyDone(PRBool aSuccess);
void NotifyDone();
protected:
void OutputScanlines(PRBool* suspend);
@ -123,7 +123,6 @@ public:
qcms_transform *mTransform;
PRPackedBool mReading;
PRPackedBool mNotifiedDone;
};
} // namespace imagelib

View File

@ -86,8 +86,7 @@ nsPNGDecoder::nsPNGDecoder() :
mCMSLine(nsnull), interlacebuf(nsnull),
mInProfile(nsnull), mTransform(nsnull),
mHeaderBuf(nsnull), mHeaderBytesRead(0),
mChannels(0), mFrameIsHidden(PR_FALSE),
mNotifiedDone(PR_FALSE)
mChannels(0), mFrameIsHidden(PR_FALSE)
{
}
@ -289,16 +288,6 @@ nsPNGDecoder::InitInternal()
}
void
nsPNGDecoder::FinishInternal()
{
// If we're a full/success decode but haven't sent stop notifications yet,
// we didn't get all the data we needed. Send error notifications.
if (!IsSizeDecode() && !mNotifiedDone)
NotifyDone(/* aSuccess = */ PR_FALSE);
}
void
nsPNGDecoder::WriteInternal(const char *aBuffer, PRUint32 aCount)
{
@ -368,26 +357,6 @@ nsPNGDecoder::WriteInternal(const char *aBuffer, PRUint32 aCount)
}
}
void
nsPNGDecoder::NotifyDone(PRBool aSuccess)
{
// We should only be called once
NS_ABORT_IF_FALSE(!mNotifiedDone, "Calling NotifyDone twice!");
// Notify
EndImageFrame();
if (aSuccess)
mImage->DecodingComplete();
if (mObserver) {
mObserver->OnStopContainer(nsnull, mImage);
mObserver->OnStopDecode(nsnull, aSuccess ? NS_OK : NS_ERROR_FAILURE,
nsnull);
}
// Mark that we've been called
mNotifiedDone = PR_TRUE;
}
// Sets up gamma pre-correction in libpng before our callback gets called.
// We need to do this if we don't end up with a CMS profile.
static void
@ -863,7 +832,8 @@ nsPNGDecoder::end_callback(png_structp png_ptr, png_infop info_ptr)
#endif
// Send final notifications
decoder->NotifyDone(/* aSuccess = */ PR_TRUE);
decoder->EndImageFrame();
decoder->PostDecodeDone();
}

View File

@ -64,7 +64,6 @@ public:
virtual void InitInternal();
virtual void WriteInternal(const char* aBuffer, PRUint32 aCount);
virtual void FinishInternal();
void CreateFrame(png_uint_32 x_offset, png_uint_32 y_offset,
PRInt32 width, PRInt32 height,
@ -72,7 +71,6 @@ public:
void SetAnimFrameInfo();
void EndImageFrame();
void NotifyDone(PRBool aSuccess);
public:
png_structp mPNG;
@ -93,7 +91,6 @@ public:
PRUint8 mChannels;
PRPackedBool mFrameHasNoAlpha;
PRPackedBool mFrameIsHidden;
PRPackedBool mNotifiedDone;
/*
* libpng callbacks

View File

@ -47,6 +47,7 @@ Decoder::Decoder()
, mInitialized(false)
, mSizeDecode(false)
, mInFrame(false)
, mDecodeDone(false)
, mDataError(false)
{
}
@ -97,7 +98,23 @@ Decoder::Finish()
{
// Implementation-specific finalization
FinishInternal();
return IsError() ? NS_ERROR_FAILURE : NS_OK;
// If the implementation left us mid-frame, finish that up.
if (mInFrame)
PostFrameStop();
if (IsError())
return NS_ERROR_FAILURE;
// If the implementation didn't post success, we assume failure
if (!IsSizeDecode() && !mDecodeDone) {
if (mObserver) {
mObserver->OnStopContainer(nsnull, mImage);
mObserver->OnStopDecode(nsnull, NS_ERROR_FAILURE, nsnull);
}
}
return NS_OK;
}
void
@ -200,6 +217,22 @@ Decoder::PostInvalidation(nsIntRect& aRect)
mInvalidRect.UnionRect(mInvalidRect, aRect);
}
void
Decoder::PostDecodeDone()
{
NS_ABORT_IF_FALSE(!IsSizeDecode(), "Can't be done with decoding with size decode!");
NS_ABORT_IF_FALSE(!mInFrame, "Can't be done decoding if we're mid-frame!");
NS_ABORT_IF_FALSE(!mDecodeDone, "Decode already done!");
mDecodeDone = true;
// Notify
mImage->DecodingComplete();
if (mObserver) {
mObserver->OnStopContainer(nsnull, mImage);
mObserver->OnStopDecode(nsnull, NS_OK, nsnull);
}
}
void
Decoder::PostDataError()
{

View File

@ -153,6 +153,13 @@ protected:
// actually pass these invalidations on right away.
void PostInvalidation(nsIntRect& aRect);
// Called by the decoders when they have successfully decoded the image. This
// may occur as the result of the decoder getting to the appropriate point in
// the stream, or by us calling FinishInternal().
//
// May not be called mid-frame.
void PostDecodeDone();
// Data errors are the fault of the source data, decoder errors are our fault
void PostDataError();
void PostDecoderError(nsresult aFailCode);
@ -174,6 +181,7 @@ protected:
bool mInitialized;
bool mSizeDecode;
bool mInFrame;
bool mDecodeDone;
bool mDataError;
};