From f11ae35b07846131c738b690049102c320b54dbd Mon Sep 17 00:00:00 2001 From: noaione Date: Sun, 23 Feb 2025 21:12:43 +0700 Subject: [PATCH 1/3] Implement a more complete JXL features Based on this following phabricator patch/commits: - https://phabricator.services.mozilla.com/D119700 - https://phabricator.services.mozilla.com/D122158 - https://phabricator.services.mozilla.com/D122159 Which add the following: - Proper color profiles support for JPEG XL - Animated JPEG XL - Progressive decoding Co-authored-by: wwwwwwww --- src/image/DecoderFactory-cpp.patch | 32 +++ src/image/decoders/nsJXLDecoder-cpp.patch | 308 ++++++++++++++++++++++ src/image/decoders/nsJXLDecoder-h.patch | 23 ++ 3 files changed, 363 insertions(+) create mode 100644 src/image/DecoderFactory-cpp.patch create mode 100644 src/image/decoders/nsJXLDecoder-cpp.patch create mode 100644 src/image/decoders/nsJXLDecoder-h.patch diff --git a/src/image/DecoderFactory-cpp.patch b/src/image/DecoderFactory-cpp.patch new file mode 100644 index 000000000..8d3df598e --- /dev/null +++ b/src/image/DecoderFactory-cpp.patch @@ -0,0 +1,32 @@ +diff --git a/image/DecoderFactory.cpp b/image/DecoderFactory.cpp +index f36f03c7f2..d2cdd79f70 100644 +--- a/image/DecoderFactory.cpp ++++ b/image/DecoderFactory.cpp +@@ -244,7 +244,12 @@ nsresult DecoderFactory::CreateAnimationDecoder( + } + + MOZ_ASSERT(aType == DecoderType::GIF || aType == DecoderType::PNG || +- aType == DecoderType::WEBP || aType == DecoderType::AVIF, ++ aType == DecoderType::WEBP || aType == DecoderType::AVIF ++#ifdef MOZ_JXL ++ || aType == DecoderType::JXL, ++#else ++ , ++#endif + "Calling CreateAnimationDecoder for non-animating DecoderType"); + + // Create an anonymous decoder. Interaction with the SurfaceCache and the +@@ -299,7 +304,12 @@ already_AddRefed DecoderFactory::CloneAnimationDecoder( + // rediscover it is animated). + DecoderType type = aDecoder->GetType(); + MOZ_ASSERT(type == DecoderType::GIF || type == DecoderType::PNG || +- type == DecoderType::WEBP || type == DecoderType::AVIF, ++ type == DecoderType::WEBP || type == DecoderType::AVIF ++#ifdef MOZ_JXL ++ || aType == DecoderType::JXL, ++#else ++ , ++#endif + "Calling CloneAnimationDecoder for non-animating DecoderType"); + + RefPtr decoder = GetDecoder(type, nullptr, /* aIsRedecode = */ true); diff --git a/src/image/decoders/nsJXLDecoder-cpp.patch b/src/image/decoders/nsJXLDecoder-cpp.patch new file mode 100644 index 000000000..91f45420c --- /dev/null +++ b/src/image/decoders/nsJXLDecoder-cpp.patch @@ -0,0 +1,308 @@ +diff --git a/image/decoders/nsJXLDecoder.cpp b/image/decoders/nsJXLDecoder.cpp +index ffb7f3cd51e1d0e480bf8ac5e936a90c11f0c93d..282472afe4fbab7d41adaf15928fa93c99e74452 100644 +--- a/image/decoders/nsJXLDecoder.cpp ++++ b/image/decoders/nsJXLDecoder.cpp +@@ -45,9 +45,20 @@ nsJXLDecoder::nsJXLDecoder(RasterImage* aImage) + Transition::TerminateSuccess()), + mDecoder(JxlDecoderMake(nullptr)), + mParallelRunner( +- JxlThreadParallelRunnerMake(nullptr, PreferredThreadCount())) { +- JxlDecoderSubscribeEvents(mDecoder.get(), +- JXL_DEC_BASIC_INFO | JXL_DEC_FULL_IMAGE); ++ JxlThreadParallelRunnerMake(nullptr, PreferredThreadCount())), ++ mUsePipeTransform(true), ++ mCMSLine(nullptr), ++ mNumFrames(0), ++ mTimeout(FrameTimeout::Forever()), ++ mSurfaceFormat(SurfaceFormat::OS_RGBX), ++ mContinue(false) { ++ int events = JXL_DEC_BASIC_INFO | JXL_DEC_FRAME | JXL_DEC_FULL_IMAGE; ++ ++ if (mCMSMode != CMSMode::Off) { ++ events |= JXL_DEC_COLOR_ENCODING; ++ } ++ ++ JxlDecoderSubscribeEvents(mDecoder.get(), events); + JxlDecoderSetParallelRunner(mDecoder.get(), JxlThreadParallelRunner, + mParallelRunner.get()); + +@@ -58,6 +69,10 @@ nsJXLDecoder::nsJXLDecoder(RasterImage* aImage) + nsJXLDecoder::~nsJXLDecoder() { + MOZ_LOG(sJXLLog, LogLevel::Debug, + ("[this=%p] nsJXLDecoder::~nsJXLDecoder", this)); ++ ++ if (mCMSLine) { ++ free(mCMSLine); ++ } + } + + size_t nsJXLDecoder::PreferredThreadCount() { +@@ -86,14 +101,20 @@ LexerResult nsJXLDecoder::DoDecode(SourceBufferIterator& aIterator, + + LexerTransition nsJXLDecoder::ReadJXLData( + const char* aData, size_t aLength) { +- const uint8_t* input = (const uint8_t*)aData; +- size_t length = aLength; +- if (mBuffer.length() != 0) { +- JXL_TRY_BOOL(mBuffer.append(aData, aLength)); +- input = mBuffer.begin(); +- length = mBuffer.length(); ++ // Ignore data we have already read. ++ // This will only occur as a result of a yield for animation. ++ if (!mContinue) { ++ const uint8_t* input = (const uint8_t*)aData; ++ size_t length = aLength; ++ if (mBuffer.length() != 0) { ++ JXL_TRY_BOOL(mBuffer.append(aData, aLength)); ++ input = mBuffer.begin(); ++ length = mBuffer.length(); ++ } ++ ++ JXL_TRY(JxlDecoderSetInput(mDecoder.get(), input, length)); + } +- JXL_TRY(JxlDecoderSetInput(mDecoder.get(), input, length)); ++ mContinue = false; + + while (true) { + JxlDecoderStatus status = JxlDecoderProcessInput(mDecoder.get()); +@@ -106,51 +127,229 @@ LexerTransition nsJXLDecoder::ReadJXLData( + size_t remaining = JxlDecoderReleaseInput(mDecoder.get()); + mBuffer.clear(); + JXL_TRY_BOOL(mBuffer.append(aData + aLength - remaining, remaining)); ++ ++ if (mNumFrames == 0 && InFrame()) { ++ // If an image was flushed by JxlDecoderFlushImage, then we know that ++ // JXL_DEC_FRAME has already been run and there is a pipe. ++ if (JxlDecoderFlushImage(mDecoder.get()) == JXL_DEC_SUCCESS) { ++ // A full frame partial image is written to the buffer. ++ mPipe.ResetToFirstRow(); ++ for (uint8_t* rowPtr = mOutBuffer.begin(); ++ rowPtr < mOutBuffer.end(); rowPtr += mInfo.xsize * mChannels) { ++ uint8_t* rowToWrite = rowPtr; ++ ++ if (!mUsePipeTransform && mTransform) { ++ qcms_transform_data(mTransform, rowToWrite, mCMSLine, ++ mInfo.xsize); ++ rowToWrite = mCMSLine; ++ } ++ ++ mPipe.WriteBuffer(reinterpret_cast(rowToWrite)); ++ } ++ ++ if (Maybe invalidRect = ++ mPipe.TakeInvalidRect()) { ++ PostInvalidation(invalidRect->mInputSpaceRect, ++ Some(invalidRect->mOutputSpaceRect)); ++ } ++ } ++ } ++ + return Transition::ContinueUnbuffered(State::JXL_DATA); + } + + case JXL_DEC_BASIC_INFO: { + JXL_TRY(JxlDecoderGetBasicInfo(mDecoder.get(), &mInfo)); + PostSize(mInfo.xsize, mInfo.ysize); ++ + if (WantsFrameCount()) { + PostFrameCount(/* aFrameCount */ 1); + } ++ + if (mInfo.alpha_bits > 0) { ++ mSurfaceFormat = SurfaceFormat::OS_RGBA; + PostHasTransparency(); + } ++ ++ if (!mInfo.have_animation && IsMetadataDecode()) { ++ return Transition::TerminateSuccess(); ++ } ++ ++ // If CMS is off or the image is RGB, always output in RGBA. ++ // If the image is grayscale, then the pipe transform can't be used. ++ if (mCMSMode != CMSMode::Off) { ++ mChannels = mInfo.num_color_channels == 1 ++ ? 1 + (mInfo.alpha_bits > 0 ? 1 : 0) ++ : 4; ++ } else { ++ mChannels = 4; ++ } ++ ++ mFormat = {mChannels, JXL_TYPE_UINT8, JXL_LITTLE_ENDIAN, 0}; ++ ++ break; ++ } ++ ++ case JXL_DEC_COLOR_ENCODING: { ++ size_t size = 0; ++ JXL_TRY(JxlDecoderGetICCProfileSize( ++ mDecoder.get(), JXL_COLOR_PROFILE_TARGET_DATA, &size)) ++ std::vector icc_profile(size); ++ JXL_TRY(JxlDecoderGetColorAsICCProfile(mDecoder.get(), ++ JXL_COLOR_PROFILE_TARGET_DATA, ++ icc_profile.data(), size)) ++ ++ mInProfile = qcms_profile_from_memory((char*)icc_profile.data(), size); ++ ++ uint32_t profileSpace = qcms_profile_get_color_space(mInProfile); ++ ++ // Skip color management if color profile is not compatible with number ++ // of channels. ++ if (profileSpace != icSigRgbData && ++ (mInfo.num_color_channels == 3 || profileSpace != icSigGrayData)) { ++ break; ++ } ++ ++ mUsePipeTransform = ++ profileSpace == icSigRgbData && mInfo.num_color_channels == 3; ++ ++ qcms_data_type inType; ++ if (mInfo.num_color_channels == 3) { ++ inType = QCMS_DATA_RGBA_8; ++ } else if (mInfo.alpha_bits > 0) { ++ inType = QCMS_DATA_GRAYA_8; ++ } else { ++ inType = QCMS_DATA_GRAY_8; ++ } ++ ++ if (!mUsePipeTransform) { ++ mCMSLine = ++ static_cast(malloc(sizeof(uint32_t) * mInfo.xsize)); ++ } ++ ++ int intent = gfxPlatform::GetRenderingIntent(); ++ if (intent == -1) { ++ intent = qcms_profile_get_rendering_intent(mInProfile); ++ } ++ ++ mTransform = ++ qcms_transform_create(mInProfile, inType, GetCMSOutputProfile(), ++ QCMS_DATA_RGBA_8, (qcms_intent)intent); ++ ++ break; ++ } ++ ++ case JXL_DEC_FRAME: { ++ if (mInfo.have_animation) { ++ JXL_TRY(JxlDecoderGetFrameHeader(mDecoder.get(), &mFrameHeader)); ++ int32_t duration = (int32_t)(1000.0 * mFrameHeader.duration * ++ mInfo.animation.tps_denominator / ++ mInfo.animation.tps_numerator); ++ ++ mTimeout = FrameTimeout::FromRawMilliseconds(duration); ++ ++ if (!HasAnimation()) { ++ PostIsAnimated(mTimeout); ++ } ++ } ++ ++ bool is_last = mInfo.have_animation ? mFrameHeader.is_last : true; ++ MOZ_LOG(sJXLLog, LogLevel::Debug, ++ ("[this=%p] nsJXLDecoder::ReadJXLData - frame %d, is_last %d, " ++ "metadata decode %d, first frame decode %d\n", ++ this, mNumFrames, is_last, IsMetadataDecode(), ++ IsFirstFrameDecode())); ++ + if (IsMetadataDecode()) { + return Transition::TerminateSuccess(); + } ++ ++ OrientedIntSize size(mInfo.xsize, mInfo.ysize); ++ ++ Maybe animParams; ++ if (!IsFirstFrameDecode()) { ++ animParams.emplace(FullFrame().ToUnknownRect(), mTimeout, mNumFrames, ++ BlendMethod::SOURCE, DisposalMethod::CLEAR); ++ } ++ ++ SurfacePipeFlags pipeFlags = SurfacePipeFlags(); ++ if (mNumFrames == 0) { ++ // The first frame may be displayed progressively. ++ pipeFlags |= SurfacePipeFlags::PROGRESSIVE_DISPLAY; ++ } ++ if (mSurfaceFormat == SurfaceFormat::OS_RGBA && ++ !(GetSurfaceFlags() & SurfaceFlags::NO_PREMULTIPLY_ALPHA)) { ++ pipeFlags |= SurfacePipeFlags::PREMULTIPLY_ALPHA; ++ } ++ ++ qcms_transform* pipeTransform = ++ mUsePipeTransform ? mTransform : nullptr; ++ ++ Maybe pipe = SurfacePipeFactory::CreateSurfacePipe( ++ this, size, OutputSize(), FullFrame(), SurfaceFormat::R8G8B8A8, ++ mSurfaceFormat, animParams, pipeTransform, pipeFlags); ++ ++ if (!pipe) { ++ MOZ_LOG(sJXLLog, LogLevel::Debug, ++ ("[this=%p] nsJXLDecoder::ReadJXLData - no pipe\n", this)); ++ return Transition::TerminateFailure(); ++ } ++ ++ mPipe = std::move(*pipe); ++ + break; + } + + case JXL_DEC_NEED_IMAGE_OUT_BUFFER: { + size_t size = 0; +- JxlPixelFormat format{4, JXL_TYPE_UINT8, JXL_LITTLE_ENDIAN, 0}; +- JXL_TRY(JxlDecoderImageOutBufferSize(mDecoder.get(), &format, &size)); ++ JXL_TRY(JxlDecoderImageOutBufferSize(mDecoder.get(), &mFormat, &size)); + + mOutBuffer.clear(); + JXL_TRY_BOOL(mOutBuffer.growBy(size)); +- JXL_TRY(JxlDecoderSetImageOutBuffer(mDecoder.get(), &format, ++ JXL_TRY(JxlDecoderSetImageOutBuffer(mDecoder.get(), &mFormat, + mOutBuffer.begin(), size)); + break; + } + + case JXL_DEC_FULL_IMAGE: { +- OrientedIntSize size(mInfo.xsize, mInfo.ysize); +- Maybe pipe = SurfacePipeFactory::CreateSurfacePipe( +- this, size, OutputSize(), FullFrame(), SurfaceFormat::R8G8B8A8, +- SurfaceFormat::OS_RGBA, Nothing(), nullptr, SurfacePipeFlags()); ++ mPipe.ResetToFirstRow(); ++ + for (uint8_t* rowPtr = mOutBuffer.begin(); rowPtr < mOutBuffer.end(); +- rowPtr += mInfo.xsize * 4) { +- pipe->WriteBuffer(reinterpret_cast(rowPtr)); ++ rowPtr += mInfo.xsize * mChannels) { ++ uint8_t* rowToWrite = rowPtr; ++ ++ if (!mUsePipeTransform && mTransform) { ++ qcms_transform_data(mTransform, rowToWrite, mCMSLine, mInfo.xsize); ++ rowToWrite = mCMSLine; ++ } ++ ++ mPipe.WriteBuffer(reinterpret_cast(rowToWrite)); + } + +- if (Maybe invalidRect = pipe->TakeInvalidRect()) { ++ if (Maybe invalidRect = mPipe.TakeInvalidRect()) { + PostInvalidation(invalidRect->mInputSpaceRect, + Some(invalidRect->mOutputSpaceRect)); + } +- PostFrameStop(); ++ ++ Opacity opacity = (mSurfaceFormat == SurfaceFormat::OS_RGBA) ++ ? Opacity::SOME_TRANSPARENCY ++ : Opacity::FULLY_OPAQUE; ++ PostFrameStop(opacity); ++ ++ if (!IsFirstFrameDecode() && mInfo.have_animation && ++ !mFrameHeader.is_last) { ++ mNumFrames++; ++ mContinue = true; ++ // Notify for a new frame but there may be data in the current buffer ++ // that can immediately be processed. ++ return Transition::ToAfterYield(State::JXL_DATA); ++ } ++ [[fallthrough]]; // We are done. ++ } ++ ++ case JXL_DEC_SUCCESS: { ++ PostLoopCount(HasAnimation() ? (int32_t)mInfo.animation.num_loops - 1 ++ : 0); + PostDecodeDone(); + return Transition::TerminateSuccess(); + } diff --git a/src/image/decoders/nsJXLDecoder-h.patch b/src/image/decoders/nsJXLDecoder-h.patch new file mode 100644 index 000000000..779ccc634 --- /dev/null +++ b/src/image/decoders/nsJXLDecoder-h.patch @@ -0,0 +1,23 @@ +diff --git a/image/decoders/nsJXLDecoder.h b/image/decoders/nsJXLDecoder.h +index 6cde7456ca03f79e74401c1d215b9d50453ebf41..2f593ca3b70100c600b86e753d7a458c83b4f15c 100644 +--- a/image/decoders/nsJXLDecoder.h ++++ b/image/decoders/nsJXLDecoder.h +@@ -48,6 +48,18 @@ class nsJXLDecoder final : public Decoder { + Vector mBuffer; + Vector mOutBuffer; + JxlBasicInfo mInfo{}; ++ JxlPixelFormat mFormat; ++ JxlFrameHeader mFrameHeader; ++ ++ bool mUsePipeTransform; ++ uint8_t mChannels; ++ uint8_t* mCMSLine; ++ ++ uint32_t mNumFrames; ++ FrameTimeout mTimeout; ++ gfx::SurfaceFormat mSurfaceFormat; ++ SurfacePipe mPipe; ++ bool mContinue; + }; + + } // namespace mozilla::image From 34b0c8e774afa1a6a84c2e186998f6260044142b Mon Sep 17 00:00:00 2001 From: noaione Date: Sun, 23 Feb 2025 22:21:25 +0700 Subject: [PATCH 2/3] Recognizes `.jxl` as a proper image type Based on: https://src.fedoraproject.org/fork/eclipseo/rpms/firefox/blob/90702891fefc97ff9e347dbab0091136822a0f3b/f/0002-Bug-1539075-Register-.jxl-extension-in-Firefox.-r-tn.patch --- src/Cargo-lock.patch | 13 ++++++ src/Cargo-toml.patch | 14 ++++++ .../BrowserContentHandler-sys-mjs.patch | 12 +++++ .../windows/msix/AppxManifest-xml-in.patch | 12 +++++ .../installer/windows/nsis/shared-nsh.patch | 46 +++++++++++++++++++ .../windows/nsis/uninstaller-nsi.patch | 12 +++++ .../rust/mime_guess/src/mime_types-rs.patch | 31 +++++++++++++ .../downloads/DownloadList-sys-mjs.patch | 12 +++++ .../extensions/parent/ext-downloads-js.patch | 20 ++++++++ .../pdfjs/content/build/pdf-mjs.patch | 37 +++++++++++++++ .../content/filepicker-properties.patch | 13 ++++++ .../unknownContentType-properties.patch | 12 +++++ src/widget/gtk/nsAppShell-cpp.patch | 14 ++++++ 13 files changed, 248 insertions(+) create mode 100644 src/Cargo-lock.patch create mode 100644 src/Cargo-toml.patch create mode 100644 src/browser/components/BrowserContentHandler-sys-mjs.patch create mode 100644 src/browser/installer/windows/msix/AppxManifest-xml-in.patch create mode 100644 src/browser/installer/windows/nsis/shared-nsh.patch create mode 100644 src/browser/installer/windows/nsis/uninstaller-nsi.patch create mode 100644 src/third_party/rust/mime_guess/src/mime_types-rs.patch create mode 100644 src/toolkit/components/downloads/DownloadList-sys-mjs.patch create mode 100644 src/toolkit/components/extensions/parent/ext-downloads-js.patch create mode 100644 src/toolkit/components/pdfjs/content/build/pdf-mjs.patch create mode 100644 src/toolkit/content/filepicker-properties.patch create mode 100644 src/toolkit/locales/en-US/chrome/mozapps/downloads/unknownContentType-properties.patch create mode 100644 src/widget/gtk/nsAppShell-cpp.patch diff --git a/src/Cargo-lock.patch b/src/Cargo-lock.patch new file mode 100644 index 000000000..fe2a60421 --- /dev/null +++ b/src/Cargo-lock.patch @@ -0,0 +1,13 @@ +diff --git a/Cargo.lock b/Cargo.lock +index 0609d96f01ded85dccf2c931d3c553be61432e6a..8ce4374dd31b4ce818c8bb548fbfb2669014b05b 100644 +--- a/Cargo.lock ++++ b/Cargo.lock +@@ -3919,8 +3919,6 @@ dependencies = [ + [[package]] + name = "mime_guess" + version = "2.0.4" +-source = "registry+https://github.com/rust-lang/crates.io-index" +-checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef" + dependencies = [ + "mime", + "unicase", diff --git a/src/Cargo-toml.patch b/src/Cargo-toml.patch new file mode 100644 index 000000000..298cb4263 --- /dev/null +++ b/src/Cargo-toml.patch @@ -0,0 +1,14 @@ +diff --git a/Cargo.toml b/Cargo.toml +index 29942b65f62497b80d63675501ae063c393943a7..a9aa4641421038fbe5b0ecd9b7353611eecefffe 100644 +--- a/Cargo.toml ++++ b/Cargo.toml +@@ -198,6 +198,9 @@ rure = { path = "third_party/rust/rure" } + # Patch `plist` to work with `indexmap` 2.* + plist = { path = "third_party/rust/plist" } + ++# Patch mime_guess to add missing mime types ++mime_guess = { path = "third_party/rust/mime_guess" } ++ + # To-be-published changes. + unicode-bidi = { git = "https://github.com/servo/unicode-bidi", rev = "ca612daf1c08c53abe07327cb3e6ef6e0a760f0c" } + nss-gk-api = { git = "https://github.com/beurdouche/nss-gk-api", rev = "e48a946811ffd64abc78de3ee284957d8d1c0d63" } diff --git a/src/browser/components/BrowserContentHandler-sys-mjs.patch b/src/browser/components/BrowserContentHandler-sys-mjs.patch new file mode 100644 index 000000000..b69095199 --- /dev/null +++ b/src/browser/components/BrowserContentHandler-sys-mjs.patch @@ -0,0 +1,12 @@ +diff --git a/browser/components/BrowserContentHandler.sys.mjs b/browser/components/BrowserContentHandler.sys.mjs +index 7aef091c0be1cb0ea0be52268949db17032f96d9..5e9105fa671d1b1979f204fc8d3be22771998ad7 100644 +--- a/browser/components/BrowserContentHandler.sys.mjs ++++ b/browser/components/BrowserContentHandler.sys.mjs +@@ -1278,6 +1278,7 @@ function maybeRecordToHandleTelemetry(uri, isLaunch) { + ".avif", + ".htm", + ".html", ++ ".jxl", + ".pdf", + ".shtml", + ".xht", diff --git a/src/browser/installer/windows/msix/AppxManifest-xml-in.patch b/src/browser/installer/windows/msix/AppxManifest-xml-in.patch new file mode 100644 index 000000000..1c638f2df --- /dev/null +++ b/src/browser/installer/windows/msix/AppxManifest-xml-in.patch @@ -0,0 +1,12 @@ +diff --git a/browser/installer/windows/msix/AppxManifest.xml.in b/browser/installer/windows/msix/AppxManifest.xml.in +index b81a73518a183b7b1d178793886c66f44651058d..89690a4177229b70013bcf35ec1d805fff7e1b26 100644 +--- a/browser/installer/windows/msix/AppxManifest.xml.in ++++ b/browser/installer/windows/msix/AppxManifest.xml.in +@@ -61,6 +61,7 @@ + .avif + .htm + .html ++ .jxl + .pdf + .shtml + .xht diff --git a/src/browser/installer/windows/nsis/shared-nsh.patch b/src/browser/installer/windows/nsis/shared-nsh.patch new file mode 100644 index 000000000..f8da06cfe --- /dev/null +++ b/src/browser/installer/windows/nsis/shared-nsh.patch @@ -0,0 +1,46 @@ +diff --git a/browser/installer/windows/nsis/shared.nsh b/browser/installer/windows/nsis/shared.nsh +index b7f8e1453089ab5f1945e1a65f038e17b5273571..5297f5ed70fe3446e55be37df486fb4ad791a446 100644 +--- a/browser/installer/windows/nsis/shared.nsh ++++ b/browser/installer/windows/nsis/shared.nsh +@@ -513,6 +513,7 @@ ${RemoveDefaultBrowserAgentShortcut} + ${AddAssociationIfNoneExist} ".svg" "FirefoxHTML$5" + ${AddAssociationIfNoneExist} ".webp" "FirefoxHTML$5" + ${AddAssociationIfNoneExist} ".avif" "FirefoxHTML$5" ++ ${AddAssociationIfNoneExist} ".jxl" "FirefoxHTML$5" + + ${AddAssociationIfNoneExist} ".pdf" "FirefoxPDF$5" + +@@ -609,6 +610,7 @@ ${RemoveDefaultBrowserAgentShortcut} + WriteRegStr ${RegKey} "$0\Capabilities\FileAssociations" ".svg" "FirefoxHTML$2" + WriteRegStr ${RegKey} "$0\Capabilities\FileAssociations" ".webp" "FirefoxHTML$2" + WriteRegStr ${RegKey} "$0\Capabilities\FileAssociations" ".avif" "FirefoxHTML$2" ++ WriteRegStr ${RegKey} "$0\Capabilities\FileAssociations" ".jxl" "FirefoxHTML$2" + + WriteRegStr ${RegKey} "$0\Capabilities\FileAssociations" ".pdf" "FirefoxPDF$2" + +@@ -681,6 +683,7 @@ ${RemoveDefaultBrowserAgentShortcut} + ${WriteApplicationsSupportedType} ${RegKey} ".webm" + ${WriteApplicationsSupportedType} ${RegKey} ".webp" + ${WriteApplicationsSupportedType} ${RegKey} ".avif" ++ ${WriteApplicationsSupportedType} ${RegKey} ".jxl" + ${WriteApplicationsSupportedType} ${RegKey} ".xht" + ${WriteApplicationsSupportedType} ${RegKey} ".xhtml" + ${WriteApplicationsSupportedType} ${RegKey} ".xml" +@@ -1728,6 +1731,8 @@ Function SetAsDefaultAppUserHKCU + Pop $0 + AppAssocReg::SetAppAsDefault "$R9" ".avif" "file" + Pop $0 ++ AppAssocReg::SetAppAsDefault "$R9" ".jxl" "file" ++ Pop $0 + AppAssocReg::SetAppAsDefault "$R9" ".xht" "file" + Pop $0 + AppAssocReg::SetAppAsDefault "$R9" ".xhtml" "file" +@@ -1857,7 +1862,7 @@ FunctionEnd + ; uninstalled. + + ; Do all of that twice, once for the local machine and once for the current user +- ++ + ; Remove protocol handlers + ClearErrors + ReadRegStr $0 HKLM "Software\Classes\${_PROTOCOL}\DefaultIcon" "" diff --git a/src/browser/installer/windows/nsis/uninstaller-nsi.patch b/src/browser/installer/windows/nsis/uninstaller-nsi.patch new file mode 100644 index 000000000..b2de9cb9a --- /dev/null +++ b/src/browser/installer/windows/nsis/uninstaller-nsi.patch @@ -0,0 +1,12 @@ +diff --git a/browser/installer/windows/nsis/uninstaller.nsi b/browser/installer/windows/nsis/uninstaller.nsi +index 559c8b46ee06bc42c91da49b5d9e397fe8ff6126..62094a5d98712a41a607ba01ca2adfa1e4f51ccd 100644 +--- a/browser/installer/windows/nsis/uninstaller.nsi ++++ b/browser/installer/windows/nsis/uninstaller.nsi +@@ -507,6 +507,7 @@ Section "Uninstall" + ${un.RegCleanFileHandler} ".svg" "FirefoxHTML-$AppUserModelID" + ${un.RegCleanFileHandler} ".webp" "FirefoxHTML-$AppUserModelID" + ${un.RegCleanFileHandler} ".avif" "FirefoxHTML-$AppUserModelID" ++ ${un.RegCleanFileHandler} ".jxl" "FirefoxHTML-$AppUserModelID" + + ${un.RegCleanFileHandler} ".pdf" "FirefoxPDF-$AppUserModelID" + diff --git a/src/third_party/rust/mime_guess/src/mime_types-rs.patch b/src/third_party/rust/mime_guess/src/mime_types-rs.patch new file mode 100644 index 000000000..9568fa141 --- /dev/null +++ b/src/third_party/rust/mime_guess/src/mime_types-rs.patch @@ -0,0 +1,31 @@ +diff --git a/third_party/rust/mime_guess/src/mime_types.rs b/third_party/rust/mime_guess/src/mime_types.rs +index 13c91b7bee77a0c0a4b45b8e05a25bb89daac66e..1521cd729ec78dbc51b86cf04546c4cd4ceb1163 100644 +--- a/third_party/rust/mime_guess/src/mime_types.rs ++++ b/third_party/rust/mime_guess/src/mime_types.rs +@@ -103,6 +103,7 @@ pub static MIME_TYPES: &[(&str, &[&str])] = &[ + ("au", &["audio/basic"]), + ("avi", &["video/x-msvideo"]), + ("avif", &["image/avif"]), ++ ("avifs", &["image/avif-sequence"]), + ("aw", &["application/applixware"]), + ("axa", &["audio/annodex"]), + ("axs", &["application/olescript"]), +@@ -449,6 +450,10 @@ pub static MIME_TYPES: &[(&str, &[&str])] = &[ + ("hdf", &["application/x-hdf"]), + ("hdml", &["text/x-hdml"]), + ("hdr", &["image/vnd.radiance"]), ++ ("heic", &["image/heic"]), ++ ("heics", &["image/heic-sequence"]), ++ ("heif", &["image/heif"]), ++ ("heifs", &["image/heif-sequence"]), + ("hh", &["text/plain"]), + ("hhc", &["application/x-oleobject"]), + ("hhk", &["application/octet-stream"]), +@@ -567,6 +572,7 @@ pub static MIME_TYPES: &[(&str, &[&str])] = &[ + ("jsonml", &["application/jsonml+json"]), + ("jsx", &["text/jscript"]), + ("jsxbin", &["text/plain"]), ++ ("jxl", &["image/jxl"]), + ("kar", &["audio/midi"]), + ("karbon", &["application/vnd.kde.karbon"]), + ("kfo", &["application/vnd.kde.kformula"]), diff --git a/src/toolkit/components/downloads/DownloadList-sys-mjs.patch b/src/toolkit/components/downloads/DownloadList-sys-mjs.patch new file mode 100644 index 000000000..f27368c52 --- /dev/null +++ b/src/toolkit/components/downloads/DownloadList-sys-mjs.patch @@ -0,0 +1,12 @@ +diff --git a/toolkit/components/downloads/DownloadList.sys.mjs b/toolkit/components/downloads/DownloadList.sys.mjs +index c4e5776940c4cdca731a82ba91d41620c4c7b75a..d580d193bda5e932cebc849c4487de504f17b6fe 100644 +--- a/toolkit/components/downloads/DownloadList.sys.mjs ++++ b/toolkit/components/downloads/DownloadList.sys.mjs +@@ -50,6 +50,7 @@ const FILE_EXTENSIONS = [ + "jpg", + "jpeg", + "json", ++ "jxl", + "m4a", + "mdb", + "mid", diff --git a/src/toolkit/components/extensions/parent/ext-downloads-js.patch b/src/toolkit/components/extensions/parent/ext-downloads-js.patch new file mode 100644 index 000000000..f867d171d --- /dev/null +++ b/src/toolkit/components/extensions/parent/ext-downloads-js.patch @@ -0,0 +1,20 @@ +diff --git a/toolkit/components/extensions/parent/ext-downloads.js b/toolkit/components/extensions/parent/ext-downloads.js +index ea6929d23d432958def5be46e42e329bc224d3aa..942cfddc090399ef239cc34ab47682cab6a33cd4 100644 +--- a/toolkit/components/extensions/parent/ext-downloads.js ++++ b/toolkit/components/extensions/parent/ext-downloads.js +@@ -87,6 +87,7 @@ const FILTER_IMAGES_EXTENSIONS = [ + "jpe", + "jpg", + "jpeg", ++ "jxl", + "gif", + "png", + "bmp", +@@ -104,6 +105,7 @@ const FILTER_IMAGES_EXTENSIONS = [ + "raw", + "webp", + "heic", ++ "avif", + ]; + + const FILTER_XML_EXTENSIONS = ["xml"]; diff --git a/src/toolkit/components/pdfjs/content/build/pdf-mjs.patch b/src/toolkit/components/pdfjs/content/build/pdf-mjs.patch new file mode 100644 index 000000000..be90bf533 --- /dev/null +++ b/src/toolkit/components/pdfjs/content/build/pdf-mjs.patch @@ -0,0 +1,37 @@ +diff --git a/toolkit/components/pdfjs/content/build/pdf.mjs b/toolkit/components/pdfjs/content/build/pdf.mjs +index 9798d4f8f9473eac434ff1a521b3728bea436723..144d42b2830a7d9eb345db18a018cd8741753c3c 100644 +--- a/toolkit/components/pdfjs/content/build/pdf.mjs ++++ b/toolkit/components/pdfjs/content/build/pdf.mjs +@@ -22,7 +22,7 @@ + + /******/ // The require scope + /******/ var __webpack_require__ = {}; +-/******/ ++/******/ + /************************************************************************/ + /******/ /* webpack/runtime/define property getters */ + /******/ (() => { +@@ -35,12 +35,12 @@ + /******/ } + /******/ }; + /******/ })(); +-/******/ ++/******/ + /******/ /* webpack/runtime/hasOwnProperty shorthand */ + /******/ (() => { + /******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop)) + /******/ })(); +-/******/ ++/******/ + /************************************************************************/ + var __webpack_exports__ = globalThis.pdfjsLib = {}; + +@@ -18593,7 +18593,7 @@ class StampEditor extends AnnotationEditor { + AnnotationEditor.initialize(l10n, uiManager); + } + static get supportedTypes() { +- const types = ["apng", "avif", "bmp", "gif", "jpeg", "png", "svg+xml", "webp", "x-icon"]; ++ const types = ["apng", "avif", "bmp", "gif", "jpeg", "jxl", "png", "svg+xml", "webp", "x-icon"]; + return shadow(this, "supportedTypes", types.map(type => `image/${type}`)); + } + static get supportedTypesStr() { diff --git a/src/toolkit/content/filepicker-properties.patch b/src/toolkit/content/filepicker-properties.patch new file mode 100644 index 000000000..c3abaca23 --- /dev/null +++ b/src/toolkit/content/filepicker-properties.patch @@ -0,0 +1,13 @@ +diff --git a/toolkit/content/filepicker.properties b/toolkit/content/filepicker.properties +index 03daec114c2882ed5ab7899b9b435d1cce936838..b6bd09c3c5625a1649b31dc99935bc90773d4133 100644 +--- a/toolkit/content/filepicker.properties ++++ b/toolkit/content/filepicker.properties +@@ -5,7 +5,7 @@ + allFilter=* + htmlFilter=*.html; *.htm; *.shtml; *.xhtml + textFilter=*.txt; *.text +-imageFilter=*.jpe; *.jpg; *.jpeg; *.gif; *.png; *.bmp; *.ico; *.svg; *.svgz; *.tif; *.tiff; *.ai; *.drw; *.pct; *.psp; *.xcf; *.psd; *.raw; *.webp; *.heic ++imageFilter=*.jpe; *.jpg; *.jpeg; *.gif; *.png; *.bmp; *.ico; *.svg; *.svgz; *.tif; *.tiff; *.ai; *.drw; *.pct; *.psp; *.xcf; *.psd; *.raw; *.webp; *.heic; *.avif; *.jxl + xmlFilter=*.xml + xulFilter=*.xul + audioFilter=*.aac; *.aif; *.flac; *.iff; *.m4a; *.m4b; *.mid; *.midi; *.mp3; *.mpa; *.mpc; *.oga; *.ogg; *.opus; *.ra; *.ram; *.snd; *.wav; *.wma diff --git a/src/toolkit/locales/en-US/chrome/mozapps/downloads/unknownContentType-properties.patch b/src/toolkit/locales/en-US/chrome/mozapps/downloads/unknownContentType-properties.patch new file mode 100644 index 000000000..c8c23196b --- /dev/null +++ b/src/toolkit/locales/en-US/chrome/mozapps/downloads/unknownContentType-properties.patch @@ -0,0 +1,12 @@ +diff --git a/toolkit/locales/en-US/chrome/mozapps/downloads/unknownContentType.properties b/toolkit/locales/en-US/chrome/mozapps/downloads/unknownContentType.properties +index fa3c5e389bad5abb05c86a3cb08d6c7abf34166c..1bb1f48c4d3964e4637462bb0b3d4a1e965ca5ec 100644 +--- a/toolkit/locales/en-US/chrome/mozapps/downloads/unknownContentType.properties ++++ b/toolkit/locales/en-US/chrome/mozapps/downloads/unknownContentType.properties +@@ -17,6 +17,7 @@ fileType=%S file + # LOCALIZATION NOTE (orderedFileSizeWithType): first %S is type, second %S is size, and third %S is unit + orderedFileSizeWithType=%1$S (%2$S %3$S) + avifExtHandlerDescription=AV1 Image File (AVIF) ++jxlExtHandlerDescription=JPEG XL Image (JXL) + pdfExtHandlerDescription=Portable Document Format (PDF) + svgExtHandlerDescription=Scalable Vector Graphics (SVG) + webpExtHandlerDescription=WebP Image diff --git a/src/widget/gtk/nsAppShell-cpp.patch b/src/widget/gtk/nsAppShell-cpp.patch new file mode 100644 index 000000000..5e170a9db --- /dev/null +++ b/src/widget/gtk/nsAppShell-cpp.patch @@ -0,0 +1,14 @@ +diff --git a/widget/gtk/nsAppShell.cpp b/widget/gtk/nsAppShell.cpp +index eef6e76a26341d30748c6c4f054092ba0bfdd865..65b6e2583e6e6891dcbf9faeeefed21cc2d40d15 100644 +--- a/widget/gtk/nsAppShell.cpp ++++ b/widget/gtk/nsAppShell.cpp +@@ -419,7 +419,8 @@ nsresult nsAppShell::Init() { + gchar* name = gdk_pixbuf_format_get_name(format); + if (strcmp(name, "jpeg") && strcmp(name, "png") && strcmp(name, "gif") && + strcmp(name, "bmp") && strcmp(name, "ico") && strcmp(name, "xpm") && +- strcmp(name, "svg") && strcmp(name, "webp") && strcmp(name, "avif")) { ++ strcmp(name, "svg") && strcmp(name, "webp") && strcmp(name, "avif") && ++ strcmp(name, "jxl")) { + gdk_pixbuf_format_set_disabled(format, TRUE); + } + g_free(name); From 46f6d28fca0c49c13d7b37bef011384b88f01a8d Mon Sep 17 00:00:00 2001 From: noaione Date: Fri, 28 Feb 2025 07:15:06 +0700 Subject: [PATCH 3/3] Remove pdf.mjs patch --- .../pdfjs/content/build/pdf-mjs.patch | 37 ------------------- 1 file changed, 37 deletions(-) delete mode 100644 src/toolkit/components/pdfjs/content/build/pdf-mjs.patch diff --git a/src/toolkit/components/pdfjs/content/build/pdf-mjs.patch b/src/toolkit/components/pdfjs/content/build/pdf-mjs.patch deleted file mode 100644 index be90bf533..000000000 --- a/src/toolkit/components/pdfjs/content/build/pdf-mjs.patch +++ /dev/null @@ -1,37 +0,0 @@ -diff --git a/toolkit/components/pdfjs/content/build/pdf.mjs b/toolkit/components/pdfjs/content/build/pdf.mjs -index 9798d4f8f9473eac434ff1a521b3728bea436723..144d42b2830a7d9eb345db18a018cd8741753c3c 100644 ---- a/toolkit/components/pdfjs/content/build/pdf.mjs -+++ b/toolkit/components/pdfjs/content/build/pdf.mjs -@@ -22,7 +22,7 @@ - - /******/ // The require scope - /******/ var __webpack_require__ = {}; --/******/ -+/******/ - /************************************************************************/ - /******/ /* webpack/runtime/define property getters */ - /******/ (() => { -@@ -35,12 +35,12 @@ - /******/ } - /******/ }; - /******/ })(); --/******/ -+/******/ - /******/ /* webpack/runtime/hasOwnProperty shorthand */ - /******/ (() => { - /******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop)) - /******/ })(); --/******/ -+/******/ - /************************************************************************/ - var __webpack_exports__ = globalThis.pdfjsLib = {}; - -@@ -18593,7 +18593,7 @@ class StampEditor extends AnnotationEditor { - AnnotationEditor.initialize(l10n, uiManager); - } - static get supportedTypes() { -- const types = ["apng", "avif", "bmp", "gif", "jpeg", "png", "svg+xml", "webp", "x-icon"]; -+ const types = ["apng", "avif", "bmp", "gif", "jpeg", "jxl", "png", "svg+xml", "webp", "x-icon"]; - return shadow(this, "supportedTypes", types.map(type => `image/${type}`)); - } - static get supportedTypesStr() {