diff --git a/image/decoders/nsBMPDecoder.cpp b/image/decoders/nsBMPDecoder.cpp index 57e4f01ad1ef..35b0db920772 100644 --- a/image/decoders/nsBMPDecoder.cpp +++ b/image/decoders/nsBMPDecoder.cpp @@ -38,7 +38,7 @@ GetBMPLog() #define LINE(row) ((mBIH.height < 0) ? (-mBIH.height - (row)) : ((row) - 1)) #define PIXEL_OFFSET(row, col) (LINE(row) * mBIH.width + col) -nsBMPDecoder::nsBMPDecoder(RasterImage& aImage) +nsBMPDecoder::nsBMPDecoder(RasterImage* aImage) : Decoder(aImage) , mPos(0) , mLOH(WIN_V3_HEADER_LENGTH) diff --git a/image/decoders/nsBMPDecoder.h b/image/decoders/nsBMPDecoder.h index 086eee4b5559..7e34576c6997 100644 --- a/image/decoders/nsBMPDecoder.h +++ b/image/decoders/nsBMPDecoder.h @@ -23,7 +23,7 @@ class nsBMPDecoder : public Decoder { public: - explicit nsBMPDecoder(RasterImage& aImage); + explicit nsBMPDecoder(RasterImage* aImage); ~nsBMPDecoder(); // Specifies whether or not the BMP file will contain alpha data diff --git a/image/decoders/nsGIFDecoder2.cpp b/image/decoders/nsGIFDecoder2.cpp index aad439cc9fa5..2b16e1d23e66 100644 --- a/image/decoders/nsGIFDecoder2.cpp +++ b/image/decoders/nsGIFDecoder2.cpp @@ -68,7 +68,7 @@ namespace image { ////////////////////////////////////////////////////////////////////// // GIF Decoder Implementation -nsGIFDecoder2::nsGIFDecoder2(RasterImage& aImage) +nsGIFDecoder2::nsGIFDecoder2(RasterImage* aImage) : Decoder(aImage) , mCurrentRow(-1) , mLastFlushedRow(-1) diff --git a/image/decoders/nsGIFDecoder2.h b/image/decoders/nsGIFDecoder2.h index 04ef594218eb..c40758018a52 100644 --- a/image/decoders/nsGIFDecoder2.h +++ b/image/decoders/nsGIFDecoder2.h @@ -23,7 +23,7 @@ class nsGIFDecoder2 : public Decoder { public: - explicit nsGIFDecoder2(RasterImage& aImage); + explicit nsGIFDecoder2(RasterImage* aImage); ~nsGIFDecoder2(); virtual void WriteInternal(const char* aBuffer, uint32_t aCount) MOZ_OVERRIDE; diff --git a/image/decoders/nsICODecoder.cpp b/image/decoders/nsICODecoder.cpp index c50541b7f254..102a9ffb70c3 100644 --- a/image/decoders/nsICODecoder.cpp +++ b/image/decoders/nsICODecoder.cpp @@ -58,7 +58,7 @@ nsICODecoder::GetNumColors() } -nsICODecoder::nsICODecoder(RasterImage& aImage) +nsICODecoder::nsICODecoder(RasterImage* aImage) : Decoder(aImage) { mPos = mImageOffset = mCurrIcon = mNumIcons = mBPP = mRowBytes = 0; @@ -249,7 +249,7 @@ nsICODecoder::WriteInternal(const char* aBuffer, uint32_t aCount) } uint16_t colorDepth = 0; - nsIntSize prefSize = mImage.GetRequestedResolution(); + nsIntSize prefSize = mImage->GetRequestedResolution(); if (prefSize.width == 0 && prefSize.height == 0) { prefSize.SizeTo(PREFICONSIZE, PREFICONSIZE); } diff --git a/image/decoders/nsICODecoder.h b/image/decoders/nsICODecoder.h index e8dfece364d4..556aea4a63db 100644 --- a/image/decoders/nsICODecoder.h +++ b/image/decoders/nsICODecoder.h @@ -23,7 +23,7 @@ class nsICODecoder : public Decoder { public: - explicit nsICODecoder(RasterImage& aImage); + explicit nsICODecoder(RasterImage* aImage); virtual ~nsICODecoder(); // Obtains the width of the icon directory entry diff --git a/image/decoders/nsIconDecoder.cpp b/image/decoders/nsIconDecoder.cpp index a1658e536b40..f4c8335dba26 100644 --- a/image/decoders/nsIconDecoder.cpp +++ b/image/decoders/nsIconDecoder.cpp @@ -15,7 +15,7 @@ namespace mozilla { namespace image { -nsIconDecoder::nsIconDecoder(RasterImage& aImage) +nsIconDecoder::nsIconDecoder(RasterImage* aImage) : Decoder(aImage), mWidth(-1), mHeight(-1), diff --git a/image/decoders/nsIconDecoder.h b/image/decoders/nsIconDecoder.h index 358423d29a62..e64f81186ba4 100644 --- a/image/decoders/nsIconDecoder.h +++ b/image/decoders/nsIconDecoder.h @@ -38,7 +38,7 @@ class nsIconDecoder : public Decoder { public: - explicit nsIconDecoder(RasterImage& aImage); + explicit nsIconDecoder(RasterImage* aImage); virtual ~nsIconDecoder(); virtual void WriteInternal(const char* aBuffer, uint32_t aCount) MOZ_OVERRIDE; diff --git a/image/decoders/nsJPEGDecoder.cpp b/image/decoders/nsJPEGDecoder.cpp index c51c4c341fac..3b48eab551a3 100644 --- a/image/decoders/nsJPEGDecoder.cpp +++ b/image/decoders/nsJPEGDecoder.cpp @@ -84,7 +84,7 @@ METHODDEF(void) my_error_exit (j_common_ptr cinfo); #define MAX_JPEG_MARKER_LENGTH (((uint32_t)1 << 16) - 1) -nsJPEGDecoder::nsJPEGDecoder(RasterImage& aImage, +nsJPEGDecoder::nsJPEGDecoder(RasterImage* aImage, Decoder::DecodeStyle aDecodeStyle) : Decoder(aImage) , mDecodeStyle(aDecodeStyle) @@ -237,7 +237,7 @@ nsJPEGDecoder::WriteInternal(const char* aBuffer, uint32_t aCount) return; // I/O suspension } - int sampleSize = mImage.GetRequestedSampleSize(); + int sampleSize = mImage->GetRequestedSampleSize(); if (sampleSize > 0) { mInfo.scale_num = 1; mInfo.scale_denom = sampleSize; diff --git a/image/decoders/nsJPEGDecoder.h b/image/decoders/nsJPEGDecoder.h index 74c1a3d83164..dce35c648700 100644 --- a/image/decoders/nsJPEGDecoder.h +++ b/image/decoders/nsJPEGDecoder.h @@ -52,7 +52,7 @@ struct Orientation; class nsJPEGDecoder : public Decoder { public: - nsJPEGDecoder(RasterImage& aImage, Decoder::DecodeStyle aDecodeStyle); + nsJPEGDecoder(RasterImage* aImage, Decoder::DecodeStyle aDecodeStyle); virtual ~nsJPEGDecoder(); virtual void InitInternal() MOZ_OVERRIDE; diff --git a/image/decoders/nsPNGDecoder.cpp b/image/decoders/nsPNGDecoder.cpp index 1cd00f87d7f6..2b45e51e1a59 100644 --- a/image/decoders/nsPNGDecoder.cpp +++ b/image/decoders/nsPNGDecoder.cpp @@ -107,7 +107,7 @@ nsPNGDecoder::AnimFrameInfo::AnimFrameInfo(png_structp aPNG, png_infop aInfo) const uint8_t nsPNGDecoder::pngSignatureBytes[] = { 137, 80, 78, 71, 13, 10, 26, 10 }; -nsPNGDecoder::nsPNGDecoder(RasterImage& aImage) +nsPNGDecoder::nsPNGDecoder(RasterImage* aImage) : Decoder(aImage), mPNG(nullptr), mInfo(nullptr), mCMSLine(nullptr), interlacebuf(nullptr), diff --git a/image/decoders/nsPNGDecoder.h b/image/decoders/nsPNGDecoder.h index cae9584cbc80..ddcee6230d38 100644 --- a/image/decoders/nsPNGDecoder.h +++ b/image/decoders/nsPNGDecoder.h @@ -24,7 +24,7 @@ class RasterImage; class nsPNGDecoder : public Decoder { public: - explicit nsPNGDecoder(RasterImage& aImage); + explicit nsPNGDecoder(RasterImage* aImage); virtual ~nsPNGDecoder(); virtual void InitInternal() MOZ_OVERRIDE; diff --git a/image/src/Decoder.cpp b/image/src/Decoder.cpp index 70ef6bee8aeb..cc2c88ee9610 100644 --- a/image/src/Decoder.cpp +++ b/image/src/Decoder.cpp @@ -20,7 +20,7 @@ using mozilla::gfx::SurfaceFormat; namespace mozilla { namespace image { -Decoder::Decoder(RasterImage &aImage) +Decoder::Decoder(RasterImage* aImage) : mImage(aImage) , mProgress(NoProgress) , mImageData(nullptr) @@ -48,6 +48,21 @@ Decoder::~Decoder() MOZ_ASSERT(mInvalidRect.IsEmpty(), "Destroying Decoder without taking all its invalidations"); mInitialized = false; + + if (!NS_IsMainThread()) { + // Dispatch mImage to main thread to prevent it from being destructed by the + // decode thread. + nsCOMPtr mainThread = do_GetMainThread(); + NS_WARN_IF_FALSE(mainThread, "Couldn't get the main thread!"); + if (mainThread) { + // Handle ambiguous nsISupports inheritance. + RasterImage* rawImg = nullptr; + mImage.swap(rawImg); + DebugOnly rv = + NS_ProxyRelease(mainThread, NS_ISUPPORTS_CAST(ImageResource*, rawImg)); + MOZ_ASSERT(NS_SUCCEEDED(rv), "Failed to proxy release to main thread"); + } + } } /* @@ -181,13 +196,13 @@ Decoder::Finish(ShutdownReason aReason) if (consoleService && errorObject && !HasDecoderError()) { nsAutoString msg(NS_LITERAL_STRING("Image corrupt or truncated: ") + - NS_ConvertUTF8toUTF16(mImage.GetURIString())); + NS_ConvertUTF8toUTF16(mImage->GetURIString())); if (NS_SUCCEEDED(errorObject->InitWithWindowID( msg, - NS_ConvertUTF8toUTF16(mImage.GetURIString()), + NS_ConvertUTF8toUTF16(mImage->GetURIString()), EmptyString(), 0, 0, nsIScriptError::errorFlag, - "Image", mImage.InnerWindowID() + "Image", mImage->InnerWindowID() ))) { consoleService->LogMessage(errorObject); } @@ -218,11 +233,11 @@ Decoder::Finish(ShutdownReason aReason) // Set image metadata before calling DecodingComplete, because // DecodingComplete calls Optimize(). - mImageMetadata.SetOnImage(&mImage); + mImageMetadata.SetOnImage(mImage); if (mDecodeDone) { MOZ_ASSERT(HasError() || mCurrentFrame, "Should have an error or a frame"); - mImage.DecodingComplete(mCurrentFrame.get()); + mImage->DecodingComplete(mCurrentFrame.get()); } } @@ -369,7 +384,7 @@ Decoder::InternalAddFrame(uint32_t aFrameNum, } InsertOutcome outcome = - SurfaceCache::Insert(frame, ImageKey(&mImage), + SurfaceCache::Insert(frame, ImageKey(mImage.get()), RasterSurfaceKey(imageSize.ToIntSize(), aDecodeFlags, aFrameNum), @@ -405,7 +420,7 @@ Decoder::InternalAddFrame(uint32_t aFrameNum, } mFrameCount++; - mImage.OnAddedFrame(mFrameCount, refreshArea); + mImage->OnAddedFrame(mFrameCount, refreshArea); return ref; } @@ -416,9 +431,9 @@ Decoder::SetSizeOnImage() MOZ_ASSERT(mImageMetadata.HasSize(), "Should have size"); MOZ_ASSERT(mImageMetadata.HasOrientation(), "Should have orientation"); - mImage.SetSize(mImageMetadata.GetWidth(), - mImageMetadata.GetHeight(), - mImageMetadata.GetOrientation()); + mImage->SetSize(mImageMetadata.GetWidth(), + mImageMetadata.GetHeight(), + mImageMetadata.GetOrientation()); } /* diff --git a/image/src/Decoder.h b/image/src/Decoder.h index cc6d6134b759..7296faf1dbc3 100644 --- a/image/src/Decoder.h +++ b/image/src/Decoder.h @@ -22,7 +22,7 @@ class Decoder { public: - explicit Decoder(RasterImage& aImage); + explicit Decoder(RasterImage* aImage); /** * Initialize an image decoder. Decoders may not be re-initialized. @@ -187,6 +187,11 @@ public: ImageMetadata& GetImageMetadata() { return mImageMetadata; } + /** + * Returns a weak pointer to the image associated with this decoder. + */ + RasterImage* GetImage() const { MOZ_ASSERT(mImage); return mImage.get(); } + // Tell the decoder infrastructure to allocate a frame. By default, frame 0 // is created as an ARGB frame with no offset and with size width * height. // If decoders need something different, they must ask for it. @@ -312,7 +317,7 @@ protected: * Member variables. * */ - RasterImage &mImage; + nsRefPtr mImage; RawAccessFrameRef mCurrentFrame; ImageMetadata mImageMetadata; nsIntRect mInvalidRect; // Tracks an invalidation region in the current frame. diff --git a/image/src/RasterImage.cpp b/image/src/RasterImage.cpp index f8dcea0c3287..cb73b848da73 100644 --- a/image/src/RasterImage.cpp +++ b/image/src/RasterImage.cpp @@ -1458,32 +1458,32 @@ RasterImage::InitDecoder(bool aDoSizeDecode) eDecoderType type = GetDecoderType(mSourceDataMimeType.get()); CONTAINER_ENSURE_TRUE(type != eDecoderType_unknown, NS_IMAGELIB_ERROR_NO_DECODER); - // Instantiate the appropriate decoder + // Instantiate the appropriate decoder. switch (type) { case eDecoderType_png: - mDecoder = new nsPNGDecoder(*this); + mDecoder = new nsPNGDecoder(this); break; case eDecoderType_gif: - mDecoder = new nsGIFDecoder2(*this); + mDecoder = new nsGIFDecoder2(this); break; case eDecoderType_jpeg: // If we have all the data we don't want to waste cpu time doing - // a progressive decode - mDecoder = new nsJPEGDecoder(*this, + // a progressive decode. + mDecoder = new nsJPEGDecoder(this, mHasBeenDecoded ? Decoder::SEQUENTIAL : Decoder::PROGRESSIVE); break; case eDecoderType_bmp: - mDecoder = new nsBMPDecoder(*this); + mDecoder = new nsBMPDecoder(this); break; case eDecoderType_ico: - mDecoder = new nsICODecoder(*this); + mDecoder = new nsICODecoder(this); break; case eDecoderType_icon: - mDecoder = new nsIconDecoder(*this); + mDecoder = new nsIconDecoder(this); break; default: - NS_ABORT_IF_FALSE(0, "Shouldn't get here!"); + MOZ_ASSERT_UNREACHABLE("Unknown decoder type"); } // Initialize the decoder