From fbaf0bb26397aa498eb9156f06d5a6fe34dd7dd8 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 03:14:29 +0200 Subject: Merging upstream version 125.0.1. Signed-off-by: Daniel Baumann --- image/IDecodingTask.cpp | 73 ++++++------------- image/IDecodingTask.h | 7 -- image/IProgressObserver.h | 2 - image/Image.cpp | 2 +- image/ProgressTracker.cpp | 4 -- image/ProgressTracker.h | 3 - image/RasterImage.cpp | 7 +- image/VectorImage.cpp | 7 +- image/decoders/nsGIFDecoder2.cpp | 3 + image/decoders/nsPNGDecoder.cpp | 19 ++++- image/decoders/nsPNGDecoder.h | 1 + image/imgLoader.cpp | 77 +++++++++++++-------- image/imgLoader.h | 24 ++++--- image/imgRequest.cpp | 22 +++--- image/nsIIconURI.idl | 11 --- image/test/browser/browser_bug666317.js | 4 +- ...ser_offscreen_image_in_out_of_process_iframe.js | 18 ++--- image/test/browser/head.js | 4 +- image/test/crashtests/crashtests.list | 2 +- image/test/mochitest/1835509.gif | Bin 0 -> 552 bytes image/test/mochitest/imgutils.js | 16 ++--- image/test/mochitest/mochitest.toml | 1 + image/test/mochitest/test_animSVGImage2.html | 2 +- image/test/mochitest/test_animation_operators.html | 2 +- image/test/mochitest/test_bug601470.html | 2 +- .../test/mochitest/test_discardAnimatedImage.html | 41 ++++++++--- .../test_discardFinishedAnimatedImage.html | 2 +- image/test/mochitest/test_has_transparency.html | 4 +- image/test/mochitest/test_net_failedtoprocess.html | 2 +- image/test/mochitest/test_removal_ondecode.html | 4 +- image/test/mochitest/test_removal_onload.html | 6 +- image/test/reftest/downscaling/reftest.list | 2 +- image/test/reftest/generic/reftest.list | 2 +- .../test/reftest/png/green10-invalidchunkname.png | Bin 0 -> 137 bytes image/test/reftest/png/green10.png | Bin 0 -> 81 bytes image/test/reftest/png/reftest.list | 1 + image/test/reftest/reftest.list | 5 +- image/test/unit/async_load_tests.js | 10 +-- image/test/unit/image_load_helpers.js | 6 +- 39 files changed, 197 insertions(+), 201 deletions(-) create mode 100644 image/test/mochitest/1835509.gif create mode 100644 image/test/reftest/png/green10-invalidchunkname.png create mode 100644 image/test/reftest/png/green10.png create mode 100644 image/test/reftest/png/reftest.list (limited to 'image') diff --git a/image/IDecodingTask.cpp b/image/IDecodingTask.cpp index 1816c9056b..670a651275 100644 --- a/image/IDecodingTask.cpp +++ b/image/IDecodingTask.cpp @@ -23,41 +23,9 @@ namespace image { // Helpers for sending notifications to the image associated with a decoder. /////////////////////////////////////////////////////////////////////////////// -void IDecodingTask::EnsureHasEventTarget(NotNull aImage) { - if (!mEventTarget) { - // We determine the event target as late as possible, at the first dispatch - // time, because the observers bound to an imgRequest will affect it. - // We cache it rather than query for the event target each time because the - // event target can change. We don't want to risk events being executed in - // a different order than they are dispatched, which can happen if we - // selected scheduler groups which have no ordering guarantees relative to - // each other (e.g. it moves from scheduler group A for doc group DA to - // scheduler group B for doc group DB due to changing observers -- if we - // dispatched the first event on A, and the second on B, we don't know which - // will execute first.) - RefPtr tracker = aImage->GetProgressTracker(); - if (tracker) { - mEventTarget = tracker->GetEventTarget(); - } else { - mEventTarget = GetMainThreadSerialEventTarget(); - } - } -} - -bool IDecodingTask::IsOnEventTarget() const { - // This is essentially equivalent to NS_IsOnMainThread() because all of the - // event targets are for the main thread (although perhaps with a different - // label / scheduler group). The observers in ProgressTracker may have - // different event targets from this, so this is just a best effort guess. - bool current = false; - mEventTarget->IsOnCurrentThread(¤t); - return current; -} - void IDecodingTask::NotifyProgress(NotNull aImage, NotNull aDecoder) { MOZ_ASSERT(aDecoder->HasProgress() && !aDecoder->IsMetadataDecode()); - EnsureHasEventTarget(aImage); // Capture the decoder's state. If we need to notify asynchronously, it's // important that we don't wait until the lambda actually runs to capture the @@ -72,7 +40,7 @@ void IDecodingTask::NotifyProgress(NotNull aImage, SurfaceFlags surfaceFlags = aDecoder->GetSurfaceFlags(); // Synchronously notify if we can. - if (IsOnEventTarget() && !(decoderFlags & DecoderFlags::ASYNC_NOTIFY)) { + if (NS_IsMainThread() && !(decoderFlags & DecoderFlags::ASYNC_NOTIFY)) { aImage->NotifyProgress(progress, invalidRect, frameCount, decoderFlags, surfaceFlags); return; @@ -86,21 +54,21 @@ void IDecodingTask::NotifyProgress(NotNull aImage, // We're forced to notify asynchronously. NotNull> image = aImage; - mEventTarget->Dispatch(CreateRenderBlockingRunnable(NS_NewRunnableFunction( - "IDecodingTask::NotifyProgress", - [=]() -> void { - image->NotifyProgress(progress, invalidRect, - frameCount, decoderFlags, - surfaceFlags); - })), - NS_DISPATCH_NORMAL); + nsCOMPtr eventTarget = GetMainThreadSerialEventTarget(); + eventTarget->Dispatch(CreateRenderBlockingRunnable(NS_NewRunnableFunction( + "IDecodingTask::NotifyProgress", + [=]() -> void { + image->NotifyProgress(progress, invalidRect, + frameCount, decoderFlags, + surfaceFlags); + })), + NS_DISPATCH_NORMAL); } void IDecodingTask::NotifyDecodeComplete(NotNull aImage, NotNull aDecoder) { MOZ_ASSERT(aDecoder->HasError() || !aDecoder->InFrame(), "Decode complete in the middle of a frame?"); - EnsureHasEventTarget(aImage); // Capture the decoder's state. DecoderFinalStatus finalStatus = aDecoder->FinalStatus(); @@ -113,7 +81,7 @@ void IDecodingTask::NotifyDecodeComplete(NotNull aImage, SurfaceFlags surfaceFlags = aDecoder->GetSurfaceFlags(); // Synchronously notify if we can. - if (IsOnEventTarget() && !(decoderFlags & DecoderFlags::ASYNC_NOTIFY)) { + if (NS_IsMainThread() && !(decoderFlags & DecoderFlags::ASYNC_NOTIFY)) { aImage->NotifyDecodeComplete(finalStatus, metadata, telemetry, progress, invalidRect, frameCount, decoderFlags, surfaceFlags); @@ -128,15 +96,16 @@ void IDecodingTask::NotifyDecodeComplete(NotNull aImage, // We're forced to notify asynchronously. NotNull> image = aImage; - mEventTarget->Dispatch(CreateRenderBlockingRunnable(NS_NewRunnableFunction( - "IDecodingTask::NotifyDecodeComplete", - [=]() -> void { - image->NotifyDecodeComplete( - finalStatus, metadata, telemetry, progress, - invalidRect, frameCount, decoderFlags, - surfaceFlags); - })), - NS_DISPATCH_NORMAL); + nsCOMPtr eventTarget = GetMainThreadSerialEventTarget(); + eventTarget->Dispatch(CreateRenderBlockingRunnable(NS_NewRunnableFunction( + "IDecodingTask::NotifyDecodeComplete", + [=]() -> void { + image->NotifyDecodeComplete( + finalStatus, metadata, telemetry, progress, + invalidRect, frameCount, decoderFlags, + surfaceFlags); + })), + NS_DISPATCH_NORMAL); } /////////////////////////////////////////////////////////////////////////////// diff --git a/image/IDecodingTask.h b/image/IDecodingTask.h index b3bce74757..380e680950 100644 --- a/image/IDecodingTask.h +++ b/image/IDecodingTask.h @@ -53,13 +53,6 @@ class IDecodingTask : public IResumable { /// Notify @aImage that @aDecoder has finished. void NotifyDecodeComplete(NotNull aImage, NotNull aDecoder); - - private: - void EnsureHasEventTarget(NotNull aImage); - - bool IsOnEventTarget() const; - - nsCOMPtr mEventTarget; }; /** diff --git a/image/IProgressObserver.h b/image/IProgressObserver.h index fea5c3f148..3a497bcfdc 100644 --- a/image/IProgressObserver.h +++ b/image/IProgressObserver.h @@ -10,8 +10,6 @@ #include "nsISupports.h" #include "nsRect.h" -class nsIEventTarget; - namespace mozilla { namespace image { diff --git a/image/Image.cpp b/image/Image.cpp index 16f754f490..596ac54ced 100644 --- a/image/Image.cpp +++ b/image/Image.cpp @@ -218,7 +218,7 @@ void ImageResource::SendOnUnlockedDraw(uint32_t aFlags) { mProgressTracker->OnUnlockedDraw(); } else { NotNull> image = WrapNotNull(this); - nsCOMPtr eventTarget = mProgressTracker->GetEventTarget(); + nsCOMPtr eventTarget = GetMainThreadSerialEventTarget(); nsCOMPtr ev = NS_NewRunnableFunction( "image::ImageResource::SendOnUnlockedDraw", [=]() -> void { RefPtr tracker = image->GetProgressTracker(); diff --git a/image/ProgressTracker.cpp b/image/ProgressTracker.cpp index 7cc3783231..63c16f6ef7 100644 --- a/image/ProgressTracker.cpp +++ b/image/ProgressTracker.cpp @@ -408,10 +408,6 @@ void ProgressTracker::EmulateRequestFinished(IProgressObserver* aObserver) { } } -already_AddRefed ProgressTracker::GetEventTarget() const { - return do_AddRef(GetMainThreadSerialEventTarget()); -} - void ProgressTracker::AddObserver(IProgressObserver* aObserver) { MOZ_ASSERT(NS_IsMainThread()); RefPtr observer = aObserver; diff --git a/image/ProgressTracker.h b/image/ProgressTracker.h index ffa66cd3bf..09b1f18a6a 100644 --- a/image/ProgressTracker.h +++ b/image/ProgressTracker.h @@ -179,9 +179,6 @@ class ProgressTracker : public mozilla::SupportsWeakPtr { bool RemoveObserver(IProgressObserver* aObserver); uint32_t ObserverCount() const; - // Get the event target we should currently dispatch events to. - already_AddRefed GetEventTarget() const; - // Resets our weak reference to our image. Image subclasses should call this // in their destructor. void ResetImage(); diff --git a/image/RasterImage.cpp b/image/RasterImage.cpp index 775238b460..06e44bda01 100644 --- a/image/RasterImage.cpp +++ b/image/RasterImage.cpp @@ -480,12 +480,7 @@ void RasterImage::OnSurfaceDiscarded(const SurfaceKey& aSurfaceKey) { bool animatedFramesDiscarded = mAnimationState && aSurfaceKey.Playback() == PlaybackType::eAnimated; - nsCOMPtr eventTarget; - if (mProgressTracker) { - eventTarget = mProgressTracker->GetEventTarget(); - } else { - eventTarget = do_GetMainThread(); - } + nsCOMPtr eventTarget = do_GetMainThread(); RefPtr image = this; nsCOMPtr ev = diff --git a/image/VectorImage.cpp b/image/VectorImage.cpp index b86f396e64..eccd04e3cf 100644 --- a/image/VectorImage.cpp +++ b/image/VectorImage.cpp @@ -1557,12 +1557,7 @@ void VectorImage::InvalidateObserversOnNextRefreshDriverTick() { // set by InvalidateFrameInternal in layout/generic/nsFrame.cpp. These bits // get cleared when we repaint the SVG into a surface by // nsIFrame::ClearInvalidationStateBits in nsDisplayList::PaintRoot. - nsCOMPtr eventTarget; - if (mProgressTracker) { - eventTarget = mProgressTracker->GetEventTarget(); - } else { - eventTarget = do_GetMainThread(); - } + nsCOMPtr eventTarget = do_GetMainThread(); RefPtr self(this); nsCOMPtr ev(NS_NewRunnableFunction( diff --git a/image/decoders/nsGIFDecoder2.cpp b/image/decoders/nsGIFDecoder2.cpp index 9b2de9124a..6dbe12c0af 100644 --- a/image/decoders/nsGIFDecoder2.cpp +++ b/image/decoders/nsGIFDecoder2.cpp @@ -1032,6 +1032,9 @@ LexerTransition nsGIFDecoder2::ReadLZWData( break; case WriteState::FAILURE: + if (mGIFStruct.images_decoded > 0) { + return Transition::TerminateSuccess(); + } return Transition::TerminateFailure(); } } diff --git a/image/decoders/nsPNGDecoder.cpp b/image/decoders/nsPNGDecoder.cpp index afc2762515..324c7613ca 100644 --- a/image/decoders/nsPNGDecoder.cpp +++ b/image/decoders/nsPNGDecoder.cpp @@ -114,6 +114,7 @@ nsPNGDecoder::nsPNGDecoder(RasterImage* aImage) mDisablePremultipliedAlpha(false), mGotInfoCallback(false), mUsePipeTransform(false), + mErrorIsRecoverable(false), mNumFrames(0) {} nsPNGDecoder::~nsPNGDecoder() { @@ -382,7 +383,9 @@ LexerTransition nsPNGDecoder::ReadPNGData( // libpng uses setjmp/longjmp for error handling. if (setjmp(png_jmpbuf(mPNG))) { - return Transition::TerminateFailure(); + return (GetFrameCount() > 0 && mErrorIsRecoverable) + ? Transition::TerminateSuccess() + : Transition::TerminateFailure(); } // Pass the data off to libpng. @@ -991,6 +994,16 @@ void nsPNGDecoder::end_callback(png_structp png_ptr, png_infop info_ptr) { void nsPNGDecoder::error_callback(png_structp png_ptr, png_const_charp error_msg) { MOZ_LOG(sPNGLog, LogLevel::Error, ("libpng error: %s\n", error_msg)); + + nsPNGDecoder* decoder = + static_cast(png_get_progressive_ptr(png_ptr)); + + if (strstr(error_msg, "invalid chunk type")) { + decoder->mErrorIsRecoverable = true; + } else { + decoder->mErrorIsRecoverable = false; + } + png_longjmp(png_ptr, 1); } @@ -1012,7 +1025,9 @@ bool nsPNGDecoder::IsValidICOResource() const { // we need to save the jump buffer here. Otherwise we'll end up without a // proper callstack. if (setjmp(png_jmpbuf(mPNG))) { - // We got here from a longjmp call indirectly from png_get_IHDR + // We got here from a longjmp call indirectly from png_get_IHDR via + // error_callback. Ignore mErrorIsRecoverable: if we got an invalid chunk + // error before even reading the IHDR we can't recover from that. return false; } diff --git a/image/decoders/nsPNGDecoder.h b/image/decoders/nsPNGDecoder.h index 89d66fa5eb..4627302b87 100644 --- a/image/decoders/nsPNGDecoder.h +++ b/image/decoders/nsPNGDecoder.h @@ -103,6 +103,7 @@ class nsPNGDecoder : public Decoder { bool mDisablePremultipliedAlpha; bool mGotInfoCallback; bool mUsePipeTransform; + bool mErrorIsRecoverable; struct AnimFrameInfo { AnimFrameInfo(); diff --git a/image/imgLoader.cpp b/image/imgLoader.cpp index 737d99ff15..eeb90cf374 100644 --- a/image/imgLoader.cpp +++ b/image/imgLoader.cpp @@ -32,6 +32,7 @@ #include "mozilla/StaticPrefs_network.h" #include "mozilla/StoragePrincipalHelper.h" #include "mozilla/dom/ContentParent.h" +#include "mozilla/dom/FetchPriority.h" #include "mozilla/dom/nsMixedContentBlocker.h" #include "mozilla/image/ImageMemoryReporter.h" #include "mozilla/layers/CompositorManagerChild.h" @@ -815,6 +816,28 @@ static bool ValidateSecurityInfo(imgRequest* aRequest, /* aSendCSPViolationReports */ false); } +static void AdjustPriorityForImages(nsIChannel* aChannel, + nsLoadFlags aLoadFlags, + FetchPriority aFetchPriority) { + // Image channels are loaded by default with reduced priority. + if (nsCOMPtr supportsPriority = + do_QueryInterface(aChannel)) { + int32_t priority = nsISupportsPriority::PRIORITY_LOW; + + // Adjust priority according to fetchpriorty attribute. + if (StaticPrefs::network_fetchpriority_enabled()) { + priority += FETCH_PRIORITY_ADJUSTMENT_FOR(images, aFetchPriority); + } + + // Further reduce priority for background loads + if (aLoadFlags & nsIRequest::LOAD_BACKGROUND) { + ++priority; + } + + supportsPriority->AdjustPriority(priority); + } +} + static nsresult NewImageChannel( nsIChannel** aResult, // If aForcePrincipalCheckForCacheEntry is true, then we will @@ -828,7 +851,8 @@ static nsresult NewImageChannel( nsIReferrerInfo* aReferrerInfo, nsILoadGroup* aLoadGroup, nsLoadFlags aLoadFlags, nsContentPolicyType aPolicyType, nsIPrincipal* aTriggeringPrincipal, nsINode* aRequestingNode, - bool aRespectPrivacy, uint64_t aEarlyHintPreloaderId) { + bool aRespectPrivacy, uint64_t aEarlyHintPreloaderId, + FetchPriority aFetchPriority) { MOZ_ASSERT(aResult); nsresult rv; @@ -948,17 +972,7 @@ static nsresult NewImageChannel( } } - // Image channels are loaded by default with reduced priority. - nsCOMPtr p = do_QueryInterface(*aResult); - if (p) { - uint32_t priority = nsISupportsPriority::PRIORITY_LOW; - - if (aLoadFlags & nsIRequest::LOAD_BACKGROUND) { - ++priority; // further reduce priority for background loads - } - - p->AdjustPriority(priority); - } + AdjustPriorityForImages(*aResult, aLoadFlags, aFetchPriority); // Create a new loadgroup for this new channel, using the old group as // the parent. The indirection keeps the channel insulated from cancels, @@ -1715,7 +1729,8 @@ bool imgLoader::ValidateRequestWithNewChannel( uint64_t aInnerWindowId, nsLoadFlags aLoadFlags, nsContentPolicyType aLoadPolicyType, imgRequestProxy** aProxyRequest, nsIPrincipal* aTriggeringPrincipal, CORSMode aCORSMode, bool aLinkPreload, - uint64_t aEarlyHintPreloaderId, bool* aNewChannelCreated) { + uint64_t aEarlyHintPreloaderId, FetchPriority aFetchPriority, + bool* aNewChannelCreated) { // now we need to insert a new channel request object in between the real // request and the proxy that basically delays loading the image until it // gets a 304 or figures out that this needs to be a new request @@ -1758,11 +1773,11 @@ bool imgLoader::ValidateRequestWithNewChannel( // cache. nsCOMPtr newChannel; bool forcePrincipalCheck; - rv = - NewImageChannel(getter_AddRefs(newChannel), &forcePrincipalCheck, aURI, - aInitialDocumentURI, aCORSMode, aReferrerInfo, aLoadGroup, - aLoadFlags, aLoadPolicyType, aTriggeringPrincipal, - aLoadingDocument, mRespectPrivacy, aEarlyHintPreloaderId); + rv = NewImageChannel(getter_AddRefs(newChannel), &forcePrincipalCheck, aURI, + aInitialDocumentURI, aCORSMode, aReferrerInfo, + aLoadGroup, aLoadFlags, aLoadPolicyType, + aTriggeringPrincipal, aLoadingDocument, mRespectPrivacy, + aEarlyHintPreloaderId, aFetchPriority); if (NS_FAILED(rv)) { return false; } @@ -1841,7 +1856,7 @@ void imgLoader::NotifyObserversForCachedImage( imgCacheEntry* aEntry, imgRequest* request, nsIURI* aURI, nsIReferrerInfo* aReferrerInfo, Document* aLoadingDocument, nsIPrincipal* aTriggeringPrincipal, CORSMode aCORSMode, - uint64_t aEarlyHintPreloaderId) { + uint64_t aEarlyHintPreloaderId, FetchPriority aFetchPriority) { if (aEntry->HasNotified()) { return; } @@ -1860,7 +1875,7 @@ void imgLoader::NotifyObserversForCachedImage( getter_AddRefs(newChannel), &forcePrincipalCheck, aURI, nullptr, aCORSMode, aReferrerInfo, nullptr, 0, nsIContentPolicy::TYPE_INTERNAL_IMAGE, aTriggeringPrincipal, - aLoadingDocument, mRespectPrivacy, aEarlyHintPreloaderId); + aLoadingDocument, mRespectPrivacy, aEarlyHintPreloaderId, aFetchPriority); if (NS_FAILED(rv)) { return; } @@ -1885,7 +1900,8 @@ bool imgLoader::ValidateEntry( nsLoadFlags aLoadFlags, nsContentPolicyType aLoadPolicyType, bool aCanMakeNewChannel, bool* aNewChannelCreated, imgRequestProxy** aProxyRequest, nsIPrincipal* aTriggeringPrincipal, - CORSMode aCORSMode, bool aLinkPreload, uint64_t aEarlyHintPreloaderId) { + CORSMode aCORSMode, bool aLinkPreload, uint64_t aEarlyHintPreloaderId, + FetchPriority aFetchPriority) { LOG_SCOPE(gImgLog, "imgLoader::ValidateEntry"); // If the expiration time is zero, then the request has not gotten far enough @@ -2013,13 +2029,13 @@ bool imgLoader::ValidateEntry( request, aURI, aInitialDocumentURI, aReferrerInfo, aLoadGroup, aObserver, aLoadingDocument, innerWindowID, aLoadFlags, aLoadPolicyType, aProxyRequest, aTriggeringPrincipal, aCORSMode, aLinkPreload, - aEarlyHintPreloaderId, aNewChannelCreated); + aEarlyHintPreloaderId, aFetchPriority, aNewChannelCreated); } if (!validateRequest) { - NotifyObserversForCachedImage(aEntry, request, aURI, aReferrerInfo, - aLoadingDocument, aTriggeringPrincipal, - aCORSMode, aEarlyHintPreloaderId); + NotifyObserversForCachedImage( + aEntry, request, aURI, aReferrerInfo, aLoadingDocument, + aTriggeringPrincipal, aCORSMode, aEarlyHintPreloaderId, aFetchPriority); } return !validateRequest; @@ -2174,7 +2190,7 @@ imgLoader::LoadImageXPCOM( 0, aLoadGroup, aObserver, aLoadingDocument, aLoadingDocument, aLoadFlags, aCacheKey, aContentPolicyType, u""_ns, /* aUseUrgentStartForChannel */ false, /* aListPreload */ false, - 0, &proxy); + 0, FetchPriority::Auto, &proxy); *_retval = proxy; return rv; } @@ -2233,7 +2249,7 @@ nsresult imgLoader::LoadImage( nsISupports* aCacheKey, nsContentPolicyType aContentPolicyType, const nsAString& initiatorType, bool aUseUrgentStartForChannel, bool aLinkPreload, uint64_t aEarlyHintPreloaderId, - imgRequestProxy** _retval) { + FetchPriority aFetchPriority, imgRequestProxy** _retval) { VerifyCacheSizes(); NS_ASSERTION(aURI, "imgLoader::LoadImage -- NULL URI pointer"); @@ -2386,7 +2402,7 @@ nsresult imgLoader::LoadImage( aLoadGroup, aObserver, aLoadingDocument, requestFlags, aContentPolicyType, true, &newChannelCreated, _retval, aTriggeringPrincipal, corsmode, aLinkPreload, - aEarlyHintPreloaderId)) { + aEarlyHintPreloaderId, aFetchPriority)) { request = entry->GetRequest(); // If this entry has no proxies, its request has no reference to the @@ -2436,7 +2452,7 @@ nsresult imgLoader::LoadImage( aInitialDocumentURI, corsmode, aReferrerInfo, aLoadGroup, requestFlags, aContentPolicyType, aTriggeringPrincipal, aContext, mRespectPrivacy, - aEarlyHintPreloaderId); + aEarlyHintPreloaderId, aFetchPriority); if (NS_FAILED(rv)) { return NS_ERROR_FAILURE; } @@ -2650,7 +2666,8 @@ nsresult imgLoader::LoadImageWithChannel(nsIChannel* channel, if (ValidateEntry(entry, uri, nullptr, nullptr, nullptr, aObserver, aLoadingDocument, requestFlags, policyType, false, - nullptr, nullptr, nullptr, corsMode, false, 0)) { + nullptr, nullptr, nullptr, corsMode, false, 0, + FetchPriority::Auto)) { request = entry->GetRequest(); } else { nsCOMPtr cacheChan(do_QueryInterface(channel)); diff --git a/image/imgLoader.h b/image/imgLoader.h index c515506790..7423517925 100644 --- a/image/imgLoader.h +++ b/image/imgLoader.h @@ -37,6 +37,7 @@ class imgMemoryReporter; namespace mozilla { namespace dom { class Document; +enum class FetchPriority : uint8_t; } } // namespace mozilla @@ -238,7 +239,8 @@ class imgLoader final : public imgILoader, nsLoadFlags aLoadFlags, nsISupports* aCacheKey, nsContentPolicyType aContentPolicyType, const nsAString& initiatorType, bool aUseUrgentStartForChannel, bool aLinkPreload, - uint64_t aEarlyHintPreloaderId, imgRequestProxy** _retval); + uint64_t aEarlyHintPreloaderId, + mozilla::dom::FetchPriority aFetchPriority, imgRequestProxy** _retval); [[nodiscard]] nsresult LoadImageWithChannel( nsIChannel* channel, imgINotificationObserver* aObserver, @@ -349,7 +351,8 @@ class imgLoader final : public imgILoader, bool aCanMakeNewChannel, bool* aNewChannelCreated, imgRequestProxy** aProxyRequest, nsIPrincipal* aTriggeringPrincipal, mozilla::CORSMode, - bool aLinkPreload, uint64_t aEarlyHintPreloaderId); + bool aLinkPreload, uint64_t aEarlyHintPreloaderId, + mozilla::dom::FetchPriority aFetchPriority); bool ValidateRequestWithNewChannel( imgRequest* request, nsIURI* aURI, nsIURI* aInitialDocumentURI, @@ -359,15 +362,14 @@ class imgLoader final : public imgILoader, nsLoadFlags aLoadFlags, nsContentPolicyType aContentPolicyType, imgRequestProxy** aProxyRequest, nsIPrincipal* aLoadingPrincipal, mozilla::CORSMode, bool aLinkPreload, uint64_t aEarlyHintPreloaderId, - bool* aNewChannelCreated); - - void NotifyObserversForCachedImage(imgCacheEntry* aEntry, imgRequest* request, - nsIURI* aURI, - nsIReferrerInfo* aReferrerInfo, - mozilla::dom::Document* aLoadingDocument, - nsIPrincipal* aLoadingPrincipal, - mozilla::CORSMode, - uint64_t aEarlyHintPreloaderId); + mozilla::dom::FetchPriority aFetchPriority, bool* aNewChannelCreated); + + void NotifyObserversForCachedImage( + imgCacheEntry* aEntry, imgRequest* request, nsIURI* aURI, + nsIReferrerInfo* aReferrerInfo, mozilla::dom::Document* aLoadingDocument, + nsIPrincipal* aTriggeringPrincipal, mozilla::CORSMode, + uint64_t aEarlyHintPreloaderId, + mozilla::dom::FetchPriority aFetchPriority); // aURI may be different from imgRequest's URI in the case of blob URIs, as we // can share requests with different URIs. nsresult CreateNewProxyForRequest(imgRequest* aRequest, nsIURI* aURI, diff --git a/image/imgRequest.cpp b/image/imgRequest.cpp index 47bdd3480c..9713d2f33e 100644 --- a/image/imgRequest.cpp +++ b/image/imgRequest.cpp @@ -334,8 +334,7 @@ void imgRequest::Cancel(nsresult aStatus) { if (NS_IsMainThread()) { ContinueCancel(aStatus); } else { - RefPtr progressTracker = GetProgressTracker(); - nsCOMPtr eventTarget = progressTracker->GetEventTarget(); + nsCOMPtr eventTarget = GetMainThreadSerialEventTarget(); nsCOMPtr ev = new imgRequestMainThreadCancel(this, aStatus); eventTarget->Dispatch(ev.forget(), NS_DISPATCH_NORMAL); } @@ -1027,26 +1026,23 @@ imgRequest::OnDataAvailable(nsIRequest* aRequest, nsIInputStream* aInStr, if (result.mImage) { image = result.mImage; - nsCOMPtr eventTarget; // Update our state to reflect this new part. { MutexAutoLock lock(mMutex); mImage = image; - // We only get an event target if we are not on the main thread, because - // we have to dispatch in that case. If we are on the main thread, but - // on a different scheduler group than ProgressTracker would give us, - // that is okay because nothing in imagelib requires that, just our - // listeners (which have their own checks). - if (!NS_IsMainThread()) { - eventTarget = mProgressTracker->GetEventTarget(); - MOZ_ASSERT(eventTarget); - } - mProgressTracker = nullptr; } + // We only get an event target if we are not on the main thread, because + // we have to dispatch in that case. + nsCOMPtr eventTarget; + if (!NS_IsMainThread()) { + eventTarget = GetMainThreadSerialEventTarget(); + MOZ_ASSERT(eventTarget); + } + // Some property objects are not threadsafe, and we need to send // OnImageAvailable on the main thread, so finish on the main thread. if (!eventTarget) { diff --git a/image/nsIIconURI.idl b/image/nsIIconURI.idl index b55ee8d8c7..b66e1a18f1 100644 --- a/image/nsIIconURI.idl +++ b/image/nsIIconURI.idl @@ -71,16 +71,6 @@ interface nsIMozIconURI : nsIURI }; %{C++ - -// CID for nsMozIconURI, if implemented on this platform. -#define NS_MOZICONURI_CID \ -{ \ - 0x43a88e0e, \ - 0x2d37, \ - 0x11d5, \ - { 0x99, 0x7, 0x0, 0x10, 0x83, 0x1, 0xe, 0x9b } \ -} - #define NS_MOZICONURIMUTATOR_CID \ { \ 0x1460df3b, \ @@ -88,5 +78,4 @@ interface nsIMozIconURI : nsIURI 0x4205, \ {0x83, 0x49, 0x83, 0x8e, 0x50, 0x7c, 0x3e, 0xf9} \ } - %} diff --git a/image/test/browser/browser_bug666317.js b/image/test/browser/browser_bug666317.js index 7f58c61c56..5d039575c8 100644 --- a/image/test/browser/browser_bug666317.js +++ b/image/test/browser/browser_bug666317.js @@ -15,11 +15,11 @@ var gScriptedObserver; var gClonedRequest; function ImageObserver(decodeCallback, discardCallback) { - this.decodeComplete = function onDecodeComplete(aRequest) { + this.decodeComplete = function onDecodeComplete() { decodeCallback(); }; - this.discard = function onDiscard(request) { + this.discard = function onDiscard() { if (!gWaitingForDiscard) { return; } diff --git a/image/test/browser/browser_offscreen_image_in_out_of_process_iframe.js b/image/test/browser/browser_offscreen_image_in_out_of_process_iframe.js index b431902eb7..346413b602 100644 --- a/image/test/browser/browser_offscreen_image_in_out_of_process_iframe.js +++ b/image/test/browser/browser_offscreen_image_in_out_of_process_iframe.js @@ -75,14 +75,14 @@ add_task(async function () { // Returns the count of frameUpdate during |time| (in ms) period. async function observeFrameUpdate(time) { function ImageDecoderObserverStub() { - this.sizeAvailable = function sizeAvailable(aRequest) {}; - this.frameComplete = function frameComplete(aRequest) {}; - this.decodeComplete = function decodeComplete(aRequest) {}; - this.loadComplete = function loadComplete(aRequest) {}; - this.frameUpdate = function frameUpdate(aRequest) {}; - this.discard = function discard(aRequest) {}; - this.isAnimated = function isAnimated(aRequest) {}; - this.hasTransparency = function hasTransparency(aRequest) {}; + this.sizeAvailable = function sizeAvailable() {}; + this.frameComplete = function frameComplete() {}; + this.decodeComplete = function decodeComplete() {}; + this.loadComplete = function loadComplete() {}; + this.frameUpdate = function frameUpdate() {}; + this.discard = function discard() {}; + this.isAnimated = function isAnimated() {}; + this.hasTransparency = function hasTransparency() {}; } // Start from the callback of setTimeout. @@ -140,7 +140,7 @@ add_task(async function () { await new Promise(resolve => requestAnimationFrame(resolve)); frameCount = await SpecialPowers.spawn(iframe, [1000], observeFrameUpdate); - ok(frameCount > 0, "There should be frameUpdate(s)"); + Assert.greater(frameCount, 0, "There should be frameUpdate(s)"); await new Promise(resolve => requestAnimationFrame(resolve)); diff --git a/image/test/browser/head.js b/image/test/browser/head.js index 29fc67a1a7..00f35babb2 100644 --- a/image/test/browser/head.js +++ b/image/test/browser/head.js @@ -27,7 +27,7 @@ function actOnMozImage(doc, id, func) { function assertPrefVal(name, val) { let boolValue = Services.prefs.getBoolPref(name); - ok(boolValue === val, `pref ${name} is set to ${val}`); + Assert.strictEqual(boolValue, val, `pref ${name} is set to ${val}`); if (boolValue !== val) { throw Error(`pref ${name} is not set to ${val}`); } @@ -121,7 +121,7 @@ async function createMozIconInFile(ext, expectSuccess = true) { await waitLoad; const icon = content.document.getElementById(`moz-icon-${_ext}-${_kSize}`); - ok(icon !== null, `got a valid ${_ext} moz-icon`); + Assert.notStrictEqual(icon, null, `got a valid ${_ext} moz-icon`); is(icon.width, _kSize, `${_kSize} px width ${_ext} moz-icon`); is(icon.height, _kSize, `${_kSize} px height ${_ext} moz-icon`); }; diff --git a/image/test/crashtests/crashtests.list b/image/test/crashtests/crashtests.list index 93dec82954..7e137b1d09 100644 --- a/image/test/crashtests/crashtests.list +++ b/image/test/crashtests/crashtests.list @@ -25,7 +25,7 @@ load 1242093-1.html load 1242778-1.png load 1249576-1.png load 1253362-1.html -skip-if(Android&&browserIsRemote) load 1355898-1.html # bug 1507207 +skip-if(Android) load 1355898-1.html # bug 1507207 load 1375842-1.html load 1413762-1.gif pref(image.downscale-during-decode.enabled,true) load 1443232-1.html diff --git a/image/test/mochitest/1835509.gif b/image/test/mochitest/1835509.gif new file mode 100644 index 0000000000..46a0cb5b65 Binary files /dev/null and b/image/test/mochitest/1835509.gif differ diff --git a/image/test/mochitest/imgutils.js b/image/test/mochitest/imgutils.js index b16ad1d065..e7e696f768 100644 --- a/image/test/mochitest/imgutils.js +++ b/image/test/mochitest/imgutils.js @@ -126,12 +126,12 @@ function getImagePref(pref) { // JS implementation of imgIScriptedNotificationObserver with stubs for all of its methods. function ImageDecoderObserverStub() { - this.sizeAvailable = function sizeAvailable(aRequest) {}; - this.frameComplete = function frameComplete(aRequest) {}; - this.decodeComplete = function decodeComplete(aRequest) {}; - this.loadComplete = function loadComplete(aRequest) {}; - this.frameUpdate = function frameUpdate(aRequest) {}; - this.discard = function discard(aRequest) {}; - this.isAnimated = function isAnimated(aRequest) {}; - this.hasTransparency = function hasTransparency(aRequest) {}; + this.sizeAvailable = function sizeAvailable() {}; + this.frameComplete = function frameComplete() {}; + this.decodeComplete = function decodeComplete() {}; + this.loadComplete = function loadComplete() {}; + this.frameUpdate = function frameUpdate() {}; + this.discard = function discard() {}; + this.isAnimated = function isAnimated() {}; + this.hasTransparency = function hasTransparency() {}; } diff --git a/image/test/mochitest/mochitest.toml b/image/test/mochitest/mochitest.toml index 96aaa8a0c3..803b8d48ad 100644 --- a/image/test/mochitest/mochitest.toml +++ b/image/test/mochitest/mochitest.toml @@ -100,6 +100,7 @@ support-files = [ "6M-pixels.png", "12M-pixels-1.png", "12M-pixels-2.png", + "1835509.gif", ] ["test_animSVGImage.html"] diff --git a/image/test/mochitest/test_animSVGImage2.html b/image/test/mochitest/test_animSVGImage2.html index 0f3ae046c5..11972bdb36 100644 --- a/image/test/mochitest/test_animSVGImage2.html +++ b/image/test/mochitest/test_animSVGImage2.html @@ -55,7 +55,7 @@ function takeReferenceSnapshot() { "reference div should disappear when it becomes display:none"); } -function myOnFrameUpdate(aRequest) { +function myOnFrameUpdate() { if (gIsTestFinished) { return; } diff --git a/image/test/mochitest/test_animation_operators.html b/image/test/mochitest/test_animation_operators.html index 2d3a6f6d67..2ccd4a7de5 100644 --- a/image/test/mochitest/test_animation_operators.html +++ b/image/test/mochitest/test_animation_operators.html @@ -101,7 +101,7 @@ function startTest(i) element.setAttribute("scrolling", "no"); element.src = url; document.body.appendChild(element); - function handleLoad(event) + function handleLoad() { iframe.loaded = true; if (iframe == reference) { diff --git a/image/test/mochitest/test_bug601470.html b/image/test/mochitest/test_bug601470.html index fdf2d074f8..c4b772c877 100644 --- a/image/test/mochitest/test_bug601470.html +++ b/image/test/mochitest/test_bug601470.html @@ -26,7 +26,7 @@ window.onload = function() { .getService(SpecialPowers.Ci.nsIMemoryReporterManager); var amount = 0; - var handleReport = function(aProcess, aPath, aKind, aUnits, aAmount, aDesc) { + var handleReport = function(aProcess, aPath, aKind, aUnits, aAmount) { amount += aAmount; } diff --git a/image/test/mochitest/test_discardAnimatedImage.html b/image/test/mochitest/test_discardAnimatedImage.html index 09bd9372c6..f9ccc806ce 100644 --- a/image/test/mochitest/test_discardAnimatedImage.html +++ b/image/test/mochitest/test_discardAnimatedImage.html @@ -16,14 +16,27 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=686905
+ + + + + + +
@@ -45,6 +58,7 @@ window.onload = function() {
 }
 
 var gImgs = ['infinitepng', 'infinitegif', 'infinitewebp', 'infiniteavif',
+             'corruptinfinitegif',
              'finitepng',   'finitegif',   'finitewebp', 'finiteavif'];
 // If we are currently counting frame updates.
 var gCountingFrameUpdates = false;
@@ -52,18 +66,25 @@ var gCountingFrameUpdates = false;
 // after discarding. (The last two images are finite looping so we don't expect
 // them to get incremented but it's possible if they don't finish their
 // animation before we discard them.)
-var gNumFrameUpdates = [0, 0, 0, 0, 0, 0];
+var gNumFrameUpdates = [0, 0, 0, 0, 0, 0, 0, 0, 0];
 // The last snapshot of the image. Used to check that the image actually changes.
-var gLastSnapShot = [null, null, null, null, null, null];
+var gLastSnapShot = [null, null, null, null, null, null, null, null, null];
 // Number of observed changes in the snapshot.
-var gNumSnapShotChanges = [0, 0, 0, 0, 0, 0];
+var gNumSnapShotChanges = [0, 0, 0, 0, 0, 0, 0, 0, 0];
 // If we've removed the observer.
-var gRemovedObserver = [false, false, false, false, false, false];
+var gRemovedObserver = [false, false, false, false, false, false, false, false, false];
 
 // 2 would probably be a good enough test, we arbitrarily choose 4.
-var kNumFrameUpdatesToExpect = 4;
+var kNumFrameUpdatesToExpect = 5;
 
 function runTest() {
+  let numImgsInDoc = document.getElementsByTagName("img").length;
+  ok(gImgs.length == numImgsInDoc, "gImgs missing img");
+  ok(gNumFrameUpdates.length == numImgsInDoc, "gNumFrameUpdates missing img");
+  ok(gLastSnapShot.length == numImgsInDoc, "gLastSnapShot missing img");
+  ok(gNumSnapShotChanges.length == numImgsInDoc, "gNumSnapShotChanges missing img");
+  ok(gRemovedObserver.length == numImgsInDoc, "gRemovedObserver missing img");
+
   var animatedDiscardable =
     SpecialPowers.getBoolPref('image.mem.animated.discardable');
   if (!animatedDiscardable) {
@@ -117,9 +138,13 @@ function checkIfFinished() {
   if ((gNumFrameUpdates[0] >= kNumFrameUpdatesToExpect) &&
       (gNumFrameUpdates[1] >= kNumFrameUpdatesToExpect) &&
       (gNumFrameUpdates[2] >= kNumFrameUpdatesToExpect) &&
+      (gNumFrameUpdates[3] >= kNumFrameUpdatesToExpect) &&
+      (gNumFrameUpdates[4] >= kNumFrameUpdatesToExpect) &&
       (gNumSnapShotChanges[0] >= kNumFrameUpdatesToExpect) &&
       (gNumSnapShotChanges[1] >= kNumFrameUpdatesToExpect) &&
-      (gNumSnapShotChanges[2] >= kNumFrameUpdatesToExpect)) {
+      (gNumSnapShotChanges[2] >= kNumFrameUpdatesToExpect) &&
+      (gNumSnapShotChanges[3] >= kNumFrameUpdatesToExpect) &&
+      (gNumSnapShotChanges[4] >= kNumFrameUpdatesToExpect)) {
     ok(true, "got expected frame updates");
     gFinished = true;
     SimpleTest.finish();
@@ -133,8 +158,8 @@ function addCallbacks(anImage, arrayIndex) {
   observer.discard = function () {
     gNumDiscards++;
     ok(true, "got image discard");
-    if (arrayIndex >= 3) {
-      // The last two images are finite, so we don't expect any frame updates,
+    if (arrayIndex >= 5) {
+      // The last four images are finite, so we don't expect any frame updates,
       // this image is done the test, so remove the observer.
       if (!gRemovedObserver[arrayIndex]) {
         gRemovedObserver[arrayIndex] = true;
diff --git a/image/test/mochitest/test_discardFinishedAnimatedImage.html b/image/test/mochitest/test_discardFinishedAnimatedImage.html
index 190cb1d1a0..f5b7a94e35 100644
--- a/image/test/mochitest/test_discardFinishedAnimatedImage.html
+++ b/image/test/mochitest/test_discardFinishedAnimatedImage.html
@@ -129,7 +129,7 @@ function addCallbacks(anImage) {
   imgLoadingContent.addObserver(scriptedObserver);
 }
 
-function removeObserver(anImage) {
+function removeObserver() {
   imgLoadingContent.removeObserver(scriptedObserver);
 }
 
diff --git a/image/test/mochitest/test_has_transparency.html b/image/test/mochitest/test_has_transparency.html
index 482aaf96b9..cec8edfe78 100644
--- a/image/test/mochitest/test_has_transparency.html
+++ b/image/test/mochitest/test_has_transparency.html
@@ -80,11 +80,11 @@ function loadNext() {
   gImg.setAttribute("src", currentFile);
 }
 
-function onHasTransparency(aRequest) {
+function onHasTransparency() {
   gHasTransparencyWasCalled = true;
 }
 
-function onDecodeComplete(aRequest) {
+function onDecodeComplete() {
   if (!gCurrentFileIsTransparent) {
     ok(!gHasTransparencyWasCalled,
        "onHasTransparency was not called for non-transparent file " + gImg.src);
diff --git a/image/test/mochitest/test_net_failedtoprocess.html b/image/test/mochitest/test_net_failedtoprocess.html
index 95ab5c0cc3..5d731f2234 100644
--- a/image/test/mochitest/test_net_failedtoprocess.html
+++ b/image/test/mochitest/test_net_failedtoprocess.html
@@ -30,7 +30,7 @@ var observer = {
     throw Components.Exception("", Cr.NS_ERROR_NO_INTERFACE);
   },
 
-  observe(subject, topic, data) {
+  observe(subject, topic) {
     ok(topic == "net:failed-to-process-uri-content", "wrong topic");
     subject = subject.QueryInterface(Ci.nsIURI);
     is(subject.asciiSpec, `${location.origin}/tests/image/test/mochitest/invalid.jpg`, "wrong subject");
diff --git a/image/test/mochitest/test_removal_ondecode.html b/image/test/mochitest/test_removal_ondecode.html
index 4ce7555757..b764c8e2ed 100644
--- a/image/test/mochitest/test_removal_ondecode.html
+++ b/image/test/mochitest/test_removal_ondecode.html
@@ -45,7 +45,7 @@ function* fileToLoad() {
   yield "rillybad.jpg";
 }
 
-function onSizeAvailable(aRequest) {
+function onSizeAvailable() {
   ok(true, "AfterLoad.onSizeAvailable called for " + gImg.src);
 }
 function onLoadComplete(aRequest) {
@@ -68,7 +68,7 @@ function onLoadComplete(aRequest) {
   }
 }
 
-function onDecodeComplete(aRequest) {
+function onDecodeComplete() {
   ok(gExpected > gRemovals, "AfterLoad.onDecodeComplete called for " + gImg.src);
   SimpleTest.executeSoon(function() {
     try {
diff --git a/image/test/mochitest/test_removal_onload.html b/image/test/mochitest/test_removal_onload.html
index 0a060542f5..288b987f2e 100644
--- a/image/test/mochitest/test_removal_onload.html
+++ b/image/test/mochitest/test_removal_onload.html
@@ -45,10 +45,10 @@ function* fileToLoad() {
   yield "rillybad.jpg";
 }
 
-function onSizeAvailable(aRequest) {
+function onSizeAvailable() {
   ok(true, "AfterLoad.onSizeAvailable called for " + gImg.src);
 }
-function onLoadComplete(aRequest) {
+function onLoadComplete() {
   ok(gExpected > gLoads, "AfterLoad.onLoadComplete called for " + gImg.src);
   gLoads++;
   SimpleTest.executeSoon(function() {
@@ -60,7 +60,7 @@ function onLoadComplete(aRequest) {
     maybeAdvance();
   });
 }
-function onDecodeComplete(aRequest) {
+function onDecodeComplete() {
   ok(true, "AfterLoad.onDecodeComplete called for " + gImg.src);
 }
 
diff --git a/image/test/reftest/downscaling/reftest.list b/image/test/reftest/downscaling/reftest.list
index f01780ffaa..9051761997 100644
--- a/image/test/reftest/downscaling/reftest.list
+++ b/image/test/reftest/downscaling/reftest.list
@@ -114,7 +114,7 @@ fuzzy(0-1,0-50) == downscale-orient.html downscale-orient-ref.html
 # ===============================================
 defaults pref(image.downscale-during-decode.enabled,true)
 
-fuzzy(0-31,0-127) fuzzy-if(d2d,0-31,0-147) == downscale-1.html downscale-1-ref.html # intermittently 147 pixels on win7 accelerated only (not win8)
+fuzzy(0-31,0-127) fuzzy-if(winWidget,0-31,0-147) == downscale-1.html downscale-1-ref.html # intermittently 147 pixels on win7 accelerated only (not win8)
 
 fuzzy(0-20,0-999) != downscale-2a.html?203,52,left about:blank
 fuzzy(0-20,0-999) != downscale-2b.html?203,52,left about:blank
diff --git a/image/test/reftest/generic/reftest.list b/image/test/reftest/generic/reftest.list
index 6f236399ef..5190b52a0e 100644
--- a/image/test/reftest/generic/reftest.list
+++ b/image/test/reftest/generic/reftest.list
@@ -3,4 +3,4 @@ skip-if(Android) != moz-icon-1.html about:blank
 == moz-icon-blank-1.html moz-icon-blank-1-ref.html
 skip-if(Android) != moz-icon-blank-1-ref.html moz-icon-blank-1-antiref.html
 skip-if(Android) != moz-icon-blank-1-ref.html moz-icon-blank-1-antiref2.html
-fuzzy-if(OSX,44-49,335-348) fuzzy-if(winWidget,64-140,45-191) == moz-icon-blank-1-almostref.html moz-icon-blank-1-ref.html
+fuzzy-if(cocoaWidget,44-49,335-348) fuzzy-if(winWidget,64-140,45-191) == moz-icon-blank-1-almostref.html moz-icon-blank-1-ref.html
diff --git a/image/test/reftest/png/green10-invalidchunkname.png b/image/test/reftest/png/green10-invalidchunkname.png
new file mode 100644
index 0000000000..6ca9cf948e
Binary files /dev/null and b/image/test/reftest/png/green10-invalidchunkname.png differ
diff --git a/image/test/reftest/png/green10.png b/image/test/reftest/png/green10.png
new file mode 100644
index 0000000000..1aa954ba2f
Binary files /dev/null and b/image/test/reftest/png/green10.png differ
diff --git a/image/test/reftest/png/reftest.list b/image/test/reftest/png/reftest.list
new file mode 100644
index 0000000000..ef3012fe7a
--- /dev/null
+++ b/image/test/reftest/png/reftest.list
@@ -0,0 +1 @@
+== green10-invalidchunkname.png green10.png
diff --git a/image/test/reftest/reftest.list b/image/test/reftest/reftest.list
index 109a0676e1..9dd3a938b3 100644
--- a/image/test/reftest/reftest.list
+++ b/image/test/reftest/reftest.list
@@ -18,6 +18,9 @@ include pngsuite-oddsizes/reftest.list
 include pngsuite-palettes/reftest.list
 include pngsuite-zlib/reftest.list
 
+# PNG tests
+include png/reftest.list
+
 # BMP tests
 skip-if(Android) include bmp/reftest.list
 
@@ -28,7 +31,7 @@ skip-if(Android) include ico/reftest.list
 include jpeg/reftest.list
 
 # JXL tests
-skip-if(Android||!jxl) include jxl/reftest.list
+skip-if(Android||release_or_beta) include jxl/reftest.list
 
 # GIF tests
 include gif/reftest.list
diff --git a/image/test/unit/async_load_tests.js b/image/test/unit/async_load_tests.js
index f19e146314..1fdbe590e3 100644
--- a/image/test/unit/async_load_tests.js
+++ b/image/test/unit/async_load_tests.js
@@ -50,7 +50,7 @@ function checkClone(other_listener, aRequest) {
   // For as long as clone notification is synchronous, we can't test the clone state reliably.
   var listener = new ImageListener(
     null,
-    function (foo, bar) {
+    function () {
       do_test_finished();
     } /* getCloneStopCallback(other_listener)*/
   );
@@ -63,7 +63,7 @@ function checkClone(other_listener, aRequest) {
 }
 
 // Ensure that all the callbacks were called on aRequest.
-function checkSizeAndLoad(listener, aRequest) {
+function checkSizeAndLoad(listener) {
   Assert.notEqual(listener.state & SIZE_AVAILABLE, 0);
   Assert.notEqual(listener.state & LOAD_COMPLETE, 0);
 
@@ -127,7 +127,7 @@ function checkSecondLoad() {
   listener.synchronous = false;
 }
 
-function firstLoadDone(oldlistener, aRequest) {
+function firstLoadDone() {
   checkSecondLoad(uri);
 
   do_test_finished();
@@ -136,7 +136,7 @@ function firstLoadDone(oldlistener, aRequest) {
 // Return a closure that allows us to check the stream listener's status when the
 // image finishes loading.
 function getChannelLoadImageStopCallback(streamlistener, next) {
-  return function channelLoadStop(imglistener, aRequest) {
+  return function channelLoadStop() {
     next();
 
     do_test_finished();
@@ -216,7 +216,7 @@ function startImageCallback(otherCb) {
   return function (listener, request) {
     // Make sure we can load the same image immediately out of the cache.
     do_test_pending();
-    var listener2 = new ImageListener(null, function (foo, bar) {
+    var listener2 = new ImageListener(null, function () {
       do_test_finished();
     });
     var outer = Cc["@mozilla.org/image/tools;1"]
diff --git a/image/test/unit/image_load_helpers.js b/image/test/unit/image_load_helpers.js
index 6d1e605bf5..3a97db00ca 100644
--- a/image/test/unit/image_load_helpers.js
+++ b/image/test/unit/image_load_helpers.js
@@ -31,12 +31,12 @@ function ImageListener(start_callback, stop_callback) {
       this.start_callback(this, aRequest);
     }
   };
-  this.frameComplete = function onFrameComplete(aRequest) {
+  this.frameComplete = function onFrameComplete() {
     Assert.ok(!this.synchronous);
 
     this.state |= FRAME_COMPLETE;
   };
-  this.decodeComplete = function onDecodeComplete(aRequest) {
+  this.decodeComplete = function onDecodeComplete() {
     Assert.ok(!this.synchronous);
 
     this.state |= DECODE_COMPLETE;
@@ -50,7 +50,7 @@ function ImageListener(start_callback, stop_callback) {
       this.stop_callback(this, aRequest);
     }
   };
-  this.frameUpdate = function onFrameUpdate(aRequest) {};
+  this.frameUpdate = function onFrameUpdate() {};
   this.isAnimated = function onIsAnimated() {};
 
   // Initialize the synchronous flag to true to start. This must be set to
-- 
cgit v1.2.3