void Decoder::CompleteDecode() { // Implementation-specific finalization BeforeFinishInternal(); if (!HasError()) { FinishInternal(); } else { FinishWithErrorInternal(); } // If the implementation left us mid-frame, finish that up. if (mInFrame && !HasError()) { PostFrameStop(); } // If PostDecodeDone() has not been called, and this decoder wasn't aborted // early because of low-memory conditions or losing a race with another // decoder, we need to send teardown notifications (and report an error to the // console later). if (!IsMetadataDecode() && !mDecodeDone && !WasAborted()) { mShouldReportError = true; // If we only have a data error, we're usable if we have at least one // complete frame. if (!HasDecoderError() && GetCompleteFrameCount() > 0) { // We're usable, so do exactly what we should have when the decoder // completed. // Not writing to the entire frame may have left us transparent. PostHasTransparency(); if (mInFrame) { PostFrameStop(); } PostDecodeDone(); } else { // We're not usable. Record some final progress indicating the error. if (!IsMetadataDecode()) { mProgress |= FLAG_DECODE_COMPLETE; } mProgress |= FLAG_HAS_ERROR; } } if (mDecodeDone && !IsMetadataDecode()) { MOZ_ASSERT(HasError() || mCurrentFrame, "Should have an error or a frame"); // If this image wasn't animated and isn't a transient image, mark its frame // as optimizable. We don't support optimizing animated images and // optimizing transient images isn't worth it. if (!HasAnimation() && !(mDecoderFlags & DecoderFlags::IMAGE_IS_TRANSIENT) && mCurrentFrame) { mCurrentFrame->SetOptimizable(); } } }
void Decoder::Finish(RasterImage::eShutdownIntent aShutdownIntent) { // Implementation-specific finalization if (!HasError()) FinishInternal(); // If the implementation left us mid-frame, finish that up. if (mInFrame && !HasError()) PostFrameStop(); // If PostDecodeDone() has not been called, we need to sent teardown // notifications. if (!IsSizeDecode() && !mDecodeDone) { // Log data errors to the error console nsCOMPtr<nsIConsoleService> consoleService = do_GetService(NS_CONSOLESERVICE_CONTRACTID); nsCOMPtr<nsIScriptError> errorObject = do_CreateInstance(NS_SCRIPTERROR_CONTRACTID); if (consoleService && errorObject && !HasDecoderError()) { nsAutoString msg(NS_LITERAL_STRING("Image corrupt or truncated: ") + NS_ConvertUTF8toUTF16(mImage.GetURIString())); if (NS_SUCCEEDED(errorObject->InitWithWindowID( msg, NS_ConvertUTF8toUTF16(mImage.GetURIString()), EmptyString(), 0, 0, nsIScriptError::errorFlag, "Image", mImage.InnerWindowID() ))) { consoleService->LogMessage(errorObject); } } bool usable = true; if (aShutdownIntent != RasterImage::eShutdownIntent_NotNeeded && !HasDecoderError()) { // If we only have a data error, we're usable if we have at least one complete frame. if (GetCompleteFrameCount() == 0) { usable = false; } } // If we're usable, do exactly what we should have when the decoder // completed. if (usable) { if (mInFrame) { PostFrameStop(); } PostDecodeDone(); } else { if (mObserver) { mObserver->OnStopDecode(NS_ERROR_FAILURE); } } } // Set image metadata before calling DecodingComplete, because DecodingComplete calls Optimize(). mImageMetadata.SetOnImage(&mImage); if (mDecodeDone) { mImage.DecodingComplete(); } }
void Decoder::Finish(ShutdownReason aReason) { MOZ_ASSERT(NS_IsMainThread()); // Implementation-specific finalization if (!HasError()) FinishInternal(); // If the implementation left us mid-frame, finish that up. if (mInFrame && !HasError()) PostFrameStop(); // If PostDecodeDone() has not been called, we need to sent teardown // notifications. if (!IsSizeDecode() && !mDecodeDone) { // Log data errors to the error console nsCOMPtr<nsIConsoleService> consoleService = do_GetService(NS_CONSOLESERVICE_CONTRACTID); nsCOMPtr<nsIScriptError> errorObject = do_CreateInstance(NS_SCRIPTERROR_CONTRACTID); if (consoleService && errorObject && !HasDecoderError()) { nsAutoString msg(NS_LITERAL_STRING("Image corrupt or truncated: ") + NS_ConvertUTF8toUTF16(mImage.GetURIString())); if (NS_SUCCEEDED(errorObject->InitWithWindowID( msg, NS_ConvertUTF8toUTF16(mImage.GetURIString()), EmptyString(), 0, 0, nsIScriptError::errorFlag, "Image", mImage.InnerWindowID() ))) { consoleService->LogMessage(errorObject); } } bool usable = !HasDecoderError(); if (aReason != ShutdownReason::NOT_NEEDED && !HasDecoderError()) { // If we only have a data error, we're usable if we have at least one complete frame. if (GetCompleteFrameCount() == 0) { usable = false; } } // If we're usable, do exactly what we should have when the decoder // completed. if (usable) { if (mInFrame) { PostFrameStop(); } PostDecodeDone(); } else { if (!IsSizeDecode()) { mProgress |= FLAG_DECODE_COMPLETE | FLAG_ONLOAD_UNBLOCKED; } mProgress |= FLAG_HAS_ERROR; } } // Set image metadata before calling DecodingComplete, because // DecodingComplete calls Optimize(). mImageMetadata.SetOnImage(&mImage); if (mDecodeDone) { MOZ_ASSERT(HasError() || mCurrentFrame, "Should have an error or a frame"); mImage.DecodingComplete(mCurrentFrame.get()); } }