diff --git a/meta-chromium/conf/layer.conf b/meta-chromium/conf/layer.conf index d2de2af72..398725bbd 100644 --- a/meta-chromium/conf/layer.conf +++ b/meta-chromium/conf/layer.conf @@ -9,6 +9,6 @@ BBFILE_PATTERN_chromium-browser-layer := "^${LAYERDIR}/" BBFILE_PRIORITY_chromium-browser-layer = "7" LAYERVERSION_chromium-browser-layer = "1" -LAYERSERIES_COMPAT_chromium-browser-layer = "scarthgap styhead walnascar" +LAYERSERIES_COMPAT_chromium-browser-layer = "whinlatter" -LAYERDEPENDS_chromium-browser-layer = "clang-layer core openembedded-layer" +LAYERDEPENDS_chromium-browser-layer = "core openembedded-layer" diff --git a/meta-chromium/recipes-browser/chromium/chromium-gn.inc b/meta-chromium/recipes-browser/chromium/chromium-gn.inc index 9ef7d74fb..e89d773b1 100644 --- a/meta-chromium/recipes-browser/chromium/chromium-gn.inc +++ b/meta-chromium/recipes-browser/chromium/chromium-gn.inc @@ -22,30 +22,13 @@ SRC_URI += "\ file://0005-avoid-link-latomic-failure-on-CentOS-8-host.patch \ file://0006-Don-t-pass-unknown-LLVM-options.patch \ file://0007-Fix-constexpr-variable-must-be-initialized-by-a-cons.patch \ - file://0008-Use-the-correct-path-to-libclang_rt.builtins.a.patch \ file://0009-Adjust-the-Rust-build-to-our-needs.patch \ file://0010-Don-t-require-profiler_builtins.rlib.patch \ - file://0011-Revert-Allow-and-use-std-hardware_destructive_interf.patch \ - file://0012-Revert-Set-Rust-symbol-visibility-to-hidden-when-C-s.patch \ - file://0013-pdfium-Fix-missing-PDFiumAPIStringBufferAdapter-temp.patch \ - file://0014-Revert-Remove-libavif-based-AVIF-decoder.patch \ - file://0015-Revert-Remove-third_party-libavif.patch \ - file://0016-Disable-crabbyavif-to-fix-build-errors.patch \ - file://0017-rust-Use-adler-instead-of-adler2.patch \ - file://0018-third_party-node-update_node_binaries-Update-nodejs-.patch \ - file://0019-Reduce-minimum-browser-window-width-to-480px.patch \ - file://0020-rust-filter-out-arm-specific-flags-from-rust-compile.patch \ - file://0021-chromium-fix-v4l2-compiler-error-on-arm.patch \ + file://0011-fix-check_version-Only-compare-node.js-major-version.patch \ + file://0012-chromium-fix-v4l2-compiler-error-on-arm.patch \ + file://23d818d3c7fba4658248f17fd7b8993199242aa9.patch \ " -# Missing third_party sources. -SRC_URI += "\ - git://chromium.googlesource.com/external/github.com/AOMediaCodec/libavif;protocol=https;branch=main;name=libavif;destsuffix=third_party/libavif/src \ -" - -SRCREV_FORMAT .= "_libavif" -SRCREV_libavif = "e7b34a1f5e9f7024d08311c7bae156061b889882" - # ARM/AArch64-specific patches. SRC_URI:append:aarch64 = "${@bb.utils.contains('TUNE_FEATURES', 'crypto', '', ' file://arm/0001-Fix-AES-crypto-SIGILL-on-rpi4-64.patch', d)}" @@ -92,6 +75,7 @@ DEPENDS += " \ libwebp \ libxkbcommon \ libxslt \ + lld-native \ ninja-native \ nodejs-native \ nspr \ @@ -106,7 +90,7 @@ DEPENDS += " \ rust-native \ virtual/libgl \ " -DEPENDS:append:runtime-llvm = " compiler-rt compiler-rt-native libcxx-native" +DEPENDS:append = " compiler-rt compiler-rt-native libcxx-native" DEPENDS:append:libc-musl = " libexecinfo" LDFLAGS:append:libc-musl = " -lexecinfo" @@ -139,10 +123,10 @@ PACKAGECONFIG[use-egl] = ",,virtual/egl virtual/libgles2" # be necessary but are OK to add). PACKAGECONFIG[component-build] = "" -# Starting with M61, Chromium defaults to building with its own copy of libc++ -# instead of the system's libstdc++. Add a knob to control this behavior -# https://groups.google.com/a/chromium.org/d/msg/chromium-packagers/8aYO3me2SCE/SZ8pJXhZAwAJ -PACKAGECONFIG[custom-libcxx] = "use_custom_libcxx=true,use_custom_libcxx=false,," +# As of Chromium 138, libc++ is required unconditionally. +# https://docs.google.com/document/d/193ig0qeM23rK1yH6bW14O3zIgVztyKaY4R1XRwgmUFk/edit?usp=sharing +# Force use_custom_libcxx=true as Chromium 138+ requires libc++ +GN_ARGS += "use_custom_libcxx=true" PACKAGECONFIG[cups] = "use_cups=true,use_cups=false,cups" PACKAGECONFIG[gtk4] = "" @@ -281,6 +265,10 @@ GN_ARGS += "disable_fieldtrial_testing_config=true" # See https://crrev.com/c/2424669 GN_ARGS += "chrome_pgo_phase=0" +# Disable passing --warning-suppression-mappings= flag to clang. +# This feature is available on Clang21+ +GN_ARGS += "clang_warning_suppression_file=""" + # API keys for accessing Google services. By default, we use an invalid key # only to prevent the "you are missing an API key" infobar from being shown on # startup. @@ -297,9 +285,12 @@ GN_ARGS += ' \ ' # Use libcxx headers for native parts -BUILD_CPPFLAGS:append:runtime-llvm = " -isysroot=${STAGING_DIR_NATIVE} -stdlib=libc++" +BUILD_CPPFLAGS:append = " -isysroot=${STAGING_DIR_NATIVE} -stdlib=libc++" # Use libgcc for native parts -BUILD_LDFLAGS:append:runtime-llvm = " -rtlib=libgcc -unwindlib=libgcc -stdlib=libc++ -lc++abi -rpath ${STAGING_LIBDIR_NATIVE}" +BUILD_LDFLAGS:append = " -rtlib=libgcc -unwindlib=libgcc -stdlib=libc++ -lc++abi -rpath ${STAGING_LIBDIR_NATIVE}" +LDFLAGS:append = " --target=${TARGET_SYS}" +CXXFLAGS:append = " --target=${TARGET_SYS} -nostdlib++" +CFLAGS:append = " --target=${TARGET_SYS}" # Toolchains we will use for the build. We need to point to the toolchain file # we've created, set the right target architecture and make sure we are not @@ -367,15 +358,16 @@ ARM_VERSION:armv6 = "6" # overriding what GN wants TUNE_CCARGS:remove = "-mthumb" +# Linking rust with partitionalloc is problematic in arm32 GN_ARGS:append:arm = ' \ arm_float_abi="${ARM_FLOAT_ABI}" \ arm_fpu="${ARM_FPU}" \ arm_tune="${ARM_TUNE}" \ arm_version=${ARM_VERSION} \ + use_partition_alloc_as_malloc=false \ + enable_backup_ref_ptr_support=false \ ' -# tcmalloc's atomicops-internals-arm-v6plus.h uses the "dmb" instruction that -# is not available on (some?) ARMv6 models, which causes the build to fail. -GN_ARGS:append:armv6 = ' use_partition_alloc_as_malloc=false enable_backup_ref_ptr_support=false' + # The WebRTC code fails to build on ARMv6 when NEON is enabled. # https://bugs.chromium.org/p/webrtc/issues/detail?id=6574 GN_ARGS:append:armv6 = ' arm_use_neon=false' @@ -447,6 +439,7 @@ python do_write_toolchain_file () { toolchain_file = os.path.join(toolchain_dir, "BUILD.gn") write_toolchain_file(d, toolchain_file) } + addtask write_toolchain_file after do_patch before do_configure do_add_nodejs_symlink () { @@ -468,29 +461,39 @@ do_add_clang_latest () { # directory that is a copy of /usr/lib/clang/$CLANG_VERSION. Chromium # manually links against libclang_rt.builtins.a and uses the `clang_version` # GN variable to find it. This allows us to set it to the same value for all - # Yocto releases. + # Yocto releases. Also copy headers so bindgen can find system headers. cd "${STAGING_LIBDIR_NATIVE}/clang" rm -rf latest - # find the directory containing the library + + # Find a directory with runtime libraries and copy it as base for dir in *; do - if [ -n "$(find $dir -name 'libclang_rt.builtins*')" ] ; then + if [ -d "$dir" ] && [ -n "$(find $dir -name 'libclang_rt.builtins*' 2>/dev/null)" ]; then + echo "Copying clang directory $dir to latest (runtime libraries)" cp -r "$dir" latest break fi done + + # Find and copy headers from any versioned directory to ensure bindgen can find them + headers_copied=false + for dir in *; do + if [ -d "$dir/include" ]; then + echo "Found headers in $dir/include, copying to latest/include" + mkdir -p latest/include + cp -r "$dir/include/"* latest/include/ + headers_copied=true + break + fi + done + + if [ "$headers_copied" = false ]; then + echo "Warning: No Clang headers found in any versioned directories" + fi } addtask add_clang_latest after do_configure before do_compile do_copy_clang_library () { - # Chromium needs to link against libclang_rt.builtins.a for both host and - # target code, and expects to find both libraries in the same directory - # (thanks to 0008-Use-the-correct-path-to-libclang_rt.builtins.a.patch). - cd "${STAGING_DIR_HOST}${nonarch_libdir}/clang" - # lib_file = "./$CLANG_VERSION/lib/linux/libclang_rt.builtins-$ARCH.a" - lib_file="$(find . -name 'libclang_rt.builtins*')" - # stripped_lib_file = "lib/linux/libclang_rt.builtins-$ARCH.a" - stripped_lib_file="${lib_file#*/*/}" - cp "$lib_file" "${STAGING_LIBDIR_NATIVE}/clang/latest/${stripped_lib_file}" + cp -r ${STAGING_LIBDIR_NATIVE}/clang/latest ${STAGING_DIR_HOST}${nonarch_libdir}/clang/ } addtask copy_clang_library after do_add_clang_latest before do_compile @@ -502,15 +505,15 @@ do_copy_target_rustlibs () { } addtask copy_target_rustlibs after do_configure before do_compile -do_copy_missing_third_party_sources () { - rm -rf ${S}/third_party/libavif/src - cp -r ${UNPACKDIR}/third_party/libavif/src/ ${S}/third_party/libavif/ -} -addtask copy_missing_third_party_sources after do_patch before do_configure - do_configure() { cd ${S} python3 ./build/linux/unbundle/replace_gn_files.py --system-libraries ${GN_UNBUNDLE_LIBS} + + # Add Rust-style target triples (converted by Yocto's rust-common.bbclass) + grep -qxF "${RUST_TARGET_SYS}" ${S}/build/rust/known-target-triples.txt || echo "${RUST_TARGET_SYS}" >> ${S}/build/rust/known-target-triples.txt + grep -qxF "${RUST_HOST_SYS}" ${S}/build/rust/known-target-triples.txt || echo "${RUST_HOST_SYS}" >> ${S}/build/rust/known-target-triples.txt + grep -qxF "${RUST_BUILD_SYS}" ${S}/build/rust/known-target-triples.txt || echo "${RUST_BUILD_SYS}" >> ${S}/build/rust/known-target-triples.txt + gn gen --args='${GN_ARGS}' "${OUTPUT_DIR}" } @@ -627,4 +630,4 @@ ALLOW_EMPTY:${PN}-dev = "0" # ERROR: QA Issue: lib32-chromium-ozone-wayland: ELF binary /usr/bin/chromium has relocations in .text [textrel] INSANE_SKIP:${PN}:append:x86 = "textrel" - +INSANE_SKIP:${PN}-dbg:append = "buildpaths" diff --git a/meta-chromium/recipes-browser/chromium/chromium-ozone-wayland_136.0.7103.113.bb b/meta-chromium/recipes-browser/chromium/chromium-ozone-wayland_140.0.7339.136.bb similarity index 100% rename from meta-chromium/recipes-browser/chromium/chromium-ozone-wayland_136.0.7103.113.bb rename to meta-chromium/recipes-browser/chromium/chromium-ozone-wayland_140.0.7339.136.bb diff --git a/meta-chromium/recipes-browser/chromium/chromium-x11_136.0.7103.113.bb b/meta-chromium/recipes-browser/chromium/chromium-x11_140.0.7339.136.bb similarity index 100% rename from meta-chromium/recipes-browser/chromium/chromium-x11_136.0.7103.113.bb rename to meta-chromium/recipes-browser/chromium/chromium-x11_140.0.7339.136.bb diff --git a/meta-chromium/recipes-browser/chromium/chromium.inc b/meta-chromium/recipes-browser/chromium/chromium.inc index e2a4f585f..5cf9355a1 100644 --- a/meta-chromium/recipes-browser/chromium/chromium.inc +++ b/meta-chromium/recipes-browser/chromium/chromium.inc @@ -4,9 +4,8 @@ HOMEPAGE = "https://www.chromium.org/Home" CVE_PRODUCT = "chromium:chromium google:chrome" SRC_URI = "https://commondatastorage.googleapis.com/chromium-browser-official/chromium-${PV}.tar.xz" -SRC_URI[sha256sum] = "7c765bd13df842a28bb52279b8d711411ac6082151473e07bd70b9a482c0a0ac" - -S = "${WORKDIR}/chromium-${PV}" +SRC_URI[sha256sum] = "ffad6af711524152cd91187a0298c8a34778e0596cf8e0e379cce233aeeea1c7" +S = "${UNPACKDIR}/chromium-${PV}" # GCC is not tested or officially supported upstream, and supporting it here # requires an ever-growing amount of backports and custom patches, without any @@ -15,7 +14,7 @@ TOOLCHAIN = "clang" # By default, clang.bbclass sets TOOLCHAIN:class-native to "gcc", but we want # to build the native recipes (e.g. GN) with clang too. -TOOLCHAIN:class-native = "clang" +TOOLCHAIN_NATIVE = "clang" # This makes the target build use libc++ and compiler_rt instead of the GNU # runtime, just like upstream does. The native binaries compiled and run as @@ -70,10 +69,10 @@ LIC_FILES_CHKSUM = "\ file://${S}/base/third_party/superfasthash/LICENSE;md5=c66981f8ad23c9f279a5b9e07385128c \ file://${S}/base/third_party/symbolize/LICENSE;md5=17ae3b22fe8fa438966625593e2eea85 \ file://${S}/base/third_party/xdg_user_dirs/LICENSE;md5=d998f250c491c329a8254dd1ca62c647 \ - file://${S}/chrome/browser/resources/chromeos/accessibility/chromevox/mv2/third_party/tamachiyomi/LICENSE;md5=15772cfcf7016e701ce54554516c0688 \ + file://${S}/chrome/browser/resources/chromeos/accessibility/chromevox/mv2/background/third_party/tamachiyomi/LICENSE;md5=15772cfcf7016e701ce54554516c0688 \ + file://${S}/chrome/browser/resources/chromeos/accessibility/chromevox/mv3/third_party/tamachiyomi/LICENSE;md5=15772cfcf7016e701ce54554516c0688 \ file://${S}/chrome/installer/mac/third_party/bsdiff/LICENSE;md5=0dbe7a50f028269750631fcbded3846a \ file://${S}/chrome/installer/mac/third_party/xz/LICENSE;md5=84982e6bf3ed99ef2647e48626ffa984 \ - file://${S}/chrome/third_party/mozilla_security_manager/LICENSE;md5=0c259b853bbf067b361100ce560adce7 \ file://${S}/ios/third_party/blink/LICENSE;md5=9fdb47308c4e0a2b6d07c5af39e5da1a \ file://${S}/ios/third_party/lottie/LICENSE;md5=1e714768add1e7fdb1288bac703bad06 \ file://${S}/ios/third_party/material_components_ios/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ @@ -84,81 +83,89 @@ LIC_FILES_CHKSUM = "\ file://${S}/ios/third_party/motion_animator_objc/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ file://${S}/ios/third_party/motion_interchange_objc/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ file://${S}/ios/third_party/motion_transitioning_objc/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ - file://${S}/native_client_sdk/src/libraries/third_party/newlib-extras/README;md5=e944d73ca3817b7ca8656eafb9497fed \ file://${S}/net/third_party/mozilla_security_manager/LICENSE;md5=f19cdef64a433efe7fd2ddbfc3a19313 \ file://${S}/net/third_party/mozilla_win/LICENSE;md5=9b13a17f35cae227ee726ee0108d72a2 \ file://${S}/net/third_party/nss/LICENSE;md5=3b1e88e1b9c0b5a4b2881d46cce06a18 \ file://${S}/net/third_party/quiche/src/LICENSE;md5=0fca02217a5d49a14dfe2d11837bb34d \ file://${S}/net/third_party/uri_template/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ file://${S}/third_party/abseil-cpp/LICENSE;md5=df52c6edb7adc22e533b2bacc3bd3915 \ - file://${S}/third_party/android_deps/autorolled/committed/libs/com_google_android_gms_play_services_auth/LICENSE;md5=e207fc5a134660990a7068d5a02c7ea8 \ - file://${S}/third_party/android_deps/autorolled/committed/libs/com_google_android_gms_play_services_auth_api_phone/LICENSE;md5=e5a8d882f7945961271786002e6a581d \ - file://${S}/third_party/android_deps/autorolled/committed/libs/com_google_android_gms_play_services_auth_base/LICENSE;md5=8b3fee5c5451b70decc3ea70f7bc0024 \ + file://${S}/third_party/android_deps/autorolled/committed/libs/com_airbnb_android_lottie/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ + file://${S}/third_party/android_deps/autorolled/committed/libs/com_google_android_annotations/LICENSE;md5=7f7d74108ee1b7a743cca7d9a86784d6 \ + file://${S}/third_party/android_deps/autorolled/committed/libs/com_google_android_datatransport_transport_api/LICENSE;md5=7f7d74108ee1b7a743cca7d9a86784d6 \ + file://${S}/third_party/android_deps/autorolled/committed/libs/com_google_android_datatransport_transport_backend_cct/LICENSE;md5=7f7d74108ee1b7a743cca7d9a86784d6 \ + file://${S}/third_party/android_deps/autorolled/committed/libs/com_google_android_datatransport_transport_runtime/LICENSE;md5=54d2f6e66dae1f9e4dbf3cb3cc197631 \ + file://${S}/third_party/android_deps/autorolled/committed/libs/com_google_android_gms_play_services_auth/LICENSE;md5=68476e84daf08f8d88e5f7ed3ee564ee \ + file://${S}/third_party/android_deps/autorolled/committed/libs/com_google_android_gms_play_services_auth_api_phone/LICENSE;md5=4a37c94d22ef29d62102bef4fc7bd8b0 \ + file://${S}/third_party/android_deps/autorolled/committed/libs/com_google_android_gms_play_services_auth_base/LICENSE;md5=2d079629e67764fecf32498ca7ff8f96 \ file://${S}/third_party/android_deps/autorolled/committed/libs/com_google_android_gms_play_services_auth_blockstore/LICENSE;md5=fff98c651a1ae8a04462a12f8ea1f7a4 \ - file://${S}/third_party/android_deps/autorolled/committed/libs/com_google_android_gms_play_services_base/LICENSE;md5=e5a8d882f7945961271786002e6a581d \ + file://${S}/third_party/android_deps/autorolled/committed/libs/com_google_android_gms_play_services_base/LICENSE;md5=4a37c94d22ef29d62102bef4fc7bd8b0 \ file://${S}/third_party/android_deps/autorolled/committed/libs/com_google_android_gms_play_services_basement/LICENSE;md5=4a37c94d22ef29d62102bef4fc7bd8b0 \ - file://${S}/third_party/android_deps/autorolled/committed/libs/com_google_android_gms_play_services_fido/LICENSE;md5=ff76e1f91bd64c4593743be9d83a4c5f \ + file://${S}/third_party/android_deps/autorolled/committed/libs/com_google_android_gms_play_services_cast/LICENSE;md5=57bc9b01373a90210affff003e590c19 \ + file://${S}/third_party/android_deps/autorolled/committed/libs/com_google_android_gms_play_services_cast_framework/LICENSE;md5=6e5955fc74e2abf3e5ca0bcb3878f837 \ + file://${S}/third_party/android_deps/autorolled/committed/libs/com_google_android_gms_play_services_clearcut/LICENSE;md5=32c019d8c1f8222a8aad9c3e1f1d2d10 \ + file://${S}/third_party/android_deps/autorolled/committed/libs/com_google_android_gms_play_services_cloud_messaging/LICENSE;md5=fff98c651a1ae8a04462a12f8ea1f7a4 \ + file://${S}/third_party/android_deps/autorolled/committed/libs/com_google_android_gms_play_services_fido/LICENSE;md5=0b31499076a79957f503e7861250586c \ + file://${S}/third_party/android_deps/autorolled/committed/libs/com_google_android_gms_play_services_flags/LICENSE;md5=5c9317538bd492b4fd01eec9d6972640 \ + file://${S}/third_party/android_deps/autorolled/committed/libs/com_google_android_gms_play_services_gcm/LICENSE;md5=92b728c587a67a1b9577e9ca141ca520 \ file://${S}/third_party/android_deps/autorolled/committed/libs/com_google_android_gms_play_services_identity_credentials/LICENSE;md5=4a37c94d22ef29d62102bef4fc7bd8b0 \ - file://${S}/third_party/android_deps/autorolled/committed/libs/com_google_android_gms_play_services_tasks/LICENSE;md5=e5a8d882f7945961271786002e6a581d \ + file://${S}/third_party/android_deps/autorolled/committed/libs/com_google_android_gms_play_services_iid/LICENSE;md5=05fc50851d6d550ef2bb400b326353f0 \ + file://${S}/third_party/android_deps/autorolled/committed/libs/com_google_android_gms_play_services_instantapps/LICENSE;md5=44b3e1cb996ad75b025cf78e53ba7d42 \ + file://${S}/third_party/android_deps/autorolled/committed/libs/com_google_android_gms_play_services_location/LICENSE;md5=18ad89b4a01838496ae844c2b9bd2a7f \ + file://${S}/third_party/android_deps/autorolled/committed/libs/com_google_android_gms_play_services_phenotype/LICENSE;md5=32c019d8c1f8222a8aad9c3e1f1d2d10 \ + file://${S}/third_party/android_deps/autorolled/committed/libs/com_google_android_gms_play_services_stats/LICENSE;md5=5c9317538bd492b4fd01eec9d6972640 \ + file://${S}/third_party/android_deps/autorolled/committed/libs/com_google_android_gms_play_services_tasks/LICENSE;md5=4a37c94d22ef29d62102bef4fc7bd8b0 \ + file://${S}/third_party/android_deps/autorolled/committed/libs/com_google_android_gms_play_services_vision/LICENSE;md5=d332b0f8bf5e67cef70541572ba69b61 \ + file://${S}/third_party/android_deps/autorolled/committed/libs/com_google_android_gms_play_services_vision_common/LICENSE;md5=d332b0f8bf5e67cef70541572ba69b61 \ file://${S}/third_party/android_deps/autorolled/committed/libs/com_google_android_libraries_identity_googleid_googleid/LICENSE;md5=498e555b4ebef5399d944fb662c61913 \ + file://${S}/third_party/android_deps/autorolled/committed/libs/com_google_android_material_material/LICENSE;md5=7f7d74108ee1b7a743cca7d9a86784d6 \ + file://${S}/third_party/android_deps/autorolled/committed/libs/com_google_android_play_core_common/LICENSE;md5=73c6700ef062ad41c3d27cab65d0c1e2 \ + file://${S}/third_party/android_deps/autorolled/committed/libs/com_google_android_play_feature_delivery/LICENSE;md5=014a1ef6f09b1a5ac887d86d5f18918d \ file://${S}/third_party/android_deps/autorolled/committed/libs/com_google_auto_service_auto_service_annotations/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ file://${S}/third_party/android_deps/autorolled/committed/libs/com_google_code_findbugs_jsr305/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ + file://${S}/third_party/android_deps/autorolled/committed/libs/com_google_code_gson_gson/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ file://${S}/third_party/android_deps/autorolled/committed/libs/com_google_errorprone_error_prone_annotations/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ + file://${S}/third_party/android_deps/autorolled/committed/libs/com_google_firebase_firebase_annotations/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ + file://${S}/third_party/android_deps/autorolled/committed/libs/com_google_firebase_firebase_common/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ + file://${S}/third_party/android_deps/autorolled/committed/libs/com_google_firebase_firebase_components/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ + file://${S}/third_party/android_deps/autorolled/committed/libs/com_google_firebase_firebase_datatransport/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ + file://${S}/third_party/android_deps/autorolled/committed/libs/com_google_firebase_firebase_encoders/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ + file://${S}/third_party/android_deps/autorolled/committed/libs/com_google_firebase_firebase_encoders_json/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ + file://${S}/third_party/android_deps/autorolled/committed/libs/com_google_firebase_firebase_encoders_proto/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ + file://${S}/third_party/android_deps/autorolled/committed/libs/com_google_firebase_firebase_iid_interop/LICENSE;md5=5c9317538bd492b4fd01eec9d6972640 \ + file://${S}/third_party/android_deps/autorolled/committed/libs/com_google_firebase_firebase_installations/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ + file://${S}/third_party/android_deps/autorolled/committed/libs/com_google_firebase_firebase_installations_interop/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ + file://${S}/third_party/android_deps/autorolled/committed/libs/com_google_firebase_firebase_measurement_connector/LICENSE;md5=b295cf94bd95a54486e200c450b9c181 \ + file://${S}/third_party/android_deps/autorolled/committed/libs/com_google_firebase_firebase_messaging/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ file://${S}/third_party/android_deps/autorolled/committed/libs/com_google_guava_failureaccess/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ + file://${S}/third_party/android_deps/autorolled/committed/libs/com_google_guava_guava/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ file://${S}/third_party/android_deps/autorolled/committed/libs/com_google_j2objc_j2objc_annotations/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ + file://${S}/third_party/android_deps/autorolled/committed/libs/com_google_protobuf_protobuf_javalite/LICENSE;md5=37b5762e07f0af8c74ce80a8bda4266b \ file://${S}/third_party/android_deps/autorolled/committed/libs/com_squareup_okio_okio_jvm/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ + file://${S}/third_party/android_deps/autorolled/committed/libs/io_grpc_grpc_api/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ + file://${S}/third_party/android_deps/autorolled/committed/libs/io_grpc_grpc_binder/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ + file://${S}/third_party/android_deps/autorolled/committed/libs/io_grpc_grpc_context/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ + file://${S}/third_party/android_deps/autorolled/committed/libs/io_grpc_grpc_core/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ + file://${S}/third_party/android_deps/autorolled/committed/libs/io_grpc_grpc_protobuf_lite/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ + file://${S}/third_party/android_deps/autorolled/committed/libs/io_grpc_grpc_stub/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ + file://${S}/third_party/android_deps/autorolled/committed/libs/io_perfmark_perfmark_api/LICENSE;md5=86d3f3a95c324c9479bd8986968f4327 \ + file://${S}/third_party/android_deps/autorolled/committed/libs/io_reactivex_rxjava2_rxandroid/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ + file://${S}/third_party/android_deps/autorolled/committed/libs/io_reactivex_rxjava2_rxjava/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ file://${S}/third_party/android_deps/autorolled/committed/libs/javax_inject_javax_inject/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ - file://${S}/third_party/android_deps/autorolled/committed/libs/org_checkerframework_checker_qual/LICENSE;md5=f32f668c1f4eea36fb53fc4cc7d96385 \ + file://${S}/third_party/android_deps/autorolled/committed/libs/org_checkerframework_checker_qual/LICENSE;md5=1d65227af566d55e64b49bc738d16053 \ + file://${S}/third_party/android_deps/autorolled/committed/libs/org_checkerframework_checker_util/LICENSE;md5=87abbc18e66acb445c00810347051776 \ + file://${S}/third_party/android_deps/autorolled/committed/libs/org_codehaus_mojo_animal_sniffer_annotations/LICENSE;md5=a5dd953e661e22a77f7b8062ae790f6a \ file://${S}/third_party/android_deps/autorolled/committed/libs/org_jetbrains_kotlinx_kotlinx_coroutines_android/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ file://${S}/third_party/android_deps/autorolled/committed/libs/org_jetbrains_kotlinx_kotlinx_coroutines_core_jvm/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ + file://${S}/third_party/android_deps/autorolled/committed/libs/org_jetbrains_kotlinx_kotlinx_coroutines_play_services/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ file://${S}/third_party/android_deps/autorolled/committed/libs/org_jetbrains_kotlinx_kotlinx_serialization_core_jvm/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ file://${S}/third_party/android_deps/autorolled/committed/libs/org_jspecify_jspecify/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ + file://${S}/third_party/android_deps/autorolled/committed/libs/org_reactivestreams_reactive_streams/LICENSE;md5=e58c24d18490515b4c3001f330261afc \ file://${S}/third_party/android_deps/libs/com_android_support_support_annotations/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ - file://${S}/third_party/android_deps/libs/com_google_android_datatransport_transport_api/LICENSE;md5=7f7d74108ee1b7a743cca7d9a86784d6 \ - file://${S}/third_party/android_deps/libs/com_google_android_datatransport_transport_backend_cct/LICENSE;md5=7f7d74108ee1b7a743cca7d9a86784d6 \ - file://${S}/third_party/android_deps/libs/com_google_android_datatransport_transport_runtime/LICENSE;md5=54d2f6e66dae1f9e4dbf3cb3cc197631 \ - file://${S}/third_party/android_deps/libs/com_google_android_gms_play_services_cast/LICENSE;md5=d4ace05266b66c1c0ccdeba11bbe745e \ - file://${S}/third_party/android_deps/libs/com_google_android_gms_play_services_cast_framework/LICENSE;md5=98aafe35230de6fc18e977f2feda5671 \ - file://${S}/third_party/android_deps/libs/com_google_android_gms_play_services_clearcut/LICENSE;md5=32c019d8c1f8222a8aad9c3e1f1d2d10 \ - file://${S}/third_party/android_deps/libs/com_google_android_gms_play_services_cloud_messaging/LICENSE;md5=fff98c651a1ae8a04462a12f8ea1f7a4 \ - file://${S}/third_party/android_deps/libs/com_google_android_gms_play_services_flags/LICENSE;md5=5c9317538bd492b4fd01eec9d6972640 \ - file://${S}/third_party/android_deps/libs/com_google_android_gms_play_services_gcm/LICENSE;md5=92b728c587a67a1b9577e9ca141ca520 \ - file://${S}/third_party/android_deps/libs/com_google_android_gms_play_services_iid/LICENSE;md5=05fc50851d6d550ef2bb400b326353f0 \ - file://${S}/third_party/android_deps/libs/com_google_android_gms_play_services_instantapps/LICENSE;md5=cd033bdb088af16ecdbcd95bd5562a30 \ - file://${S}/third_party/android_deps/libs/com_google_android_gms_play_services_location/LICENSE;md5=18ad89b4a01838496ae844c2b9bd2a7f \ - file://${S}/third_party/android_deps/libs/com_google_android_gms_play_services_phenotype/LICENSE;md5=32c019d8c1f8222a8aad9c3e1f1d2d10 \ - file://${S}/third_party/android_deps/libs/com_google_android_gms_play_services_stats/LICENSE;md5=5c9317538bd492b4fd01eec9d6972640 \ - file://${S}/third_party/android_deps/libs/com_google_android_gms_play_services_vision/LICENSE;md5=d332b0f8bf5e67cef70541572ba69b61 \ - file://${S}/third_party/android_deps/libs/com_google_android_gms_play_services_vision_common/LICENSE;md5=d332b0f8bf5e67cef70541572ba69b61 \ - file://${S}/third_party/android_deps/libs/com_google_android_material_material/LICENSE;md5=7f7d74108ee1b7a743cca7d9a86784d6 \ - file://${S}/third_party/android_deps/libs/com_google_android_play_core_common/LICENSE;md5=73c6700ef062ad41c3d27cab65d0c1e2 \ - file://${S}/third_party/android_deps/libs/com_google_android_play_feature_delivery/LICENSE;md5=014a1ef6f09b1a5ac887d86d5f18918d \ file://${S}/third_party/android_deps/libs/com_google_ar_impress/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ - file://${S}/third_party/android_deps/libs/com_google_dagger_dagger/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ - file://${S}/third_party/android_deps/libs/com_google_firebase_firebase_annotations/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ - file://${S}/third_party/android_deps/libs/com_google_firebase_firebase_common/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ - file://${S}/third_party/android_deps/libs/com_google_firebase_firebase_common_ktx/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ - file://${S}/third_party/android_deps/libs/com_google_firebase_firebase_components/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ - file://${S}/third_party/android_deps/libs/com_google_firebase_firebase_datatransport/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ - file://${S}/third_party/android_deps/libs/com_google_firebase_firebase_encoders/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ - file://${S}/third_party/android_deps/libs/com_google_firebase_firebase_encoders_json/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ - file://${S}/third_party/android_deps/libs/com_google_firebase_firebase_encoders_proto/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ - file://${S}/third_party/android_deps/libs/com_google_firebase_firebase_iid/LICENSE;md5=57214b126e4e648c9066e6e23d43be77 \ - file://${S}/third_party/android_deps/libs/com_google_firebase_firebase_iid_interop/LICENSE;md5=5c9317538bd492b4fd01eec9d6972640 \ - file://${S}/third_party/android_deps/libs/com_google_firebase_firebase_installations/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ - file://${S}/third_party/android_deps/libs/com_google_firebase_firebase_installations_interop/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ - file://${S}/third_party/android_deps/libs/com_google_firebase_firebase_measurement_connector/LICENSE;md5=298bd2a9dc20becb6693cfdccd58001a \ - file://${S}/third_party/android_deps/libs/com_google_firebase_firebase_messaging/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ - file://${S}/third_party/android_deps/libs/com_google_guava_guava_android/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ - file://${S}/third_party/android_deps/libs/com_google_protobuf_protobuf_javalite/LICENSE;md5=37b5762e07f0af8c74ce80a8bda4266b \ - file://${S}/third_party/android_deps/libs/jakarta_inject_jakarta_inject_api/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ - file://${S}/third_party/android_deps/libs/org_checkerframework_checker_util/LICENSE;md5=87abbc18e66acb445c00810347051776 \ - file://${S}/third_party/android_deps/libs/org_codehaus_mojo_animal_sniffer_annotations/LICENSE;md5=a5dd953e661e22a77f7b8062ae790f6a \ file://${S}/third_party/android_deps/libs/org_jetbrains_kotlin_kotlin_android_extensions_runtime/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ file://${S}/third_party/android_deps/libs/org_jetbrains_kotlin_kotlin_parcelize_runtime/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ file://${S}/third_party/android_deps/libs/org_jetbrains_kotlinx_atomicfu_jvm/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ file://${S}/third_party/android_deps/libs/org_jetbrains_kotlinx_kotlinx_coroutines_guava/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ - file://${S}/third_party/android_deps/libs/org_jetbrains_kotlinx_kotlinx_coroutines_play_services/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ file://${S}/third_party/android_media/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ file://${S}/third_party/android_opengl/LICENSE;md5=d10e92761a860d4113a7a525c78daf13 \ file://${S}/third_party/android_provider/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ @@ -220,6 +227,10 @@ LIC_FILES_CHKSUM = "\ file://${S}/third_party/androidx/committed/libs/androidx_datastore_datastore_android/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ file://${S}/third_party/androidx/committed/libs/androidx_datastore_datastore_core_android/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ file://${S}/third_party/androidx/committed/libs/androidx_datastore_datastore_core_okio_jvm/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ + file://${S}/third_party/androidx/committed/libs/androidx_datastore_datastore_preferences_android/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ + file://${S}/third_party/androidx/committed/libs/androidx_datastore_datastore_preferences_core_android/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ + file://${S}/third_party/androidx/committed/libs/androidx_datastore_datastore_preferences_external_protobuf/LICENSE;md5=37b5762e07f0af8c74ce80a8bda4266b \ + file://${S}/third_party/androidx/committed/libs/androidx_datastore_datastore_preferences_proto/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ file://${S}/third_party/androidx/committed/libs/androidx_documentfile_documentfile/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ file://${S}/third_party/androidx/committed/libs/androidx_drawerlayout_drawerlayout/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ file://${S}/third_party/androidx/committed/libs/androidx_dynamicanimation_dynamicanimation/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ @@ -245,6 +256,7 @@ LIC_FILES_CHKSUM = "\ file://${S}/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_livedata/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ file://${S}/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_livedata_core/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ file://${S}/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_livedata_core_ktx/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ + file://${S}/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_livedata_ktx/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ file://${S}/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_process/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ file://${S}/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_runtime_android/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ file://${S}/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_runtime_compose_android/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ @@ -271,6 +283,12 @@ LIC_FILES_CHKSUM = "\ file://${S}/third_party/androidx/committed/libs/androidx_navigation_navigation_common_android/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ file://${S}/third_party/androidx/committed/libs/androidx_navigation_navigation_compose_android/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ file://${S}/third_party/androidx/committed/libs/androidx_navigation_navigation_runtime_android/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ + file://${S}/third_party/androidx/committed/libs/androidx_navigationevent_navigationevent_android/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ + file://${S}/third_party/androidx/committed/libs/androidx_navigationevent_navigationevent_compose_android/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ + file://${S}/third_party/androidx/committed/libs/androidx_paging_paging_common_android/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ + file://${S}/third_party/androidx/committed/libs/androidx_paging_paging_common_ktx/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ + file://${S}/third_party/androidx/committed/libs/androidx_paging_paging_compose_android/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ + file://${S}/third_party/androidx/committed/libs/androidx_paging_paging_runtime/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ file://${S}/third_party/androidx/committed/libs/androidx_palette_palette/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ file://${S}/third_party/androidx/committed/libs/androidx_pdf_pdf_document_service/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ file://${S}/third_party/androidx/committed/libs/androidx_pdf_pdf_viewer/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ @@ -316,6 +334,7 @@ LIC_FILES_CHKSUM = "\ file://${S}/third_party/angle/src/third_party/libXNVCtrl/LICENSE;md5=9e6c209899aa4986d090320bbca2fc76 \ file://${S}/third_party/angle/src/third_party/volk/LICENSE.md;md5=af213f738e88117b90238ef76ad25ae6 \ file://${S}/third_party/angle/third_party/flatbuffers/LICENSE;md5=a873c5645c184d51e0f9b34e1d7cf559 \ + file://${S}/third_party/angle/third_party/re2/LICENSE;md5=3b5c31eb512bdf3cb11ffd5713963760 \ file://${S}/third_party/angle/third_party/spirv-headers/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ file://${S}/third_party/angle/third_party/spirv-tools/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ file://${S}/third_party/angle/third_party/vulkan-headers/LICENSE.txt;md5=3b83ef96387f14655fc854ddc3c6bd57 \ @@ -325,12 +344,11 @@ LIC_FILES_CHKSUM = "\ file://${S}/third_party/arcore-android-sdk/LICENSE;md5=c1bc4f7fbdd7a5a3f2c0dfefd457665e \ file://${S}/third_party/ashmem/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ file://${S}/third_party/axe-core/LICENSE;md5=f27a50d2e878867827842f2c60e30bfc \ - file://${S}/third_party/beto-core/LICENSE;md5=2b42edef8fa55315f34f2370b4715ca9 \ file://${S}/third_party/bidimapper/LICENSE;md5=2b42edef8fa55315f34f2370b4715ca9 \ file://${S}/third_party/bidimapper/licenses/LICENSE.mitt;md5=4ed316158806c1e39b6b6e457c85b10f \ - file://${S}/third_party/bidimapper/licenses/LICENSE.zod;md5=7aa01d261c2ac4ca667875e22474c798 \ + file://${S}/third_party/bidimapper/licenses/LICENSE.zod;md5=f42ef978174c95f1075ac280e6659583 \ file://${S}/third_party/blink/LICENSE_FOR_ABOUT_CREDITS;md5=11e90d553b211de885f245900c4ccf89 \ - file://${S}/third_party/boringssl/src/LICENSE;md5=bfca80950e49496c340e3327990eb7e7 \ + file://${S}/third_party/boringssl/src/LICENSE;md5=0131a611be3a37729f61e0b26319da57 \ file://${S}/third_party/boringssl/src/third_party/fiat/LICENSE;md5=7a7086e01a29257a15f3b0c9a42a12ff \ file://${S}/third_party/brotli/LICENSE;md5=941ee9cd1609382f946352712a319b4b \ file://${S}/third_party/bspatch/LICENSE;md5=3e837ede9697ce4c789c3ca32aabe003 \ @@ -349,6 +367,7 @@ LIC_FILES_CHKSUM = "\ file://${S}/third_party/catapult/third_party/idna/LICENSE.rst;md5=782775b32f96098512e283fb5d4546cd \ file://${S}/third_party/catapult/third_party/ijson/LICENSE.txt;md5=2809bd5857eee6be054555222fd89712 \ file://${S}/third_party/catapult/third_party/jquery/LICENSE.txt;md5=18d9b3a646e7608b8951c4f6aa1bbf25 \ + file://${S}/third_party/catapult/third_party/jszip/LICENSE.markdown;md5=a90157b1fcb598898b3b75dc56a0c770 \ file://${S}/third_party/catapult/third_party/mapreduce/LICENSE;md5=175792518e4ac015ab6696d16c4f607e \ file://${S}/third_party/catapult/third_party/pipeline/LICENSE;md5=8f7bb094c7232b058c7e9f2e431f389c \ file://${S}/third_party/catapult/third_party/polymer/LICENSE.polymer;md5=324f45ce459ffd97e41d175a4e95a4be \ @@ -366,11 +385,11 @@ LIC_FILES_CHKSUM = "\ file://${S}/third_party/catapult/third_party/webapp2/LICENSE;md5=40b32c2af961e8ca20e66cdea65bcb36 \ file://${S}/third_party/catapult/third_party/webtest/license.rst;md5=64f013a9d7a2a8ffc8d016a2d4214bcd \ file://${S}/third_party/catapult/tracing/third_party/jpeg-js/LICENSE;md5=11ed819ab28c14377693b9c990511293 \ + file://${S}/third_party/catapult/tracing/third_party/jszip/LICENSE.markdown;md5=a90157b1fcb598898b3b75dc56a0c770 \ file://${S}/third_party/catapult/tracing/third_party/oboe/LICENCE;md5=a50188ab5dc0b5b3963791e0c5f43c6b \ file://${S}/third_party/catapult/tracing/third_party/pako/LICENSE;md5=a4f08d6b2d1bf3f3a1bc296a6109a25b \ file://${S}/third_party/ced/LICENSE;md5=175792518e4ac015ab6696d16c4f607e \ file://${S}/third_party/chromevox/LICENSE;md5=45739090b454125d851ac7bb1bbd23a2 \ - file://${S}/third_party/chromevox/third_party/closure-library/LICENSE;md5=e23fadd6ceef8c618fc1c65191d846fa \ file://${S}/third_party/chromevox/third_party/sre/LICENSE;md5=2ee41112a44fe7014dce33e26468ba93 \ file://${S}/third_party/cld_3/LICENSE;md5=d8b32ba83f8b11e4badd979f4319e706 \ file://${S}/third_party/cldr/LICENSE;md5=fe2500bb52e825476d4b93d6f1458232 \ @@ -411,25 +430,27 @@ LIC_FILES_CHKSUM = "\ file://${S}/third_party/devtools-frontend/src/front_end/third_party/puppeteer/third_party/mitt/LICENSE;md5=dd3fad292d640766ce5bcb6cb97c109e \ file://${S}/third_party/devtools-frontend/src/front_end/third_party/puppeteer/third_party/parsel/LICENSE;md5=3df37ae2a2559e34c226b7734e5a1d08 \ file://${S}/third_party/devtools-frontend/src/front_end/third_party/puppeteer/third_party/rxjs/LICENSE;md5=ddcbb07c54c85eff62e3e6ebab2fa6dd \ + file://${S}/third_party/devtools-frontend/src/front_end/third_party/source-map-scopes-codec/LICENSE;md5=b1af585df834f3dc605fa479379b01d3 \ file://${S}/third_party/devtools-frontend/src/front_end/third_party/third-party-web/LICENSE;md5=fdc2dc205eb6e6da8e9d1add67084a96 \ file://${S}/third_party/devtools-frontend/src/front_end/third_party/wasmparser/package/LICENSE;md5=2ee41112a44fe7014dce33e26468ba93 \ file://${S}/third_party/devtools-frontend/src/front_end/third_party/web-vitals/package/LICENSE;md5=2c4a96430ec4639e0a80babbfb239a96 \ - file://${S}/third_party/distributed_point_functions/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ file://${S}/third_party/dom_distiller_js/LICENSE;md5=6cd778870ce5c0c08c8e16fbdf378532 \ + file://${S}/third_party/dragonbox/src/LICENSE-Apache2-LLVM;md5=2e982d844baa4df1c80de75470e0c5cb \ + file://${S}/third_party/dragonbox/src/LICENSE-Boost;md5=e4224ccaecb14d942c71d31bef20d78c \ file://${S}/third_party/eigen3/LICENSE;md5=48a3fe23ed1353e0995dadfda05ffdb6 \ file://${S}/third_party/emoji-metadata/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ file://${S}/third_party/emoji-segmenter/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ - file://${S}/third_party/expat/src/expat/COPYING;md5=7b3b078238d0901d3b339289117cb7fb \ + file://${S}/third_party/expat/src/expat/COPYING;md5=f4fedd6116da0e171f7cb4d2923d7ac2 \ file://${S}/third_party/farmhash/LICENSE;md5=7dfaa79e2b070897e495fec386e3acfc \ file://${S}/third_party/fast_float/src/LICENSE-MIT;md5=32b11d50c7d9788d4270f6a83f3e68eb \ file://${S}/third_party/fdlibm/LICENSE;md5=b17367d6c97e638599071d99a3049dfe \ - file://${S}/third_party/ffmpeg/CREDITS.chromium;md5=a0156e1de86eb34eb5d75486b539aa58 \ + file://${S}/third_party/ffmpeg/CREDITS.chromium;md5=331b973a7612318cb2a0e01629ca7e52 \ file://${S}/third_party/fft2d/LICENSE;md5=a062f975da2ca26745be122d5a0b1356 \ file://${S}/third_party/flac/COPYING.Xiph;md5=3d6da238b5b57a0965d6730291119f65 \ file://${S}/third_party/flatbuffers/LICENSE;md5=a873c5645c184d51e0f9b34e1d7cf559 \ file://${S}/third_party/fontconfig/src/COPYING;md5=00252fd272bf2e722925613ad74cb6c7 \ file://${S}/third_party/fp16/LICENSE;md5=855dd24c28c76c916c5c2301b1958728 \ - file://${S}/third_party/freetype/src/docs/FTL.TXT;md5=9f37b4e6afa3fef9dba8932b16bd3f97 \ + file://${S}/third_party/freetype/src/docs/FTL.TXT;md5=72d844cd2f3bcaf6a85244b508032be7 \ file://${S}/third_party/fuchsia-gn-sdk/LICENSE;md5=4c8b7c5e9d0a48795db3dcd70f738ea5 \ file://${S}/third_party/fusejs/LICENSE;md5=f61de6d0d3d200550e44d63cc2a4fb67 \ file://${S}/third_party/fxdiv/src/LICENSE;md5=0c2eed7ba400a6fea8fec2a582b177e8 \ @@ -453,7 +474,6 @@ LIC_FILES_CHKSUM = "\ file://${S}/third_party/isimpledom/LICENSE;md5=822502c0e010ccdbb6a3e681dd47888e \ file://${S}/third_party/jni_zero/LICENSE;md5=70dc659673a50c63e07b2287222230e6 \ file://${S}/third_party/jsoncpp/LICENSE;md5=c56ee55c03a55f8105b969d8270632ce \ - file://${S}/third_party/jszip/LICENSE;md5=401d270383d75b05d76fc13fc1750765 \ file://${S}/third_party/khronos/LICENSE;md5=1d2ef853a9ae7ace4e16fda0d48f597b \ file://${S}/third_party/lens_server_proto/LICENSE;md5=57b69a83c4a9b2401aa4de147cb22bd4 \ file://${S}/third_party/leveldatabase/src/LICENSE;md5=92d1b128950b11ba8495b64938fc164d \ @@ -488,7 +508,7 @@ LIC_FILES_CHKSUM = "\ file://${S}/third_party/libwebp/src/PATENTS;md5=c6926d0cb07d296f886ab6e0cc5a85b7 \ file://${S}/third_party/libx11/LICENSE;md5=28a27b3e1a66e95206d5645b787dad69 \ file://${S}/third_party/libxcb-keysyms/LICENSE;md5=5b0382211c6a98f8e4861daa0f3f4322 \ - file://${S}/third_party/libxml/src/Copyright;md5=f437ed9058e8e5135e47c01e973376ba \ + file://${S}/third_party/libxml/src/Copyright;md5=5873615e8a9ecbf5c8857c4312ee05d6 \ file://${S}/third_party/libxslt/src/Copyright;md5=0cd9a07afbeb24026c9b03aecfeba458 \ file://${S}/third_party/libyuv/LICENSE;md5=464282cfb405b005b9637f11103a7325 \ file://${S}/third_party/libzip/LICENSE;md5=6bb2408fd544544b86946e67ec2da9a0 \ @@ -501,10 +521,10 @@ LIC_FILES_CHKSUM = "\ file://${S}/third_party/material_design_icons/LICENSE;md5=175792518e4ac015ab6696d16c4f607e \ file://${S}/third_party/material_web_components/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ file://${S}/third_party/mediapipe/LICENSE;md5=87a30e5cfa12d1ab9ada4fb6f3feed4b \ - file://${S}/third_party/mesa_headers/LICENSE;md5=072744090020e72ad7387e201873fe43 \ file://${S}/third_party/metrics_proto/LICENSE;md5=cfaf8febfe7b4f3e07a08dd4d0db1914 \ file://${S}/third_party/microsoft_webauthn/LICENSE;md5=b98fddd052bb2f5ddbcdbd417ffb26a8 \ file://${S}/third_party/minigbm/LICENSE;md5=fcd558ab2fd7f53408826e80eb0c11eb \ + file://${S}/third_party/ml_dtypes/src/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ file://${S}/third_party/modp_b64/LICENSE;md5=eb7e2e0af1d4971360553aedadee8d86 \ file://${S}/third_party/nearby/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ file://${S}/third_party/neon_2_sse/LICENSE;md5=53abad1ded16f44100126962f4bbef6c \ @@ -517,7 +537,7 @@ LIC_FILES_CHKSUM = "\ file://${S}/third_party/openscreen/src/LICENSE;md5=5ff965dafeb8e99de6698664decb9e89 \ file://${S}/third_party/openscreen/src/third_party/protobuf/LICENSE;md5=37b5762e07f0af8c74ce80a8bda4266b \ file://${S}/third_party/openscreen/src/third_party/tinycbor/src/LICENSE;md5=6c1ac30774dd6476b42b5b020cd2aa5f \ - file://${S}/third_party/opus/src/COPYING;md5=e304cdf74c2a1b0a33a5084c128a23a3 \ + file://${S}/third_party/opus/src/COPYING;md5=4b365c2155d66e550e1447075d6744a5 \ file://${S}/third_party/ots/LICENSE;md5=e06eff2aa65b917034a81599bea73dc4 \ file://${S}/third_party/pdfium/LICENSE;md5=c93507531cc9bb8e24a05f2a1a4036c7 \ file://${S}/third_party/pdfium/third_party/agg23/copying;md5=d501f87982fe576fa1bfdf4f0ae741af \ @@ -527,7 +547,7 @@ LIC_FILES_CHKSUM = "\ file://${S}/third_party/pdfium/third_party/lcms/LICENSE;md5=e9ce323c4b71c943a785db90142b228a \ file://${S}/third_party/pdfium/third_party/libopenjpeg/LICENSE;md5=c648878b4840d7babaade1303e7f108c \ file://${S}/third_party/pdfium/third_party/libtiff/LICENSE.md;md5=a3e32d664d6db1386b4689c8121531c3 \ - file://${S}/third_party/perfetto/LICENSE;md5=65fc11c16d093b463bafae828ec00d41 \ + file://${S}/third_party/perfetto/LICENSE;md5=c0c9924c5c63b4834b8b1959816c8e3b \ file://${S}/third_party/pffft/LICENSE;md5=0f39e43e9bc20e7e103e54750e1ec3a2 \ file://${S}/third_party/polymer/LICENSE.polymer;md5=324f45ce459ffd97e41d175a4e95a4be \ file://${S}/third_party/private-join-and-compute/src/LICENSE;md5=175792518e4ac015ab6696d16c4f607e \ @@ -537,10 +557,11 @@ LIC_FILES_CHKSUM = "\ file://${S}/third_party/pthreadpool/src/LICENSE;md5=1609499688b503850848d795dce4da2d \ file://${S}/third_party/puffin/LICENSE;md5=b1ed361f9fc790c1054d81a7ef041a34 \ file://${S}/third_party/re2/LICENSE;md5=3b5c31eb512bdf3cb11ffd5713963760 \ + file://${S}/third_party/readability/LICENSE;md5=15e880a72f4d171d9a6735bdbd831972 \ file://${S}/third_party/rjsmin/LICENSE;md5=34f8c1142fd6208a8be89399cb521df9 \ file://${S}/third_party/rnnoise/COPYING;md5=1890bf89a18f8339491894a0b45428bf \ file://${S}/third_party/ruy/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ - file://${S}/third_party/screen-ai/THIRD_PARTY_LICENSES;md5=c1060306f371a5ac9a35cfba2d55f902 \ + file://${S}/third_party/screen-ai/THIRD_PARTY_LICENSES;md5=b96cd7885ca6a74ae8f020ddafaa9349 \ file://${S}/third_party/securemessage/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57 \ file://${S}/third_party/selenium-atoms/LICENSE;md5=5cd827bdaf8605a596a7ac9dcf808ea1 \ file://${S}/third_party/selenium-atoms/LICENSE.sizzle;md5=7a9495742f21b7624515e120b720cc65 \ @@ -578,7 +599,6 @@ LIC_FILES_CHKSUM = "\ file://${S}/third_party/vulkan-headers/LICENSE.txt;md5=3b83ef96387f14655fc854ddc3c6bd57 \ file://${S}/third_party/vulkan-loader/src/LICENSE.txt;md5=7dbefed23242760aa3475ee42801c5ac \ file://${S}/third_party/vulkan_memory_allocator/LICENSE.txt;md5=6eed3e06ed116324029b9de40eaf0ee5 \ - file://${S}/third_party/wasm_tts_engine/EIGEN_LICENSE;md5=fb0a45fc2d5c3c92cf3e5c8e19e0e758 \ file://${S}/third_party/wayland-protocols/gtk/COPYING;md5=5f30f0716dfdd0d91eb439ebec522ec2 \ file://${S}/third_party/wayland-protocols/kde/COPYING.LIB;md5=2d5025d4aa3495befef8f17206a5b0a1 \ file://${S}/third_party/wayland-protocols/src/COPYING;md5=c7b12b6702da38ca028ace54aae3d484 \ diff --git a/meta-chromium/recipes-browser/chromium/files/0001-Drop-GN-compiler-settings-conflicting-with-OE.patch b/meta-chromium/recipes-browser/chromium/files/0001-Drop-GN-compiler-settings-conflicting-with-OE.patch index ed58c3371..691062e4d 100644 --- a/meta-chromium/recipes-browser/chromium/files/0001-Drop-GN-compiler-settings-conflicting-with-OE.patch +++ b/meta-chromium/recipes-browser/chromium/files/0001-Drop-GN-compiler-settings-conflicting-with-OE.patch @@ -1,7 +1,7 @@ -From feb3b8299f312e4074fc76fe7b6dfa236a5823d8 Mon Sep 17 00:00:00 2001 +From 69bdbc33f4e6f2882f6ac8fb6bae883577887239 Mon Sep 17 00:00:00 2001 From: Max Ihlenfeldt Date: Tue, 25 Jun 2024 11:06:19 +0000 -Subject: [PATCH] Drop GN compiler settings conflicting with OE +Subject: [PATCH 01/11] Drop GN compiler settings conflicting with OE The clang cross compiler built with meta-clang has lots of these settings built-in and specifying them with GN confuses the compiler: @@ -19,37 +19,34 @@ Signed-off-by: Max Ihlenfeldt 1 file changed, 46 deletions(-) diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn -index e7a60d56b5..b0e9e04bf3 100644 +index 59942a3cf6..cf5e62eb15 100644 --- a/build/config/compiler/BUILD.gn +++ b/build/config/compiler/BUILD.gn -@@ -1211,26 +1211,6 @@ config("compiler_cpu_abi") { - "-msse3", - ] - } +@@ -1301,23 +1301,6 @@ + "-mfpmath=sse", + "-msse3", + ] - } else if (current_cpu == "arm") { -- if (is_clang && !is_android && !is_nacl && !is_chromeos_device) { +- if (is_clang && !is_android && !is_chromeos_device) { - cflags += [ "--target=arm-linux-gnueabihf" ] - ldflags += [ "--target=arm-linux-gnueabihf" ] - } -- if (!is_nacl) { -- cflags += [ -- "-march=$arm_arch", -- "-mfloat-abi=$arm_float_abi", -- ] -- } +- cflags += [ +- "-march=$arm_arch", +- "-mfloat-abi=$arm_float_abi", +- ] - if (arm_tune != "") { - cflags += [ "-mtune=$arm_tune" ] - } - } else if (current_cpu == "arm64") { -- if (is_clang && !is_android && !is_nacl && !is_fuchsia && -- !is_chromeos_device) { +- if (is_clang && !is_android && !is_fuchsia && !is_chromeos_device) { - cflags += [ "--target=aarch64-linux-gnu" ] - ldflags += [ "--target=aarch64-linux-gnu" ] - } - } else if (current_cpu == "mipsel" && !is_nacl) { + } else if (current_cpu == "mipsel") { ldflags += [ "-Wl,--hash-style=sysv" ] if (custom_toolchain == "") { -@@ -1238,9 +1218,6 @@ config("compiler_cpu_abi") { +@@ -1325,9 +1308,6 @@ if (is_android) { cflags += [ "--target=mipsel-linux-android" ] ldflags += [ "--target=mipsel-linux-android" ] @@ -59,7 +56,7 @@ index e7a60d56b5..b0e9e04bf3 100644 } } else { cflags += [ "-EL" ] -@@ -1320,8 +1297,6 @@ config("compiler_cpu_abi") { +@@ -1407,8 +1387,6 @@ ldflags += [ "-Wl,--hash-style=sysv" ] if (custom_toolchain == "") { if (is_clang) { @@ -68,7 +65,7 @@ index e7a60d56b5..b0e9e04bf3 100644 } else { cflags += [ "-EB" ] ldflags += [ "-EB" ] -@@ -1370,8 +1345,6 @@ config("compiler_cpu_abi") { +@@ -1457,8 +1435,6 @@ cflags += [ "--target=mips64el-linux-android" ] ldflags += [ "--target=mips64el-linux-android" ] } else { @@ -77,7 +74,7 @@ index e7a60d56b5..b0e9e04bf3 100644 } } else { cflags += [ -@@ -1429,8 +1402,6 @@ config("compiler_cpu_abi") { +@@ -1516,8 +1492,6 @@ ldflags += [ "-Wl,--hash-style=sysv" ] if (custom_toolchain == "") { if (is_clang) { @@ -86,15 +83,14 @@ index e7a60d56b5..b0e9e04bf3 100644 } else { cflags += [ "-EB", -@@ -1599,23 +1570,6 @@ config("compiler_deterministic") { - } +@@ -1686,23 +1660,6 @@ } } -- + - # Tells the compiler not to use absolute paths when passing the default - # paths to the tools it invokes. We don't want this because we don't - # really need it and it can mess up the RBE cache entries. -- if (is_clang && (!is_nacl || is_nacl_saigo)) { +- if (is_clang) { - cflags += [ "-no-canonical-prefixes" ] - - # Same for links: Let the compiler driver invoke the linker @@ -107,6 +103,10 @@ index e7a60d56b5..b0e9e04bf3 100644 - ldflags += [ "-no-canonical-prefixes" ] - } - } - } +- + if (use_clang_modules) { + cflags += [ + # This removes absolute paths from .pcm files. +-- +2.39.5 - config("clang_revision") { diff --git a/meta-chromium/recipes-browser/chromium/files/0002-v8-qemu-wrapper.patch b/meta-chromium/recipes-browser/chromium/files/0002-v8-qemu-wrapper.patch index 9261b47c1..4b9123942 100644 --- a/meta-chromium/recipes-browser/chromium/files/0002-v8-qemu-wrapper.patch +++ b/meta-chromium/recipes-browser/chromium/files/0002-v8-qemu-wrapper.patch @@ -1,7 +1,7 @@ -From d326bbe195c6853c600d01b9d438b5ee430b55c2 Mon Sep 17 00:00:00 2001 +From d5d34b719189ca2c3318e6636bf55197962e500c Mon Sep 17 00:00:00 2001 From: Raphael Kubo da Costa Date: Tue, 7 Nov 2017 15:24:32 +0100 -Subject: [PATCH] v8: qemu wrapper +Subject: [PATCH 02/11] v8: qemu wrapper The patch below makes the V8 binaries run during the build be invoked through QEMU, as they are built for the target. @@ -10,7 +10,6 @@ Upstream-Status: Inappropriate [embedder specific] Signed-off-by: Raphael Kubo da Costa Signed-off-by: Maksim Sisov - --- tools/v8_context_snapshot/BUILD.gn | 1 + v8/BUILD.gn | 4 ++++ @@ -22,25 +21,25 @@ index 70c32b2fc9..88497d1436 100644 +++ b/tools/v8_context_snapshot/BUILD.gn @@ -49,6 +49,7 @@ if (use_v8_context_snapshot) { output_path = rebase_path(output_file, root_build_dir) - + args = [ + "./v8-qemu-wrapper.sh", "./" + rebase_path( get_label_info( ":v8_context_snapshot_generator($v8_snapshot_toolchain)", diff --git a/v8/BUILD.gn b/v8/BUILD.gn -index 9a2b2cdd94..8c217b57c9 100644 +index f2f72a02c6..014104d3e7 100644 --- a/v8/BUILD.gn +++ b/v8/BUILD.gn -@@ -2228,6 +2228,7 @@ template("run_torque") { +@@ -2265,6 +2265,7 @@ template("run_torque") { } - + args = [ + "./v8-qemu-wrapper.sh", "./" + rebase_path( get_label_info(":torque($toolchain)", "root_out_dir") + "/torque", root_build_dir), -@@ -2391,6 +2392,7 @@ action("generate_bytecode_builtins_list") { +@@ -2440,6 +2441,7 @@ action("generate_bytecode_builtins_list") { outputs = [ "$target_gen_dir/builtins-generated/bytecodes-builtins-list.h" ] deps = [ ":bytecode_builtins_list_generator($v8_generator_toolchain)" ] args = [ @@ -48,19 +47,22 @@ index 9a2b2cdd94..8c217b57c9 100644 "./" + rebase_path( get_label_info( ":bytecode_builtins_list_generator($v8_generator_toolchain)", -@@ -2470,6 +2472,7 @@ template("run_mksnapshot") { +@@ -2523,6 +2525,7 @@ template("run_mksnapshot") { } - + args += [ + "./v8-qemu-wrapper.sh", "./" + rebase_path(get_label_info(":mksnapshot($v8_snapshot_toolchain)", "root_out_dir") + "/mksnapshot", root_build_dir), -@@ -7427,6 +7430,7 @@ if (v8_enable_i18n_support) { +@@ -7566,6 +7569,7 @@ if (v8_enable_i18n_support) { outputs = [ output_file ] - + args = [ + "./v8-qemu-wrapper.sh", "./" + rebase_path( get_label_info( ":gen-regexp-special-case($v8_generator_toolchain)", +-- +2.39.5 + diff --git a/meta-chromium/recipes-browser/chromium/files/0003-wrapper-extra-flags.patch b/meta-chromium/recipes-browser/chromium/files/0003-wrapper-extra-flags.patch index 5f012500a..f129d8e54 100644 --- a/meta-chromium/recipes-browser/chromium/files/0003-wrapper-extra-flags.patch +++ b/meta-chromium/recipes-browser/chromium/files/0003-wrapper-extra-flags.patch @@ -1,7 +1,7 @@ -From a8c669d57bd409ba07255bd52fe3c9f0817de2ac Mon Sep 17 00:00:00 2001 +From 5b09c349a19ed28bbadba3061ca16d5aabb044e5 Mon Sep 17 00:00:00 2001 From: Raphael Kubo da Costa Date: Wed, 8 Nov 2017 16:43:47 +0100 -Subject: [PATCH] wrapper: extra flags +Subject: [PATCH 03/11] wrapper: extra flags The patch below is used to allow running Chromium as root as well as passing extra flags to it by default. @@ -9,7 +9,6 @@ extra flags to it by default. Upstream-Status: Inappropriate [embedder specific] Signed-off-by: Raphael Kubo da Costa - --- chrome/installer/linux/common/wrapper | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) @@ -21,9 +20,12 @@ index aaa46bf71f..7d8c8dd5fb 100755 @@ -36,5 +36,7 @@ exec < /dev/null exec > >(exec cat) exec 2> >(exec cat >&2) - + +CHROME_EXTRA_ARGS="" + # Note: exec -a below is a bashism. -exec -a "$0" "$HERE/@@PROGNAME@@" "$@" +exec -a "$0" "$HERE/@@PROGNAME@@" ${CHROME_EXTRA_ARGS} "$@" +-- +2.39.5 + diff --git a/meta-chromium/recipes-browser/chromium/files/0004-Delete-compiler-options-not-available-in-release-ver.patch b/meta-chromium/recipes-browser/chromium/files/0004-Delete-compiler-options-not-available-in-release-ver.patch index 55401d2f2..7b598b50a 100644 --- a/meta-chromium/recipes-browser/chromium/files/0004-Delete-compiler-options-not-available-in-release-ver.patch +++ b/meta-chromium/recipes-browser/chromium/files/0004-Delete-compiler-options-not-available-in-release-ver.patch @@ -1,8 +1,8 @@ -From 0a052a88bf96542e0bb7585ccbfd39e681a32e3d Mon Sep 17 00:00:00 2001 +From 5d022ee1f84195bafcc6436a6e1f9b6f00e986cc Mon Sep 17 00:00:00 2001 From: Khem Raj Date: Wed, 4 Dec 2019 19:06:54 -0800 -Subject: [PATCH] Delete compiler options not available in release versions of - clang _yet_ +Subject: [PATCH 04/11] Delete compiler options not available in release + versions of clang _yet_ * CREL feature is not supported on the current clang toolchain version, which causes build to fail with the following error: @@ -15,38 +15,43 @@ Upstream-Status: Inappropriate [ clang/master already supports them ] Signed-off-by: Khem Raj Signed-off-by: Randy MacLeod Signed-off-by: Ariel D'Alessandro - --- build/config/compiler/BUILD.gn | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn -index b0e9e04bf3..46ed84d73c 100644 +index cf5e62eb15..58e0fd0a71 100644 --- a/build/config/compiler/BUILD.gn +++ b/build/config/compiler/BUILD.gn -@@ -614,13 +614,6 @@ config("compiler") { - } else { +@@ -687,16 +687,6 @@ cflags += [ "-ffp-contract=off" ] } -- + - # Enable ELF CREL (see crbug.com/357878242) for all platforms that use ELF - # (excluding toolchains that use an older version of LLVM). -- if (is_linux && !llvm_android_mainline && +- # TODO(crbug.com/376278218): This causes segfault on Linux ARM builds. +- # It also causes segfault on Linux s390x: +- # https://github.com/llvm/llvm-project/issues/149511 +- if (is_linux && use_lld && !llvm_android_mainline && current_cpu != "arm" && +- current_cpu != "s390x" && - default_toolchain != "//build/toolchain/cros:target") { - cflags += [ "-Wa,--crel,--allow-experimental-crel" ] - } } - + # C11/C++11 compiler flags setup. -@@ -1934,6 +1927,11 @@ config("default_warnings") { - } - - cflags += [ -+ # Disable unknown warnings, since system clang may not have -+ # backported newer warning yet unlike internal clang that -+ # chromium uses. -+ "-Wno-unknown-warning-option", +@@ -2086,6 +2076,11 @@ + # this as well. http://crbug.com/316352 + "-Wno-unneeded-internal-declaration", + ++ # Disable unknown warnings, since system clang may not have ++ # backported newer warning yet unlike internal clang that ++ # chromium uses. ++ "-Wno-unknown-warning-option", + - # TODO(crbug.com/330524456): -Wcast-function-type is under -Wextra now. - "-Wno-cast-function-type", + # TODO(crbug.com/330524456): -Wcast-function-type is under -Wextra now. + "-Wno-cast-function-type", + +-- +2.39.5 diff --git a/meta-chromium/recipes-browser/chromium/files/0005-avoid-link-latomic-failure-on-CentOS-8-host.patch b/meta-chromium/recipes-browser/chromium/files/0005-avoid-link-latomic-failure-on-CentOS-8-host.patch index ff4660210..d9d034854 100644 --- a/meta-chromium/recipes-browser/chromium/files/0005-avoid-link-latomic-failure-on-CentOS-8-host.patch +++ b/meta-chromium/recipes-browser/chromium/files/0005-avoid-link-latomic-failure-on-CentOS-8-host.patch @@ -1,7 +1,7 @@ -From be9a610454f3a90e2610443a424efcb34b4903e5 Mon Sep 17 00:00:00 2001 +From 9eb5a6ed9a73d7fab673f049ea7e5b9c4218434c Mon Sep 17 00:00:00 2001 From: Hongxu Jia Date: Fri, 22 Jan 2021 00:02:25 +0800 -Subject: [PATCH] avoid link latomic failure on CentOS 8 host +Subject: [PATCH 05/11] avoid link latomic failure on CentOS 8 host When host (such as CentOS 8) did not install libatomic, there was a link failure on native. In fact, only target requires to link atomic, @@ -11,17 +11,16 @@ Upstream-Status: Inappropriate [oe specific] Signed-off-by: Hongxu Jia Signed-off-by: Randy MacLeod - --- base/BUILD.gn | 2 ++ build/config/linux/BUILD.gn | 2 ++ 2 files changed, 4 insertions(+) diff --git a/base/BUILD.gn b/base/BUILD.gn -index 57a6af0061..2703e81421 100644 +index 5b41b3d805..2925aa607e 100644 --- a/base/BUILD.gn +++ b/base/BUILD.gn -@@ -1104,7 +1104,9 @@ component("base") { +@@ -1107,7 +1107,9 @@ component("base") { # Needed for if using newer C++ library than sysroot, except if # building inside the cros_sdk environment - use host_toolchain as a # more robust check for this. @@ -38,10 +37,13 @@ index 131bb71d1d..20f918ab82 100644 @@ -40,7 +40,9 @@ config("runtime_library") { defines = [ "OS_CHROMEOS" ] } - + + # Only target requires if ((!is_chromeos || default_toolchain != "//build/toolchain/cros:target") && + (current_toolchain != host_toolchain) && (!use_custom_libcxx || current_cpu == "mipsel")) { libs = [ "atomic" ] } +-- +2.39.5 + diff --git a/meta-chromium/recipes-browser/chromium/files/0006-Don-t-pass-unknown-LLVM-options.patch b/meta-chromium/recipes-browser/chromium/files/0006-Don-t-pass-unknown-LLVM-options.patch index de6266158..7e8cf1391 100644 --- a/meta-chromium/recipes-browser/chromium/files/0006-Don-t-pass-unknown-LLVM-options.patch +++ b/meta-chromium/recipes-browser/chromium/files/0006-Don-t-pass-unknown-LLVM-options.patch @@ -1,7 +1,7 @@ -From 8e9bf93215630604eed49476d6e848ad3ec3bdba Mon Sep 17 00:00:00 2001 +From 9a75e4248e3099a26ddcdfb0efc42cf82b4ec131 Mon Sep 17 00:00:00 2001 From: Max Ihlenfeldt Date: Fri, 8 Dec 2023 11:47:43 +0000 -Subject: [PATCH] Don't pass unknown LLVM options +Subject: [PATCH 06/11] Don't pass unknown LLVM options Because we compile and link with an older LLVM version than upstream, we need to drop the following LLVM options that aren't available yet: @@ -17,13 +17,13 @@ Signed-off-by: Max Ihlenfeldt 1 file changed, 18 deletions(-) diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn -index 46ed84d73c..5f7cfb69e9 100644 +index 58e0fd0a71..b3385edfc0 100644 --- a/build/config/compiler/BUILD.gn +++ b/build/config/compiler/BUILD.gn -@@ -590,24 +590,6 @@ config("compiler") { +@@ -604,24 +604,6 @@ config("compiler") { } } - + - # TODO(crbug.com/40283598): This causes binary size growth and potentially - # other problems. - # TODO(crbug.com/40284925): This isn't supported by Cronet's mainline llvm version. @@ -45,3 +45,6 @@ index 46ed84d73c..5f7cfb69e9 100644 # TODO(crbug.com/40192287): Investigate why/if this should be needed. if (is_win) { cflags += [ "/clang:-ffp-contract=off" ] +-- +2.39.5 + diff --git a/meta-chromium/recipes-browser/chromium/files/0007-Fix-constexpr-variable-must-be-initialized-by-a-cons.patch b/meta-chromium/recipes-browser/chromium/files/0007-Fix-constexpr-variable-must-be-initialized-by-a-cons.patch index c0dcffa6c..c13c3607a 100644 --- a/meta-chromium/recipes-browser/chromium/files/0007-Fix-constexpr-variable-must-be-initialized-by-a-cons.patch +++ b/meta-chromium/recipes-browser/chromium/files/0007-Fix-constexpr-variable-must-be-initialized-by-a-cons.patch @@ -1,8 +1,8 @@ -From 713169dbbcb3081744ea103749597885bb1b97a2 Mon Sep 17 00:00:00 2001 +From feb7f0598505fa6240a84ef8441c8c47d8e7b8f2 Mon Sep 17 00:00:00 2001 From: Max Ihlenfeldt Date: Fri, 22 Mar 2024 10:43:47 +0000 -Subject: [PATCH] Fix "constexpr variable must be initialized by a constant - expression" +Subject: [PATCH 07/11] Fix "constexpr variable must be initialized by a + constant expression" clang 17 still has some problems with constexpr strings. We need to change the problematic expressions to be const instead. @@ -26,5 +26,8 @@ index e926bdca5b..799c4b3f80 100644 +const inline std::string kLegacyHierarchyCountryCodeString{"XX"}; +const AddressCountryCode kLegacyHierarchyCountryCode = AddressCountryCode(kLegacyHierarchyCountryCodeString); - + // Creates an instance of the address hierarchy model corresponding to the +-- +2.39.5 + diff --git a/meta-chromium/recipes-browser/chromium/files/0008-Use-the-correct-path-to-libclang_rt.builtins.a.patch b/meta-chromium/recipes-browser/chromium/files/0008-Use-the-correct-path-to-libclang_rt.builtins.a.patch deleted file mode 100644 index 465bc5412..000000000 --- a/meta-chromium/recipes-browser/chromium/files/0008-Use-the-correct-path-to-libclang_rt.builtins.a.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 6fcf4a20eef34ad3577505b8c36cd2ecd5e97676 Mon Sep 17 00:00:00 2001 -From: Max Ihlenfeldt -Date: Tue, 19 Dec 2023 12:14:05 +0000 -Subject: [PATCH] Use the correct path to libclang_rt.builtins.a - -Chromium needs to link against libclang_rt.builtins.a, but it expects -it in a slightly different directory than where it actually is in our -sysroot. Thus, we need adjust the where Chromium looks for the library. - -Note that the directory used by this patch is actually independent of -the target architecture. This has the added benefit that we can just -copy the target's libclang_rt.builtins.a to the host's sysroot (to the -same directory where the host's library is). This is necessary because -Chromium needs to link against this library for both host and target -code, but only allows us to specify a single `clang_base_path`. - -Upstream-Status: Inappropriate [specific to our sysroot setup] -Signed-off-by: Max Ihlenfeldt ---- - build/config/clang/BUILD.gn | 9 +++++---- - 1 file changed, 5 insertions(+), 4 deletions(-) - -diff --git a/build/config/clang/BUILD.gn b/build/config/clang/BUILD.gn -index 0d648fa310..4652cb5127 100644 ---- a/build/config/clang/BUILD.gn -+++ b/build/config/clang/BUILD.gn -@@ -199,14 +199,15 @@ template("clang_lib") { - assert(false) # Unhandled cpu type - } - } else if (is_linux || is_chromeos) { -+ _dir = "linux" - if (current_cpu == "x64") { -- _dir = "x86_64-unknown-linux-gnu" -+ _suffix = "-x86_64" - } else if (current_cpu == "x86") { -- _dir = "i386-unknown-linux-gnu" -+ _suffix = "-i386" - } else if (current_cpu == "arm") { -- _dir = "armv7-unknown-linux-gnueabihf" -+ _suffix = "-armhf" - } else if (current_cpu == "arm64") { -- _dir = "aarch64-unknown-linux-gnu" -+ _suffix = "-aarch64" - } else { - assert(false) # Unhandled cpu type - } diff --git a/meta-chromium/recipes-browser/chromium/files/0009-Adjust-the-Rust-build-to-our-needs.patch b/meta-chromium/recipes-browser/chromium/files/0009-Adjust-the-Rust-build-to-our-needs.patch index 391c5cda7..4eaf4989a 100644 --- a/meta-chromium/recipes-browser/chromium/files/0009-Adjust-the-Rust-build-to-our-needs.patch +++ b/meta-chromium/recipes-browser/chromium/files/0009-Adjust-the-Rust-build-to-our-needs.patch @@ -1,7 +1,7 @@ -From 394ff496602bf9695c7f815f5f73c0027ab4ddc7 Mon Sep 17 00:00:00 2001 +From 8a8e2590d1c05348ed6f3155cf4038a8c7a6ba48 Mon Sep 17 00:00:00 2001 From: Max Ihlenfeldt Date: Tue, 16 Jan 2024 12:29:30 +0000 -Subject: [PATCH] Adjust the Rust build to our needs +Subject: [PATCH 09/11] Adjust the Rust build to our needs 1. Set `RUSTC_BOOTSTRAP=1` environment variable when calling rustc, to avoid the need of a nightly Rust toolchain. @@ -12,21 +12,25 @@ Subject: [PATCH] Adjust the Rust build to our needs part for the Rust "target triple", but Chromium assumes the vendor to always be "-unknown". This new arg lets us override the default when building target code. +4. Use host rust compiler when with host_system_allocator_toolchain +5. Remove arm32 bit specific clang flags from rust compiler invocation Upstream-Status: Inappropriate [specific to our build setup] +Co-authored-by: Caner Altinbasak Signed-off-by: Max Ihlenfeldt --- - build/config/rust.gni | 28 ++++++++++++++++++++-------- - build/rust/rustc_wrapper.py | 1 + + build/config/rust.gni | 28 ++++++++++++++++++---------- + ...ni_impl/filter_clang_args.py | 5 +++++ + ...ni_impl/rustc_wrapper.py | 1 + build/rust/std/BUILD.gn | 28 +++++++++++++++++++++------- build/rust/std/find_std_rlibs.py | 16 +++++++++++----- - 4 files changed, 53 insertions(+), 20 deletions(-) + 5 files changed, 56 insertions(+), 22 deletions(-) diff --git a/build/config/rust.gni b/build/config/rust.gni -index 74b3b9ced5..5affd0b445 100644 +index bd18d13119..e260576fba 100644 --- a/build/config/rust.gni +++ b/build/config/rust.gni -@@ -102,6 +102,11 @@ declare_args() { +@@ -95,6 +95,11 @@ declare_args() { # a platform. Mostly applicable to Windows, where new versions can handle ANSI # escape sequences but it's not reliable in general. force_rustc_color_output = false @@ -36,15 +40,15 @@ index 74b3b9ced5..5affd0b445 100644 + # platform default. + rust_target_triple_vendor_for_target = "" } - - # Use the Rust toolchain built in-tree. When false, we use the prebuilt Rust -@@ -174,14 +179,21 @@ if (enable_rust) { + + declare_args() { +@@ -187,14 +192,21 @@ if (enable_rust) { # https://issues.chromium.org/u/1/issues/372512092#comment5 for an example. rust_abi_target = "" if (is_linux || is_chromeos) { + vendor = "-unknown" + -+ is_host = current_toolchain == host_toolchain || toolchain_for_rust_host_build_tools ++ is_host = current_toolchain == host_toolchain || current_toolchain == host_system_allocator_toolchain || toolchain_for_rust_host_build_tools + if (!is_host && rust_target_triple_vendor_for_target != "") { + vendor = rust_target_triple_vendor_for_target + } @@ -63,26 +67,29 @@ index 74b3b9ced5..5affd0b445 100644 cargo_target_abi = "" } else if (current_cpu == "arm") { if (arm_float_abi == "hard") { -@@ -201,21 +213,21 @@ if (is_linux || is_chromeos) { +@@ -213,18 +225,14 @@ if (is_linux || is_chromeos) { + # The thumbv7 vs. armv7 distinction is for legacy reasons and both # targets in fact target Thumb, see: # https://github.com/rust-lang/rust/issues/44722 - if (arm_use_neon) { +- if (arm_use_neon) { - rust_abi_target = "thumbv7neon-unknown-linux-gnueabi" + float_suffix -+ rust_abi_target = "armv7" + vendor + "-linux-gnueabi" + float_suffix - } else { +- } else { - rust_abi_target = "armv7-unknown-linux-gnueabi" + float_suffix -+ rust_abi_target = "armv7" + vendor + "-linux-gnueabi" + float_suffix - } +- } ++ rust_abi_target = "armv7" + vendor + "-linux-gnueabi" + float_suffix cargo_target_abi = "eabi" + float_suffix } else { -- rust_abi_target = "arm-unknown-linux-gnueabi" + float_suffix -+ rust_abi_target = "arm" + vendor + "-linux-gnueabi" + float_suffix + rust_abi_target = "arm-unknown-linux-gnueabi" + float_suffix cargo_target_abi = "eabi" + float_suffix } } else if (current_cpu == "riscv64") { - rust_abi_target = "riscv64gc-unknown-linux-gnu" + rust_abi_target = "riscv64gc" + vendor + "-linux-gnu" cargo_target_abi = "" + } else if (current_cpu == "ppc64") { + rust_abi_target = "powerpc64le-unknown-linux-gnu" +@@ -237,7 +245,7 @@ if (is_linux || is_chromeos) { + cargo_target_abi = "" } else { # Best guess for other future platforms. - rust_abi_target = current_cpu + "-unknown-linux-gnu" @@ -90,36 +97,52 @@ index 74b3b9ced5..5affd0b445 100644 cargo_target_abi = "" } } else if (is_android) { -diff --git a/build/rust/rustc_wrapper.py b/build/rust/rustc_wrapper.py +diff --git a/build/rust/gni_impl/filter_clang_args.py b/build/rust/gni_impl/filter_clang_args.py +index 5a1843c0df..7fb4b49516 100644 +--- a/build/rust/gni_impl/filter_clang_args.py ++++ b/build/rust/gni_impl/filter_clang_args.py +@@ -24,6 +24,11 @@ def filter_clang_args(clangargs): + pass + elif args[i].startswith('-plugin-arg'): + i += 2 ++ # Filter out ARM-specific flags that aren't supported on other architectures ++ elif args[i].startswith('-mbranch-protection'): ++ pass # Skip this argument ++ elif args[i].startswith('-mfpu='): ++ pass + else: + yield args[i] + i += 1 +diff --git a/build/rust/gni_impl/rustc_wrapper.py b/build/rust/gni_impl/rustc_wrapper.py index 8f2096dfe5..de43d44eed 100755 ---- a/build/rust/rustc_wrapper.py -+++ b/build/rust/rustc_wrapper.py +--- a/build/rust/gni_impl/rustc_wrapper.py ++++ b/build/rust/gni_impl/rustc_wrapper.py @@ -160,6 +160,7 @@ def main(): rustc_args = remaining_args[:ldflags_separator] ldflags = remaining_args[ldflags_separator + 1:rustenv_separator] rustenv = remaining_args[rustenv_separator + 1:sources_separator] + rustenv += ["RUSTC_BOOTSTRAP=1"] - + abs_build_root = os.getcwd().replace('\\', '/') + '/' is_windows = sys.platform == 'win32' or args.target_windows diff --git a/build/rust/std/BUILD.gn b/build/rust/std/BUILD.gn -index 6b996aa1fe..146f6633ce 100644 +index bb2c988452..fdddf68d46 100644 --- a/build/rust/std/BUILD.gn +++ b/build/rust/std/BUILD.gn -@@ -207,7 +207,8 @@ if (toolchain_has_rust) { +@@ -168,7 +168,8 @@ if (toolchain_has_rust) { # our locally-built std. Both reside in root_out_dir: we must only have one of # each per GN toolchain anyway. - + - sysroot_lib_subdir = "lib/rustlib/$rust_abi_target/lib" + sysroot_target_subdir = "lib/rustlib/$rust_abi_target" + sysroot_lib_subdir = "$sysroot_target_subdir/lib" - + if (!rust_prebuilt_stdlib) { local_rustc_sysroot = "$root_out_dir/local_rustc_sysroot" -@@ -336,12 +337,12 @@ if (toolchain_has_rust) { +@@ -295,12 +296,12 @@ if (toolchain_has_rust) { rust_abi_target, ] - + - outputs = [] + outputs = [ "$target_out_dir/target.json" ] foreach(lib, all_stdlibs_to_copy) { @@ -130,9 +153,9 @@ index 6b996aa1fe..146f6633ce 100644 - outputs += [ "$target_out_dir/$lib" ] + outputs += [ "$target_out_dir/lib/$lib" ] } - + visibility = [ ":*" ] -@@ -354,8 +355,18 @@ if (toolchain_has_rust) { +@@ -313,8 +314,18 @@ if (toolchain_has_rust) { "enable_rust=false") deps = [ ":find_stdlib" ] sources = get_target_outputs(":find_stdlib") @@ -150,10 +173,10 @@ index 6b996aa1fe..146f6633ce 100644 + deps = [ ":find_stdlib" ] + sources = [ "$target_out_dir/target.json" ] + outputs = [ "$prebuilt_rustc_sysroot/$sysroot_target_subdir/target.json" ] - + visibility = [ ":*" ] } -@@ -395,7 +406,10 @@ if (toolchain_has_rust) { +@@ -354,7 +365,10 @@ if (toolchain_has_rust) { ":prebuilt_stdlib_libs", ":stdlib_public_dependent_libs", ] @@ -162,26 +185,26 @@ index 6b996aa1fe..146f6633ce 100644 + ":prebuilt_rustc_copy_to_sysroot", + ":prebuilt_rustc_copy_target_json_to_sysroot", + ] - - # The host builds tools toolchain supports Rust only and does not use - # the allocator remapping to point it to PartitionAlloc. + } + } + } diff --git a/build/rust/std/find_std_rlibs.py b/build/rust/std/find_std_rlibs.py index 386258f890..e8fdaa904a 100755 --- a/build/rust/std/find_std_rlibs.py +++ b/build/rust/std/find_std_rlibs.py @@ -17,7 +17,7 @@ import re from collections import defaultdict - + EXPECTED_STDLIB_INPUT_REGEX = re.compile(r"([0-9a-z_]+)(?:-([0-9]+))?$") -RLIB_NAME_REGEX = re.compile(r"lib([0-9a-z_]+)-([0-9a-f]+)\.rlib$") +RLIB_NAME_REGEX = re.compile(r"lib([0-9a-z_]+)(-([0-9a-f]+))?\.rlib$") - - + + def main(): @@ -52,6 +52,8 @@ def main(): rustc_args.extend(["--target", args.target]) rustlib_dir = subprocess.check_output(rustc_args).rstrip().decode() - + + lib_output_dir = os.path.join(args.output, 'lib') + # Copy the rlibs to a predictable location. Whilst we're doing so, @@ -193,7 +216,7 @@ index 386258f890..e8fdaa904a 100755 depfile.write( - "%s:" % (os.path.join(args.output, "lib%s.rlib" % args.depfile_target))) + "%s:" % (os.path.join(lib_output_dir, "lib%s.rlib" % args.depfile_target))) - + def copy_file(infile, outfile): depfile.write(f" {infile}") @@ -99,7 +101,7 @@ def main(): @@ -202,27 +225,30 @@ index 386258f890..e8fdaa904a 100755 # which we need for statically computable gn dependency rules. - (crate_name, metadata) = RLIB_NAME_REGEX.match(f).group(1, 2) + (crate_name, metadata) = RLIB_NAME_REGEX.match(f).group(1, 3) - + # Use the number of times we've seen this name to disambiguate the output # filenames. Since we sort the input filenames including the metadata, @@ -117,14 +119,18 @@ def main(): output_filename = f"lib{concise_name}.rlib" - + infile = os.path.join(rustlib_dir, f) - outfile = os.path.join(args.output, output_filename) + outfile = os.path.join(lib_output_dir, output_filename) copy_file(infile, outfile) - + for f in extra_libs: infile = os.path.join(rustlib_dir, f) - outfile = os.path.join(args.output, f) + outfile = os.path.join(lib_output_dir, f) copy_file(infile, outfile) - + + infile = os.path.join(os.environ['RUST_TARGET_PATH'], f'{args.target}.json') + outfile = os.path.join(args.output, 'target.json') + copy_file(infile, outfile) + depfile.write("\n") - + + +-- +2.39.5 diff --git a/meta-chromium/recipes-browser/chromium/files/0010-Don-t-require-profiler_builtins.rlib.patch b/meta-chromium/recipes-browser/chromium/files/0010-Don-t-require-profiler_builtins.rlib.patch index fa15e7d6a..56c5156a2 100644 --- a/meta-chromium/recipes-browser/chromium/files/0010-Don-t-require-profiler_builtins.rlib.patch +++ b/meta-chromium/recipes-browser/chromium/files/0010-Don-t-require-profiler_builtins.rlib.patch @@ -1,7 +1,7 @@ -From d6862d22d64ddb3e1b85c086eb8c14e69450ceb0 Mon Sep 17 00:00:00 2001 +From 6d8f717cb23cc00c25182d5377ffebc9028761d3 Mon Sep 17 00:00:00 2001 From: Max Ihlenfeldt Date: Wed, 7 Feb 2024 11:58:30 +0000 -Subject: [PATCH] Don't require profiler_builtins.rlib +Subject: [PATCH 10/11] Don't require profiler_builtins.rlib This library is only needed for profiling builds, which we don't do. Including it leads to compile errors on with OE's current master branch @@ -14,10 +14,10 @@ Signed-off-by: Max Ihlenfeldt 1 file changed, 1 deletion(-) diff --git a/build/rust/std/BUILD.gn b/build/rust/std/BUILD.gn -index 38e5ab7645..b5f5291283 100644 +index fdddf68d46..7afe61ab75 100644 --- a/build/rust/std/BUILD.gn +++ b/build/rust/std/BUILD.gn -@@ -100,7 +100,6 @@ if (toolchain_has_rust) { +@@ -76,7 +76,6 @@ if (toolchain_has_rust) { # don't need to pass to the C++ linker because they're used for specialized # purposes. skip_stdlib_files = [ @@ -25,3 +25,6 @@ index 38e5ab7645..b5f5291283 100644 "rustc_std_workspace_alloc", "rustc_std_workspace_core", "rustc_std_workspace_std", +-- +2.39.5 + diff --git a/meta-chromium/recipes-browser/chromium/files/0011-Revert-Allow-and-use-std-hardware_destructive_interf.patch b/meta-chromium/recipes-browser/chromium/files/0011-Revert-Allow-and-use-std-hardware_destructive_interf.patch deleted file mode 100644 index 0dca0b54d..000000000 --- a/meta-chromium/recipes-browser/chromium/files/0011-Revert-Allow-and-use-std-hardware_destructive_interf.patch +++ /dev/null @@ -1,116 +0,0 @@ -From 5f8558eedf059e4711d234e6da0413ab26b86334 Mon Sep 17 00:00:00 2001 -From: Max Ihlenfeldt -Date: Mon, 21 Oct 2024 10:08:17 +0000 -Subject: [PATCH] Revert "Allow (and use) - std::hardware_destructive_interference_size." - -libcxx only defines `std::hardware_{con,de}structive_interference_size` -if `__GCC_{CON,DE}STRUCTIVE_SIZE` are defined. clang only defines these -since version 19.1, see -https://github.com/llvm/llvm-project/commit/72c373bf. - -As Scarthgap uses clang 18.1, we need to revert -https://crrev.com/c/5767325, which uses -`std::hardware_destructive_interference_size`. - -Upstream-Status: Inappropriate [specific to older versions of clang] -Signed-off-by: Max Ihlenfeldt ---- - .../providers/cast/channel/enum_table.h | 4 +- - styleguide/c++/c++-features.md | 54 ++++++++++--------- - 2 files changed, 31 insertions(+), 27 deletions(-) - -diff --git a/components/media_router/common/providers/cast/channel/enum_table.h b/components/media_router/common/providers/cast/channel/enum_table.h -index fdf8941c32..9340ba2857 100644 ---- a/components/media_router/common/providers/cast/channel/enum_table.h -+++ b/components/media_router/common/providers/cast/channel/enum_table.h -@@ -12,7 +12,6 @@ - - #include - #include --#include - #include - #include - #include -@@ -368,7 +367,8 @@ class EnumTable { - - private: - #ifdef ARCH_CPU_64_BITS -- alignas(std::hardware_destructive_interference_size) -+ // Align the data on a cache line boundary. -+ alignas(64) - #endif - std::initializer_list data_; - bool is_sorted_; -diff --git a/styleguide/c++/c++-features.md b/styleguide/c++/c++-features.md -index fec5e73654..ffaf71fd54 100644 ---- a/styleguide/c++/c++-features.md -+++ b/styleguide/c++/c++-features.md -@@ -587,6 +587,35 @@ Overlaps with utilities in `base/strings/string_number_conversions.h`, which are - easier to use correctly. - *** - -+### std::hardware_{con,de}structive_interference_size [banned] -+ -+```c++ -+struct SharedData { -+ ReadOnlyFrequentlyUsed data; -+ alignas(std::hardware_destructive_interference_size) std::atomic counter; -+}; -+``` -+ -+**Description:** The `std::hardware_destructive_interference_size` constant is -+useful to avoid false sharing (destructive interference) between variables that -+would otherwise occupy the same cacheline. In contrast, -+`std::hardware_constructive_interference_size` is helpful to promote true -+sharing (constructive interference), e.g. to support better locality for -+non-contended data. -+ -+**Documentation:** -+[`std::hardware_destructive_interference_size`](https://en.cppreference.com/w/cpp/thread/hardware_destructive_interference_size), -+[`std::hardware_constructive_interference_size`](https://en.cppreference.com/w/cpp/thread/hardware_destructive_interference_size) -+ -+**Notes:** -+*** promo -+Banned for now since these are -+[not supported yet](https://github.com/llvm/llvm-project/issues/60174). Allow -+once supported. -+ -+[Discussion thread](https://groups.google.com/a/chromium.org/g/cxx/c/cwktrFxxUY4) -+*** -+ - ### std::{pmr::memory_resource,polymorphic_allocator} [banned] - - ```c++ -@@ -1170,31 +1199,6 @@ avoiding the need to use the `erase(remove(...` paradigm. - [Migration bug](https://crbug.com/1414639) - *** - --### std::hardware_{con,de}structive_interference_size [allowed] -- --```c++ --struct SharedData { -- ReadOnlyFrequentlyUsed data; -- alignas(std::hardware_destructive_interference_size) std::atomic counter; --}; --``` -- --**Description:** The `std::hardware_destructive_interference_size` constant is --useful to avoid false sharing (destructive interference) between variables that --would otherwise occupy the same cacheline. In contrast, --`std::hardware_constructive_interference_size` is helpful to promote true --sharing (constructive interference), e.g. to support better locality for --non-contended data. -- --**Documentation:** --[`std::hardware_destructive_interference_size`](https://en.cppreference.com/w/cpp/thread/hardware_destructive_interference_size), --[`std::hardware_constructive_interference_size`](https://en.cppreference.com/w/cpp/thread/hardware_destructive_interference_size) -- --**Notes:** --*** promo --[Discussion thread](https://groups.google.com/a/chromium.org/g/cxx/c/cwktrFxxUY4) --*** -- - ### std::is_[un]bounded_array [allowed] - - ```c++ diff --git a/meta-chromium/recipes-browser/chromium/files/0011-fix-check_version-Only-compare-node.js-major-version.patch b/meta-chromium/recipes-browser/chromium/files/0011-fix-check_version-Only-compare-node.js-major-version.patch new file mode 100644 index 000000000..0ac0c5bd1 --- /dev/null +++ b/meta-chromium/recipes-browser/chromium/files/0011-fix-check_version-Only-compare-node.js-major-version.patch @@ -0,0 +1,42 @@ +From 8dec7cef6d2e041b363371f611156b473a8aca95 Mon Sep 17 00:00:00 2001 +From: Caner Altinbasak +Date: Wed, 2 Jul 2025 15:46:35 +0100 +Subject: [PATCH 11/11] fix(check_version):Only compare node.js major version + number + +Yocto has a slightly newer version of node.js available. Compare only +the major version to avoid build errors. + +Upstream-Status: Inappropriate [specific to our build setup] +--- + third_party/node/check_version.js | 11 ++++++++--- + 1 file changed, 8 insertions(+), 3 deletions(-) + +diff --git a/third_party/node/check_version.js b/third_party/node/check_version.js +index 0a037ab449..72201b473e 100644 +--- a/third_party/node/check_version.js ++++ b/third_party/node/check_version.js +@@ -28,12 +28,17 @@ async function main() { + await readFile(args.expected_version_file, {encoding: 'utf-8'}); + const expectedVersion = extractExpectedVersion(contents); + ++ // Extract major version numbers for comparison ++ const expectedMajor = expectedVersion.match(/^v?(\d+)/)?.[1]; ++ const actualMajor = process.version.match(/^v?(\d+)/)?.[1]; ++ + const errorMessage = +- `Failed NodeJS version check: Expected version '${expectedVersion}', ` + +- `but found '${process.version}'. Did you run 'gclient sync'? If the ` + ++ `Failed NodeJS version check: Expected major version '${expectedMajor}', ` + ++ `but found '${actualMajor}'. Expected full version was '${expectedVersion}', ` + ++ `actual version is '${process.version}'. Did you run 'gclient sync'? If the ` + + `problem persists try running 'gclient sync -f' instead, or deleting ` + + `third_party/node/{linux,win,mac} folders and trying again.`; + +- assert.equal(expectedVersion, process.version, errorMessage); ++ assert.equal(expectedMajor, actualMajor, errorMessage); + } + main(); +-- +2.39.5 + diff --git a/meta-chromium/recipes-browser/chromium/files/0012-Revert-Set-Rust-symbol-visibility-to-hidden-when-C-s.patch b/meta-chromium/recipes-browser/chromium/files/0012-Revert-Set-Rust-symbol-visibility-to-hidden-when-C-s.patch deleted file mode 100644 index 0d291298b..000000000 --- a/meta-chromium/recipes-browser/chromium/files/0012-Revert-Set-Rust-symbol-visibility-to-hidden-when-C-s.patch +++ /dev/null @@ -1,73 +0,0 @@ -From 6302ea4936e24232af4d50257b94a079471063cf Mon Sep 17 00:00:00 2001 -From: Ariel D'Alessandro -Date: Thu, 14 Nov 2024 22:23:28 -0300 -Subject: [PATCH] Revert "Set Rust symbol visibility to hidden when C++ symbols - are" - -This reverts chromium commit ee3900fd57b3c580aefff15c64052904d81b7760. -* Change-Id: https://crrev.com/c/5966273 - -Fixes the following compilation error: - -``` -| FAILED: obj/third_party/rust/ryu/v1/lib/libryu_lib.rlib -[...] -| error: unknown unstable option: `default-visibility` -``` - -This patch will be dropped once Rust >= 1.83 is available, which -includes: -* rust-lang/rust#130005 [0] -* rust-lang/rust#131519 [1] - -Note that currently meta-lts-mixins [2] provides the following versions: -* kirkstone: `1.80.1` -* scarthgap: `1.81.0` - -[0] https://github.com/rust-lang/rust/pull/130005 -[1] https://github.com/rust-lang/rust/pull/131519 -[2] https://git.yoctoproject.org/meta-lts-mixins - -Upstream-Status: Inappropriate [specific to older versions of rust] -Signed-off-by: Ariel D'Alessandro ---- - build/config/gcc/BUILD.gn | 1 - - build/sanitizers/asan_suppressions.cc | 13 +++++++++++++ - 2 files changed, 13 insertions(+), 1 deletion(-) - -diff --git a/build/config/gcc/BUILD.gn b/build/config/gcc/BUILD.gn -index a659210b196aa..147ebfc53426c 100644 ---- a/build/config/gcc/BUILD.gn -+++ b/build/config/gcc/BUILD.gn -@@ -32,7 +32,6 @@ declare_args() { - # See http://gcc.gnu.org/wiki/Visibility - config("symbol_visibility_hidden") { - cflags = [ "-fvisibility=hidden" ] -- rustflags = [ "-Zdefault-visibility=hidden" ] - - # Visibility attribute is not supported on AIX. - if (current_os != "aix") { -diff --git a/build/sanitizers/asan_suppressions.cc b/build/sanitizers/asan_suppressions.cc -index bfbd4b792a919..f0557be762c40 100644 ---- a/build/sanitizers/asan_suppressions.cc -+++ b/build/sanitizers/asan_suppressions.cc -@@ -15,6 +15,19 @@ - // // http://crbug.com/178677 - // "interceptor_via_lib:libsqlite3.so\n" - char kASanDefaultSuppressions[] = -+ // https://crbug.com/1471542 false positive odr violations from Rust code. -+ "odr_violation:^core::\n" -+ "odr_violation:^object::\n" -+ "odr_violation:^std::io::\n" -+ "odr_violation:^serde::\n" -+ "odr_violation:^serde_json_lenient::\n" -+ "odr_violation:^std::panicking::\n" -+ "odr_violation:^std::thread::Builder::\n" -+ "odr_violation:^read_fonts::tables::\n" -+ "odr_violation:^std_detect::detect::cache::\n" -+ "odr_violation:^alloc::sync::\n" -+ "odr_violation:^log::\n" -+ - // End of suppressions. - // PLEASE READ ABOVE BEFORE ADDING NEW SUPPRESSIONS. - ""; // Please keep this semicolon. diff --git a/meta-chromium/recipes-browser/chromium/files/0021-chromium-fix-v4l2-compiler-error-on-arm.patch b/meta-chromium/recipes-browser/chromium/files/0012-chromium-fix-v4l2-compiler-error-on-arm.patch similarity index 95% rename from meta-chromium/recipes-browser/chromium/files/0021-chromium-fix-v4l2-compiler-error-on-arm.patch rename to meta-chromium/recipes-browser/chromium/files/0012-chromium-fix-v4l2-compiler-error-on-arm.patch index 431132813..6fd9cc17e 100644 --- a/meta-chromium/recipes-browser/chromium/files/0021-chromium-fix-v4l2-compiler-error-on-arm.patch +++ b/meta-chromium/recipes-browser/chromium/files/0012-chromium-fix-v4l2-compiler-error-on-arm.patch @@ -1,4 +1,4 @@ -From 568dd0026ac86878bf6f0c99ac837a964525860f Mon Sep 17 00:00:00 2001 +From 335090e8e3480bdeea12687f8aa2b0e3dd4bf868 Mon Sep 17 00:00:00 2001 From: Caner Altinbasak Date: Sat, 26 Jul 2025 12:47:57 +0100 Subject: [PATCH] chromium: fix v4l2 compiler error on arm diff --git a/meta-chromium/recipes-browser/chromium/files/0013-pdfium-Fix-missing-PDFiumAPIStringBufferAdapter-temp.patch b/meta-chromium/recipes-browser/chromium/files/0013-pdfium-Fix-missing-PDFiumAPIStringBufferAdapter-temp.patch deleted file mode 100644 index e47cc472f..000000000 --- a/meta-chromium/recipes-browser/chromium/files/0013-pdfium-Fix-missing-PDFiumAPIStringBufferAdapter-temp.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 20deec0782b78d1c8302764e852ff174f7a4f564 Mon Sep 17 00:00:00 2001 -From: Ariel D'Alessandro -Date: Fri, 15 Nov 2024 00:49:27 -0300 -Subject: [PATCH] pdfium: Fix missing PDFiumAPIStringBufferAdapter template - argument - -Fix the following compilation error: - -``` -| ../../pdf/pdfium/pdfium_api_wrappers.cc:150:32: error: alias template - 'PDFiumAPIStringBufferAdapter' requires template arguments; argument - deduction only allowed for class templates -| 150 | PDFiumAPIStringBufferAdapter adapter(&name, expected_size, -| | ^ -| ../../pdf/pdfium/pdfium_api_string_buffer_adapter.h:173:1: note: template - is declared here -| 173 | using PDFiumAPIStringBufferAdapter = -| | ^ -| 1 error generated. -``` - -This patch will be dropped once clang >= 19.1.0 is available, which -includes support for class template argument deduction (CTAD) for type -alias templates (P1814R0 [0]) (#54051 [1]). - -Note that currently meta-clang [2] provides the clang version `18.1.6`. - -[0] https://wg21.link/p1814r0 -[1] https://github.com/llvm/llvm-project/issues/54051 -[2] https://github.com/kraj/meta-clang - -Upstream-Status: Inappropriate [specific to older versions of clang] -Signed-off-by: Ariel D'Alessandro ---- - pdf/pdfium/pdfium_api_wrappers.cc | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/pdf/pdfium/pdfium_api_wrappers.cc b/pdf/pdfium/pdfium_api_wrappers.cc -index b13fe20875e61..60c973b7152ab 100644 ---- a/pdf/pdfium/pdfium_api_wrappers.cc -+++ b/pdf/pdfium/pdfium_api_wrappers.cc -@@ -147,7 +147,7 @@ std::u16string GetPageObjectMarkName(FPDF_PAGEOBJECTMARK mark) { - - // Number of characters, including the NUL. - const size_t expected_size = base::checked_cast(buflen_bytes / 2); -- PDFiumAPIStringBufferAdapter adapter(&name, expected_size, -+ PDFiumAPIStringBufferAdapter adapter(&name, expected_size, - /*check_expected_size=*/true); - unsigned long actual_buflen_bytes = 0; // NOLINT(runtime/int) - bool result = diff --git a/meta-chromium/recipes-browser/chromium/files/0014-Revert-Remove-libavif-based-AVIF-decoder.patch b/meta-chromium/recipes-browser/chromium/files/0014-Revert-Remove-libavif-based-AVIF-decoder.patch deleted file mode 100644 index d7f2d2abf..000000000 --- a/meta-chromium/recipes-browser/chromium/files/0014-Revert-Remove-libavif-based-AVIF-decoder.patch +++ /dev/null @@ -1,3744 +0,0 @@ -From 75e1653ce9bf360e4c1cb5b86872ebff0b67a35b Mon Sep 17 00:00:00 2001 -From: Ariel D'Alessandro -Date: Thu, 17 Jul 2025 12:51:22 -0300 -Subject: [PATCH] Revert "Remove libavif based AVIF decoder" - -This reverts commit ce78002f97a433e53ab16805e16b895f9b52ea24. - -In order to disable crabbyavif to fix build errors, re-enable libavif so -it can be used in replacement. - -Upstream-Status: Inappropriate [upstream ticket https://crbug.com/357017325] -Signed-off-by: Ariel D'Alessandro ---- - .../common/ProductionSupportedFlagList.java | 3 + - chrome/browser/about_flags.cc | 4 + - chrome/browser/flag-metadata.json | 5 + - chrome/browser/flag_descriptions.cc | 5 + - chrome/browser/flag_descriptions.h | 3 + - third_party/blink/common/features.cc | 2 + - third_party/blink/public/common/features.h | 3 + - third_party/blink/renderer/platform/BUILD.gn | 13 + - .../renderer/platform/image-decoders/BUILD.gn | 12 +- - .../image-decoders/avif/avif_image_decoder.cc | 1295 ++++++++++++ - .../image-decoders/avif/avif_image_decoder.h | 191 ++ - .../avif/avif_image_decoder_fuzzer.cc | 30 + - .../avif/avif_image_decoder_test.cc | 1758 +++++++++++++++++ - .../avif/gen_crabbyavif_wrapper.py | 164 ++ - .../platform/image-decoders/image_decoder.cc | 17 +- - .../image_decoder_fuzzer_utils.cc | 8 + - .../image_decoder_fuzzer_utils.h | 1 + - 17 files changed, 3508 insertions(+), 6 deletions(-) - create mode 100644 third_party/blink/renderer/platform/image-decoders/avif/avif_image_decoder.cc - create mode 100644 third_party/blink/renderer/platform/image-decoders/avif/avif_image_decoder.h - create mode 100644 third_party/blink/renderer/platform/image-decoders/avif/avif_image_decoder_fuzzer.cc - create mode 100644 third_party/blink/renderer/platform/image-decoders/avif/avif_image_decoder_test.cc - create mode 100644 third_party/blink/renderer/platform/image-decoders/avif/gen_crabbyavif_wrapper.py - -diff --git a/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java b/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java -index def02f59887c1..3bfa4dc335cb1 100644 ---- a/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java -+++ b/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java -@@ -434,6 +434,9 @@ public final class ProductionSupportedFlagList { - Flag.baseFeature( - BaseFeatures.RUN_TASKS_BY_BATCHES, - "Run tasks in queue for 8ms before before sending a system message."), -+ Flag.baseFeature( -+ BlinkFeatures.CRABBY_AVIF, -+ "If enabled, CrabbyAvif will be used instead of libavif for decoding AVIF images."), - Flag.baseFeature( - NetworkServiceFeatures.DEPRECATE_UNLOAD, - "If false prevents the gradual deprecation of the unload event."), -diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc -index 5156e5d3f2c74..1a0e2039bda1d 100644 ---- a/chrome/browser/about_flags.cc -+++ b/chrome/browser/about_flags.cc -@@ -7780,6 +7780,10 @@ const FeatureEntry kFeatureEntries[] = { - flag_descriptions::kAvifGainmapHdrImagesDescription, kOsAll, - FEATURE_VALUE_TYPE(blink::features::kAvifGainmapHdrImages)}, - -+ {"crabbyavif", flag_descriptions::kCrabbyAvifName, -+ flag_descriptions::kCrabbyAvifDescription, kOsAll, -+ FEATURE_VALUE_TYPE(blink::features::kCrabbyAvif)}, -+ - {"file-handling-icons", flag_descriptions::kFileHandlingIconsName, - flag_descriptions::kFileHandlingIconsDescription, kOsDesktop, - FEATURE_VALUE_TYPE(blink::features::kFileHandlingIcons)}, -diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json -index d6851e527feb1..bd09150e90221 100644 ---- a/chrome/browser/flag-metadata.json -+++ b/chrome/browser/flag-metadata.json -@@ -1658,6 +1658,11 @@ - "owners": ["sebsg@chromium.org", "bling-transactions-eng@google.com"], - "expiry_milestone": 135 - }, -+ { -+ "name": "crabbyavif", -+ "owners": [ "vigneshv@google.com", "image-codecs-eng@google.com" ], -+ "expiry_milestone": 133 -+ }, - { - "name": "cras-processor-wav-dump", - "owners": ["aaronyu@google.com", "chromeos-audio@google.com" ], -diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc -index c06c6c65b1398..1050fe6c31ca1 100644 ---- a/chrome/browser/flag_descriptions.cc -+++ b/chrome/browser/flag_descriptions.cc -@@ -446,6 +446,11 @@ const char kAvifGainmapHdrImagesDescription[] = - "If enabled, Chrome uses the gainmap (if present) in AVIF images to render " - "the HDR version on HDR displays and the SDR version on SDR displays."; - -+const char kCrabbyAvifName[] = "CrabbyAvif for decoding AVIF images"; -+const char kCrabbyAvifDescription[] = -+ "If enabled, CrabbyAvif will be used instead of libavif for decoding AVIF " -+ "images"; -+ - const char kTangibleSyncName[] = "Tangible Sync"; - const char kTangibleSyncDescription[] = - "Enables the tangible sync when a user starts the sync consent flow"; -diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h -index be3f7a6e96f05..0e4e01f106ba8 100644 ---- a/chrome/browser/flag_descriptions.h -+++ b/chrome/browser/flag_descriptions.h -@@ -312,6 +312,9 @@ extern const char kForestFeatureDescription[]; - extern const char kAvifGainmapHdrImagesName[]; - extern const char kAvifGainmapHdrImagesDescription[]; - -+extern const char kCrabbyAvifName[]; -+extern const char kCrabbyAvifDescription[]; -+ - extern const char kTangibleSyncName[]; - extern const char kTangibleSyncDescription[]; - -diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc -index 720c38313bd13..e4d60ff6ade3e 100644 ---- a/third_party/blink/common/features.cc -+++ b/third_party/blink/common/features.cc -@@ -510,6 +510,8 @@ BASE_FEATURE(kCorrectFloatExtensionTestForWebGL, - "CorrectFloatExtensionTestForWebGL", - base::FEATURE_ENABLED_BY_DEFAULT); - -+BASE_FEATURE(kCrabbyAvif, "CrabbyAvif", base::FEATURE_ENABLED_BY_DEFAULT); -+ - // When enabled, add a new option, {imageOrientation: 'none'}, to - // createImageBitmap, which ignores the image orientation metadata of the source - // and renders the image as encoded. -diff --git a/third_party/blink/public/common/features.h b/third_party/blink/public/common/features.h -index 9970347ef0ccb..220f447a0725e 100644 ---- a/third_party/blink/public/common/features.h -+++ b/third_party/blink/public/common/features.h -@@ -366,6 +366,9 @@ BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE_PARAM( - // See http://crbug.com/40788570. - BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kDevToolsImprovedNetworkError); - -+// Enables the use of CrabbyAvif for decoding AVIF images. -+BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kCrabbyAvif); -+ - // Enables input IPC to directly target the renderer's compositor thread without - // hopping through the IO thread first. - BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kDirectCompositorThreadIpc); -diff --git a/third_party/blink/renderer/platform/BUILD.gn b/third_party/blink/renderer/platform/BUILD.gn -index 291676c658372..57505f9d2622c 100644 ---- a/third_party/blink/renderer/platform/BUILD.gn -+++ b/third_party/blink/renderer/platform/BUILD.gn -@@ -2786,6 +2786,19 @@ fuzzer_test("web_icon_sizes_fuzzer") { - additional_configs = [ "//third_party/blink/renderer:inside_blink" ] - } - -+# Fuzzer for blink::AVIFImageDecoder -+fuzzer_test("blink_avif_decoder_fuzzer") { -+ sources = [ "image-decoders/avif/avif_image_decoder_fuzzer.cc" ] -+ deps = [ -+ ":blink_fuzzer_test_support", -+ ":blink_image_decoder_fuzzer_test_support", -+ ":platform", -+ ] -+ seed_corpuses = [ "//third_party/blink/web_tests/images/resources/avif" ] -+ libfuzzer_options = [ "rss_limit_mb=8192" ] -+ additional_configs = [ "//third_party/blink/renderer:inside_blink" ] -+} -+ - # Fuzzer for blink::CrabbyAVIFImageDecoder - fuzzer_test("blink_crabbyavif_decoder_fuzzer") { - sources = [ "image-decoders/avif/crabbyavif_image_decoder_fuzzer.cc" ] -diff --git a/third_party/blink/renderer/platform/image-decoders/BUILD.gn b/third_party/blink/renderer/platform/image-decoders/BUILD.gn -index 870c7e8537249..e638c6bfcd93a 100644 ---- a/third_party/blink/renderer/platform/image-decoders/BUILD.gn -+++ b/third_party/blink/renderer/platform/image-decoders/BUILD.gn -@@ -79,11 +79,16 @@ component("image_decoders") { - - if (enable_av1_decoder) { - sources += [ -+ "avif/avif_image_decoder.cc", -+ "avif/avif_image_decoder.h", - "avif/crabbyavif_image_decoder.cc", - "avif/crabbyavif_image_decoder.h", - ] - -- deps += [ "//third_party/crabbyavif" ] -+ deps += [ -+ "//third_party/crabbyavif", -+ "//third_party/libavif", -+ ] - } - - if (enable_rust_png) { -@@ -130,6 +135,9 @@ source_set("unit_tests") { - } - - if (enable_av1_decoder) { -- sources += [ "avif/crabbyavif_image_decoder_test.cc" ] -+ sources += [ -+ "avif/avif_image_decoder_test.cc", -+ "avif/crabbyavif_image_decoder_test.cc", -+ ] - } - } -diff --git a/third_party/blink/renderer/platform/image-decoders/avif/avif_image_decoder.cc b/third_party/blink/renderer/platform/image-decoders/avif/avif_image_decoder.cc -new file mode 100644 -index 0000000000000..eb9448d06d30a ---- /dev/null -+++ b/third_party/blink/renderer/platform/image-decoders/avif/avif_image_decoder.cc -@@ -0,0 +1,1295 @@ -+// Copyright 2020 The Chromium Authors -+// Use of this source code is governed by a BSD-style license that can be -+// found in the LICENSE file. -+ -+#ifdef UNSAFE_BUFFERS_BUILD -+// TODO(crbug.com/351564777): Remove this and convert code to safer constructs. -+#pragma allow_unsafe_buffers -+#endif -+ -+#include "third_party/blink/renderer/platform/image-decoders/avif/avif_image_decoder.h" -+ -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include "base/bits.h" -+#include "base/containers/adapters.h" -+#include "base/feature_list.h" -+#include "base/functional/bind.h" -+#include "base/logging.h" -+#include "base/memory/scoped_refptr.h" -+#include "base/metrics/histogram_functions.h" -+#include "base/numerics/safe_conversions.h" -+#include "base/timer/elapsed_timer.h" -+#include "build/build_config.h" -+#include "cc/base/math_util.h" -+#include "media/base/video_color_space.h" -+#include "skia/ext/cicp.h" -+#include "third_party/blink/public/common/features.h" -+#include "third_party/blink/renderer/platform/image-decoders/fast_shared_buffer_reader.h" -+#include "third_party/blink/renderer/platform/image-decoders/image_animation.h" -+#include "third_party/blink/renderer/platform/image-decoders/image_decoder.h" -+#include "third_party/blink/renderer/platform/image-decoders/rw_buffer.h" -+#include "third_party/libavif/src/include/avif/avif.h" -+#include "third_party/libyuv/include/libyuv.h" -+#include "third_party/skia/include/core/SkColorSpace.h" -+#include "third_party/skia/include/core/SkTypes.h" -+#include "third_party/skia/include/private/SkXmp.h" -+#include "ui/gfx/color_space.h" -+#include "ui/gfx/icc_profile.h" -+ -+#if defined(ARCH_CPU_BIG_ENDIAN) -+#error Blink assumes a little-endian target. -+#endif -+ -+namespace blink { -+ -+namespace { -+ -+// The maximum AVIF file size we are willing to decode. This helps libavif -+// detect invalid sizes and offsets in an AVIF file before the file size is -+// known. -+constexpr uint64_t kMaxAvifFileSize = 0x10000000; // 256 MB -+ -+const char* AvifDecoderErrorMessage(const avifDecoder* decoder) { -+ // decoder->diag.error is a char array that stores a null-terminated C string. -+ return *decoder->diag.error != '\0' ? decoder->diag.error -+ : "(no error message)"; -+} -+ -+// Builds a gfx::ColorSpace from the ITU-T H.273 (CICP) color description. -+gfx::ColorSpace GetColorSpace( -+ avifColorPrimaries color_primaries, -+ avifTransferCharacteristics transfer_characteristics, -+ avifMatrixCoefficients matrix_coefficients, -+ avifRange yuv_range, -+ bool grayscale) { -+ // (As of ISO/IEC 23000-22:2019 Amendment 2) MIAF Section 7.3.6.4 says: -+ // If a coded image has no associated colour property, the default property -+ // is defined as having colour_type equal to 'nclx' with properties as -+ // follows: -+ // – colour_primaries equal to 1, -+ // - transfer_characteristics equal to 13, -+ // - matrix_coefficients equal to 5 or 6 (which are functionally identical), -+ // and -+ // - full_range_flag equal to 1. -+ // ... -+ // These values correspond to AVIF_COLOR_PRIMARIES_BT709, -+ // AVIF_TRANSFER_CHARACTERISTICS_SRGB, and AVIF_MATRIX_COEFFICIENTS_BT601, -+ // respectively. -+ // -+ // Note that this only specifies the default color property when the color -+ // property is absent. It does not really specify the default values for -+ // colour_primaries, transfer_characteristics, and matrix_coefficients when -+ // they are equal to 2 (unspecified). But we will interpret it as specifying -+ // the default values for these variables because we must choose some defaults -+ // and these are the most reasonable defaults to choose. We also advocate that -+ // all AVIF decoders choose these defaults: -+ // https://github.com/AOMediaCodec/av1-avif/issues/84 -+ const auto primaries = color_primaries == AVIF_COLOR_PRIMARIES_UNSPECIFIED -+ ? AVIF_COLOR_PRIMARIES_BT709 -+ : color_primaries; -+ const auto transfer = -+ transfer_characteristics == AVIF_TRANSFER_CHARACTERISTICS_UNSPECIFIED -+ ? AVIF_TRANSFER_CHARACTERISTICS_SRGB -+ : transfer_characteristics; -+ const auto matrix = -+ (grayscale || matrix_coefficients == AVIF_MATRIX_COEFFICIENTS_UNSPECIFIED) -+ ? AVIF_MATRIX_COEFFICIENTS_BT601 -+ : matrix_coefficients; -+ const auto range = yuv_range == AVIF_RANGE_FULL -+ ? gfx::ColorSpace::RangeID::FULL -+ : gfx::ColorSpace::RangeID::LIMITED; -+ media::VideoColorSpace color_space(primaries, transfer, matrix, range); -+ if (color_space.IsSpecified()) { -+ return color_space.ToGfxColorSpace(); -+ } -+ // media::VideoColorSpace and gfx::ColorSpace do not support CICP -+ // MatrixCoefficients 12, 13, 14. -+ DCHECK_GE(matrix, 12); -+ DCHECK_LE(matrix, 14); -+ if (yuv_range == AVIF_RANGE_FULL) { -+ return gfx::ColorSpace::CreateJpeg(); -+ } -+ return gfx::ColorSpace::CreateREC709(); -+} -+ -+// Builds a gfx::ColorSpace from the ITU-T H.273 (CICP) color description in the -+// image. -+gfx::ColorSpace GetColorSpace(const avifImage* image) { -+ const bool grayscale = image->yuvFormat == AVIF_PIXEL_FORMAT_YUV400; -+ return GetColorSpace(image->colorPrimaries, image->transferCharacteristics, -+ image->matrixCoefficients, image->yuvRange, grayscale); -+} -+ -+// |y_size| is the width or height of the Y plane. Returns the width or height -+// of the U and V planes. |chroma_shift| represents the subsampling of the -+// chroma (U and V) planes in the x (for width) or y (for height) direction. -+int UVSize(int y_size, int chroma_shift) { -+ DCHECK(chroma_shift == 0 || chroma_shift == 1); -+ return (y_size + chroma_shift) >> chroma_shift; -+} -+ -+float FractionToFloat(auto numerator, uint32_t denominator) { -+ // First cast to double and not float because uint32_t->float conversion can -+ // cause precision loss. -+ return static_cast(numerator) / denominator; -+} -+ -+// If the image has a gain map, returns the alternate image's color space, if -+// it's different from the base image's and can be converted to a SkColorSpace. -+// If the alternate image color space is the same as the base image, there is no -+// need to specify it in SkGainmapInfo, and using the base image's color space -+// may be more accurate if the profile cannot be exactly represented as a -+// SkColorSpace object. -+sk_sp GetAltImageColorSpace(const avifImage& image) { -+ const avifGainMap* gain_map = image.gainMap; -+ if (!gain_map) { -+ return nullptr; -+ } -+ sk_sp color_space; -+ if (gain_map->altICC.size) { -+ if (image.icc.size == gain_map->altICC.size && -+ memcmp(gain_map->altICC.data, image.icc.data, gain_map->altICC.size) == -+ 0) { -+ // Same ICC as the base image, no need to specify it. -+ return nullptr; -+ } -+ std::unique_ptr profile = ColorProfile::Create( -+ base::span(gain_map->altICC.data, gain_map->altICC.size)); -+ if (!profile) { -+ DVLOG(1) << "Failed to parse gain map ICC profile"; -+ return nullptr; -+ } -+ const skcms_ICCProfile* icc_profile = profile->GetProfile(); -+ if (icc_profile->has_CICP) { -+ color_space = -+ skia::CICPGetSkColorSpace(icc_profile->CICP.color_primaries, -+ icc_profile->CICP.transfer_characteristics, -+ icc_profile->CICP.matrix_coefficients, -+ icc_profile->CICP.video_full_range_flag, -+ /*prefer_srgb_trfn=*/true); -+ } else if (icc_profile->has_toXYZD50) { -+ // The transfer function is irrelevant for gain map tone mapping, -+ // set it to something standard in case it's not set or not -+ // supported. -+ skcms_ICCProfile with_srgb = *icc_profile; -+ skcms_SetTransferFunction(&with_srgb, skcms_sRGB_TransferFunction()); -+ color_space = SkColorSpace::Make(with_srgb); -+ } -+ } else if (gain_map->altColorPrimaries != AVIF_COLOR_PRIMARIES_UNSPECIFIED) { -+ if (image.icc.size == 0 && -+ image.colorPrimaries == gain_map->altColorPrimaries) { -+ // Same as base image, no need to specify it. -+ return nullptr; -+ } -+ const bool grayscale = (gain_map->altPlaneCount == 1); -+ const gfx::ColorSpace alt_color_space = GetColorSpace( -+ gain_map->altColorPrimaries, gain_map->altTransferCharacteristics, -+ gain_map->altMatrixCoefficients, gain_map->altYUVRange, grayscale); -+ color_space = alt_color_space.GetAsFullRangeRGB().ToSkColorSpace(); -+ } -+ -+ if (!color_space) { -+ DVLOG(1) << "Gain map image contains an unsupported color space"; -+ } -+ -+ return color_space; -+} -+ -+} // namespace -+ -+AVIFImageDecoder::AVIFImageDecoder(AlphaOption alpha_option, -+ HighBitDepthDecodingOption hbd_option, -+ ColorBehavior color_behavior, -+ cc::AuxImage aux_image, -+ wtf_size_t max_decoded_bytes, -+ AnimationOption animation_option) -+ : ImageDecoder(alpha_option, -+ hbd_option, -+ color_behavior, -+ aux_image, -+ max_decoded_bytes), -+ animation_option_(animation_option) {} -+ -+AVIFImageDecoder::~AVIFImageDecoder() = default; -+ -+String AVIFImageDecoder::FilenameExtension() const { -+ return "avif"; -+} -+ -+const AtomicString& AVIFImageDecoder::MimeType() const { -+ DEFINE_STATIC_LOCAL(const AtomicString, avif_mime_type, ("image/avif")); -+ return avif_mime_type; -+} -+ -+bool AVIFImageDecoder::ImageIsHighBitDepth() { -+ return bit_depth_ > 8; -+} -+ -+void AVIFImageDecoder::OnSetData(scoped_refptr data) { -+ have_parsed_current_data_ = false; -+ const bool all_data_received = IsAllDataReceived(); -+ avif_io_data_.reader = data_; -+ avif_io_data_.all_data_received = all_data_received; -+ avif_io_.sizeHint = all_data_received ? data_->size() : kMaxAvifFileSize; -+ -+ // ImageFrameGenerator::GetYUVAInfo() and ImageFrameGenerator::DecodeToYUV() -+ // assume that allow_decode_to_yuv_ and other image metadata are available -+ // after calling ImageDecoder::Create() with data_complete=true. -+ if (all_data_received) { -+ ParseMetadata(); -+ } -+} -+ -+cc::YUVSubsampling AVIFImageDecoder::GetYUVSubsampling() const { -+ switch (avif_yuv_format_) { -+ case AVIF_PIXEL_FORMAT_YUV420: -+ return cc::YUVSubsampling::k420; -+ case AVIF_PIXEL_FORMAT_YUV422: -+ return cc::YUVSubsampling::k422; -+ case AVIF_PIXEL_FORMAT_YUV444: -+ return cc::YUVSubsampling::k444; -+ case AVIF_PIXEL_FORMAT_YUV400: -+ return cc::YUVSubsampling::kUnknown; -+ case AVIF_PIXEL_FORMAT_NONE: -+ // avif_yuv_format_ is initialized to AVIF_PIXEL_FORMAT_NONE in the -+ // constructor. If we have called SetSize() successfully at the end -+ // of UpdateDemuxer(), avif_yuv_format_ cannot possibly be -+ // AVIF_PIXEL_FORMAT_NONE. -+ CHECK(!IsDecodedSizeAvailable()); -+ return cc::YUVSubsampling::kUnknown; -+ default: -+ break; -+ } -+ NOTREACHED() << "Invalid YUV format: " << avif_yuv_format_; -+} -+ -+gfx::Size AVIFImageDecoder::DecodedYUVSize(cc::YUVIndex index) const { -+ DCHECK(IsDecodedSizeAvailable()); -+ if (index == cc::YUVIndex::kU || index == cc::YUVIndex::kV) { -+ return gfx::Size(UVSize(Size().width(), chroma_shift_x_), -+ UVSize(Size().height(), chroma_shift_y_)); -+ } -+ return Size(); -+} -+ -+wtf_size_t AVIFImageDecoder::DecodedYUVWidthBytes(cc::YUVIndex index) const { -+ DCHECK(IsDecodedSizeAvailable()); -+ // Try to return the same width bytes as used by the dav1d library. This will -+ // allow DecodeToYUV() to copy each plane with a single memcpy() call. -+ // -+ // The comments for Dav1dPicAllocator in dav1d/picture.h require the pixel -+ // width be padded to a multiple of 128 pixels. -+ wtf_size_t aligned_width = static_cast( -+ base::bits::AlignUpDeprecatedDoNotUse(Size().width(), 128)); -+ if (index == cc::YUVIndex::kU || index == cc::YUVIndex::kV) { -+ aligned_width >>= chroma_shift_x_; -+ } -+ // When the stride is a multiple of 1024, dav1d_default_picture_alloc() -+ // slightly pads the stride to avoid a reduction in cache hit rate in most -+ // L1/L2 cache implementations. Match that trick here. (Note that this padding -+ // is not documented in dav1d/picture.h.) -+ if ((aligned_width & 1023) == 0) { -+ aligned_width += 64; -+ } -+ -+ // High bit depth YUV is stored as a uint16_t, double the number of bytes. -+ if (bit_depth_ > 8) { -+ DCHECK_LE(bit_depth_, 16); -+ aligned_width *= 2; -+ } -+ -+ return aligned_width; -+} -+ -+SkYUVColorSpace AVIFImageDecoder::GetYUVColorSpace() const { -+ DCHECK(CanDecodeToYUV()); -+ DCHECK_NE(yuv_color_space_, SkYUVColorSpace::kIdentity_SkYUVColorSpace); -+ return yuv_color_space_; -+} -+ -+uint8_t AVIFImageDecoder::GetYUVBitDepth() const { -+ DCHECK(CanDecodeToYUV()); -+ return bit_depth_; -+} -+ -+std::optional AVIFImageDecoder::GetHDRMetadata() const { -+ return hdr_metadata_; -+} -+ -+void AVIFImageDecoder::DecodeToYUV() { -+ DCHECK(image_planes_); -+ DCHECK(CanDecodeToYUV()); -+ -+ if (Failed()) { -+ return; -+ } -+ -+ DCHECK(decoder_); -+ DCHECK_EQ(decoded_frame_count_, 1u); // Not animation. -+ -+ // If the image is decoded progressively, just render the highest progressive -+ // frame in image_planes_ because the callers of DecodeToYUV() assume that a -+ // complete scan will not be updated. -+ const int frame_index = progressive_ ? (decoder_->imageCount - 1) : 0; -+ // TODO(crbug.com/943519): Implement YUV incremental decoding as in Decode(). -+ decoder_->allowIncremental = AVIF_FALSE; -+ -+ // libavif cannot decode to an external buffer. So we need to copy from -+ // libavif's internal buffer to |image_planes_|. -+ // TODO(crbug.com/1099825): Enhance libavif to decode to an external buffer. -+ auto ret = DecodeImage(frame_index); -+ if (ret != AVIF_RESULT_OK) { -+ if (ret != AVIF_RESULT_WAITING_ON_IO) { -+ SetFailed(); -+ } -+ return; -+ } -+ const avifImage* image = decoded_image_; -+ -+ DCHECK(!image->alphaPlane); -+ static_assert(cc::YUVIndex::kY == static_cast(AVIF_CHAN_Y), ""); -+ static_assert(cc::YUVIndex::kU == static_cast(AVIF_CHAN_U), ""); -+ static_assert(cc::YUVIndex::kV == static_cast(AVIF_CHAN_V), ""); -+ -+ // Disable subnormal floats which can occur when converting to half float. -+ std::unique_ptr disable_subnormals; -+ const bool is_f16 = image_planes_->color_type() == kA16_float_SkColorType; -+ if (is_f16) { -+ disable_subnormals = std::make_unique(); -+ } -+ const float kHighBitDepthMultiplier = -+ (is_f16 ? 1.0f : 65535.0f) / ((1 << bit_depth_) - 1); -+ -+ // Initialize |width| and |height| to the width and height of the luma plane. -+ uint32_t width = image->width; -+ uint32_t height = image->height; -+ -+ for (wtf_size_t plane_index = 0; plane_index < cc::kNumYUVPlanes; -+ ++plane_index) { -+ const cc::YUVIndex plane = static_cast(plane_index); -+ const wtf_size_t src_row_bytes = -+ base::strict_cast(image->yuvRowBytes[plane_index]); -+ const wtf_size_t dst_row_bytes = image_planes_->RowBytes(plane); -+ -+ if (bit_depth_ == 8) { -+ DCHECK_EQ(image_planes_->color_type(), kGray_8_SkColorType); -+ const uint8_t* src = image->yuvPlanes[plane_index]; -+ uint8_t* dst = static_cast(image_planes_->Plane(plane)); -+ libyuv::CopyPlane(src, src_row_bytes, dst, dst_row_bytes, width, height); -+ } else { -+ DCHECK_GT(bit_depth_, 8u); -+ DCHECK_LE(bit_depth_, 16u); -+ const uint16_t* src = -+ reinterpret_cast(image->yuvPlanes[plane_index]); -+ uint16_t* dst = static_cast(image_planes_->Plane(plane)); -+ if (image_planes_->color_type() == kA16_unorm_SkColorType) { -+ const wtf_size_t src_stride = src_row_bytes / 2; -+ const wtf_size_t dst_stride = dst_row_bytes / 2; -+ for (uint32_t j = 0; j < height; ++j) { -+ for (uint32_t i = 0; i < width; ++i) { -+ dst[j * dst_stride + i] = -+ src[j * src_stride + i] * kHighBitDepthMultiplier + 0.5f; -+ } -+ } -+ } else if (image_planes_->color_type() == kA16_float_SkColorType) { -+ // Note: Unlike CopyPlane_16, HalfFloatPlane wants the stride in bytes. -+ libyuv::HalfFloatPlane(src, src_row_bytes, dst, dst_row_bytes, -+ kHighBitDepthMultiplier, width, height); -+ } else { -+ NOTREACHED() << "Unsupported color type: " -+ << static_cast(image_planes_->color_type()); -+ } -+ } -+ if (plane == cc::YUVIndex::kY) { -+ // Having processed the luma plane, change |width| and |height| to the -+ // width and height of the chroma planes. -+ width = UVSize(width, chroma_shift_x_); -+ height = UVSize(height, chroma_shift_y_); -+ } -+ } -+ image_planes_->SetHasCompleteScan(); -+} -+ -+int AVIFImageDecoder::RepetitionCount() const { -+ if (decoded_frame_count_ > 1) { -+ switch (decoder_->repetitionCount) { -+ case AVIF_REPETITION_COUNT_INFINITE: -+ return kAnimationLoopInfinite; -+ case AVIF_REPETITION_COUNT_UNKNOWN: -+ // The AVIF file does not have repetitions specified using an EditList -+ // box. Loop infinitely for backward compatibility with older versions -+ // of Chrome. -+ return kAnimationLoopInfinite; -+ default: -+ return decoder_->repetitionCount; -+ } -+ } -+ return kAnimationNone; -+} -+ -+bool AVIFImageDecoder::FrameIsReceivedAtIndex(wtf_size_t index) const { -+ if (!IsDecodedSizeAvailable()) { -+ return false; -+ } -+ if (decoded_frame_count_ == 1) { -+ return ImageDecoder::FrameIsReceivedAtIndex(index); -+ } -+ if (index >= frame_buffer_cache_.size()) { -+ return false; -+ } -+ if (IsAllDataReceived()) { -+ return true; -+ } -+ avifExtent data_extent; -+ if (avifDecoderNthImageMaxExtent(decoder_.get(), index, &data_extent) != -+ AVIF_RESULT_OK) { -+ return false; -+ } -+ return data_extent.size == 0 || -+ data_extent.offset + data_extent.size <= data_->size(); -+} -+ -+std::optional AVIFImageDecoder::FrameTimestampAtIndex( -+ wtf_size_t index) const { -+ return index < frame_buffer_cache_.size() -+ ? frame_buffer_cache_[index].Timestamp() -+ : std::nullopt; -+} -+ -+base::TimeDelta AVIFImageDecoder::FrameDurationAtIndex(wtf_size_t index) const { -+ return index < frame_buffer_cache_.size() -+ ? frame_buffer_cache_[index].Duration() -+ : base::TimeDelta(); -+} -+ -+bool AVIFImageDecoder::ImageHasBothStillAndAnimatedSubImages() const { -+ // Per MIAF, all animated AVIF files must have a still image, even if it's -+ // just a pointer to the first frame of the animation. -+ return decoder_ && decoder_->imageSequenceTrackPresent; -+} -+ -+// static -+bool AVIFImageDecoder::MatchesAVIFSignature( -+ const FastSharedBufferReader& fast_reader) { -+ // avifPeekCompatibleFileType() clamps compatible brands at 32 when reading in -+ // the ftyp box in ISO BMFF for the 'avif' or 'avis' brand. So the maximum -+ // number of bytes read is 144 bytes (size 4 bytes, type 4 bytes, major brand -+ // 4 bytes, minor version 4 bytes, and 4 bytes * 32 compatible brands). -+ char buffer[144]; -+ avifROData input; -+ input.size = std::min(sizeof(buffer), fast_reader.size()); -+ input.data = reinterpret_cast( -+ fast_reader.GetConsecutiveData(0, input.size, buffer)); -+ return avifPeekCompatibleFileType(&input); -+} -+ -+gfx::ColorSpace AVIFImageDecoder::GetColorSpaceForTesting() const { -+ const auto* image = GetDecoderImage(); -+ CHECK(image); -+ return GetColorSpace(image); -+} -+ -+void AVIFImageDecoder::ParseMetadata() { -+ if (!UpdateDemuxer()) { -+ SetFailed(); -+ } -+} -+ -+void AVIFImageDecoder::DecodeSize() { -+ ParseMetadata(); -+} -+ -+wtf_size_t AVIFImageDecoder::DecodeFrameCount() { -+ if (!Failed()) { -+ ParseMetadata(); -+ } -+ return IsDecodedSizeAvailable() ? decoded_frame_count_ -+ : frame_buffer_cache_.size(); -+} -+ -+void AVIFImageDecoder::InitializeNewFrame(wtf_size_t index) { -+ auto& buffer = frame_buffer_cache_[index]; -+ if (decode_to_half_float_) { -+ buffer.SetPixelFormat(ImageFrame::PixelFormat::kRGBA_F16); -+ } -+ -+ // For AVIFs, the frame always fills the entire image. -+ buffer.SetOriginalFrameRect(gfx::Rect(Size())); -+ -+ avifImageTiming timing; -+ auto ret = avifDecoderNthImageTiming(decoder_.get(), index, &timing); -+ DCHECK_EQ(ret, AVIF_RESULT_OK); -+ buffer.SetTimestamp(base::Seconds(timing.pts)); -+ buffer.SetDuration(base::Seconds(timing.duration)); -+} -+ -+void AVIFImageDecoder::Decode(wtf_size_t index) { -+ if (Failed()) { -+ return; -+ } -+ -+ UpdateAggressivePurging(index); -+ -+ int frame_index = index; -+ // If the image is decoded progressively, find the highest progressive -+ // frame that we have received and decode from that frame index. Internally -+ // decoder_ still decodes the lower progressive frames, but they are only used -+ // as reference frames and not rendered. -+ if (progressive_) { -+ DCHECK_EQ(index, 0u); -+ // decoder_->imageIndex is the current image index. decoder_->imageIndex is -+ // initialized to -1. decoder_->imageIndex + 1 is the next image index. -+ DCHECK_LT(decoder_->imageIndex + 1, decoder_->imageCount); -+ for (frame_index = decoder_->imageIndex + 1; -+ frame_index + 1 < decoder_->imageCount; ++frame_index) { -+ avifExtent data_extent; -+ auto rv = avifDecoderNthImageMaxExtent(decoder_.get(), frame_index + 1, -+ &data_extent); -+ if (rv != AVIF_RESULT_OK) { -+ DVLOG(1) << "avifDecoderNthImageMaxExtent(" << frame_index + 1 -+ << ") failed: " << avifResultToString(rv) << ": " -+ << AvifDecoderErrorMessage(decoder_.get()); -+ SetFailed(); -+ return; -+ } -+ if (data_extent.size != 0 && -+ data_extent.offset + data_extent.size > data_->size()) { -+ break; -+ } -+ } -+ } -+ -+ // Allow AVIF frames to be partially decoded before all data is received. -+ // Only enabled for non-progressive still images because animations look -+ // better without incremental decoding and because progressive decoding makes -+ // incremental decoding unnecessary. -+ decoder_->allowIncremental = (decoder_->imageCount == 1); -+ -+ auto ret = DecodeImage(frame_index); -+ if (ret != AVIF_RESULT_OK && ret != AVIF_RESULT_WAITING_ON_IO) { -+ SetFailed(); -+ return; -+ } -+ const avifImage* image = decoded_image_; -+ -+ // ImageDecoder::SizeCalculationMayOverflow(), called by UpdateDemuxer() -+ // before being here, made sure the image height fits in an int. -+ int displayable_height = -+ static_cast(avifDecoderDecodedRowCount(decoder_.get())); -+ if (image == cropped_image_.get()) { -+ displayable_height -= clap_origin_.y(); -+ displayable_height = -+ std::clamp(displayable_height, 0, static_cast(image->height)); -+ } -+ -+ if (displayable_height == 0) { -+ return; // There is nothing to display. -+ } -+ -+ ImageFrame& buffer = frame_buffer_cache_[index]; -+ DCHECK_NE(buffer.GetStatus(), ImageFrame::kFrameComplete); -+ -+ if (buffer.GetStatus() == ImageFrame::kFrameEmpty) { -+ if (!InitFrameBuffer(index)) { -+ DVLOG(1) << "Failed to create frame buffer..."; -+ SetFailed(); -+ return; -+ } -+ DCHECK_EQ(buffer.GetStatus(), ImageFrame::kFramePartial); -+ // The buffer is transparent outside the decoded area while the image is -+ // loading. The correct alpha value for the frame will be set when it is -+ // fully decoded. -+ buffer.SetHasAlpha(true); -+ if (decoder_->allowIncremental) { -+ // In case of buffer disposal after decoding. -+ incrementally_displayed_height_ = 0; -+ } -+ } -+ -+ const int last_displayed_height = -+ decoder_->allowIncremental ? incrementally_displayed_height_ : 0; -+ if (displayable_height == last_displayed_height) { -+ return; // There is no new row to display. -+ } -+ DCHECK_GT(displayable_height, last_displayed_height); -+ -+ // Only render the newly decoded rows. -+ if (!RenderImage(image, last_displayed_height, &displayable_height, -+ &buffer)) { -+ SetFailed(); -+ return; -+ } -+ if (displayable_height == last_displayed_height) { -+ return; // There is no new row to display. -+ } -+ DCHECK_GT(displayable_height, last_displayed_height); -+ ColorCorrectImage(last_displayed_height, displayable_height, &buffer); -+ buffer.SetPixelsChanged(true); -+ if (decoder_->allowIncremental) { -+ incrementally_displayed_height_ = displayable_height; -+ } -+ -+ if (static_cast(displayable_height) == image->height && -+ (!progressive_ || frame_index + 1 == decoder_->imageCount)) { -+ buffer.SetHasAlpha(!!image->alphaPlane); -+ buffer.SetStatus(ImageFrame::kFrameComplete); -+ PostDecodeProcessing(index); -+ } -+} -+ -+bool AVIFImageDecoder::CanReusePreviousFrameBuffer(wtf_size_t index) const { -+ // (a) Technically we can reuse the bitmap of the previous frame because the -+ // AVIF decoder handles frame dependence internally and we never need to -+ // preserve previous frames to decode later ones, and (b) since this function -+ // will not currently be called, this is really more for the reader than any -+ // functional purpose. -+ return true; -+} -+ -+// static -+avifResult AVIFImageDecoder::ReadFromSegmentReader(avifIO* io, -+ uint32_t read_flags, -+ uint64_t offset, -+ size_t size, -+ avifROData* out) { -+ if (read_flags != 0) { -+ // Unsupported read_flags -+ return AVIF_RESULT_IO_ERROR; -+ } -+ -+ AvifIOData* io_data = static_cast(io->data); -+ -+ // Sanitize/clamp incoming request -+ if (offset > io_data->reader->size()) { -+ // The offset is past the end of the buffer or available data. -+ return io_data->all_data_received ? AVIF_RESULT_IO_ERROR -+ : AVIF_RESULT_WAITING_ON_IO; -+ } -+ -+ // It is more convenient to work with a variable of the size_t type. Since -+ // offset <= io_data->reader->size() <= SIZE_MAX, this cast is safe. -+ size_t position = static_cast(offset); -+ const size_t available_size = io_data->reader->size() - position; -+ if (size > available_size) { -+ if (!io_data->all_data_received) { -+ return AVIF_RESULT_WAITING_ON_IO; -+ } -+ size = available_size; -+ } -+ -+ out->size = size; -+ -+ base::span data = io_data->reader->GetSomeData(position); -+ if (data.size() >= size) { -+ out->data = data.data(); -+ return AVIF_RESULT_OK; -+ } -+ -+ io_data->buffer.clear(); -+ io_data->buffer.reserve(size); -+ -+ while (size != 0) { -+ data = io_data->reader->GetSomeData(position); -+ size_t copy_size = std::min(data.size(), size); -+ io_data->buffer.insert(io_data->buffer.end(), data.begin(), data.end()); -+ position += copy_size; -+ size -= copy_size; -+ } -+ -+ out->data = io_data->buffer.data(); -+ return AVIF_RESULT_OK; -+} -+ -+bool AVIFImageDecoder::UpdateDemuxer() { -+ DCHECK(!Failed()); -+ if (IsDecodedSizeAvailable()) { -+ return true; -+ } -+ -+ if (have_parsed_current_data_) { -+ return true; -+ } -+ have_parsed_current_data_ = true; -+ -+ if (!decoder_) { -+ decoder_.reset(avifDecoderCreate()); -+ if (!decoder_) { -+ return false; -+ } -+ -+ // For simplicity, use a hardcoded maxThreads of 2, independent of the image -+ // size and processor count. Note: even if we want maxThreads to depend on -+ // the image size, it is impossible to do so because maxThreads is passed to -+ // dav1d_open() inside avifDecoderParse(), but the image size is not known -+ // until avifDecoderParse() returns successfully. See -+ // https://github.com/AOMediaCodec/libavif/issues/636. -+ decoder_->maxThreads = 2; -+ -+ if (animation_option_ != AnimationOption::kUnspecified && -+ avifDecoderSetSource( -+ decoder_.get(), -+ animation_option_ == AnimationOption::kPreferAnimation -+ ? AVIF_DECODER_SOURCE_TRACKS -+ : AVIF_DECODER_SOURCE_PRIMARY_ITEM) != AVIF_RESULT_OK) { -+ return false; -+ } -+ -+ // Chrome doesn't use XMP and Exif metadata. Ignoring XMP and Exif will -+ // ensure avifDecoderParse() isn't waiting for some tiny Exif payload hiding -+ // at the end of a file. -+ decoder_->ignoreXMP = AVIF_TRUE; -+ decoder_->ignoreExif = AVIF_TRUE; -+ -+ // Turn off libavif's 'clap' (clean aperture) property validation. We -+ // validate 'clap' ourselves and ignore invalid 'clap' properties. -+ decoder_->strictFlags &= ~AVIF_STRICT_CLAP_VALID; -+ // Allow the PixelInformationProperty ('pixi') to be missing in AV1 image -+ // items. libheif v1.11.0 or older does not add the 'pixi' item property to -+ // AV1 image items. (This issue has been corrected in libheif v1.12.0.) See -+ // crbug.com/1198455. -+ decoder_->strictFlags &= ~AVIF_STRICT_PIXI_REQUIRED; -+ -+ if (base::FeatureList::IsEnabled(features::kAvifGainmapHdrImages) && -+ aux_image_ == cc::AuxImage::kGainmap) { -+ decoder_->imageContentToDecode = AVIF_IMAGE_CONTENT_GAIN_MAP; -+ } -+ -+ avif_io_.destroy = nullptr; -+ avif_io_.read = ReadFromSegmentReader; -+ avif_io_.write = nullptr; -+ avif_io_.persistent = AVIF_FALSE; -+ avif_io_.data = &avif_io_data_; -+ avifDecoderSetIO(decoder_.get(), &avif_io_); -+ } -+ -+ // If all data is received, there is no point in decoding progressively. -+ decoder_->allowProgressive = !IsAllDataReceived(); -+ -+ auto ret = avifDecoderParse(decoder_.get()); -+ if (ret == AVIF_RESULT_WAITING_ON_IO) { -+ return true; -+ } -+ if (ret != AVIF_RESULT_OK) { -+ DVLOG(1) << "avifDecoderParse failed: " << avifResultToString(ret) << ". " -+ << decoder_->diag.error; -+ return false; -+ } -+ -+ // Image metadata is available in decoder_->image after avifDecoderParse() -+ // even though decoder_->imageIndex is invalid (-1). -+ DCHECK_EQ(decoder_->imageIndex, -1); -+ // This variable is named |container| to emphasize the fact that the current -+ // contents of decoder_->image come from the container, not any frame. -+ const auto* container = GetDecoderImage(); -+ if (!container) { -+ return false; -+ } -+ -+ // The container width and container height are read from either the tkhd -+ // (track header) box of a track or the ispe (image spatial extents) property -+ // of an image item, both of which are mandatory in the spec. -+ if (container->width == 0 || container->height == 0) { -+ DVLOG(1) << "Container width and height must be present"; -+ return false; -+ } -+ -+ // The container depth is read from either the av1C box of a track or the av1C -+ // property of an image item, both of which are mandatory in the spec. -+ if (container->depth == 0) { -+ DVLOG(1) << "Container depth must be present"; -+ return false; -+ } -+ -+ DCHECK_GT(decoder_->imageCount, 0); -+ progressive_ = decoder_->progressiveState == AVIF_PROGRESSIVE_STATE_ACTIVE; -+ // If the image is progressive, decoder_->imageCount is the number of -+ // progressive frames, but there is only one still image. -+ decoded_frame_count_ = progressive_ ? 1 : decoder_->imageCount; -+ container_width_ = container->width; -+ container_height_ = container->height; -+ bit_depth_ = container->depth; -+ decode_to_half_float_ = -+ ImageIsHighBitDepth() && -+ high_bit_depth_decoding_option_ == kHighBitDepthToHalfFloat; -+ -+ // Verify that AVIF_PIXEL_FORMAT_{YUV444,YUV422,YUV420,YUV400} are -+ // consecutive. -+ static_assert(AVIF_PIXEL_FORMAT_YUV422 == AVIF_PIXEL_FORMAT_YUV444 + 1); -+ static_assert(AVIF_PIXEL_FORMAT_YUV420 == AVIF_PIXEL_FORMAT_YUV422 + 1); -+ static_assert(AVIF_PIXEL_FORMAT_YUV400 == AVIF_PIXEL_FORMAT_YUV420 + 1); -+ // Assert that after avifDecoderParse() returns AVIF_RESULT_OK, -+ // decoder_->image->yuvFormat (the same as container->yuvFormat) is one of the -+ // four YUV formats in AV1. -+ CHECK(container->yuvFormat >= AVIF_PIXEL_FORMAT_YUV444 && -+ container->yuvFormat <= AVIF_PIXEL_FORMAT_YUV400) -+ << "Invalid YUV format: " << container->yuvFormat; -+ avif_yuv_format_ = container->yuvFormat; -+ avifPixelFormatInfo format_info; -+ avifGetPixelFormatInfo(container->yuvFormat, &format_info); -+ chroma_shift_x_ = format_info.chromaShiftX; -+ chroma_shift_y_ = format_info.chromaShiftY; -+ -+ if (container->clli.maxCLL || container->clli.maxPALL) { -+ hdr_metadata_ = gfx::HDRMetadata(); -+ hdr_metadata_->cta_861_3 = gfx::HdrMetadataCta861_3( -+ container->clli.maxCLL, container->clli.maxPALL); -+ } -+ -+ // SetEmbeddedColorProfile() must be called before IsSizeAvailable() becomes -+ // true. So call SetEmbeddedColorProfile() before calling SetSize(). The color -+ // profile is either an ICC profile or the CICP color description. -+ -+ if (!IgnoresColorSpace()) { -+ // The CICP color description is always present because we can always get it -+ // from the AV1 sequence header for the frames. If an ICC profile is -+ // present, use it instead of the CICP color description. -+ if (container->icc.size) { -+ std::unique_ptr profile = ColorProfile::Create( -+ base::span(container->icc.data, container->icc.size)); -+ if (!profile) { -+ DVLOG(1) << "Failed to parse image ICC profile"; -+ return false; -+ } -+ uint32_t data_color_space = profile->GetProfile()->data_color_space; -+ const bool is_mono = container->yuvFormat == AVIF_PIXEL_FORMAT_YUV400; -+ if (is_mono) { -+ if (data_color_space != skcms_Signature_Gray && -+ data_color_space != skcms_Signature_RGB) { -+ profile = nullptr; -+ } -+ } else { -+ if (data_color_space != skcms_Signature_RGB) { -+ profile = nullptr; -+ } -+ } -+ if (!profile) { -+ DVLOG(1) -+ << "Image contains ICC profile that does not match its color space"; -+ return false; -+ } -+ SetEmbeddedColorProfile(std::move(profile)); -+ } else if (container->colorPrimaries != AVIF_COLOR_PRIMARIES_UNSPECIFIED || -+ container->transferCharacteristics != -+ AVIF_TRANSFER_CHARACTERISTICS_UNSPECIFIED) { -+ gfx::ColorSpace frame_cs = GetColorSpace(container); -+ -+ sk_sp sk_color_space = -+ frame_cs.GetAsFullRangeRGB().ToSkColorSpace(); -+ if (!sk_color_space) { -+ DVLOG(1) << "Image contains an unsupported color space"; -+ return false; -+ } -+ -+ skcms_ICCProfile profile; -+ sk_color_space->toProfile(&profile); -+ SetEmbeddedColorProfile(std::make_unique(profile)); -+ } -+ } -+ -+ // |angle| * 90 specifies the angle of anti-clockwise rotation in degrees. -+ // Legal values: [0-3]. -+ int angle = 0; -+ if (container->transformFlags & AVIF_TRANSFORM_IROT) { -+ angle = container->irot.angle; -+ CHECK_LT(angle, 4); -+ } -+ // |axis| specifies how the mirroring is performed. -+ // -1: No mirroring. -+ // 0: The top and bottom parts of the image are exchanged. -+ // 1: The left and right parts of the image are exchanged. -+ int axis = -1; -+ if (container->transformFlags & AVIF_TRANSFORM_IMIR) { -+ axis = container->imir.axis; -+ CHECK_LT(axis, 2); -+ } -+ // MIAF Section 7.3.6.7 (Clean aperture, rotation and mirror) says: -+ // These properties, if used, shall be indicated to be applied in the -+ // following order: clean aperture first, then rotation, then mirror. -+ // -+ // In the kAxisAngleToOrientation array, the first dimension is axis (with an -+ // offset of 1). The second dimension is angle. -+ constexpr std::array, 3> -+ kAxisAngleToOrientation = {{ -+ // No mirroring. -+ {ImageOrientationEnum::kOriginTopLeft, -+ ImageOrientationEnum::kOriginLeftBottom, -+ ImageOrientationEnum::kOriginBottomRight, -+ ImageOrientationEnum::kOriginRightTop}, -+ // Top-to-bottom mirroring. Change Top<->Bottom in the first row. -+ {ImageOrientationEnum::kOriginBottomLeft, -+ ImageOrientationEnum::kOriginLeftTop, -+ ImageOrientationEnum::kOriginTopRight, -+ ImageOrientationEnum::kOriginRightBottom}, -+ // Left-to-right mirroring. Change Left<->Right in the first row. -+ {ImageOrientationEnum::kOriginTopRight, -+ ImageOrientationEnum::kOriginRightBottom, -+ ImageOrientationEnum::kOriginBottomLeft, -+ ImageOrientationEnum::kOriginLeftTop}, -+ }}; -+ orientation_ = kAxisAngleToOrientation[axis + 1][angle]; -+ -+ // Determine whether the image can be decoded to YUV. -+ // * Alpha channel is not supported. -+ // * Multi-frame images (animations) are not supported. (The DecodeToYUV() -+ // method does not have an 'index' parameter.) -+ allow_decode_to_yuv_ = -+ avif_yuv_format_ != AVIF_PIXEL_FORMAT_YUV400 && !decoder_->alphaPresent && -+ decoded_frame_count_ == 1 && -+ GetColorSpace(container).ToSkYUVColorSpace(container->depth, -+ &yuv_color_space_) && -+ // TODO(crbug.com/911246): Support color space transforms for YUV decodes. -+ !ColorTransform(); -+ -+ // Record bpp information only for 8-bit, color, still images that do not have -+ // alpha. -+ if (container->depth == 8 && avif_yuv_format_ != AVIF_PIXEL_FORMAT_YUV400 && -+ !decoder_->alphaPresent && decoded_frame_count_ == 1) { -+ static constexpr char kType[] = "Avif"; -+ update_bpp_histogram_callback_ = base::BindOnce(&UpdateBppHistogram); -+ } -+ -+ unsigned width = container->width; -+ unsigned height = container->height; -+ // If the image is cropped, pass the size of the cropped image (the clean -+ // aperture) to SetSize(). -+ if (container->transformFlags & AVIF_TRANSFORM_CLAP) { -+ AVIFCleanApertureType clap_type; -+ avifCropRect crop_rect; -+ avifDiagnostics diag; -+ avifBool valid_clap = avifCropRectConvertCleanApertureBox( -+ &crop_rect, &container->clap, container->width, container->height, -+ container->yuvFormat, &diag); -+ if (!valid_clap) { -+ DVLOG(1) << "Invalid 'clap' property: " << diag.error -+ << "; showing the full image."; -+ clap_type = AVIFCleanApertureType::kInvalid; -+ ignore_clap_ = true; -+ } else if (crop_rect.x != 0 || crop_rect.y != 0) { -+ // To help discourage the creation of files with privacy risks, also -+ // consider 'clap' properties whose origins are not at (0, 0) as invalid. -+ // See https://github.com/AOMediaCodec/av1-avif/issues/188 and -+ // https://github.com/AOMediaCodec/av1-avif/issues/189. -+ DVLOG(1) << "Origin of 'clap' property anchored to (" << crop_rect.x -+ << ", " << crop_rect.y << "); showing the full image."; -+ clap_type = AVIFCleanApertureType::kNonzeroOrigin; -+ ignore_clap_ = true; -+ } else { -+ clap_type = AVIFCleanApertureType::kZeroOrigin; -+ clap_origin_.SetPoint(crop_rect.x, crop_rect.y); -+ width = crop_rect.width; -+ height = crop_rect.height; -+ } -+ clap_type_ = clap_type; -+ } -+ return SetSize(width, height); -+} -+ -+avifResult AVIFImageDecoder::DecodeImage(wtf_size_t index) { -+ const auto ret = avifDecoderNthImage(decoder_.get(), index); -+ // |index| should be less than what DecodeFrameCount() returns, so we should -+ // not get the AVIF_RESULT_NO_IMAGES_REMAINING error. -+ DCHECK_NE(ret, AVIF_RESULT_NO_IMAGES_REMAINING); -+ if (ret != AVIF_RESULT_OK && ret != AVIF_RESULT_WAITING_ON_IO) { -+ DVLOG(1) << "avifDecoderNthImage(" << index -+ << ") failed: " << avifResultToString(ret) << ": " -+ << AvifDecoderErrorMessage(decoder_.get()); -+ return ret; -+ } -+ -+ const auto* image = GetDecoderImage(); -+ CHECK(image); -+ // Frame size must be equal to container size. -+ if (image->width != container_width_ || image->height != container_height_) { -+ DVLOG(1) << "Frame size " << image->width << "x" << image->height -+ << " differs from container size " << container_width_ << "x" -+ << container_height_; -+ return AVIF_RESULT_UNKNOWN_ERROR; -+ } -+ // Frame bit depth must be equal to container bit depth. -+ if (image->depth != bit_depth_) { -+ DVLOG(1) << "Frame bit depth must be equal to container bit depth"; -+ return AVIF_RESULT_UNKNOWN_ERROR; -+ } -+ // Frame YUV format must be equal to container YUV format. -+ if (image->yuvFormat != avif_yuv_format_) { -+ DVLOG(1) << "Frame YUV format must be equal to container YUV format"; -+ return AVIF_RESULT_UNKNOWN_ERROR; -+ } -+ -+ decoded_image_ = image; -+ if ((image->transformFlags & AVIF_TRANSFORM_CLAP) && !ignore_clap_) { -+ CropDecodedImage(); -+ } -+ -+ if (ret == AVIF_RESULT_OK) { -+ if (IsAllDataReceived() && update_bpp_histogram_callback_) { -+ std::move(update_bpp_histogram_callback_).Run(Size(), data_->size()); -+ } -+ -+ if (clap_type_.has_value()) { -+ base::UmaHistogramEnumeration("Blink.ImageDecoders.Avif.CleanAperture", -+ clap_type_.value()); -+ clap_type_.reset(); -+ } -+ } -+ return ret; -+} -+ -+void AVIFImageDecoder::CropDecodedImage() { -+ DCHECK_NE(decoded_image_, cropped_image_.get()); -+ if (!cropped_image_) { -+ cropped_image_.reset(avifImageCreateEmpty()); -+ } -+ avifCropRect rect; -+ rect.x = clap_origin_.x(); -+ rect.y = clap_origin_.y(); -+ rect.width = Size().width(); -+ rect.height = Size().height(); -+ const avifResult result = -+ avifImageSetViewRect(cropped_image_.get(), decoded_image_, &rect); -+ CHECK_EQ(result, AVIF_RESULT_OK); -+ decoded_image_ = cropped_image_.get(); -+} -+ -+bool AVIFImageDecoder::RenderImage(const avifImage* image, -+ int from_row, -+ int* to_row, -+ ImageFrame* buffer) { -+ DCHECK_LT(from_row, *to_row); -+ -+ // libavif uses libyuv for the YUV 4:2:0 to RGB upsampling and/or conversion -+ // as follows: -+ // - convert the top RGB row 0, -+ // - convert the RGB rows 1 and 2, then RGB rows 3 and 4 etc., -+ // - convert the bottom (odd) RGB row if there is an even number of RGB rows. -+ // -+ // Unfortunately this cannot be applied incrementally as is. The RGB values -+ // would differ because the first and last RGB rows have a formula using only -+ // one UV row, while the other RGB rows use two UV rows as input each. -+ // See https://crbug.com/libyuv/934. -+ // -+ // The workaround is a backup of the last converted even RGB row, called top -+ // row, located right before |from_row|. The conversion is then called -+ // starting at this top row, overwriting it with invalid values. The remaining -+ // pairs of rows are correctly aligned and their freshly converted values are -+ // valid. Then the backed up row is put back, fixing the issue. -+ // The bottom row is postponed if the other half of the pair it belongs to is -+ // not yet decoded. -+ // -+ // UV rows | Y/RGB rows -+ // | all | first decoding | second decoding -+ // ____ 0 ____ 0 (from_row) -+ // 0 ---- ____ 1 ____ 1 -+ // ____ 2 ____ 2 ____ 2 (backed up) -+ // 1 ---- ____ 3 ____ 3 (postponed) ____ 3 (from_row) -+ // ____ 4 4 (*to_row) ____ 4 -+ // 2 ---- ____ 5 ____ 5 -+ // 6 (*to_row) -+ -+ const bool use_libyuv_bilinear_upsampling = -+ !decode_to_half_float_ && image->yuvFormat == AVIF_PIXEL_FORMAT_YUV420; -+ const bool save_top_row = use_libyuv_bilinear_upsampling && from_row > 0; -+ const bool postpone_bottom_row = -+ use_libyuv_bilinear_upsampling && -+ static_cast(*to_row) < image->height; -+ if (postpone_bottom_row) { -+ // libavif outputs an even number of rows because 4:2:0 samples are decoded -+ // in pairs. -+ DCHECK(!(*to_row & 1)); -+ --*to_row; -+ if (from_row == *to_row) { -+ return true; // Nothing to do. -+ } -+ } -+ if (save_top_row) { -+ // |from_row| is odd because it is equal to the output value of |*to_row| -+ // from the previous RenderImage() call, and |*to_row| was even and then -+ // decremented at that time. -+ DCHECK(from_row & 1); -+ --from_row; -+ } -+ -+ // Focus |image| on rows [from_row, *to_row). -+ std::unique_ptr view( -+ nullptr, avifImageDestroy); -+ if (from_row > 0 || static_cast(*to_row) < image->height) { -+ const avifCropRect rect = {0, static_cast(from_row), image->width, -+ static_cast(*to_row - from_row)}; -+ view.reset(avifImageCreateEmpty()); -+ const avifResult result = avifImageSetViewRect(view.get(), image, &rect); -+ CHECK_EQ(result, AVIF_RESULT_OK); -+ image = view.get(); -+ } -+ -+ avifRGBImage rgb_image; -+ avifRGBImageSetDefaults(&rgb_image, image); -+ -+ if (decode_to_half_float_) { -+ rgb_image.depth = 16; -+ rgb_image.isFloat = AVIF_TRUE; -+ rgb_image.pixels = -+ reinterpret_cast(buffer->GetAddrF16(0, from_row)); -+ rgb_image.rowBytes = image->width * sizeof(uint64_t); -+ // When decoding to half float, the pixel ordering is always RGBA on all -+ // platforms. -+ rgb_image.format = AVIF_RGB_FORMAT_RGBA; -+ } else { -+ rgb_image.depth = 8; -+ rgb_image.pixels = reinterpret_cast(buffer->GetAddr(0, from_row)); -+ rgb_image.rowBytes = image->width * sizeof(uint32_t); -+ // When decoding to 8-bit, Android uses little-endian RGBA pixels. All other -+ // platforms use BGRA pixels. -+ static_assert(SK_B32_SHIFT == 16 - SK_R32_SHIFT); -+ static_assert(SK_G32_SHIFT == 8); -+ static_assert(SK_A32_SHIFT == 24); -+#if SK_B32_SHIFT -+ rgb_image.format = AVIF_RGB_FORMAT_RGBA; -+#else -+ rgb_image.format = AVIF_RGB_FORMAT_BGRA; -+#endif -+ } -+ rgb_image.alphaPremultiplied = buffer->PremultiplyAlpha(); -+ rgb_image.maxThreads = decoder_->maxThreads; -+ -+ if (save_top_row) { -+ previous_last_decoded_row_.resize(rgb_image.rowBytes); -+ memcpy(previous_last_decoded_row_.data(), rgb_image.pixels, -+ rgb_image.rowBytes); -+ } -+ const avifResult result = avifImageYUVToRGB(image, &rgb_image); -+ if (save_top_row) { -+ memcpy(rgb_image.pixels, previous_last_decoded_row_.data(), -+ rgb_image.rowBytes); -+ } -+ return result == AVIF_RESULT_OK; -+} -+ -+void AVIFImageDecoder::ColorCorrectImage(int from_row, -+ int to_row, -+ ImageFrame* buffer) { -+ // Postprocess the image data according to the profile. -+ const ColorProfileTransform* const transform = ColorTransform(); -+ if (!transform) { -+ return; -+ } -+ const auto alpha_format = (buffer->HasAlpha() && buffer->PremultiplyAlpha()) -+ ? skcms_AlphaFormat_PremulAsEncoded -+ : skcms_AlphaFormat_Unpremul; -+ if (decode_to_half_float_) { -+ const skcms_PixelFormat color_format = skcms_PixelFormat_RGBA_hhhh; -+ for (int y = from_row; y < to_row; ++y) { -+ ImageFrame::PixelDataF16* const row = buffer->GetAddrF16(0, y); -+ const bool success = skcms_Transform( -+ row, color_format, alpha_format, transform->SrcProfile(), row, -+ color_format, alpha_format, transform->DstProfile(), Size().width()); -+ DCHECK(success); -+ } -+ } else { -+ const skcms_PixelFormat color_format = XformColorFormat(); -+ for (int y = from_row; y < to_row; ++y) { -+ ImageFrame::PixelData* const row = buffer->GetAddr(0, y); -+ const bool success = skcms_Transform( -+ row, color_format, alpha_format, transform->SrcProfile(), row, -+ color_format, alpha_format, transform->DstProfile(), Size().width()); -+ DCHECK(success); -+ } -+ } -+} -+ -+bool AVIFImageDecoder::GetGainmapInfoAndData( -+ SkGainmapInfo& out_gainmap_info, -+ scoped_refptr& out_gainmap_data) const { -+ if (!base::FeatureList::IsEnabled(features::kAvifGainmapHdrImages)) { -+ return false; -+ } -+ // Ensure that parsing succeeded. -+ if (!IsDecodedSizeAvailable()) { -+ return false; -+ } -+ if (!decoder_->image->gainMap) { -+ return false; -+ } -+ const avifGainMap& gain_map = *decoder_->image->gainMap; -+ if (gain_map.baseHdrHeadroom.d == 0 || gain_map.alternateHdrHeadroom.d == 0) { -+ DVLOG(1) << "Invalid gainmap metadata: a denominator value is zero"; -+ return false; -+ } -+ const float base_headroom = std::exp2( -+ FractionToFloat(gain_map.baseHdrHeadroom.n, gain_map.baseHdrHeadroom.d)); -+ const float alternate_headroom = std::exp2(FractionToFloat( -+ gain_map.alternateHdrHeadroom.n, gain_map.alternateHdrHeadroom.d)); -+ const bool base_is_hdr = base_headroom > alternate_headroom; -+ out_gainmap_info.fDisplayRatioSdr = -+ base_is_hdr ? alternate_headroom : base_headroom; -+ out_gainmap_info.fDisplayRatioHdr = -+ base_is_hdr ? base_headroom : alternate_headroom; -+ out_gainmap_info.fBaseImageType = base_is_hdr -+ ? SkGainmapInfo::BaseImageType::kHDR -+ : SkGainmapInfo::BaseImageType::kSDR; -+ if (!gain_map.useBaseColorSpace) { -+ // Try to use the alternate image's color space. -+ out_gainmap_info.fGainmapMathColorSpace = -+ GetAltImageColorSpace(*decoder_->image); -+ } -+ for (int i = 0; i < 3; ++i) { -+ if (gain_map.gainMapMin[i].d == 0 || gain_map.gainMapMax[i].d == 0 || -+ gain_map.gainMapGamma[i].d == 0 || gain_map.baseOffset[i].d == 0 || -+ gain_map.alternateOffset[i].d == 0) { -+ DVLOG(1) << "Invalid gainmap metadata: a denominator value is zero"; -+ return false; -+ } -+ if (gain_map.gainMapGamma[i].n == 0) { -+ DVLOG(1) << "Invalid gainmap metadata: gamma is zero"; -+ return false; -+ } -+ -+ const float min_log2 = -+ FractionToFloat(gain_map.gainMapMin[i].n, gain_map.gainMapMin[i].d); -+ const float max_log2 = -+ FractionToFloat(gain_map.gainMapMax[i].n, gain_map.gainMapMax[i].d); -+ out_gainmap_info.fGainmapRatioMin[i] = std::exp2(min_log2); -+ out_gainmap_info.fGainmapRatioMax[i] = std::exp2(max_log2); -+ -+ // Numerator and denominator intentionally swapped to get 1.0/gamma. -+ out_gainmap_info.fGainmapGamma[i] = -+ FractionToFloat(gain_map.gainMapGamma[i].d, gain_map.gainMapGamma[i].n); -+ const float base_offset = -+ FractionToFloat(gain_map.baseOffset[i].n, gain_map.baseOffset[i].d); -+ const float alternate_offset = FractionToFloat( -+ gain_map.alternateOffset[i].n, gain_map.alternateOffset[i].d); -+ out_gainmap_info.fEpsilonSdr[i] = -+ base_is_hdr ? alternate_offset : base_offset; -+ out_gainmap_info.fEpsilonHdr[i] = -+ base_is_hdr ? base_offset : alternate_offset; -+ } -+ out_gainmap_data = data_; -+ return true; -+} -+ -+avifImage* AVIFImageDecoder::GetDecoderImage() const { -+ if (aux_image_ == cc::AuxImage::kGainmap) { -+ if (!decoder_->image->gainMap) { -+ DVLOG(1) << "Attempted to access gain map image, but gainMap is nullptr"; -+ return nullptr; -+ } -+ return decoder_->image->gainMap->image; -+ } -+ return decoder_->image; -+} -+ -+AVIFImageDecoder::AvifIOData::AvifIOData() = default; -+AVIFImageDecoder::AvifIOData::AvifIOData( -+ scoped_refptr reader, -+ bool all_data_received) -+ : reader(std::move(reader)), all_data_received(all_data_received) {} -+AVIFImageDecoder::AvifIOData::~AvifIOData() = default; -+ -+} // namespace blink -diff --git a/third_party/blink/renderer/platform/image-decoders/avif/avif_image_decoder.h b/third_party/blink/renderer/platform/image-decoders/avif/avif_image_decoder.h -new file mode 100644 -index 0000000000000..75247663ef158 ---- /dev/null -+++ b/third_party/blink/renderer/platform/image-decoders/avif/avif_image_decoder.h -@@ -0,0 +1,191 @@ -+// Copyright 2020 The Chromium Authors -+// Use of this source code is governed by a BSD-style license that can be -+// found in the LICENSE file. -+ -+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_IMAGE_DECODERS_AVIF_AVIF_IMAGE_DECODER_H_ -+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_IMAGE_DECODERS_AVIF_AVIF_IMAGE_DECODER_H_ -+ -+#include -+#include -+ -+#include "base/functional/callback.h" -+#include "third_party/blink/renderer/platform/allow_discouraged_type.h" -+#include "third_party/blink/renderer/platform/image-decoders/image_decoder.h" -+#include "third_party/blink/renderer/platform/wtf/vector.h" -+#include "third_party/libavif/src/include/avif/avif.h" -+#include "third_party/skia/include/core/SkImageInfo.h" -+#include "ui/gfx/color_space.h" -+#include "ui/gfx/geometry/point.h" -+ -+namespace blink { -+ -+class FastSharedBufferReader; -+ -+class PLATFORM_EXPORT AVIFImageDecoder final : public ImageDecoder { -+ public: -+ AVIFImageDecoder(AlphaOption, -+ HighBitDepthDecodingOption, -+ ColorBehavior, -+ cc::AuxImage, -+ wtf_size_t max_decoded_bytes, -+ AnimationOption); -+ AVIFImageDecoder(const AVIFImageDecoder&) = delete; -+ AVIFImageDecoder& operator=(const AVIFImageDecoder&) = delete; -+ ~AVIFImageDecoder() override; -+ -+ // ImageDecoder: -+ String FilenameExtension() const override; -+ const AtomicString& MimeType() const override; -+ bool ImageIsHighBitDepth() override; -+ void OnSetData(scoped_refptr data) override; -+ bool GetGainmapInfoAndData( -+ SkGainmapInfo& out_gainmap_info, -+ scoped_refptr& out_gainmap_data) const override; -+ cc::YUVSubsampling GetYUVSubsampling() const override; -+ gfx::Size DecodedYUVSize(cc::YUVIndex) const override; -+ wtf_size_t DecodedYUVWidthBytes(cc::YUVIndex) const override; -+ SkYUVColorSpace GetYUVColorSpace() const override; -+ uint8_t GetYUVBitDepth() const override; -+ std::optional GetHDRMetadata() const override; -+ void DecodeToYUV() override; -+ int RepetitionCount() const override; -+ bool FrameIsReceivedAtIndex(wtf_size_t) const override; -+ std::optional FrameTimestampAtIndex( -+ wtf_size_t) const override; -+ base::TimeDelta FrameDurationAtIndex(wtf_size_t) const override; -+ bool ImageHasBothStillAndAnimatedSubImages() const override; -+ -+ // Returns true if the data in fast_reader begins with a valid FileTypeBox -+ // (ftyp) that supports the brand 'avif' or 'avis'. -+ static bool MatchesAVIFSignature(const FastSharedBufferReader& fast_reader); -+ -+ gfx::ColorSpace GetColorSpaceForTesting() const; -+ -+ private: -+ // If the AVIF image has a clean aperture ('clap') property, what kind of -+ // clean aperture it is. Values synced with 'AVIFCleanApertureType' in -+ // src/tools/metrics/histograms/enums.xml. -+ // -+ // These values are persisted to logs. Entries should not be renumbered and -+ // numeric values should never be reused. -+ enum class AVIFCleanApertureType { -+ kInvalid = 0, // The clean aperture property is invalid. -+ kNonzeroOrigin = 1, // The origin of the clean aperture is not (0, 0). -+ kZeroOrigin = 2, // The origin of the clean aperture is (0, 0). -+ kMaxValue = kZeroOrigin, -+ }; -+ -+ struct AvifIOData { -+ AvifIOData(); -+ AvifIOData(scoped_refptr reader, -+ bool all_data_received); -+ ~AvifIOData(); -+ -+ scoped_refptr reader; -+ std::vector buffer ALLOW_DISCOURAGED_TYPE("Required by libavif"); -+ bool all_data_received = false; -+ }; -+ -+ void ParseMetadata(); -+ -+ // ImageDecoder: -+ void DecodeSize() override; -+ wtf_size_t DecodeFrameCount() override; -+ void InitializeNewFrame(wtf_size_t) override; -+ void Decode(wtf_size_t) override; -+ bool CanReusePreviousFrameBuffer(wtf_size_t) const override; -+ -+ // Implements avifIOReadFunc, the |read| function in the avifIO struct. -+ static avifResult ReadFromSegmentReader(avifIO* io, -+ uint32_t read_flags, -+ uint64_t offset, -+ size_t size, -+ avifROData* out); -+ -+ // Creates |decoder_| if not yet created and decodes the size and frame count. -+ bool UpdateDemuxer(); -+ -+ // Decodes the frame at index |index| and checks if the frame's size, bit -+ // depth, and YUV format matches those reported by the container. The decoded -+ // frame is available in decoded_image_. -+ avifResult DecodeImage(wtf_size_t index); -+ -+ // Crops |decoded_image_|. -+ void CropDecodedImage(); -+ -+ // Renders the rows [from_row, *to_row) of |image| to |buffer|. Returns -+ // whether |image| was rendered successfully. On return, the in/out argument -+ // |*to_row| may be decremented in case of subsampled chroma needing more -+ // data. -+ bool RenderImage(const avifImage* image, -+ int from_row, -+ int* to_row, -+ ImageFrame* buffer); -+ -+ // Applies color profile correction to the rows [from_row, to_row) of -+ // |buffer|, if desired. -+ void ColorCorrectImage(int from_row, int to_row, ImageFrame* buffer); -+ -+ // Returns decoder_->image or decoder_->image->gainMap->image depending on -+ // aux_image_. May be nullptr if requesting the gain map image -+ // (cc::AuxImage::kGainmap) but no gain map is present. -+ avifImage* GetDecoderImage() const; -+ -+ bool have_parsed_current_data_ = false; -+ // The image width and height (before cropping, if any) from the container. -+ // -+ // Note: container_width_, container_height_, decoder_->image->width, and -+ // decoder_->image->height are the width and height of the full image. Size() -+ // returns the size of the cropped image (the clean aperture). -+ uint32_t container_width_ = 0; -+ uint32_t container_height_ = 0; -+ // The bit depth from the container. -+ uint8_t bit_depth_ = 0; -+ bool decode_to_half_float_ = false; -+ uint8_t chroma_shift_x_ = 0; -+ uint8_t chroma_shift_y_ = 0; -+ std::optional hdr_metadata_; -+ bool progressive_ = false; -+ // Number of displayed rows for a non-progressive still image. -+ int incrementally_displayed_height_ = 0; -+ // The YUV format from the container. -+ avifPixelFormat avif_yuv_format_ = AVIF_PIXEL_FORMAT_NONE; -+ wtf_size_t decoded_frame_count_ = 0; -+ SkYUVColorSpace yuv_color_space_ = SkYUVColorSpace::kIdentity_SkYUVColorSpace; -+ // Used to call UpdateBppHistogram<"Avif">() at most once to record the -+ // bits-per-pixel value of the image when the image is successfully decoded. -+ base::OnceCallback update_bpp_histogram_callback_; -+ std::optional clap_type_; -+ // Whether the 'clap' (clean aperture) property should be ignored, e.g. -+ // because the 'clap' property is invalid or unsupported. -+ bool ignore_clap_ = false; -+ // The origin (top left corner) of the clean aperture. Used only when the -+ // image has a valid 'clap' (clean aperture) property. -+ gfx::Point clap_origin_; -+ // A copy of decoder_->image with the width, height, and plane buffers -+ // adjusted to those of the clean aperture. Used only when the image has a -+ // 'clap' (clean aperture) property. -+ std::unique_ptr cropped_image_{ -+ nullptr, avifImageDestroy}; -+ // Set by a successful DecodeImage() call to either decoder_->image or -+ // cropped_image_.get() depending on whether the image has a 'clap' (clean -+ // aperture) property. -+ raw_ptr decoded_image_ = nullptr; -+ // The declaration order of the next three fields is important. decoder_ -+ // points to avif_io_, and avif_io_ points to avif_io_data_. The destructor -+ // must destroy them in that order. -+ AvifIOData avif_io_data_; -+ avifIO avif_io_ = {}; -+ std::unique_ptr decoder_{ -+ nullptr, avifDecoderDestroy}; -+ -+ const AnimationOption animation_option_; -+ -+ // Used temporarily for incremental decoding and for some YUV to RGB color -+ // conversions. -+ Vector previous_last_decoded_row_; -+}; -+ -+} // namespace blink -+ -+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_IMAGE_DECODERS_AVIF_AVIF_IMAGE_DECODER_H_ -diff --git a/third_party/blink/renderer/platform/image-decoders/avif/avif_image_decoder_fuzzer.cc b/third_party/blink/renderer/platform/image-decoders/avif/avif_image_decoder_fuzzer.cc -new file mode 100644 -index 0000000000000..f337ad075244a ---- /dev/null -+++ b/third_party/blink/renderer/platform/image-decoders/avif/avif_image_decoder_fuzzer.cc -@@ -0,0 +1,30 @@ -+// Copyright 2024 The Chromium Authors -+// Use of this source code is governed by a BSD-style license that can be -+// found in the LICENSE file. -+ -+#include "third_party/blink/renderer/platform/image-decoders/avif/avif_image_decoder.h" -+ -+#include -+#include -+#include -+ -+#include -+ -+#include "third_party/blink/renderer/platform/graphics/color_behavior.h" -+#include "third_party/blink/renderer/platform/image-decoders/image_decoder.h" -+#include "third_party/blink/renderer/platform/image-decoders/image_decoder_fuzzer_utils.h" -+#include "third_party/blink/renderer/platform/testing/blink_fuzzer_test_support.h" -+#include "third_party/blink/renderer/platform/testing/task_environment.h" -+#include "third_party/blink/renderer/platform/wtf/shared_buffer.h" -+#include "third_party/blink/renderer/platform/wtf/wtf_size_t.h" -+ -+namespace blink { -+ -+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { -+ static BlinkFuzzerTestSupport test_support; -+ FuzzedDataProvider fdp(data, size); -+ FuzzDecoder(DecoderType::kAvifDecoder, fdp); -+ return 0; -+} -+ -+} // namespace blink -diff --git a/third_party/blink/renderer/platform/image-decoders/avif/avif_image_decoder_test.cc b/third_party/blink/renderer/platform/image-decoders/avif/avif_image_decoder_test.cc -new file mode 100644 -index 0000000000000..9ec2b420bdf7d ---- /dev/null -+++ b/third_party/blink/renderer/platform/image-decoders/avif/avif_image_decoder_test.cc -@@ -0,0 +1,1758 @@ -+// Copyright 2020 The Chromium Authors -+// Use of this source code is governed by a BSD-style license that can be -+// found in the LICENSE file. -+ -+#ifdef UNSAFE_BUFFERS_BUILD -+// TODO(crbug.com/351564777): Remove this and convert code to safer constructs. -+#pragma allow_unsafe_buffers -+#endif -+ -+#include "third_party/blink/renderer/platform/image-decoders/avif/avif_image_decoder.h" -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include "base/barrier_closure.h" -+#include "base/bit_cast.h" -+#include "base/functional/bind.h" -+#include "base/strings/stringprintf.h" -+#include "base/synchronization/waitable_event.h" -+#include "base/task/thread_pool.h" -+#include "base/test/metrics/histogram_tester.h" -+#include "base/test/scoped_feature_list.h" -+#include "base/test/task_environment.h" -+#include "testing/gtest/include/gtest/gtest.h" -+#include "third_party/blink/public/common/features.h" -+#include "third_party/blink/public/platform/platform.h" -+#include "third_party/blink/renderer/platform/image-decoders/image_decoder_test_helpers.h" -+#include "third_party/blink/renderer/platform/wtf/shared_buffer.h" -+#include "ui/gfx/color_space.h" -+#include "ui/gfx/color_transform.h" -+ -+#define FIXME_SUPPORT_ICC_PROFILE_NO_TRANSFORM 0 -+#define FIXME_SUPPORT_ICC_PROFILE_TRANSFORM 0 -+#define FIXME_DISTINGUISH_LOSSY_OR_LOSSLESS 0 -+ -+namespace blink { -+ -+namespace { -+ -+std::unique_ptr CreateAVIFDecoderWithOptions( -+ ImageDecoder::AlphaOption alpha_option, -+ ImageDecoder::HighBitDepthDecodingOption high_bit_depth_option, -+ ColorBehavior color_behavior, -+ cc::AuxImage aux_image, -+ ImageDecoder::AnimationOption animation_option) { -+ return std::make_unique( -+ alpha_option, high_bit_depth_option, color_behavior, aux_image, -+ ImageDecoder::kNoDecodedImageByteLimit, animation_option); -+} -+ -+std::unique_ptr CreateAVIFDecoder() { -+ return CreateAVIFDecoderWithOptions( -+ ImageDecoder::kAlphaNotPremultiplied, ImageDecoder::kDefaultBitDepth, -+ ColorBehavior::kTag, cc::AuxImage::kDefault, -+ ImageDecoder::AnimationOption::kUnspecified); -+} -+ -+std::unique_ptr CreateGainMapAVIFDecoder() { -+ return CreateAVIFDecoderWithOptions( -+ ImageDecoder::kAlphaNotPremultiplied, ImageDecoder::kDefaultBitDepth, -+ ColorBehavior::kTag, cc::AuxImage::kGainmap, -+ ImageDecoder::AnimationOption::kUnspecified); -+} -+ -+struct ExpectedColor { -+ gfx::Point point; -+ SkColor color; -+}; -+ -+enum class ColorType { -+ kRgb, -+ kRgbA, -+ kMono, -+ kMonoA, -+}; -+ -+struct StaticColorCheckParam { -+ const char* path; -+ int bit_depth; -+ ColorType color_type; -+ ImageDecoder::CompressionFormat compression_format; -+ ImageDecoder::AlphaOption alpha_option; -+ ColorBehavior color_behavior; -+ ImageOrientationEnum orientation = ImageOrientationEnum::kDefault; -+ int color_threshold; -+ std::vector colors; -+}; -+ -+std::ostream& operator<<(std::ostream& os, const StaticColorCheckParam& param) { -+ const char* color_type; -+ switch (param.color_type) { -+ case ColorType::kRgb: -+ color_type = "kRgb"; -+ break; -+ case ColorType::kRgbA: -+ color_type = "kRgbA"; -+ break; -+ case ColorType::kMono: -+ color_type = "kMono"; -+ break; -+ case ColorType::kMonoA: -+ color_type = "kMonoA"; -+ break; -+ } -+ const char* alpha_option = -+ (param.alpha_option == ImageDecoder::kAlphaPremultiplied -+ ? "kAlphaPremultiplied" -+ : "kAlphaNotPremultiplied"); -+ const char* color_behavior; -+ if (param.color_behavior == ColorBehavior::kIgnore) { -+ color_behavior = "Ignore"; -+ } else if (param.color_behavior == ColorBehavior::kTag) { -+ color_behavior = "Tag"; -+ } else { -+ DCHECK(param.color_behavior == ColorBehavior::kTransformToSRGB); -+ color_behavior = "TransformToSRGB"; -+ } -+ const char* orientation; -+ switch (param.orientation) { -+ case ImageOrientationEnum::kOriginTopLeft: -+ orientation = "kOriginTopLeft"; -+ break; -+ case ImageOrientationEnum::kOriginTopRight: -+ orientation = "kOriginTopRight"; -+ break; -+ case ImageOrientationEnum::kOriginBottomRight: -+ orientation = "kOriginBottomRight"; -+ break; -+ case ImageOrientationEnum::kOriginBottomLeft: -+ orientation = "kOriginBottomLeft"; -+ break; -+ case ImageOrientationEnum::kOriginLeftTop: -+ orientation = "kOriginLeftTop"; -+ break; -+ case ImageOrientationEnum::kOriginRightTop: -+ orientation = "kOriginRightTop"; -+ break; -+ case ImageOrientationEnum::kOriginRightBottom: -+ orientation = "kOriginRightBottom"; -+ break; -+ case ImageOrientationEnum::kOriginLeftBottom: -+ orientation = "kOriginLeftBottom"; -+ break; -+ } -+ return os << "\nStaticColorCheckParam {\n path: \"" << param.path -+ << "\",\n bit_depth: " << param.bit_depth -+ << ",\n color_type: " << color_type -+ << ",\n alpha_option: " << alpha_option -+ << ",\n color_behavior: " << color_behavior -+ << ",\n orientation: " << orientation << "\n}"; -+} -+ -+StaticColorCheckParam kTestParams[] = { -+ { -+ "/images/resources/avif/red-at-12-oclock-with-color-profile-lossy.avif", -+ 8, -+ ColorType::kRgb, -+ ImageDecoder::kLossyFormat, -+ ImageDecoder::kAlphaNotPremultiplied, // q=60(lossy) -+ ColorBehavior::kTag, -+ ImageOrientationEnum::kOriginTopLeft, -+ 0, -+ {}, // we just check that this image is lossy. -+ }, -+ { -+ "/images/resources/avif/red-at-12-oclock-with-color-profile-lossy.avif", -+ 8, -+ ColorType::kRgb, -+ ImageDecoder::kLossyFormat, -+ ImageDecoder::kAlphaNotPremultiplied, // q=60(lossy) -+ ColorBehavior::kIgnore, -+ ImageOrientationEnum::kOriginTopLeft, -+ 0, -+ {}, // we just check that the decoder won't crash when -+ // ColorBehavior::kIgnore is used. -+ }, -+ {"/images/resources/avif/red-with-alpha-8bpc.avif", -+ 8, -+ ColorType::kRgbA, -+ ImageDecoder::kLosslessFormat, -+ ImageDecoder::kAlphaNotPremultiplied, -+ ColorBehavior::kTag, -+ ImageOrientationEnum::kOriginTopLeft, -+ 3, -+ { -+ {gfx::Point(0, 0), SkColorSetARGB(0, 255, 0, 0)}, -+ {gfx::Point(1, 1), SkColorSetARGB(127, 255, 0, 0)}, -+ {gfx::Point(2, 2), SkColorSetARGB(255, 255, 0, 0)}, -+ }}, -+ {"/images/resources/avif/red-full-range-420-8bpc.avif", -+ 8, -+ ColorType::kRgb, -+ ImageDecoder::kLosslessFormat, -+ ImageDecoder::kAlphaNotPremultiplied, -+ ColorBehavior::kTag, -+ ImageOrientationEnum::kOriginTopLeft, -+ 1, -+ { -+ {gfx::Point(0, 0), SkColorSetARGB(255, 255, 0, 0)}, -+ {gfx::Point(1, 1), SkColorSetARGB(255, 255, 0, 0)}, -+ {gfx::Point(2, 2), SkColorSetARGB(255, 255, 0, 0)}, -+ }}, -+ {"/images/resources/avif/red-full-range-unspecified-420-8bpc.avif", -+ 8, -+ ColorType::kRgb, -+ ImageDecoder::kLosslessFormat, -+ ImageDecoder::kAlphaNotPremultiplied, -+ ColorBehavior::kTag, -+ ImageOrientationEnum::kOriginTopLeft, -+ 0, -+ { -+ {gfx::Point(0, 0), SkColorSetARGB(255, 255, 0, 0)}, -+ {gfx::Point(1, 1), SkColorSetARGB(255, 255, 0, 0)}, -+ {gfx::Point(2, 2), SkColorSetARGB(255, 255, 0, 0)}, -+ }}, -+ {"/images/resources/avif/silver-full-range-srgb-420-8bpc.avif", -+ 8, -+ ColorType::kRgb, -+ ImageDecoder::kLosslessFormat, -+ ImageDecoder::kAlphaNotPremultiplied, -+ ColorBehavior::kTag, -+ ImageOrientationEnum::kOriginTopLeft, -+ 0, -+ { -+ {gfx::Point(0, 0), SkColorSetARGB(255, 192, 192, 192)}, -+ {gfx::Point(1, 1), SkColorSetARGB(255, 192, 192, 192)}, -+ {gfx::Point(2, 2), SkColorSetARGB(255, 192, 192, 192)}, -+ }}, -+ {"/images/resources/avif/silver-400-matrix-6.avif", -+ 8, -+ ColorType::kRgb, -+ ImageDecoder::kLosslessFormat, -+ ImageDecoder::kAlphaNotPremultiplied, -+ ColorBehavior::kTag, -+ ImageOrientationEnum::kOriginTopLeft, -+ 0, -+ { -+ {gfx::Point(0, 0), SkColorSetARGB(255, 192, 192, 192)}, -+ {gfx::Point(1, 1), SkColorSetARGB(255, 192, 192, 192)}, -+ {gfx::Point(2, 2), SkColorSetARGB(255, 192, 192, 192)}, -+ }}, -+ {"/images/resources/avif/silver-400-matrix-0.avif", -+ 8, -+ ColorType::kRgb, -+ ImageDecoder::kLosslessFormat, -+ ImageDecoder::kAlphaNotPremultiplied, -+ ColorBehavior::kTag, -+ ImageOrientationEnum::kOriginTopLeft, -+ 0, -+ { -+ {gfx::Point(0, 0), SkColorSetARGB(255, 192, 192, 192)}, -+ {gfx::Point(1, 1), SkColorSetARGB(255, 192, 192, 192)}, -+ {gfx::Point(2, 2), SkColorSetARGB(255, 192, 192, 192)}, -+ }}, -+ {"/images/resources/avif/alpha-mask-limited-range-8bpc.avif", -+ 8, -+ ColorType::kMono, -+ ImageDecoder::kLosslessFormat, -+ ImageDecoder::kAlphaNotPremultiplied, -+ ColorBehavior::kTag, -+ ImageOrientationEnum::kOriginTopLeft, -+ 1, -+ { -+ {gfx::Point(0, 0), SkColorSetARGB(255, 0, 0, 0)}, -+ {gfx::Point(1, 1), SkColorSetARGB(255, 128, 128, 128)}, -+ {gfx::Point(2, 2), SkColorSetARGB(255, 255, 255, 255)}, -+ }}, -+ {"/images/resources/avif/alpha-mask-full-range-8bpc.avif", -+ 8, -+ ColorType::kMono, -+ ImageDecoder::kLosslessFormat, -+ ImageDecoder::kAlphaNotPremultiplied, -+ ColorBehavior::kTag, -+ ImageOrientationEnum::kOriginTopLeft, -+ 1, -+ { -+ {gfx::Point(0, 0), SkColorSetARGB(255, 0, 0, 0)}, -+ {gfx::Point(1, 1), SkColorSetARGB(255, 128, 128, 128)}, -+ {gfx::Point(2, 2), SkColorSetARGB(255, 255, 255, 255)}, -+ }}, -+ {"/images/resources/avif/red-with-alpha-8bpc.avif", -+ 8, -+ ColorType::kRgbA, -+ ImageDecoder::kLosslessFormat, -+ ImageDecoder::kAlphaPremultiplied, -+ ColorBehavior::kTransformToSRGB, -+ ImageOrientationEnum::kOriginTopLeft, -+ 4, -+ { -+ {gfx::Point(0, 0), SkColorSetARGB(0, 0, 0, 0)}, -+ {gfx::Point(1, 1), SkColorSetARGB(127, 255, 0, 0)}, -+ {gfx::Point(2, 2), SkColorSetARGB(255, 255, 0, 0)}, -+ }}, -+#if FIXME_SUPPORT_ICC_PROFILE_NO_TRANSFORM -+ {"/images/resources/avif/red-with-profile-8bpc.avif", -+ 8, -+ ColorType::kRgb, -+ ImageDecoder::kLosslessFormat, -+ ImageDecoder::kAlphaNotPremultiplied, -+ ColorBehavior::kIgnore, -+ ImageOrientationEnum::kOriginTopLeft, -+ 1, -+ { -+ {gfx::Point(0, 0), SkColorSetARGB(255, 0, 0, 255)}, -+ {gfx::Point(1, 1), SkColorSetARGB(255, 0, 0, 255)}, -+ {gfx::Point(2, 2), SkColorSetARGB(255, 0, 0, 255)}, -+ }}, -+#endif -+#if FIXME_SUPPORT_ICC_PROFILE_TRANSFORM -+ {"/images/resources/avif/red-with-profile-8bpc.avif", -+ 8, -+ ColorType::kRgb, -+ ImageDecoder::kLosslessFormat, -+ ImageDecoder::kAlphaNotPremultiplied, -+ ColorBehavior::kTransformToSRGB, -+ ImageOrientationEnum::kOriginTopLeft, -+ 1, -+ { -+ /* -+ * "Color Spin" ICC profile, embedded in this image, -+ * changes blue to red. -+ */ -+ {gfx::Point(0, 0), SkColorSetARGB(255, 255, 0, 0)}, -+ {gfx::Point(1, 1), SkColorSetARGB(255, 255, 0, 0)}, -+ {gfx::Point(2, 2), SkColorSetARGB(255, 255, 0, 0)}, -+ }}, -+#endif -+ {"/images/resources/avif/red-with-alpha-10bpc.avif", -+ 10, -+ ColorType::kRgbA, -+ ImageDecoder::kLosslessFormat, -+ ImageDecoder::kAlphaNotPremultiplied, -+ ColorBehavior::kTag, -+ ImageOrientationEnum::kOriginTopLeft, -+ 2, -+ { -+ {gfx::Point(0, 0), SkColorSetARGB(0, 255, 0, 0)}, -+ {gfx::Point(1, 1), SkColorSetARGB(128, 255, 0, 0)}, -+ {gfx::Point(2, 2), SkColorSetARGB(255, 255, 0, 0)}, -+ }}, -+ {"/images/resources/avif/red-with-alpha-10bpc.avif", -+ 10, -+ ColorType::kRgbA, -+ ImageDecoder::kLosslessFormat, -+ ImageDecoder::kAlphaPremultiplied, -+ ColorBehavior::kTransformToSRGB, -+ ImageOrientationEnum::kOriginTopLeft, -+ 2, -+ { -+ {gfx::Point(0, 0), SkColorSetARGB(0, 0, 0, 0)}, -+ {gfx::Point(1, 1), SkColorSetARGB(128, 255, 0, 0)}, -+ {gfx::Point(2, 2), SkColorSetARGB(255, 255, 0, 0)}, -+ }}, -+ {"/images/resources/avif/red-full-range-420-10bpc.avif", -+ 10, -+ ColorType::kRgb, -+ ImageDecoder::kLosslessFormat, -+ ImageDecoder::kAlphaNotPremultiplied, -+ ColorBehavior::kTag, -+ ImageOrientationEnum::kOriginTopLeft, -+ 0, -+ { -+ {gfx::Point(0, 0), SkColorSetARGB(255, 255, 0, 0)}, -+ {gfx::Point(1, 1), SkColorSetARGB(255, 255, 0, 0)}, -+ {gfx::Point(2, 2), SkColorSetARGB(255, 255, 0, 0)}, -+ }}, -+ {"/images/resources/avif/alpha-mask-limited-range-10bpc.avif", -+ 10, -+ ColorType::kMono, -+ ImageDecoder::kLosslessFormat, -+ ImageDecoder::kAlphaNotPremultiplied, -+ ColorBehavior::kTag, -+ ImageOrientationEnum::kOriginTopLeft, -+ 1, -+ { -+ {gfx::Point(0, 0), SkColorSetARGB(255, 0, 0, 0)}, -+ {gfx::Point(1, 1), SkColorSetARGB(255, 128, 128, 128)}, -+ {gfx::Point(2, 2), SkColorSetARGB(255, 255, 255, 255)}, -+ }}, -+ {"/images/resources/avif/alpha-mask-full-range-10bpc.avif", -+ 10, -+ ColorType::kMono, -+ ImageDecoder::kLosslessFormat, -+ ImageDecoder::kAlphaNotPremultiplied, -+ ColorBehavior::kTag, -+ ImageOrientationEnum::kOriginTopLeft, -+ 1, -+ { -+ {gfx::Point(0, 0), SkColorSetARGB(255, 0, 0, 0)}, -+ {gfx::Point(1, 1), SkColorSetARGB(255, 128, 128, 128)}, -+ {gfx::Point(2, 2), SkColorSetARGB(255, 255, 255, 255)}, -+ }}, -+#if FIXME_SUPPORT_ICC_PROFILE_NO_TRANSFORM -+ {"/images/resources/avif/red-with-profile-10bpc.avif", -+ 10, -+ ColorType::kRgb, -+ ImageDecoder::kLosslessFormat, -+ ImageDecoder::kAlphaNotPremultiplied, -+ ColorBehavior::kIgnore, -+ ImageOrientationEnum::kOriginTopLeft, -+ 1, -+ { -+ {gfx::Point(0, 0), SkColorSetARGB(255, 0, 0, 255)}, -+ {gfx::Point(1, 1), SkColorSetARGB(255, 0, 0, 255)}, -+ {gfx::Point(2, 2), SkColorSetARGB(255, 0, 0, 255)}, -+ }}, -+#endif -+#if FIXME_SUPPORT_ICC_PROFILE_TRANSFORM -+ {"/images/resources/avif/red-with-profile-10bpc.avif", -+ 10, -+ ColorType::kRgb, -+ ImageDecoder::kLosslessFormat, -+ ImageDecoder::kAlphaNotPremultiplied, -+ ColorBehavior::kTransformToSRGB, -+ ImageOrientationEnum::kOriginTopLeft, -+ 1, -+ { -+ /* -+ * "Color Spin" ICC profile, embedded in this image, -+ * changes blue to red. -+ */ -+ {gfx::Point(0, 0), SkColorSetARGB(255, 255, 0, 0)}, -+ {gfx::Point(1, 1), SkColorSetARGB(255, 255, 0, 0)}, -+ {gfx::Point(2, 2), SkColorSetARGB(255, 255, 0, 0)}, -+ }}, -+#endif -+ {"/images/resources/avif/red-with-alpha-12bpc.avif", -+ 12, -+ ColorType::kRgbA, -+ ImageDecoder::kLosslessFormat, -+ ImageDecoder::kAlphaNotPremultiplied, -+ ColorBehavior::kTag, -+ ImageOrientationEnum::kOriginTopLeft, -+ 2, -+ { -+ {gfx::Point(0, 0), SkColorSetARGB(0, 255, 0, 0)}, -+ {gfx::Point(1, 1), SkColorSetARGB(128, 255, 0, 0)}, -+ {gfx::Point(2, 2), SkColorSetARGB(255, 255, 0, 0)}, -+ }}, -+ {"/images/resources/avif/red-with-alpha-12bpc.avif", -+ 12, -+ ColorType::kRgbA, -+ ImageDecoder::kLosslessFormat, -+ ImageDecoder::kAlphaPremultiplied, -+ ColorBehavior::kTransformToSRGB, -+ ImageOrientationEnum::kOriginTopLeft, -+ 2, -+ { -+ {gfx::Point(0, 0), SkColorSetARGB(0, 0, 0, 0)}, -+ {gfx::Point(1, 1), SkColorSetARGB(128, 255, 0, 0)}, -+ {gfx::Point(2, 2), SkColorSetARGB(255, 255, 0, 0)}, -+ }}, -+ {"/images/resources/avif/red-full-range-420-12bpc.avif", -+ 12, -+ ColorType::kRgb, -+ ImageDecoder::kLosslessFormat, -+ ImageDecoder::kAlphaNotPremultiplied, -+ ColorBehavior::kTag, -+ ImageOrientationEnum::kOriginTopLeft, -+ 0, -+ { -+ {gfx::Point(0, 0), SkColorSetARGB(255, 255, 0, 0)}, -+ {gfx::Point(1, 1), SkColorSetARGB(255, 255, 0, 0)}, -+ {gfx::Point(2, 2), SkColorSetARGB(255, 255, 0, 0)}, -+ }}, -+ {"/images/resources/avif/alpha-mask-limited-range-12bpc.avif", -+ 12, -+ ColorType::kMono, -+ ImageDecoder::kLosslessFormat, -+ ImageDecoder::kAlphaNotPremultiplied, -+ ColorBehavior::kTag, -+ ImageOrientationEnum::kOriginTopLeft, -+ 1, -+ { -+ {gfx::Point(0, 0), SkColorSetARGB(255, 0, 0, 0)}, -+ {gfx::Point(1, 1), SkColorSetARGB(255, 128, 128, 128)}, -+ {gfx::Point(2, 2), SkColorSetARGB(255, 255, 255, 255)}, -+ }}, -+ {"/images/resources/avif/alpha-mask-full-range-12bpc.avif", -+ 12, -+ ColorType::kMono, -+ ImageDecoder::kLosslessFormat, -+ ImageDecoder::kAlphaNotPremultiplied, -+ ColorBehavior::kTag, -+ ImageOrientationEnum::kOriginTopLeft, -+ 1, -+ { -+ {gfx::Point(0, 0), SkColorSetARGB(255, 0, 0, 0)}, -+ {gfx::Point(1, 1), SkColorSetARGB(255, 128, 128, 128)}, -+ {gfx::Point(2, 2), SkColorSetARGB(255, 255, 255, 255)}, -+ }}, -+#if FIXME_SUPPORT_ICC_PROFILE_NO_TRANSFORM -+ {"/images/resources/avif/red-with-profile-12bpc.avif", -+ 12, -+ ColorType::kRgb, -+ ImageDecoder::kLosslessFormat, -+ ImageDecoder::kAlphaNotPremultiplied, -+ ColorBehavior::kIgnore, -+ ImageOrientationEnum::kOriginTopLeft, -+ 1, -+ { -+ {gfx::Point(0, 0), SkColorSetARGB(255, 0, 0, 255)}, -+ {gfx::Point(1, 1), SkColorSetARGB(255, 0, 0, 255)}, -+ {gfx::Point(2, 2), SkColorSetARGB(255, 0, 0, 255)}, -+ }}, -+#endif -+#if FIXME_SUPPORT_ICC_PROFILE_TRANSFORM -+ {"/images/resources/avif/red-with-profile-12bpc.avif", -+ 12, -+ ColorType::kRgb, -+ ImageDecoder::kLosslessFormat, -+ ImageDecoder::kAlphaNotPremultiplied, -+ ColorBehavior::kTransformToSRGB, -+ ImageOrientationEnum::kOriginTopLeft, -+ 1, -+ { -+ /* -+ * "Color Spin" ICC profile, embedded in this image, -+ * changes blue to red. -+ */ -+ {gfx::Point(0, 0), SkColorSetARGB(255, 255, 0, 0)}, -+ {gfx::Point(1, 1), SkColorSetARGB(255, 255, 0, 0)}, -+ {gfx::Point(2, 2), SkColorSetARGB(255, 255, 0, 0)}, -+ }}, -+#endif -+ {"/images/resources/avif/red-and-purple-crop.avif", -+ 8, -+ ColorType::kRgbA, -+ ImageDecoder::kLosslessFormat, -+ ImageDecoder::kAlphaNotPremultiplied, -+ ColorBehavior::kTag, -+ ImageOrientationEnum::kOriginTopLeft, -+ 0, -+ { -+ // The clean aperture's size is 200x50. The left half is red and the -+ // right half is purple. Alpha values in the clean aperture are 255. -+ // (Alpha values to the right of the clean aperture are 128.) -+ {gfx::Point(0, 0), SkColorSetARGB(255, 255, 0, 0)}, // red -+ {gfx::Point(99, 24), SkColorSetARGB(255, 255, 0, 0)}, // red -+ {gfx::Point(100, 25), SkColorSetARGB(255, 127, 0, 128)}, // purple -+ {gfx::Point(199, 49), SkColorSetARGB(255, 127, 0, 128)}, // purple -+ }}, -+ {"/images/resources/avif/red-full-range-angle-1-420-8bpc.avif", -+ 8, -+ ColorType::kRgb, -+ ImageDecoder::kLosslessFormat, -+ ImageDecoder::kAlphaNotPremultiplied, -+ ColorBehavior::kTag, -+ ImageOrientationEnum::kOriginLeftBottom, -+ 0, -+ { -+ {gfx::Point(0, 0), SkColorSetARGB(255, 255, 0, 0)}, -+ {gfx::Point(1, 1), SkColorSetARGB(255, 255, 0, 0)}, -+ {gfx::Point(2, 2), SkColorSetARGB(255, 255, 0, 0)}, -+ }}, -+ {"/images/resources/avif/red-full-range-mode-0-420-8bpc.avif", -+ 8, -+ ColorType::kRgb, -+ ImageDecoder::kLosslessFormat, -+ ImageDecoder::kAlphaNotPremultiplied, -+ ColorBehavior::kTag, -+ ImageOrientationEnum::kOriginBottomLeft, -+ 0, -+ { -+ {gfx::Point(0, 0), SkColorSetARGB(255, 255, 0, 0)}, -+ {gfx::Point(1, 1), SkColorSetARGB(255, 255, 0, 0)}, -+ {gfx::Point(2, 2), SkColorSetARGB(255, 255, 0, 0)}, -+ }}, -+ {"/images/resources/avif/red-full-range-mode-1-420-8bpc.avif", -+ 8, -+ ColorType::kRgb, -+ ImageDecoder::kLosslessFormat, -+ ImageDecoder::kAlphaNotPremultiplied, -+ ColorBehavior::kTag, -+ ImageOrientationEnum::kOriginTopRight, -+ 0, -+ { -+ {gfx::Point(0, 0), SkColorSetARGB(255, 255, 0, 0)}, -+ {gfx::Point(1, 1), SkColorSetARGB(255, 255, 0, 0)}, -+ {gfx::Point(2, 2), SkColorSetARGB(255, 255, 0, 0)}, -+ }}, -+ {"/images/resources/avif/red-full-range-angle-2-mode-0-420-8bpc.avif", -+ 8, -+ ColorType::kRgb, -+ ImageDecoder::kLosslessFormat, -+ ImageDecoder::kAlphaNotPremultiplied, -+ ColorBehavior::kTag, -+ ImageOrientationEnum::kOriginTopRight, -+ 0, -+ { -+ {gfx::Point(0, 0), SkColorSetARGB(255, 255, 0, 0)}, -+ {gfx::Point(1, 1), SkColorSetARGB(255, 255, 0, 0)}, -+ {gfx::Point(2, 2), SkColorSetARGB(255, 255, 0, 0)}, -+ }}, -+ {"/images/resources/avif/red-full-range-angle-3-mode-1-420-8bpc.avif", -+ 8, -+ ColorType::kRgb, -+ ImageDecoder::kLosslessFormat, -+ ImageDecoder::kAlphaNotPremultiplied, -+ ColorBehavior::kTag, -+ ImageOrientationEnum::kOriginLeftTop, -+ 0, -+ { -+ {gfx::Point(0, 0), SkColorSetARGB(255, 255, 0, 0)}, -+ {gfx::Point(1, 1), SkColorSetARGB(255, 255, 0, 0)}, -+ {gfx::Point(2, 2), SkColorSetARGB(255, 255, 0, 0)}, -+ }}, -+ // TODO(ryoh): Add other color profile images, such as BT2020CL, -+ // SMPTE 274M -+ // TODO(ryoh): Add images with different combinations of ColorPrimaries, -+ // TransferFunction and MatrixCoefficients, -+ // such as: -+ // sRGB ColorPrimaries, BT.2020 TransferFunction and -+ // BT.709 MatrixCoefficients -+ // TODO(ryoh): Add Mono + Alpha Images. -+}; -+ -+enum class ErrorPhase { kParse, kDecode }; -+ -+// If 'error_phase' is ErrorPhase::kParse, error is expected during parse -+// (SetData() call); else error is expected during decode -+// (DecodeFrameBufferAtIndex() call). -+void TestInvalidStaticImage(const char* avif_file, ErrorPhase error_phase) { -+ std::unique_ptr decoder = CreateAVIFDecoder(); -+ -+ scoped_refptr data = ReadFileToSharedBuffer(avif_file); -+ ASSERT_TRUE(data.get()); -+ decoder->SetData(std::move(data), true); -+ -+ if (error_phase == ErrorPhase::kParse) { -+ EXPECT_FALSE(decoder->IsSizeAvailable()); -+ EXPECT_TRUE(decoder->Failed()); -+ EXPECT_EQ(0u, decoder->FrameCount()); -+ EXPECT_FALSE(decoder->DecodeFrameBufferAtIndex(0)); -+ } else { -+ EXPECT_TRUE(decoder->IsSizeAvailable()); -+ EXPECT_FALSE(decoder->Failed()); -+ EXPECT_GT(decoder->FrameCount(), 0u); -+ ImageFrame* frame = decoder->DecodeFrameBufferAtIndex(0); -+ ASSERT_TRUE(frame); -+ EXPECT_NE(ImageFrame::kFrameComplete, frame->GetStatus()); -+ EXPECT_TRUE(decoder->Failed()); -+ } -+} -+ -+float HalfFloatToUnorm(uint16_t h) { -+ const uint32_t f = ((h & 0x8000) << 16) | (((h & 0x7c00) + 0x1c000) << 13) | -+ ((h & 0x03ff) << 13); -+ return base::bit_cast(f); -+} -+ -+void ReadYUV(const char* file_name, -+ const gfx::Size& expected_y_size, -+ const gfx::Size& expected_uv_size, -+ SkColorType color_type, -+ int bit_depth, -+ gfx::Point3F* rgb_pixel = nullptr) { -+ scoped_refptr data = -+ ReadFileToSharedBuffer("web_tests/images/resources/avif/", file_name); -+ ASSERT_TRUE(data); -+ -+ auto decoder = CreateAVIFDecoder(); -+ decoder->SetData(std::move(data), true); -+ -+ ASSERT_TRUE(decoder->IsDecodedSizeAvailable()); -+ ASSERT_TRUE(decoder->CanDecodeToYUV()); -+ EXPECT_NE(decoder->GetYUVSubsampling(), cc::YUVSubsampling::kUnknown); -+ EXPECT_NE(decoder->GetYUVColorSpace(), -+ SkYUVColorSpace::kIdentity_SkYUVColorSpace); -+ EXPECT_EQ(decoder->GetYUVBitDepth(), bit_depth); -+ -+ gfx::Size size = decoder->DecodedSize(); -+ gfx::Size y_size = decoder->DecodedYUVSize(cc::YUVIndex::kY); -+ gfx::Size u_size = decoder->DecodedYUVSize(cc::YUVIndex::kU); -+ gfx::Size v_size = decoder->DecodedYUVSize(cc::YUVIndex::kV); -+ -+ EXPECT_EQ(size, y_size); -+ EXPECT_EQ(u_size, v_size); -+ -+ EXPECT_EQ(expected_y_size, y_size); -+ EXPECT_EQ(expected_uv_size, u_size); -+ -+ wtf_size_t row_bytes[3]; -+ row_bytes[0] = decoder->DecodedYUVWidthBytes(cc::YUVIndex::kY); -+ row_bytes[1] = decoder->DecodedYUVWidthBytes(cc::YUVIndex::kU); -+ row_bytes[2] = decoder->DecodedYUVWidthBytes(cc::YUVIndex::kV); -+ -+ size_t planes_data_size = row_bytes[0] * y_size.height() + -+ row_bytes[1] * u_size.height() + -+ row_bytes[2] * v_size.height(); -+ auto planes_data = std::make_unique(planes_data_size); -+ -+ void* planes[3]; -+ planes[0] = planes_data.get(); -+ planes[1] = static_cast(planes[0]) + row_bytes[0] * y_size.height(); -+ planes[2] = static_cast(planes[1]) + row_bytes[1] * u_size.height(); -+ -+ decoder->SetImagePlanes( -+ std::make_unique(planes, row_bytes, color_type)); -+ -+ decoder->DecodeToYUV(); -+ EXPECT_FALSE(decoder->Failed()); -+ EXPECT_TRUE(decoder->HasDisplayableYUVData()); -+ -+ auto metadata = decoder->MakeMetadataForDecodeAcceleration(); -+ EXPECT_EQ(cc::ImageType::kAVIF, metadata.image_type); -+ EXPECT_EQ(size, metadata.image_size); -+ if (expected_y_size == expected_uv_size) { -+ EXPECT_EQ(cc::YUVSubsampling::k444, metadata.yuv_subsampling); -+ } else if (expected_y_size.height() == expected_uv_size.height()) { -+ EXPECT_EQ(cc::YUVSubsampling::k422, metadata.yuv_subsampling); -+ } else { -+ EXPECT_EQ(cc::YUVSubsampling::k420, metadata.yuv_subsampling); -+ } -+ -+ if (!rgb_pixel) { -+ return; -+ } -+ -+ if (bit_depth > 8) { -+ rgb_pixel->set_x(reinterpret_cast(planes[0])[0]); -+ rgb_pixel->set_y(reinterpret_cast(planes[1])[0]); -+ rgb_pixel->set_z(reinterpret_cast(planes[2])[0]); -+ } else { -+ rgb_pixel->set_x(reinterpret_cast(planes[0])[0]); -+ rgb_pixel->set_y(reinterpret_cast(planes[1])[0]); -+ rgb_pixel->set_z(reinterpret_cast(planes[2])[0]); -+ } -+ -+ if (color_type == kGray_8_SkColorType) { -+ const float max_channel = (1 << bit_depth) - 1; -+ rgb_pixel->set_x(rgb_pixel->x() / max_channel); -+ rgb_pixel->set_y(rgb_pixel->y() / max_channel); -+ rgb_pixel->set_z(rgb_pixel->z() / max_channel); -+ } else if (color_type == kA16_unorm_SkColorType) { -+ constexpr float kR16MaxChannel = 65535.0f; -+ rgb_pixel->set_x(rgb_pixel->x() / kR16MaxChannel); -+ rgb_pixel->set_y(rgb_pixel->y() / kR16MaxChannel); -+ rgb_pixel->set_z(rgb_pixel->z() / kR16MaxChannel); -+ } else { -+ DCHECK_EQ(color_type, kA16_float_SkColorType); -+ rgb_pixel->set_x(HalfFloatToUnorm(rgb_pixel->x())); -+ rgb_pixel->set_y(HalfFloatToUnorm(rgb_pixel->y())); -+ rgb_pixel->set_z(HalfFloatToUnorm(rgb_pixel->z())); -+ } -+ -+ // Convert our YUV pixel to RGB to avoid an excessive amounts of test -+ // expectations. We otherwise need bit_depth * yuv_sampling * color_type. -+ gfx::ColorTransform::Options options; -+ options.src_bit_depth = bit_depth; -+ options.dst_bit_depth = bit_depth; -+ auto transform = gfx::ColorTransform::NewColorTransform( -+ reinterpret_cast(decoder.get()) -+ ->GetColorSpaceForTesting(), -+ gfx::ColorSpace(), options); -+ transform->Transform(rgb_pixel, 1); -+} -+ -+void TestYUVRed(const char* file_name, -+ const gfx::Size& expected_uv_size, -+ SkColorType color_type = kGray_8_SkColorType, -+ int bit_depth = 8) { -+ SCOPED_TRACE(base::StringPrintf("file_name=%s, color_type=%d", file_name, -+ int{color_type})); -+ -+ constexpr gfx::Size kRedYSize(3, 3); -+ -+ gfx::Point3F decoded_pixel; -+ ASSERT_NO_FATAL_FAILURE(ReadYUV(file_name, kRedYSize, expected_uv_size, -+ color_type, bit_depth, &decoded_pixel)); -+ -+ // Allow the RGB value to be off by one step. 1/max_value is the minimum -+ // amount of error possible if error exists for integer sources. -+ // -+ // For half float values we have additional error from precision limitations, -+ // which gets worse at the extents of [-0.5, 1] -- which is the case for our R -+ // channel since we're using a pure red source. -+ // -+ // https://en.wikipedia.org/wiki/Half-precision_floating-point_format#Precision_limitations_on_decimal_values_in_[0,_1] -+ const double kMinError = 1.0 / ((1 << bit_depth) - 1); -+ const double kError = color_type == kA16_float_SkColorType -+ ? kMinError + std::pow(2, -11) -+ : kMinError; -+ EXPECT_NEAR(decoded_pixel.x(), 1, kError); // R -+ EXPECT_NEAR(decoded_pixel.y(), 0, kMinError); // G -+ EXPECT_NEAR(decoded_pixel.z(), 0, kMinError); // B -+} -+ -+void DecodeTask(const Vector* data, base::RepeatingClosure* done) { -+ std::unique_ptr decoder = CreateAVIFDecoder(); -+ -+ scoped_refptr data_copy = SharedBuffer::Create(); -+ data_copy->Append(*data); -+ decoder->SetData(std::move(data_copy), true); -+ -+ EXPECT_TRUE(decoder->IsSizeAvailable()); -+ EXPECT_FALSE(decoder->Failed()); -+ EXPECT_EQ(decoder->FrameCount(), 1u); -+ ImageFrame* frame = decoder->DecodeFrameBufferAtIndex(0); -+ ASSERT_TRUE(frame); -+ EXPECT_EQ(ImageFrame::kFrameComplete, frame->GetStatus()); -+ EXPECT_FALSE(decoder->Failed()); -+ -+ done->Run(); -+} -+ -+void InspectImage( -+ const StaticColorCheckParam& param, -+ ImageDecoder::HighBitDepthDecodingOption high_bit_depth_option) { -+ std::unique_ptr decoder = CreateAVIFDecoderWithOptions( -+ param.alpha_option, high_bit_depth_option, param.color_behavior, -+ cc::AuxImage::kDefault, ImageDecoder::AnimationOption::kUnspecified); -+ scoped_refptr data = ReadFileToSharedBuffer(param.path); -+ ASSERT_TRUE(data.get()); -+#if FIXME_DISTINGUISH_LOSSY_OR_LOSSLESS -+ EXPECT_EQ(param.compression_format, -+ ImageDecoder::GetCompressionFormat(data, "image/avif")); -+#endif -+ decoder->SetData(std::move(data), true); -+ EXPECT_EQ(1u, decoder->FrameCount()); -+ EXPECT_EQ(kAnimationNone, decoder->RepetitionCount()); -+ EXPECT_EQ(param.bit_depth > 8, decoder->ImageIsHighBitDepth()); -+ auto metadata = decoder->MakeMetadataForDecodeAcceleration(); -+ EXPECT_EQ(cc::ImageType::kAVIF, metadata.image_type); -+ // TODO(wtc): Check metadata.yuv_subsampling. -+ ImageFrame* frame = decoder->DecodeFrameBufferAtIndex(0); -+ ASSERT_TRUE(frame); -+ EXPECT_EQ(ImageFrame::kFrameComplete, frame->GetStatus()); -+ EXPECT_FALSE(decoder->Failed()); -+ EXPECT_EQ(param.orientation, decoder->Orientation()); -+ EXPECT_EQ(param.color_type == ColorType::kRgbA || -+ param.color_type == ColorType::kMonoA, -+ frame->HasAlpha()); -+ auto get_color_channel = [](SkColorChannel channel, SkColor color) { -+ switch (channel) { -+ case SkColorChannel::kR: -+ return SkColorGetR(color); -+ case SkColorChannel::kG: -+ return SkColorGetG(color); -+ case SkColorChannel::kB: -+ return SkColorGetB(color); -+ case SkColorChannel::kA: -+ return SkColorGetA(color); -+ } -+ }; -+ auto color_difference = [get_color_channel](SkColorChannel channel, -+ SkColor color1, -+ SkColor color2) -> int { -+ return std::abs(static_cast(get_color_channel(channel, color1)) - -+ static_cast(get_color_channel(channel, color2))); -+ }; -+ for (const auto& expected : param.colors) { -+ const SkBitmap& bitmap = frame->Bitmap(); -+ SkColor frame_color = -+ bitmap.getColor(expected.point.x(), expected.point.y()); -+ -+ EXPECT_LE(color_difference(SkColorChannel::kR, frame_color, expected.color), -+ param.color_threshold); -+ EXPECT_LE(color_difference(SkColorChannel::kG, frame_color, expected.color), -+ param.color_threshold); -+ EXPECT_LE(color_difference(SkColorChannel::kB, frame_color, expected.color), -+ param.color_threshold); -+ // TODO(ryoh): Create alpha_threshold field for alpha channels. -+ EXPECT_LE(color_difference(SkColorChannel::kA, frame_color, expected.color), -+ param.color_threshold); -+ if (param.color_type == ColorType::kMono || -+ param.color_type == ColorType::kMonoA) { -+ EXPECT_EQ(SkColorGetR(frame_color), SkColorGetG(frame_color)); -+ EXPECT_EQ(SkColorGetR(frame_color), SkColorGetB(frame_color)); -+ } -+ } -+} -+ -+void TestAvifBppHistogram(const char* image_name, -+ const char* histogram_name = nullptr, -+ base::HistogramBase::Sample32 sample = 0) { -+ TestBppHistogram(CreateAVIFDecoder, "Avif", image_name, histogram_name, -+ sample); -+} -+ -+struct AVIFImageParam { -+ const char* path; -+ size_t expected_frame_count; -+ int expected_repetition_count; -+}; -+ -+constexpr AVIFImageParam kAnimatedTestParams[] = { -+ // star-animated-8bpc.avif, star-animated-10bpc.avif, and -+ // star-animated-12bpc.avif contain an EditListBox whose `flags` field is -+ // equal to 0, meaning the edit list is not repeated. Therefore their -+ // `expected_repetition_count` is 0. -+ {"/images/resources/avif/star-animated-8bpc.avif", 5u, 0}, -+ {"/images/resources/avif/star-animated-8bpc-with-alpha.avif", 5u, -+ kAnimationLoopInfinite}, -+ {"/images/resources/avif/star-animated-10bpc.avif", 5u, 0}, -+ {"/images/resources/avif/star-animated-10bpc-with-alpha.avif", 5u, -+ kAnimationLoopInfinite}, -+ {"/images/resources/avif/star-animated-12bpc.avif", 5u, 0}, -+ {"/images/resources/avif/star-animated-12bpc-with-alpha.avif", 5u, -+ kAnimationLoopInfinite}, -+ {"/images/resources/avif/star-animated-8bpc-1-repetition.avif", 5u, 1}, -+ {"/images/resources/avif/star-animated-8bpc-10-repetition.avif", 5u, 10}, -+ {"/images/resources/avif/star-animated-8bpc-infinite-repetition.avif", 5u, -+ kAnimationLoopInfinite}, -+}; -+ -+constexpr AVIFImageParam kStaticTestParams[] = { -+ {"/images/resources/avif/red-at-12-oclock-with-color-profile-lossy.avif", 1, -+ kAnimationNone}, -+ {"/images/resources/avif/red-at-12-oclock-with-color-profile-8bpc.avif", 1, -+ kAnimationNone}, -+ {"/images/resources/avif/red-at-12-oclock-with-color-profile-10bpc.avif", 1, -+ kAnimationNone}, -+ {"/images/resources/avif/red-at-12-oclock-with-color-profile-12bpc.avif", 1, -+ kAnimationNone}, -+ {"/images/resources/avif/tiger_3layer_1res.avif", 1, kAnimationNone}, -+ {"/images/resources/avif/tiger_3layer_3res.avif", 1, kAnimationNone}, -+ {"/images/resources/avif/tiger_420_8b_grid1x13.avif", 1, kAnimationNone}, -+ {"/images/resources/avif/dice_444_10b_grid4x3.avif", 1, kAnimationNone}, -+ {"/images/resources/avif/gracehopper_422_12b_grid2x4.avif", 1, -+ kAnimationNone}, -+ {"/images/resources/avif/small-with-gainmap-iso.avif", 1, kAnimationNone}, -+}; -+ -+using AVIFValidImagesTest = ::testing::TestWithParam; -+ -+INSTANTIATE_TEST_SUITE_P(AnimatedAVIF, -+ AVIFValidImagesTest, -+ ::testing::ValuesIn(kAnimatedTestParams)); -+ -+INSTANTIATE_TEST_SUITE_P(StaticAVIF, -+ AVIFValidImagesTest, -+ ::testing::ValuesIn(kStaticTestParams)); -+ -+TEST_P(AVIFValidImagesTest, ByteByByteDecode) { -+ TestByteByByteDecode(&CreateAVIFDecoder, GetParam().path, -+ GetParam().expected_frame_count, -+ GetParam().expected_repetition_count); -+} -+ -+TEST(AnimatedAVIFTests, HasMultipleSubImages) { -+ std::unique_ptr decoder = CreateAVIFDecoder(); -+ decoder->SetData( -+ ReadFileToSharedBuffer("/images/resources/avif/star-animated-8bpc.avif"), -+ true); -+ EXPECT_TRUE(decoder->ImageHasBothStillAndAnimatedSubImages()); -+} -+ -+TEST(StaticAVIFTests, DoesNotHaveMultipleSubImages) { -+ std::unique_ptr decoder = CreateAVIFDecoder(); -+ decoder->SetData( -+ ReadFileToSharedBuffer("/images/resources/avif/" -+ "red-at-12-oclock-with-color-profile-8bpc.avif"), -+ true); -+ EXPECT_FALSE(decoder->ImageHasBothStillAndAnimatedSubImages()); -+} -+ -+TEST(StaticAVIFTests, HasTimingInformation) { -+ std::unique_ptr decoder = CreateAVIFDecoder(); -+ decoder->SetData( -+ ReadFileToSharedBuffer("/images/resources/avif/" -+ "red-at-12-oclock-with-color-profile-8bpc.avif"), -+ true); -+ EXPECT_TRUE(!!decoder->DecodeFrameBufferAtIndex(0)); -+ -+ // libavif has placeholder values for timestamp and duration on still images, -+ // so any duration value is valid, but the timestamp should be zero. -+ EXPECT_EQ(base::TimeDelta(), decoder->FrameTimestampAtIndex(0)); -+} -+ -+TEST(AnimatedAVIFTests, HasTimingInformation) { -+ std::unique_ptr decoder = CreateAVIFDecoder(); -+ decoder->SetData( -+ ReadFileToSharedBuffer("/images/resources/avif/star-animated-8bpc.avif"), -+ true); -+ -+ constexpr auto kDuration = base::Milliseconds(100); -+ -+ EXPECT_TRUE(!!decoder->DecodeFrameBufferAtIndex(0)); -+ EXPECT_EQ(base::TimeDelta(), decoder->FrameTimestampAtIndex(0)); -+ EXPECT_EQ(kDuration, decoder->FrameDurationAtIndex(0)); -+ -+ EXPECT_TRUE(!!decoder->DecodeFrameBufferAtIndex(1)); -+ EXPECT_EQ(kDuration, decoder->FrameTimestampAtIndex(1)); -+ EXPECT_EQ(kDuration, decoder->FrameDurationAtIndex(1)); -+} -+ -+TEST(StaticAVIFTests, NoCrashWhenCheckingForMultipleSubImages) { -+ std::unique_ptr decoder = CreateAVIFDecoder(); -+ constexpr char kHeader[] = {0x00, 0x00, 0x00, 0x20, 0x66, 0x74, 0x79, 0x70}; -+ auto buffer = SharedBuffer::Create(); -+ buffer->Append(kHeader); -+ decoder->SetData(std::move(buffer), false); -+ EXPECT_FALSE(decoder->ImageHasBothStillAndAnimatedSubImages()); -+} -+ -+// TODO(ryoh): Add corrupted video tests. -+ -+TEST(StaticAVIFTests, invalidImages) { -+ // Image data is truncated. -+ TestInvalidStaticImage( -+ "/images/resources/avif/" -+ "red-at-12-oclock-with-color-profile-truncated.avif", -+ ErrorPhase::kParse); -+ // Chunk size in AV1 frame header doesn't match the file size. -+ TestInvalidStaticImage( -+ "/images/resources/avif/" -+ "red-at-12-oclock-with-color-profile-with-wrong-frame-header.avif", -+ ErrorPhase::kDecode); -+} -+ -+TEST(StaticAVIFTests, GetIsoGainmapInfoAndData) { -+ base::test::ScopedFeatureList scoped_feature_list; -+ scoped_feature_list.InitWithFeatures( -+ /*enabled_features=*/{features::kAvifGainmapHdrImages}, -+ /*disabled_features=*/{}); -+ -+ scoped_refptr data = ReadFileToSharedBuffer( -+ "/images/resources/avif/small-with-gainmap-iso.avif"); -+ std::unique_ptr decoder = CreateAVIFDecoder(); -+ decoder->SetData(data, true); -+ EXPECT_FALSE(decoder->Failed()); -+ EXPECT_EQ(decoder->Size(), gfx::Size(134, 100)); -+ SkGainmapInfo gainmap_info; -+ scoped_refptr gainmap_data; -+ const bool has_gainmap = -+ decoder->GetGainmapInfoAndData(gainmap_info, gainmap_data); -+ ASSERT_TRUE(has_gainmap); -+ -+ // Check gainmap metadata. -+ constexpr double kEpsilon = 0.00001; -+ EXPECT_NEAR(gainmap_info.fGainmapRatioMin[0], 1.0, kEpsilon); -+ EXPECT_NEAR(gainmap_info.fGainmapRatioMin[1], 1.0, kEpsilon); -+ EXPECT_NEAR(gainmap_info.fGainmapRatioMin[2], 1.0, kEpsilon); -+ EXPECT_NEAR(gainmap_info.fGainmapRatioMin[3], 1.0, kEpsilon); -+ -+ EXPECT_NEAR(gainmap_info.fGainmapRatioMax[0], std::exp2(1.4427), kEpsilon); -+ EXPECT_NEAR(gainmap_info.fGainmapRatioMax[1], std::exp2(1.4427), kEpsilon); -+ EXPECT_NEAR(gainmap_info.fGainmapRatioMax[2], std::exp2(1.4427), kEpsilon); -+ EXPECT_NEAR(gainmap_info.fGainmapRatioMax[3], 1., kEpsilon); -+ -+ EXPECT_NEAR(gainmap_info.fGainmapGamma[0], 1.0, kEpsilon); -+ EXPECT_NEAR(gainmap_info.fGainmapGamma[1], 1.0, kEpsilon); -+ EXPECT_NEAR(gainmap_info.fGainmapGamma[2], 1.0, kEpsilon); -+ EXPECT_NEAR(gainmap_info.fGainmapGamma[3], 1.0, kEpsilon); -+ -+ EXPECT_NEAR(gainmap_info.fEpsilonSdr[0], 0.015625, kEpsilon); -+ EXPECT_NEAR(gainmap_info.fEpsilonSdr[1], 0.015625, kEpsilon); -+ EXPECT_NEAR(gainmap_info.fEpsilonSdr[2], 0.015625, kEpsilon); -+ EXPECT_NEAR(gainmap_info.fEpsilonSdr[3], 1.0, kEpsilon); -+ -+ EXPECT_NEAR(gainmap_info.fEpsilonHdr[0], 0.015625, kEpsilon); -+ EXPECT_NEAR(gainmap_info.fEpsilonHdr[1], 0.015625, kEpsilon); -+ EXPECT_NEAR(gainmap_info.fEpsilonHdr[2], 0.015625, kEpsilon); -+ EXPECT_NEAR(gainmap_info.fEpsilonHdr[3], 1.0, kEpsilon); -+ -+ EXPECT_NEAR(gainmap_info.fDisplayRatioSdr, 1.0, kEpsilon); -+ EXPECT_NEAR(gainmap_info.fDisplayRatioHdr, std::exp2(1.4427), kEpsilon); -+ -+ EXPECT_EQ(gainmap_info.fBaseImageType, SkGainmapInfo::BaseImageType::kSDR); -+ -+ EXPECT_EQ(gainmap_info.fGainmapMathColorSpace, nullptr); -+ -+ // Check that the gainmap can be decoded. -+ std::unique_ptr gainmap_decoder = CreateGainMapAVIFDecoder(); -+ gainmap_decoder->SetData(gainmap_data, true); -+ EXPECT_FALSE(decoder->Failed()); -+ EXPECT_EQ(gainmap_decoder->Size(), gfx::Size(33, 25)); -+ ImageFrame* gainmap_frame = gainmap_decoder->DecodeFrameBufferAtIndex(0); -+ EXPECT_TRUE(gainmap_frame); -+} -+ -+TEST(StaticAVIFTests, GetIsoGainmapInfoAndDataHdrToSdr) { -+ base::test::ScopedFeatureList scoped_feature_list; -+ scoped_feature_list.InitWithFeatures( -+ /*enabled_features=*/{features::kAvifGainmapHdrImages}, -+ /*disabled_features=*/{}); -+ -+ scoped_refptr data = ReadFileToSharedBuffer( -+ "/images/resources/avif/small-with-gainmap-iso-hdrbase.avif"); -+ std::unique_ptr decoder = CreateAVIFDecoder(); -+ decoder->SetData(data, true); -+ EXPECT_FALSE(decoder->Failed()); -+ EXPECT_EQ(decoder->Size(), gfx::Size(134, 100)); -+ SkGainmapInfo gainmap_info; -+ scoped_refptr gainmap_data; -+ const bool has_gainmap = -+ decoder->GetGainmapInfoAndData(gainmap_info, gainmap_data); -+ ASSERT_TRUE(has_gainmap); -+ -+ // Check gainmap metadata. -+ constexpr double kEpsilon = 0.00001; -+ EXPECT_NEAR(gainmap_info.fGainmapRatioMin[0], 1.0, kEpsilon); -+ EXPECT_NEAR(gainmap_info.fGainmapRatioMin[1], 1.0, kEpsilon); -+ EXPECT_NEAR(gainmap_info.fGainmapRatioMin[2], 1.0, kEpsilon); -+ EXPECT_NEAR(gainmap_info.fGainmapRatioMin[3], 1.0, kEpsilon); -+ -+ EXPECT_NEAR(gainmap_info.fGainmapRatioMax[0], std::exp2(1.4427), kEpsilon); -+ EXPECT_NEAR(gainmap_info.fGainmapRatioMax[1], std::exp2(1.4427), kEpsilon); -+ EXPECT_NEAR(gainmap_info.fGainmapRatioMax[2], std::exp2(1.4427), kEpsilon); -+ EXPECT_NEAR(gainmap_info.fGainmapRatioMax[3], 1.0, kEpsilon); -+ -+ EXPECT_NEAR(gainmap_info.fGainmapGamma[0], 1.0, kEpsilon); -+ EXPECT_NEAR(gainmap_info.fGainmapGamma[1], 1.0, kEpsilon); -+ EXPECT_NEAR(gainmap_info.fGainmapGamma[2], 1.0, kEpsilon); -+ EXPECT_NEAR(gainmap_info.fGainmapGamma[3], 1.0, kEpsilon); -+ -+ EXPECT_NEAR(gainmap_info.fEpsilonSdr[0], 0.015625, kEpsilon); -+ EXPECT_NEAR(gainmap_info.fEpsilonSdr[1], 0.015625, kEpsilon); -+ EXPECT_NEAR(gainmap_info.fEpsilonSdr[2], 0.015625, kEpsilon); -+ EXPECT_NEAR(gainmap_info.fEpsilonSdr[3], 1.0, kEpsilon); -+ -+ EXPECT_NEAR(gainmap_info.fEpsilonHdr[0], 0.015625, kEpsilon); -+ EXPECT_NEAR(gainmap_info.fEpsilonHdr[1], 0.015625, kEpsilon); -+ EXPECT_NEAR(gainmap_info.fEpsilonHdr[2], 0.015625, kEpsilon); -+ EXPECT_NEAR(gainmap_info.fEpsilonHdr[3], 1.0, kEpsilon); -+ -+ EXPECT_NEAR(gainmap_info.fDisplayRatioSdr, 1.0, kEpsilon); -+ EXPECT_NEAR(gainmap_info.fDisplayRatioHdr, std::exp2(1.4427), kEpsilon); -+ -+ EXPECT_EQ(gainmap_info.fBaseImageType, SkGainmapInfo::BaseImageType::kHDR); -+ -+ // Check that the gainmap can be decoded. -+ std::unique_ptr gainmap_decoder = CreateGainMapAVIFDecoder(); -+ gainmap_decoder->SetData(gainmap_data, true); -+ EXPECT_FALSE(decoder->Failed()); -+ EXPECT_EQ(gainmap_decoder->Size(), gfx::Size(33, 25)); -+ ImageFrame* gainmap_frame = gainmap_decoder->DecodeFrameBufferAtIndex(0); -+ EXPECT_TRUE(gainmap_frame); -+} -+ -+TEST(StaticAVIFTests, GetIsoGainmapColorSpaceSameICC) { -+ base::test::ScopedFeatureList scoped_feature_list; -+ scoped_feature_list.InitWithFeatures( -+ /*enabled_features=*/{features::kAvifGainmapHdrImages}, -+ /*disabled_features=*/{}); -+ -+ // The image has use_base_color_space set to false (i.e. use the alternate -+ // image's color space), and the base and alternate image ICC profiles are the -+ // same, so the alternate image color space should be ignored. -+ scoped_refptr data = ReadFileToSharedBuffer( -+ "/images/resources/avif/small-with-gainmap-iso-usealtcolorspace.avif"); -+ std::unique_ptr decoder = CreateAVIFDecoder(); -+ decoder->SetData(data, true); -+ SkGainmapInfo gainmap_info; -+ scoped_refptr gainmap_data; -+ const bool has_gainmap = -+ decoder->GetGainmapInfoAndData(gainmap_info, gainmap_data); -+ ASSERT_TRUE(has_gainmap); -+ -+ EXPECT_EQ(gainmap_info.fGainmapMathColorSpace, nullptr); -+} -+ -+void ExpectMatrixNear(const skcms_Matrix3x3& lhs, -+ const skcms_Matrix3x3& rhs, -+ float epsilon) { -+ for (int r = 0; r < 3; r++) { -+ for (int c = 0; c < 3; c++) { -+ EXPECT_NEAR(lhs.vals[r][c], rhs.vals[r][c], epsilon); -+ } -+ } -+} -+ -+TEST(StaticAVIFTests, GetIsoGainmapColorSpaceDifferentICC) { -+ base::test::ScopedFeatureList scoped_feature_list; -+ scoped_feature_list.InitWithFeatures( -+ /*enabled_features=*/{features::kAvifGainmapHdrImages}, -+ /*disabled_features=*/{}); -+ -+ // The image has use_base_color_space set to false (i.e. use the alternate -+ // image's color space), and the base and alternate image ICC profiles are -+ // different, so the alternate ICC profile should be set as -+ // fGainmapMathColorSpace. -+ // Base is sRGB, alternate is P3. -+ scoped_refptr data = ReadFileToSharedBuffer( -+ "/images/resources/avif/" -+ "small-with-gainmap-iso-usealtcolorspace-differenticc.avif"); -+ std::unique_ptr decoder = CreateAVIFDecoder(); -+ decoder->SetData(data, true); -+ SkGainmapInfo gainmap_info; -+ scoped_refptr gainmap_data; -+ const bool has_gainmap = -+ decoder->GetGainmapInfoAndData(gainmap_info, gainmap_data); -+ ASSERT_TRUE(has_gainmap); -+ -+ // Check that the gain map color space is specified. -+ EXPECT_NE(gainmap_info.fGainmapMathColorSpace, nullptr); -+ // Only compare the color primaries, the transfer function is irrelevant. -+ skcms_Matrix3x3 matrix; -+ ASSERT_TRUE(gainmap_info.fGainmapMathColorSpace->toXYZD50(&matrix)); -+ ExpectMatrixNear(matrix, SkNamedGamut::kDisplayP3, 0.001); -+} -+ -+TEST(StaticAVIFTests, GetIsoGainmapColorSpaceDifferentCICP) { -+ base::test::ScopedFeatureList scoped_feature_list; -+ scoped_feature_list.InitWithFeatures( -+ /*enabled_features=*/{features::kAvifGainmapHdrImages}, -+ /*disabled_features=*/{}); -+ -+ // The image has use_base_color_space set to false (i.e. use the alternate -+ // image's color space), and the base and alternate images don't have ICC -+ // but CICP values instead. The alternate image's CICP values should be used. -+ // Base is sRGB, alternate is Rec 2020. -+ scoped_refptr data = ReadFileToSharedBuffer( -+ "/images/resources/avif/gainmap-sdr-srgb-to-hdr-wcg-rec2020.avif"); -+ std::unique_ptr decoder = CreateAVIFDecoder(); -+ decoder->SetData(data, true); -+ SkGainmapInfo gainmap_info; -+ scoped_refptr gainmap_data; -+ const bool has_gainmap = -+ decoder->GetGainmapInfoAndData(gainmap_info, gainmap_data); -+ ASSERT_TRUE(has_gainmap); -+ -+ // Check that the gain map color space is specified. -+ EXPECT_NE(gainmap_info.fGainmapMathColorSpace, nullptr); -+ // Only compare the color primaries, the transfer function is irrelevant. -+ skcms_Matrix3x3 matrix; -+ ASSERT_TRUE(gainmap_info.fGainmapMathColorSpace->toXYZD50(&matrix)); -+ ExpectMatrixNear(matrix, SkNamedGamut::kRec2020, 0.0001); -+} -+ -+TEST(StaticAVIFTests, GetGainmapInfoAndDataWithFeatureDisabled) { -+ base::test::ScopedFeatureList scoped_feature_list; -+ scoped_feature_list.InitWithFeatures( -+ /*enabled_features=*/{}, -+ /*disabled_features=*/{features::kAvifGainmapHdrImages}); -+ -+ const std::string image = "small-with-gainmap-iso.avif"; -+ scoped_refptr data = -+ ReadFileToSharedBuffer("web_tests/images/resources/avif", image.c_str()); -+ std::unique_ptr decoder = CreateAVIFDecoder(); -+ decoder->SetData(data, true); -+ SkGainmapInfo gainmap_info; -+ scoped_refptr gainmap_data; -+ const bool has_gainmap = -+ decoder->GetGainmapInfoAndData(gainmap_info, gainmap_data); -+ ASSERT_FALSE(has_gainmap); -+ -+ // Check that we get an error if we try decoding the gain map. -+ std::unique_ptr gainmap_decoder = CreateGainMapAVIFDecoder(); -+ gainmap_decoder->SetData(data, true); -+ EXPECT_FALSE(gainmap_decoder->IsSizeAvailable()); -+ EXPECT_TRUE(gainmap_decoder->Failed()); -+ EXPECT_EQ(gainmap_decoder->FrameCount(), 0u); -+ EXPECT_FALSE(gainmap_decoder->DecodeFrameBufferAtIndex(0)); -+} -+ -+TEST(StaticAVIFTests, GetGainmapInfoAndDataWithTruncatedData) { -+ base::test::ScopedFeatureList scoped_feature_list; -+ scoped_feature_list.InitWithFeatures( -+ /*enabled_features=*/{features::kAvifGainmapHdrImages}, -+ /*disabled_features=*/{}); -+ -+ const std::string image = "small-with-gainmap-iso.avif"; -+ const Vector data_vector = -+ ReadFile("web_tests/images/resources/avif", image.c_str()); -+ scoped_refptr half_data = SharedBuffer::Create( -+ base::span(data_vector).first(data_vector.size() / 2)); -+ -+ std::unique_ptr decoder = CreateAVIFDecoder(); -+ decoder->SetData(half_data, true); -+ SkGainmapInfo gainmap_info; -+ scoped_refptr gainmap_data; -+ const bool has_gainmap = -+ decoder->GetGainmapInfoAndData(gainmap_info, gainmap_data); -+ ASSERT_FALSE(has_gainmap); -+} -+ -+TEST(StaticAVIFTests, GetGainmapWithGammaZero) { -+ base::test::ScopedFeatureList scoped_feature_list; -+ scoped_feature_list.InitWithFeatures( -+ /*enabled_features=*/{features::kAvifGainmapHdrImages}, -+ /*disabled_features=*/{}); -+ -+ const std::string image = "small-with-gainmap-iso-gammazero.avif"; -+ scoped_refptr data = -+ ReadFileToSharedBuffer("web_tests/images/resources/avif", image.c_str()); -+ std::unique_ptr decoder = CreateAVIFDecoder(); -+ decoder->SetData(data, true); -+ SkGainmapInfo gainmap_info; -+ scoped_refptr gainmap_data; -+ const bool has_gainmap = -+ decoder->GetGainmapInfoAndData(gainmap_info, gainmap_data); -+ ASSERT_FALSE(has_gainmap); -+} -+ -+TEST(StaticAVIFTests, YUV) { -+ // 3x3, YUV 4:2:0 -+ constexpr gfx::Size kUVSize420(2, 2); -+ TestYUVRed("red-limited-range-420-8bpc.avif", kUVSize420); -+ TestYUVRed("red-full-range-420-8bpc.avif", kUVSize420); -+ -+ // 3x3, YUV 4:2:2 -+ constexpr gfx::Size kUVSize422(2, 3); -+ TestYUVRed("red-limited-range-422-8bpc.avif", kUVSize422); -+ -+ // 3x3, YUV 4:4:4 -+ constexpr gfx::Size kUVSize444(3, 3); -+ TestYUVRed("red-limited-range-444-8bpc.avif", kUVSize444); -+ -+ // Full range BT709 color space is uncommon, but should be supported. -+ TestYUVRed("red-full-range-bt709-444-8bpc.avif", kUVSize444); -+ -+ for (const auto ct : {kA16_unorm_SkColorType, kA16_float_SkColorType}) { -+ // 3x3, YUV 4:2:0, 10bpc -+ TestYUVRed("red-limited-range-420-10bpc.avif", kUVSize420, ct, 10); -+ -+ // 3x3, YUV 4:2:2, 10bpc -+ TestYUVRed("red-limited-range-422-10bpc.avif", kUVSize422, ct, 10); -+ -+ // 3x3, YUV 4:4:4, 10bpc -+ TestYUVRed("red-limited-range-444-10bpc.avif", kUVSize444, ct, 10); -+ -+ // 3x3, YUV 4:2:0, 12bpc -+ TestYUVRed("red-limited-range-420-12bpc.avif", kUVSize420, ct, 12); -+ -+ // 3x3, YUV 4:2:2, 12bpc -+ TestYUVRed("red-limited-range-422-12bpc.avif", kUVSize422, ct, 12); -+ -+ // 3x3, YUV 4:4:4, 12bpc -+ TestYUVRed("red-limited-range-444-12bpc.avif", kUVSize444, ct, 12); -+ -+ // Various common color spaces should be supported. -+ TestYUVRed("red-full-range-bt2020-pq-444-10bpc.avif", kUVSize444, ct, 10); -+ TestYUVRed("red-full-range-bt2020-pq-444-12bpc.avif", kUVSize444, ct, 12); -+ TestYUVRed("red-full-range-bt2020-hlg-444-10bpc.avif", kUVSize444, ct, 10); -+ TestYUVRed("red-full-range-bt2020-hlg-444-12bpc.avif", kUVSize444, ct, 12); -+ } -+} -+ -+TEST(StaticAVIFTests, SizeAvailableBeforeAllDataReceived) { -+ scoped_refptr stream_buffer = WTF::SharedBuffer::Create(); -+ scoped_refptr segment_reader = -+ SegmentReader::CreateFromSharedBuffer(stream_buffer); -+ std::unique_ptr decoder = ImageDecoder::CreateByMimeType( -+ "image/avif", segment_reader, /*data_complete=*/false, -+ ImageDecoder::kAlphaPremultiplied, ImageDecoder::kDefaultBitDepth, -+ ColorBehavior::kTag, cc::AuxImage::kDefault, -+ Platform::GetMaxDecodedImageBytes(), SkISize::MakeEmpty(), -+ ImageDecoder::AnimationOption::kUnspecified); -+ EXPECT_FALSE(decoder->IsSizeAvailable()); -+ -+ Vector data = -+ ReadFile("/images/resources/avif/red-limited-range-420-8bpc.avif"); -+ stream_buffer->Append(data); -+ EXPECT_EQ(stream_buffer->size(), 318u); -+ decoder->SetData(stream_buffer, /*all_data_received=*/false); -+ // All bytes are appended so we should have size, even though we pass -+ // all_data_received=false. -+ EXPECT_TRUE(decoder->IsSizeAvailable()); -+ -+ decoder->SetData(stream_buffer, /*all_data_received=*/true); -+ EXPECT_TRUE(decoder->IsSizeAvailable()); -+} -+ -+TEST(StaticAVIFTests, ProgressiveDecoding) { -+ base::HistogramTester histogram_tester; -+ scoped_refptr stream_buffer = WTF::SharedBuffer::Create(); -+ scoped_refptr segment_reader = -+ SegmentReader::CreateFromSharedBuffer(stream_buffer); -+ std::unique_ptr decoder = ImageDecoder::CreateByMimeType( -+ "image/avif", segment_reader, /*data_complete=*/false, -+ ImageDecoder::kAlphaPremultiplied, ImageDecoder::kDefaultBitDepth, -+ ColorBehavior::kTag, cc::AuxImage::kDefault, -+ Platform::GetMaxDecodedImageBytes(), SkISize::MakeEmpty(), -+ ImageDecoder::AnimationOption::kUnspecified); -+ -+ Vector data = ReadFile("/images/resources/avif/tiger_3layer_1res.avif"); -+ ASSERT_EQ(data.size(), 70944u); -+ -+ // This image has three layers. The first layer is 8299 bytes. Because of -+ // image headers and other overhead, if we pass exactly 8299 bytes to the -+ // decoder, the decoder does not have enough data to decode the first layer. -+ stream_buffer->Append(base::span(data).first(8299u)); -+ decoder->SetData(stream_buffer, /*all_data_received=*/false); -+ EXPECT_TRUE(decoder->IsSizeAvailable()); -+ EXPECT_FALSE(decoder->Failed()); -+ EXPECT_EQ(decoder->FrameCount(), 1u); -+ histogram_tester.ExpectTotalCount("Blink.DecodedImage.AvifDensity.Count.02MP", -+ 0); -+ ImageFrame* frame = decoder->DecodeFrameBufferAtIndex(0); -+ ASSERT_TRUE(frame); -+ EXPECT_EQ(frame->GetStatus(), ImageFrame::kFrameEmpty); -+ EXPECT_FALSE(decoder->Failed()); -+ -+ // An additional 301 bytes are enough data for the decoder to decode the first -+ // layer. With progressive decoding, the frame buffer status will transition -+ // to ImageFrame::kFramePartial. -+ stream_buffer->Append(base::span(data).subspan(8299u, 301u)); -+ decoder->SetData(stream_buffer, /*all_data_received=*/false); -+ EXPECT_FALSE(decoder->Failed()); -+ frame = decoder->DecodeFrameBufferAtIndex(0); -+ ASSERT_TRUE(frame); -+ EXPECT_EQ(frame->GetStatus(), ImageFrame::kFramePartial); -+ EXPECT_FALSE(decoder->Failed()); -+ -+ base::HistogramTester::CountsMap expected_counts; -+ EXPECT_THAT(histogram_tester.GetTotalCountsForPrefix( -+ "Blink.DecodedImage.AvifDensity.Count."), -+ testing::ContainerEq(expected_counts)); -+ -+ // Now send the rest of the data. -+ stream_buffer->Append(base::span(data).subspan(8299u + 301u, 62344u)); -+ decoder->SetData(stream_buffer, /*all_data_received=*/true); -+ EXPECT_FALSE(decoder->Failed()); -+ frame = decoder->DecodeFrameBufferAtIndex(0); -+ ASSERT_TRUE(frame); -+ EXPECT_EQ(frame->GetStatus(), ImageFrame::kFrameComplete); -+ EXPECT_FALSE(decoder->Failed()); -+ -+ constexpr int kImageArea = 1216 * 832; // = 1011712 -+ constexpr int kFileSize = 70944; -+ constexpr int kSample = -+ (kFileSize * 100 * 8 + kImageArea / 2) / kImageArea; // = 56 -+ histogram_tester.ExpectUniqueSample( -+ "Blink.DecodedImage.AvifDensity.Count.02MP", kSample, 1); -+ expected_counts["Blink.DecodedImage.AvifDensity.Count.02MP"] = 1; -+ EXPECT_THAT(histogram_tester.GetTotalCountsForPrefix( -+ "Blink.DecodedImage.AvifDensity.Count."), -+ testing::ContainerEq(expected_counts)); -+} -+ -+TEST(StaticAVIFTests, IncrementalDecoding) { -+ base::HistogramTester histogram_tester; -+ scoped_refptr stream_buffer = WTF::SharedBuffer::Create(); -+ scoped_refptr segment_reader = -+ SegmentReader::CreateFromSharedBuffer(stream_buffer); -+ std::unique_ptr decoder = ImageDecoder::CreateByMimeType( -+ "image/avif", segment_reader, /*data_complete=*/false, -+ ImageDecoder::kAlphaPremultiplied, ImageDecoder::kDefaultBitDepth, -+ ColorBehavior::kTag, cc::AuxImage::kDefault, -+ Platform::GetMaxDecodedImageBytes(), SkISize::MakeEmpty(), -+ ImageDecoder::AnimationOption::kUnspecified); -+ -+ Vector data = -+ ReadFile("/images/resources/avif/tiger_420_8b_grid1x13.avif"); -+ -+ constexpr int kImageArea = 1216 * 832; // = 1011712 -+ constexpr int kFileSize = 72257; -+ constexpr int kSample = -+ (kFileSize * 100 * 8 + kImageArea / 2) / kImageArea; // = 57 -+ -+ struct Step { -+ size_t size; // In bytes. -+ ImageFrame::Status status; -+ int num_decoded_rows; // In pixels. -+ }; -+ // There are 13 tiles. Tiles are as wide as the image and 64 pixels tall. -+ // |num_decoded_rows| may be odd due to an output pixel row missing the -+ // following upsampled decoded chroma row (belonging to the next tile). -+ const Step steps[] = { -+ {2000, ImageFrame::kFrameEmpty, 0}, -+ // Decoding half of the bytes gives 6 tile rows. -+ {data.size() / 2, ImageFrame::kFramePartial, 6 * 64 - 1}, -+ // Decoding all bytes but one gives 12 tile rows. -+ {data.size() - 1, ImageFrame::kFramePartial, 12 * 64 - 1}, -+ // Decoding all bytes gives all 13 tile rows. -+ {data.size(), ImageFrame::kFrameComplete, 13 * 64}}; -+ size_t previous_size = 0; -+ auto data_span = base::span(data); -+ for (const Step& step : steps) { -+ stream_buffer->Append( -+ data_span.subspan(previous_size, step.size - previous_size)); -+ decoder->SetData(stream_buffer, step.status == ImageFrame::kFrameComplete); -+ -+ EXPECT_EQ(decoder->FrameCount(), 1u); -+ ImageFrame* frame = decoder->DecodeFrameBufferAtIndex(0); -+ ASSERT_TRUE(frame); -+ ASSERT_FALSE(decoder->Failed()); -+ EXPECT_EQ(frame->GetStatus(), step.status); -+ -+ const SkBitmap& bitmap = frame->Bitmap(); -+ for (int y = 0; y < bitmap.height(); ++y) { -+ const uint32_t* row = bitmap.getAddr32(0, y); -+ const bool is_row_decoded = y < step.num_decoded_rows; -+ for (int x = 0; x < bitmap.width(); ++x) { -+ // The input image is opaque. Pixels outside the decoded area are fully -+ // transparent black pixels, with each channel value being 0. -+ const bool is_pixel_decoded = row[x] != 0x00000000u; -+ ASSERT_EQ(is_pixel_decoded, is_row_decoded); -+ } -+ } -+ previous_size = step.size; -+ -+ base::HistogramTester::CountsMap expected_counts; -+ if (step.status == ImageFrame::kFrameComplete) { -+ histogram_tester.ExpectUniqueSample( -+ "Blink.DecodedImage.AvifDensity.Count.02MP", kSample, 1); -+ expected_counts["Blink.DecodedImage.AvifDensity.Count.02MP"] = 1; -+ } -+ EXPECT_THAT(histogram_tester.GetTotalCountsForPrefix( -+ "Blink.DecodedImage.AvifDensity.Count."), -+ testing::ContainerEq(expected_counts)); -+ } -+} -+ -+// Reproduces crbug.com/1402841. Decodes a large AVIF image 104 times in -+// parallel from base::ThreadPool. Should not cause temporary deadlock of -+// base::ThreadPool. -+TEST(StaticAVIFTests, ParallelDecoding) { -+ // The base::test::TaskEnvironment constructor creates a base::ThreadPool -+ // instance with 4 foreground threads. The number 4 comes from the -+ // test::TaskEnvironment::kNumForegroundThreadPoolThreads constant. -+ base::test::TaskEnvironment task_environment; -+ -+ // This test image is fast to decode (all neutral gray pixels) and its -+ // allocation size is large enough to cause -+ // media::PaintCanvasVideoRenderer::ConvertVideoFrameToRGBPixels() to pick -+ // n_tasks > 1 if AVIFImageDecoder did not pass disable_threading=true to it. -+ Vector data = ReadFile("/images/resources/avif/gray1024x704.avif"); -+ -+ // Task timeout in tests is 30 seconds (see https://crrev.com/c/1949028). -+ // Four blocking tasks cause a temporary deadlock (1.2 seconds) of -+ // base::ThreadPool, so we need at least 30 / 1.2 * 4 = 100 decodes for the -+ // test to time out without the bug fix. We add a margin of 4 decodes, i.e., -+ // (30 / 1.2 + 1) * 4 = 104. -+ const size_t n_decodes = 104; -+ base::WaitableEvent event; -+ base::RepeatingClosure barrier = base::BarrierClosure( -+ n_decodes, -+ base::BindOnce(&base::WaitableEvent::Signal, base::Unretained(&event))); -+ -+ for (size_t i = 0; i < n_decodes; ++i) { -+ base::ThreadPool::PostTask( -+ FROM_HERE, -+ base::BindOnce(DecodeTask, base::Unretained(&data), &barrier)); -+ } -+ -+ event.Wait(); -+} -+ -+TEST(StaticAVIFTests, AlphaHasNoIspeProperty) { -+ std::unique_ptr decoder = CreateAVIFDecoder(); -+ decoder->SetData( -+ ReadFileToSharedBuffer("/images/resources/avif/green-no-alpha-ispe.avif"), -+ true); -+ EXPECT_FALSE(decoder->IsSizeAvailable()); -+ EXPECT_TRUE(decoder->Failed()); -+} -+ -+TEST(StaticAVIFTests, UnsupportedTransferFunctionInColrProperty) { -+ std::unique_ptr decoder = CreateAVIFDecoder(); -+ decoder->SetData(ReadFileToSharedBuffer( -+ "/images/resources/avif/red-unsupported-transfer.avif"), -+ true); -+ EXPECT_FALSE(decoder->IsSizeAvailable()); -+ EXPECT_TRUE(decoder->Failed()); -+} -+ -+TEST(StaticAVIFTests, ClapPropertyZeroOrigin) { -+ constexpr int kClapWidth = 200; -+ constexpr int kClapHeight = 50; -+ std::unique_ptr decoder1 = CreateAVIFDecoder(); -+ decoder1->SetData( -+ ReadFileToSharedBuffer("/images/resources/avif/red-and-purple-crop.avif"), -+ true); -+ ASSERT_TRUE(decoder1->IsSizeAvailable()); -+ gfx::Size size1 = decoder1->Size(); -+ ASSERT_EQ(size1.width(), kClapWidth); -+ ASSERT_EQ(size1.height(), kClapHeight); -+ ImageFrame* frame1 = decoder1->DecodeFrameBufferAtIndex(0); -+ ASSERT_TRUE(frame1); -+ EXPECT_EQ(ImageFrame::kFrameComplete, frame1->GetStatus()); -+ EXPECT_FALSE(decoder1->Failed()); -+ const SkBitmap& bitmap1 = frame1->Bitmap(); -+ -+ // The second image is the uncropped version of the first image. -+ std::unique_ptr decoder2 = CreateAVIFDecoder(); -+ decoder2->SetData(ReadFileToSharedBuffer( -+ "/images/resources/avif/red-and-purple-and-blue.avif"), -+ true); -+ ASSERT_TRUE(decoder2->IsSizeAvailable()); -+ gfx::Size size2 = decoder2->Size(); -+ ASSERT_EQ(size2.width(), 300); -+ ASSERT_EQ(size2.height(), 100); -+ ImageFrame* frame2 = decoder2->DecodeFrameBufferAtIndex(0); -+ ASSERT_TRUE(frame2); -+ EXPECT_EQ(ImageFrame::kFrameComplete, frame2->GetStatus()); -+ EXPECT_FALSE(decoder2->Failed()); -+ const SkBitmap& bitmap2 = frame2->Bitmap(); -+ -+ // Compare pixel data. -+ for (int row = 0; row < kClapHeight; ++row) { -+ for (int col = 0; col < kClapWidth; ++col) { -+ EXPECT_EQ(bitmap1.getColor(/*x=*/col, /*y=*/row), -+ bitmap2.getColor(/*x=*/col, /*y=*/row)); -+ } -+ } -+} -+ -+// Verifies that an invalid 'clap' (clean aperture) image property is handled by -+// ignoring the 'clap' property and showing the full image. -+TEST(StaticAVIFTests, InvalidClapPropertyHandling) { -+ // The first image has a valid 'clap' property. The full image has size -+ // 320x280. The clean aperture has size 180x100, located at (40, 80) of the -+ // full image. -+ // -+ // Since the origin of the clean aperture is not located at (0, 0), we treat -+ // the 'clap' property as invalid. So the full image is shown. -+ std::unique_ptr decoder1 = CreateAVIFDecoder(); -+ decoder1->SetData(ReadFileToSharedBuffer( -+ "/images/resources/avif/blue-and-magenta-crop.avif"), -+ true); -+ ASSERT_TRUE(decoder1->IsSizeAvailable()); -+ gfx::Size size1 = decoder1->Size(); -+ ASSERT_EQ(size1.width(), 320); -+ ASSERT_EQ(size1.height(), 280); -+ ImageFrame* frame1 = decoder1->DecodeFrameBufferAtIndex(0); -+ ASSERT_TRUE(frame1); -+ EXPECT_EQ(ImageFrame::kFrameComplete, frame1->GetStatus()); -+ EXPECT_FALSE(decoder1->Failed()); -+ const SkBitmap& bitmap1 = frame1->Bitmap(); -+ -+ // The second image is the same as the first image except that the 'clap' -+ // property is invalid. In this case the full image is shown. -+ std::unique_ptr decoder2 = CreateAVIFDecoder(); -+ decoder2->SetData( -+ ReadFileToSharedBuffer( -+ "/images/resources/avif/blue-and-magenta-crop-invalid.avif"), -+ true); -+ ASSERT_TRUE(decoder2->IsSizeAvailable()); -+ gfx::Size size2 = decoder2->Size(); -+ ASSERT_EQ(size2.width(), 320); -+ ASSERT_EQ(size2.height(), 280); -+ ImageFrame* frame2 = decoder2->DecodeFrameBufferAtIndex(0); -+ ASSERT_TRUE(frame2); -+ EXPECT_EQ(ImageFrame::kFrameComplete, frame2->GetStatus()); -+ EXPECT_FALSE(decoder2->Failed()); -+ const SkBitmap& bitmap2 = frame2->Bitmap(); -+ -+ // Compare pixel data. -+ for (int row = 0; row < size1.height(); ++row) { -+ for (int col = 0; col < size1.width(); ++col) { -+ EXPECT_EQ(bitmap1.getColor(/*x=*/col, /*y=*/row), -+ bitmap2.getColor(/*x=*/col, /*y=*/row)); -+ } -+ } -+} -+ -+TEST(StaticAVIFTests, BppHistogramSmall) { -+ constexpr int kImageArea = 768 * 512; // = 393216 -+ constexpr int kFileSize = 25724; -+ constexpr int kSample = -+ (kFileSize * 100 * 8 + kImageArea / 2) / kImageArea; // = 52 -+ TestAvifBppHistogram("/images/resources/avif/kodim03.avif", -+ "Blink.DecodedImage.AvifDensity.Count.0.4MP", kSample); -+} -+ -+TEST(StaticAVIFTests, BppHistogramSmall3x3) { -+ // The centi bpp = 318 * 100 * 8 / (3 * 3) ~= 28267, which is greater than the -+ // histogram's max value (1000), so this sample goes into the overflow bucket. -+ constexpr int kSample = 1000; -+ TestAvifBppHistogram("/images/resources/avif/red-full-range-420-8bpc.avif", -+ "Blink.DecodedImage.AvifDensity.Count.0.1MP", kSample); -+} -+ -+TEST(StaticAVIFTests, BppHistogramSmall900000) { -+ constexpr int kImageArea = 1200 * 750; // = 900000 -+ constexpr int kFileSize = 8144; -+ constexpr int kSample = -+ (kFileSize * 100 * 8 + kImageArea / 2) / kImageArea; // = 7 -+ TestAvifBppHistogram("/images/resources/avif/peach_900000.avif", -+ "Blink.DecodedImage.AvifDensity.Count.0.9MP", kSample); -+} -+ -+TEST(StaticAVIFTests, BppHistogramBig) { -+ constexpr int kImageArea = 4032 * 3024; // = 12192768 -+ constexpr int kFileSize = 88692; -+ constexpr int kSample = -+ (kFileSize * 100 * 8 + kImageArea / 2) / kImageArea; // = 6 -+ TestAvifBppHistogram("/images/resources/avif/bee.avif", -+ "Blink.DecodedImage.AvifDensity.Count.13MP", kSample); -+} -+ -+TEST(StaticAVIFTests, BppHistogramBig13000000) { -+ constexpr int kImageArea = 4000 * 3250; // = 13000000 -+ constexpr int kFileSize = 16725; -+ constexpr int kSample = -+ (kFileSize * 100 * 8 + kImageArea / 2) / kImageArea; // = 1 -+ TestAvifBppHistogram("/images/resources/avif/peach_13000000.avif", -+ "Blink.DecodedImage.AvifDensity.Count.13MP", kSample); -+} -+ -+TEST(StaticAVIFTests, BppHistogramHuge) { -+ constexpr int kImageArea = 4624 * 3472; // = 16054528 -+ constexpr int kFileSize = 20095; -+ constexpr int kSample = -+ (kFileSize * 100 * 8 + kImageArea / 2) / kImageArea; // = 1 -+ TestAvifBppHistogram("/images/resources/avif/peach.avif", -+ "Blink.DecodedImage.AvifDensity.Count.14+MP", kSample); -+} -+ -+TEST(StaticAVIFTests, BppHistogramHuge13000002) { -+ constexpr int kImageArea = 3961 * 3282; // = 13000002 -+ constexpr int kFileSize = 16379; -+ constexpr int kSample = -+ (kFileSize * 100 * 8 + kImageArea / 2) / kImageArea; // = 1 -+ TestAvifBppHistogram("/images/resources/avif/peach_13000002.avif", -+ "Blink.DecodedImage.AvifDensity.Count.14+MP", kSample); -+} -+ -+TEST(StaticAVIFTests, BppHistogramInvalid) { -+ base::HistogramTester histogram_tester; -+ std::unique_ptr decoder = CreateAVIFDecoder(); -+ decoder->SetData( -+ ReadFileToSharedBuffer( -+ "/images/resources/avif/" -+ "red-at-12-oclock-with-color-profile-with-wrong-frame-header.avif"), -+ true); -+ ASSERT_TRUE(decoder->IsSizeAvailable()); -+ EXPECT_FALSE(decoder->Failed()); -+ EXPECT_EQ(decoder->FrameCount(), 1u); -+ ImageFrame* frame = decoder->DecodeFrameBufferAtIndex(0); -+ ASSERT_TRUE(frame); -+ EXPECT_NE(ImageFrame::kFrameComplete, frame->GetStatus()); -+ EXPECT_TRUE(decoder->Failed()); -+ const base::HistogramTester::CountsMap empty_counts; -+ EXPECT_THAT(histogram_tester.GetTotalCountsForPrefix( -+ "Blink.DecodedImage.AvifDensity.Count."), -+ testing::ContainerEq(empty_counts)); -+} -+ -+TEST(StaticAVIFTests, BppHistogram10bit) { -+ TestAvifBppHistogram("/images/resources/avif/red-full-range-420-10bpc.avif"); -+} -+ -+TEST(StaticAVIFTests, BppHistogramMonochrome) { -+ TestAvifBppHistogram("/images/resources/avif/silver-400-matrix-6.avif"); -+} -+ -+TEST(StaticAVIFTests, BppHistogramAlpha) { -+ TestAvifBppHistogram("/images/resources/avif/red-with-alpha-8bpc.avif"); -+} -+ -+TEST(StaticAVIFTests, BppHistogramAnimated) { -+ TestAvifBppHistogram("/images/resources/avif/star-animated-8bpc.avif"); -+} -+ -+using StaticAVIFColorTests = ::testing::TestWithParam; -+ -+INSTANTIATE_TEST_SUITE_P(Parameterized, -+ StaticAVIFColorTests, -+ ::testing::ValuesIn(kTestParams)); -+ -+TEST_P(StaticAVIFColorTests, InspectImage) { -+ InspectImage(GetParam(), ImageDecoder::kDefaultBitDepth); -+} -+ -+TEST_P(StaticAVIFColorTests, InspectImageHalfFloat) { -+ InspectImage(GetParam(), ImageDecoder::kHighBitDepthToHalfFloat); -+} -+ -+} // namespace -+ -+} // namespace blink -diff --git a/third_party/blink/renderer/platform/image-decoders/avif/gen_crabbyavif_wrapper.py b/third_party/blink/renderer/platform/image-decoders/avif/gen_crabbyavif_wrapper.py -new file mode 100644 -index 0000000000000..82f1c0c3df73a ---- /dev/null -+++ b/third_party/blink/renderer/platform/image-decoders/avif/gen_crabbyavif_wrapper.py -@@ -0,0 +1,164 @@ -+# Copyright 2024 The Chromium Authors -+# Use of this source code is governed by a BSD-style license that can be -+# found in the LICENSE file. -+"""Script to generate crabbyavif wrapper using the libavif wrapper as the base. -+ -+When the libavif wrapper files (any of avif_image_decoder*) are changed, this -+script must be run to update the crabbyavif wrappers -+(crabbyavif_image_decoder*). -+""" -+ -+import os -+import re -+ -+ -+def _read_file(filename): -+ with open(filename) as file: -+ return file.read() -+ -+ -+def _write_file(filename, contents): -+ with open(filename, "w") as file: -+ file.write(contents) -+ -+ -+def _apply_replacements(contents, replacements): -+ for find, replace in replacements: -+ contents = re.sub(find, replace, contents) -+ return contents -+ -+ -+_COMMON_REPLACEMENTS = ( -+ (r"Copyright 2020", "Copyright 2024"), -+ (r"third_party/libavif/src", "third_party/crabbyavif/src"), -+ (r"avif_image_decoder.h", "crabbyavif_image_decoder.h"), -+ (r"AVIFImageDecoder", "CrabbyAVIFImageDecoder"), -+ (r"AVIF_TRUE", "CRABBY_AVIF_TRUE"), -+ (r"AVIF_FALSE", "CRABBY_AVIF_FALSE"), -+ (r"AVIF_REPETITION_COUNT_", "CRABBY_AVIF_REPETITION_COUNT_"), -+) -+ -+_NOTICE = """// WARNING: Auto-generated by gen_crabbyavif_wrapper.py. -+// Do not modify manually. -+""" -+ -+ -+def _generate_crabbyavif_file(source_file, replacements): -+ contents = _read_file(source_file) -+ contents = _apply_replacements(contents, _COMMON_REPLACEMENTS) -+ contents = _apply_replacements(contents, replacements) -+ contents = contents.split("\n") -+ # Copyright notice is 3 lines, insert the notice as the 4th line. -+ contents.insert(3, _NOTICE) -+ contents = "\n".join(contents) -+ crabby_source_file = "crabby%(source_file)s" % locals() -+ _write_file(crabby_source_file, contents) -+ os.system("clang-format -style chromium -i %(crabby_source_file)s" % -+ locals()) -+ -+ -+_HEADER_REPLACEMENTS = ( -+ (r"AVIF_AVIF_IMAGE_DECODER_H_", "AVIF_CRABBYAVIF_IMAGE_DECODER_H_"), -+ (r"AVIF_PIXEL_FORMAT_NONE", "crabbyavif::AVIF_PIXEL_FORMAT_NONE"), -+ # Functions -+ (r"avifDecoderDestroy", "crabbyavif::crabby_avifDecoderDestroy"), -+ (r"avifImageDestroy", "crabbyavif::crabby_avifImageDestroy"), -+ # Types -+ (r"avifIO", "crabbyavif::avifIO"), -+ (r"avifPixelFormat", "crabbyavif::avifPixelFormat"), -+ (r"avifROData", "crabbyavif::avifROData"), -+ (r"avifResult", "crabbyavif::avifResult"), -+ (r"\bavifDecoder\b", "crabbyavif::avifDecoder"), -+ (r"\bavifImage\b", "crabbyavif::avifImage"), -+) -+ -+_CC_REPLACEMENTS = ( -+ # Functions (to be namespaced and prefixed with "crabby_") -+ ( -+ r"\bavifCropRectConvertCleanApertureBox\b", -+ "crabbyavif::crabby_avifCropRectConvertCleanApertureBox", -+ ), -+ (r"\bavifDecoderCreate\b", "crabbyavif::crabby_avifDecoderCreate"), -+ ( -+ r"\bavifDecoderDecodedRowCount\b", -+ "crabbyavif::crabby_avifDecoderDecodedRowCount", -+ ), -+ (r"\bavifDecoderDestroy\b", "crabbyavif::crabby_avifDecoderDestroy"), -+ (r"\bavifDecoderNthImage\b", "crabbyavif::crabby_avifDecoderNthImage"), -+ ( -+ r"\bavifDecoderNthImageMaxExtent\b", -+ "crabbyavif::crabby_avifDecoderNthImageMaxExtent", -+ ), -+ ( -+ r"\bavifDecoderNthImageMaxExtent\b", -+ "crabbyavif::crabby_avifDecoderNthImageMaxExtent", -+ ), -+ ( -+ r"\bavifDecoderNthImageTiming\b", -+ "crabbyavif::crabby_avifDecoderNthImageTiming", -+ ), -+ (r"\bavifDecoderParse\b", "crabbyavif::crabby_avifDecoderParse"), -+ (r"\bavifDecoderSetIO\b", "crabbyavif::crabby_avifDecoderSetIO"), -+ (r"\bavifDecoderSetSource\b", "crabbyavif::crabby_avifDecoderSetSource"), -+ ( -+ r"\bavifGetPixelFormatInfo\b", -+ "crabbyavif::crabby_avifGetPixelFormatInfo", -+ ), -+ (r"\bavifImageCreateEmpty\b", "crabbyavif::crabby_avifImageCreateEmpty"), -+ (r"\bavifImageDestroy\b", "crabbyavif::crabby_avifImageDestroy"), -+ (r"\bavifImageSetViewRect\b", "crabbyavif::crabby_avifImageSetViewRect"), -+ (r"\bavifImageYUVToRGB\b", "crabbyavif::crabby_avifImageYUVToRGB"), -+ ( -+ r"\bavifPeekCompatibleFileType\b", -+ "crabbyavif::crabby_avifPeekCompatibleFileType", -+ ), -+ ( -+ r"\bavifRGBImageSetDefaults\b", -+ "crabbyavif::crabby_avifRGBImageSetDefaults", -+ ), -+ (r"\bavifResultToString\b", "crabbyavif::crabby_avifResultToString"), -+ # Symbols (to be namespaced). -+ (r"avifBool\b", "crabbyavif::avifBool"), -+ (r"avifColorPrimaries\b", "crabbyavif::avifColorPrimaries"), -+ (r"avifCropRect\b", "crabbyavif::avifCropRect"), -+ (r"avifDecoder\b", "crabbyavif::avifDecoder"), -+ (r"avifDiagnostics\b", "crabbyavif::avifDiagnostics"), -+ (r"avifExtent\b", "crabbyavif::avifExtent"), -+ (r"avifGainMap\b", "crabbyavif::avifGainMap"), -+ (r"avifGainMapMetadata\b", "crabbyavif::avifGainMapMetadata"), -+ (r"avifIO\b", "crabbyavif::avifIO"), -+ (r"avifImage\b", "crabbyavif::avifImage"), -+ (r"avifImageTiming\b", "crabbyavif::avifImageTiming"), -+ (r"avifMatrixCoefficients\b", "crabbyavif::avifMatrixCoefficients"), -+ (r"avifPixelFormatInfo\b", "crabbyavif::avifPixelFormatInfo"), -+ (r"avifRGBImage\b", "crabbyavif::avifRGBImage"), -+ (r"avifROData\b", "crabbyavif::avifROData"), -+ (r"avifRange\b", "crabbyavif::avifRange"), -+ (r"avifResult\b", "crabbyavif::avifResult"), -+ ( -+ r"avifTransferCharacteristics\b", -+ "crabbyavif::avifTransferCharacteristics", -+ ), -+ (r"\bAVIF_", "crabbyavif::AVIF_"), -+ (r"\bCRABBY_AVIF_", "crabbyavif::CRABBY_AVIF_"), -+) -+ -+_TEST_REPLACEMENTS = ( -+ (r"\bAVIFValidImagesTest\b", "CrabbyAVIFValidImagesTest"), -+ (r"\bAnimatedAVIFTests\b", "CrabbyAnimatedAVIFTests"), -+ (r"\bStaticAVIFColorTests\b", "CrabbyStaticAVIFColorTests"), -+ (r"\bStaticAVIFTests\b", "CrabbyStaticAVIFTests"), -+) -+ -+_FUZZER_REPLACEMENTS = ((r"kAvifDecoder", "kCrabbyAvifDecoder"), ) -+ -+def main(): -+ _generate_crabbyavif_file("avif_image_decoder.h", _HEADER_REPLACEMENTS) -+ _generate_crabbyavif_file("avif_image_decoder.cc", _CC_REPLACEMENTS) -+ _generate_crabbyavif_file("avif_image_decoder_test.cc", _TEST_REPLACEMENTS) -+ _generate_crabbyavif_file("avif_image_decoder_fuzzer.cc", -+ _FUZZER_REPLACEMENTS) -+ -+ -+if __name__ == "__main__": -+ main() -diff --git a/third_party/blink/renderer/platform/image-decoders/image_decoder.cc b/third_party/blink/renderer/platform/image-decoders/image_decoder.cc -index 0cc5dfa276964..0523ccbd18509 100644 ---- a/third_party/blink/renderer/platform/image-decoders/image_decoder.cc -+++ b/third_party/blink/renderer/platform/image-decoders/image_decoder.cc -@@ -52,6 +52,7 @@ - #include "ui/gfx/geometry/size_conversions.h" - - #if BUILDFLAG(ENABLE_AV1_DECODER) -+#include "third_party/blink/renderer/platform/image-decoders/avif/avif_image_decoder.h" - #include "third_party/blink/renderer/platform/image-decoders/avif/crabbyavif_image_decoder.h" - #endif - -@@ -197,7 +198,9 @@ String SniffMimeTypeInternal(scoped_refptr reader) { - return "image/bmp"; - } - #if BUILDFLAG(ENABLE_AV1_DECODER) -- if (CrabbyAVIFImageDecoder::MatchesAVIFSignature(fast_reader)) { -+ if (base::FeatureList::IsEnabled(blink::features::kCrabbyAvif) -+ ? CrabbyAVIFImageDecoder::MatchesAVIFSignature(fast_reader) -+ : AVIFImageDecoder::MatchesAVIFSignature(fast_reader)) { - return "image/avif"; - } - #endif -@@ -307,9 +310,15 @@ std::unique_ptr ImageDecoder::CreateByMimeType( - max_decoded_bytes); - #if BUILDFLAG(ENABLE_AV1_DECODER) - } else if (mime_type == "image/avif") { -- decoder = std::make_unique( -- alpha_option, high_bit_depth_decoding_option, color_behavior, aux_image, -- max_decoded_bytes, animation_option); -+ if (base::FeatureList::IsEnabled(blink::features::kCrabbyAvif)) { -+ decoder = std::make_unique( -+ alpha_option, high_bit_depth_decoding_option, color_behavior, -+ aux_image, max_decoded_bytes, animation_option); -+ } else { -+ decoder = std::make_unique( -+ alpha_option, high_bit_depth_decoding_option, color_behavior, -+ aux_image, max_decoded_bytes, animation_option); -+ } - #endif - } - -diff --git a/third_party/blink/renderer/platform/image-decoders/image_decoder_fuzzer_utils.cc b/third_party/blink/renderer/platform/image-decoders/image_decoder_fuzzer_utils.cc -index 93805eafce9fd..d07cbcd599f15 100644 ---- a/third_party/blink/renderer/platform/image-decoders/image_decoder_fuzzer_utils.cc -+++ b/third_party/blink/renderer/platform/image-decoders/image_decoder_fuzzer_utils.cc -@@ -5,6 +5,7 @@ - #include "third_party/blink/renderer/platform/image-decoders/image_decoder_fuzzer_utils.h" - - #include "third_party/blink/renderer/platform/graphics/color_behavior.h" -+#include "third_party/blink/renderer/platform/image-decoders/avif/avif_image_decoder.h" - #include "third_party/blink/renderer/platform/image-decoders/avif/crabbyavif_image_decoder.h" - #include "third_party/blink/renderer/platform/image-decoders/bmp/bmp_image_decoder.h" - #include "third_party/blink/renderer/platform/image-decoders/image_decoder.h" -@@ -72,6 +73,13 @@ std::unique_ptr CreateImageDecoder(DecoderType decoder_type, - /*max_decoded_bytes=*/fdp.ConsumeIntegral(), - /*offset=*/fdp.ConsumeIntegral()); - } -+ case DecoderType::kAvifDecoder: { -+ return std::make_unique( -+ GetAlphaOption(fdp), GetHbdOption(fdp), GetColorBehavior(fdp), -+ GetAuxImageType(fdp), -+ /*max_decoded_bytes=*/fdp.ConsumeIntegral(), -+ GetAnimationOption(fdp)); -+ } - case DecoderType::kCrabbyAvifDecoder: { - return std::make_unique( - GetAlphaOption(fdp), GetHbdOption(fdp), GetColorBehavior(fdp), -diff --git a/third_party/blink/renderer/platform/image-decoders/image_decoder_fuzzer_utils.h b/third_party/blink/renderer/platform/image-decoders/image_decoder_fuzzer_utils.h -index f6ad7fe6b4c52..d1227387a9145 100644 ---- a/third_party/blink/renderer/platform/image-decoders/image_decoder_fuzzer_utils.h -+++ b/third_party/blink/renderer/platform/image-decoders/image_decoder_fuzzer_utils.h -@@ -15,6 +15,7 @@ enum class DecoderType { - kBmpDecoder, - kJpegDecoder, - kPngDecoder, -+ kAvifDecoder, - kCrabbyAvifDecoder, - }; - diff --git a/meta-chromium/recipes-browser/chromium/files/0015-Revert-Remove-third_party-libavif.patch b/meta-chromium/recipes-browser/chromium/files/0015-Revert-Remove-third_party-libavif.patch deleted file mode 100644 index f0991eb71..000000000 --- a/meta-chromium/recipes-browser/chromium/files/0015-Revert-Remove-third_party-libavif.patch +++ /dev/null @@ -1,333 +0,0 @@ -From d71a0fc5b00c20492fbfd15a561548c2e40ae2d4 Mon Sep 17 00:00:00 2001 -From: Ariel D'Alessandro -Date: Thu, 17 Jul 2025 13:11:35 -0300 -Subject: [PATCH] Revert "Remove third_party/libavif" - -This reverts commit 16708cb7341629a2793a6a06a370e2b846313e56. - -In order to disable crabbyavif to fix build errors, re-enable libavif so -it can be used in replacement. - -Upstream-Status: Inappropriate [upstream ticket https://crbug.com/357017325] -Signed-off-by: Ariel D'Alessandro ---- - DEPS | 7 + - third_party/libavif/BUILD.gn | 172 +++++++++++++++++++ - third_party/libavif/DIR_METADATA | 6 + - third_party/libavif/OWNERS | 2 + - third_party/libavif/README.chromium | 13 ++ - third_party/libavif/avif_apps_shared_stubs.c | 50 ++++++ - third_party/libavif/src | 1 + - 7 files changed, 251 insertions(+) - create mode 100644 third_party/libavif/BUILD.gn - create mode 100644 third_party/libavif/DIR_METADATA - create mode 100644 third_party/libavif/OWNERS - create mode 100644 third_party/libavif/README.chromium - create mode 100644 third_party/libavif/avif_apps_shared_stubs.c - create mode 160000 third_party/libavif/src - -diff --git a/DEPS b/DEPS -index f527d6b0d4b78..3b31fee5d5d3a 100644 ---- a/DEPS -+++ b/DEPS -@@ -445,6 +445,10 @@ vars = { - # and whatever else without interference from each other. - 'wuffs_revision': 'e3f919ccfe3ef542cfc983a82146070258fb57f8', - # Three lines of non-changing comments so that -+ # the commit queue can handle CLs rolling libavif -+ # and whatever else without interference from each other. -+ 'libavif_revision': 'e7b34a1f5e9f7024d08311c7bae156061b889882', -+ # Three lines of non-changing comments so that - # the commit queue can handle CLs rolling crabbyavif - # and whatever else without interference from each other. - 'crabbyavif_revision': '02d0fad2c512380b7270d6e704c86521075d7d54', -@@ -2268,6 +2272,9 @@ deps = { - 'src/third_party/libaom/source/libaom': - Var('aomedia_git') + '/aom.git' + '@' + '9680f2b1781fb33b9eeb52409b75c679c8a954be', - -+ 'src/third_party/libavif/src': -+ Var('chromium_git') + '/external/github.com/AOMediaCodec/libavif.git' + '@' + Var('libavif_revision'), -+ - 'src/third_party/crabbyavif/src': - Var('chromium_git') + '/external/github.com/webmproject/CrabbyAvif.git' + '@' + Var('crabbyavif_revision'), - -diff --git a/third_party/libavif/BUILD.gn b/third_party/libavif/BUILD.gn -new file mode 100644 -index 0000000000000..c2cc9e2d9fd87 ---- /dev/null -+++ b/third_party/libavif/BUILD.gn -@@ -0,0 +1,172 @@ -+# Copyright 2020 The Chromium Authors -+# Use of this source code is governed by a BSD-style license that can be -+# found in the LICENSE file. -+ -+import("//media/media_options.gni") -+import("//testing/libfuzzer/fuzzer_test.gni") -+ -+# Public configuration exported to users of the libavif target. -+config("avif_public_config") { -+ if (is_component_build) { -+ defines = [ "AVIF_DLL" ] -+ } -+} -+ -+# Private configuration used in building libavif. -+config("avif_config") { -+ include_dirs = [ "src/include/" ] -+ defines = [ "AVIF_LIBYUV_ENABLED" ] -+ if (is_component_build) { -+ defines += [ "AVIF_BUILDING_SHARED_LIBS" ] -+ } -+ -+ if (enable_dav1d_decoder) { -+ include_dirs += [ "../dav1d/libdav1d/include/" ] -+ defines += [ "AVIF_CODEC_DAV1D" ] -+ } -+} -+ -+libavif_decoder_sources = [ -+ "src/include/avif/internal.h", -+ "src/src/alpha.c", -+ "src/src/avif.c", -+ "src/src/colr.c", -+ "src/src/colrconvert.c", -+ "src/src/diag.c", -+ "src/src/exif.c", -+ "src/src/gainmap.c", -+ "src/src/io.c", -+ "src/src/mem.c", -+ "src/src/obu.c", -+ "src/src/properties.c", -+ "src/src/rawdata.c", -+ "src/src/read.c", -+ "src/src/reformat.c", -+ "src/src/reformat_libsharpyuv.c", -+ "src/src/reformat_libyuv.c", -+ "src/src/scale.c", -+ "src/src/stream.c", -+ "src/src/utils.c", -+] -+ -+component("libavif") { -+ public = [ "src/include/avif/avif.h" ] -+ public_configs = [ ":avif_public_config" ] -+ -+ sources = libavif_decoder_sources -+ -+ configs += [ ":avif_config" ] -+ -+ deps = [ "//third_party/libyuv" ] -+ -+ if (enable_dav1d_decoder) { -+ sources += [ "src/src/codec_dav1d.c" ] -+ deps += [ "//third_party/dav1d" ] -+ } -+} -+ -+# Note only the decoder fuzzers are enabled as only the decoder is being used -+# in Chrome. avif_fuzztest_read_image is not enabled due to libpng not having -+# PNG_READ_iTXt_SUPPORTED enabled. -+config("avif_fuzztest_config") { -+ include_dirs = [ -+ "src/include", -+ "src/apps/shared", -+ ] -+} -+ -+# This is used to satisfy dependencies in avif_fuzztest_helpers. The encoder -+# functions are not used. -+component("libavif_enc") { -+ public = [ "src/include/avif/avif.h" ] -+ public_configs = [ ":avif_public_config" ] -+ -+ sources = libavif_decoder_sources + [ -+ "src/src/write.c", -+ ] -+ testonly = true -+ -+ configs += [ ":avif_config" ] -+ -+ deps = [ -+ "//third_party/libwebp:libwebp_sharpyuv", -+ "//third_party/libyuv", -+ ] -+ defines = [ "AVIF_LIBSHARPYUV_ENABLED" ] -+ -+ if (enable_dav1d_decoder) { -+ sources += [ "src/src/codec_dav1d.c" ] -+ deps += [ "//third_party/dav1d" ] -+ } -+} -+ -+source_set("avif_apps_shared") { -+ sources = [ -+ "avif_apps_shared_stubs.c", -+ "src/apps/shared/avifexif.c", -+ "src/apps/shared/avifexif.h", -+ "src/apps/shared/avifjpeg.h", -+ "src/apps/shared/avifpng.h", -+ "src/apps/shared/avifutil.c", -+ "src/apps/shared/avifutil.h", -+ "src/apps/shared/y4m.c", -+ "src/apps/shared/y4m.h", -+ ] -+ testonly = true -+ configs += [ ":avif_fuzztest_config" ] -+ deps = [ ":libavif_enc" ] -+} -+ -+source_set("avif_fuzztest_helpers") { -+ sources = [ -+ "src/tests/gtest/avif_fuzztest_helpers.cc", -+ "src/tests/gtest/avifincrtest_helpers.cc", -+ "src/tests/gtest/aviftest_helpers.cc", -+ ] -+ testonly = true -+ configs += [ ":avif_fuzztest_config" ] -+ deps = [ -+ ":avif_apps_shared", -+ ":libavif_enc", -+ "//testing/gtest", -+ "//third_party/fuzztest:fuzztest", -+ ] -+} -+ -+# TODO: b/308013905 - These tests require seeds from -+# third_party/libavif/src/tests/data which -+# aren't available in the fuzzing environment. These targets can be enabled if -+# they are made hermetic. -+# -+# test("avif_fuzztest_dec") { -+# sources = [ "src/tests/gtest/avif_fuzztest_dec.cc" ] -+# fuzztests = [ "DecodeAvifTest.Decode" ] -+# configs += [ ":avif_fuzztest_config" ] -+# deps = [ -+# ":avif_fuzztest_helpers", -+# ":libavif_enc", -+# "//third_party/fuzztest:fuzztest_gtest_main", -+# ] -+# } -+# -+# test("avif_fuzztest_dec_incr") { -+# sources = [ "src/tests/gtest/avif_fuzztest_dec_incr.cc" ] -+# fuzztests = [ "DecodeAvifFuzzTest.DecodeIncr" ] -+# configs += [ ":avif_fuzztest_config" ] -+# deps = [ -+# ":avif_fuzztest_helpers", -+# ":libavif_enc", -+# "//third_party/fuzztest:fuzztest_gtest_main", -+# ] -+# } -+ -+test("avif_fuzztest_yuvrgb") { -+ sources = [ "src/tests/gtest/avif_fuzztest_yuvrgb.cc" ] -+ fuzztests = [ "YuvRgbFuzzTest.Convert" ] -+ configs += [ ":avif_fuzztest_config" ] -+ deps = [ -+ ":avif_fuzztest_helpers", -+ ":libavif_enc", -+ "//third_party/fuzztest:fuzztest_gtest_main", -+ ] -+} -diff --git a/third_party/libavif/DIR_METADATA b/third_party/libavif/DIR_METADATA -new file mode 100644 -index 0000000000000..beadfa62dc3ad ---- /dev/null -+++ b/third_party/libavif/DIR_METADATA -@@ -0,0 +1,6 @@ -+monorail: { -+ component: "Internals>Images>Codecs" -+} -+buganizer_public: { -+ component_id: 1456316 -+} -diff --git a/third_party/libavif/OWNERS b/third_party/libavif/OWNERS -new file mode 100644 -index 0000000000000..6946c0b7788b5 ---- /dev/null -+++ b/third_party/libavif/OWNERS -@@ -0,0 +1,2 @@ -+file://media/OWNERS -+wtc@google.com -diff --git a/third_party/libavif/README.chromium b/third_party/libavif/README.chromium -new file mode 100644 -index 0000000000000..81904b69c35c5 ---- /dev/null -+++ b/third_party/libavif/README.chromium -@@ -0,0 +1,13 @@ -+Name: libavif - Library for encoding and decoding .avif files -+Short Name: libavif -+URL: https://github.com/AOMediaCodec/libavif -+Version: N/A -+Revision: DEPS -+License: BSD-2-Clause, MIT -+License File: src/LICENSE -+Security Critical: yes -+Shipped: yes -+ -+Description: -+This contains the source to the AV1 image format demuxer; used for demuxing and -+decoding .avif files in Chromium. -diff --git a/third_party/libavif/avif_apps_shared_stubs.c b/third_party/libavif/avif_apps_shared_stubs.c -new file mode 100644 -index 0000000000000..18980cbc5b0b5 ---- /dev/null -+++ b/third_party/libavif/avif_apps_shared_stubs.c -@@ -0,0 +1,50 @@ -+// Copyright 2024 The Chromium Authors -+// Use of this source code is governed by a BSD-style license that can be -+// found in the LICENSE file. -+ -+// This file provides functions necessary to link the decoder fuzz tests. The -+// functions are not used by the tests being built, but their dependencies in -+// apps/shared and avif_*_helpers.cc unconditionally reference them. -+ -+#include -+ -+#include "src/apps/shared/avifjpeg.h" -+#include "src/apps/shared/avifpng.h" -+ -+avifBool avifJPEGRead(const char * inputFilename, -+ avifImage * avif, -+ avifPixelFormat requestedFormat, -+ uint32_t requestedDepth, -+ avifChromaDownsampling chromaDownsampling, -+ avifBool ignoreColorProfile, -+ avifBool ignoreExif, -+ avifBool ignoreXMP, -+ avifBool ignoreGainMap, -+ uint32_t imageSizeLimit) { -+ fprintf(stderr, "The tests were built without JPEG support!\n"); -+ return AVIF_FALSE; -+} -+ -+avifBool avifPNGRead(const char * inputFilename, -+ avifImage * avif, -+ avifPixelFormat requestedFormat, -+ uint32_t requestedDepth, -+ avifChromaDownsampling chromaDownsampling, -+ avifBool ignoreColorProfile, -+ avifBool ignoreExif, -+ avifBool ignoreXMP, -+ avifBool allowChangingCicp, -+ uint32_t imageSizeLimit, -+ uint32_t * outPNGDepth) { -+ fprintf(stderr, "The tests were built without PNG support!\n"); -+ return AVIF_FALSE; -+} -+ -+avifBool avifPNGWrite(const char * outputFilename, -+ const avifImage * avif, -+ uint32_t requestedDepth, -+ avifChromaUpsampling chromaUpsampling, -+ int compressionLevel) { -+ fprintf(stderr, "The tests were built without PNG support!\n"); -+ return AVIF_FALSE; -+} -diff --git a/third_party/libavif/src b/third_party/libavif/src -new file mode 160000 -index 0000000000000..e7b34a1f5e9f7 ---- /dev/null -+++ b/third_party/libavif/src -@@ -0,0 +1 @@ -+Subproject commit e7b34a1f5e9f7024d08311c7bae156061b889882 diff --git a/meta-chromium/recipes-browser/chromium/files/0016-Disable-crabbyavif-to-fix-build-errors.patch b/meta-chromium/recipes-browser/chromium/files/0016-Disable-crabbyavif-to-fix-build-errors.patch deleted file mode 100644 index cdd4e27a1..000000000 --- a/meta-chromium/recipes-browser/chromium/files/0016-Disable-crabbyavif-to-fix-build-errors.patch +++ /dev/null @@ -1,97 +0,0 @@ -From a51bea5534076916587c4bebc2299d7881d6fad7 Mon Sep 17 00:00:00 2001 -From: Max Ihlenfeldt -Date: Mon, 5 Aug 2024 09:33:42 +0000 -Subject: [PATCH] Disable crabbyavif to fix build errors - -It seems the way upstream sets up bindgen does not play well with -cross-compiling in certain configurations. Currently, this only affects -building the crabbyavif third-party library, which is still being tested -behind a feature flag. Until we find a way to fix the bindgen setup -(either upstream or downstream), we just disable crabbyavif by reverting -the CL that added it to the build, https://crrev.com/c/5542730. - -Upstream-Status: Inappropriate [upstream ticket https://crbug.com/357017325] -Signed-off-by: Max Ihlenfeldt ---- - .../renderer/platform/image-decoders/BUILD.gn | 8 +------- - .../platform/image-decoders/image_decoder.cc | 18 ++++-------------- - 2 files changed, 5 insertions(+), 21 deletions(-) - -diff --git a/third_party/blink/renderer/platform/image-decoders/BUILD.gn b/third_party/blink/renderer/platform/image-decoders/BUILD.gn -index 6dbddaa2e3..2b5f660196 100644 ---- a/third_party/blink/renderer/platform/image-decoders/BUILD.gn -+++ b/third_party/blink/renderer/platform/image-decoders/BUILD.gn -@@ -82,12 +82,9 @@ component("image_decoders") { - sources += [ - "avif/avif_image_decoder.cc", - "avif/avif_image_decoder.h", -- "avif/crabbyavif_image_decoder.cc", -- "avif/crabbyavif_image_decoder.h", - ] - - deps += [ -- "//third_party/crabbyavif", - "//third_party/libavif", - ] - } -@@ -136,9 +133,6 @@ source_set("unit_tests") { - } - - if (enable_av1_decoder) { -- sources += [ -- "avif/avif_image_decoder_test.cc", -- "avif/crabbyavif_image_decoder_test.cc", -- ] -+ sources += [ "avif/avif_image_decoder_test.cc" ] - } - } -diff --git a/third_party/blink/renderer/platform/image-decoders/image_decoder.cc b/third_party/blink/renderer/platform/image-decoders/image_decoder.cc -index bdbbe08142..8b08f320cd 100644 ---- a/third_party/blink/renderer/platform/image-decoders/image_decoder.cc -+++ b/third_party/blink/renderer/platform/image-decoders/image_decoder.cc -@@ -37,7 +37,6 @@ - #include "media/media_buildflags.h" - #include "skia/ext/cicp.h" - #include "third_party/blink/public/common/buildflags.h" --#include "third_party/blink/public/common/features.h" - #include "third_party/blink/public/platform/platform.h" - #include "third_party/blink/renderer/platform/image-decoders/bmp/bmp_image_decoder.h" - #include "third_party/blink/renderer/platform/image-decoders/fast_shared_buffer_reader.h" -@@ -53,7 +52,6 @@ - - #if BUILDFLAG(ENABLE_AV1_DECODER) - #include "third_party/blink/renderer/platform/image-decoders/avif/avif_image_decoder.h" --#include "third_party/blink/renderer/platform/image-decoders/avif/crabbyavif_image_decoder.h" - #endif - - namespace blink { -@@ -198,9 +196,7 @@ String SniffMimeTypeInternal(scoped_refptr reader) { - return "image/bmp"; - } - #if BUILDFLAG(ENABLE_AV1_DECODER) -- if (base::FeatureList::IsEnabled(blink::features::kCrabbyAvif) -- ? CrabbyAVIFImageDecoder::MatchesAVIFSignature(fast_reader) -- : AVIFImageDecoder::MatchesAVIFSignature(fast_reader)) { -+ if (AVIFImageDecoder::MatchesAVIFSignature(fast_reader)) { - return "image/avif"; - } - #endif -@@ -310,15 +306,9 @@ std::unique_ptr ImageDecoder::CreateByMimeType( - max_decoded_bytes); - #if BUILDFLAG(ENABLE_AV1_DECODER) - } else if (mime_type == "image/avif") { -- if (base::FeatureList::IsEnabled(blink::features::kCrabbyAvif)) { -- decoder = std::make_unique( -- alpha_option, high_bit_depth_decoding_option, color_behavior, -- aux_image, max_decoded_bytes, animation_option); -- } else { -- decoder = std::make_unique( -- alpha_option, high_bit_depth_decoding_option, color_behavior, -- aux_image, max_decoded_bytes, animation_option); -- } -+ decoder = std::make_unique( -+ alpha_option, high_bit_depth_decoding_option, color_behavior, -+ aux_image, max_decoded_bytes, animation_option); - #endif - } - diff --git a/meta-chromium/recipes-browser/chromium/files/0017-rust-Use-adler-instead-of-adler2.patch b/meta-chromium/recipes-browser/chromium/files/0017-rust-Use-adler-instead-of-adler2.patch deleted file mode 100644 index 6cae0abc0..000000000 --- a/meta-chromium/recipes-browser/chromium/files/0017-rust-Use-adler-instead-of-adler2.patch +++ /dev/null @@ -1,38 +0,0 @@ -From d1d686cb5cebca571cb9eafc5a3cabff6971ddb6 Mon Sep 17 00:00:00 2001 -From: Ariel D'Alessandro -Date: Sat, 26 Apr 2025 17:19:24 -0300 -Subject: [PATCH] rust: Use adler instead of adler2 - -Upstream Rust replaced adler with adler2, for older versions of Rust we still -need to tell GN that we have the older lib when it tries to copy the Rust -sysroot into the bulid directory. - -It looks that in rust-1.85.0, `adler` has not yet been replaced with `adler2`. -Therefore, the condition should likely be adjusted. - -This patch will be dropped once Rust >= 1.86.0 is available, which -replaced adler with adler2. - -Note that currently layer provides Rust version `1.85.1`. - -[0] https://git.yoctoproject.org/meta-lts-mixins/log/?h=scarthgap/rust - -Upstream-Status: Inappropriate [specific to older versions of rust] -Signed-off-by: Ariel D'Alessandro ---- - build/rust/std/BUILD.gn | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/build/rust/std/BUILD.gn b/build/rust/std/BUILD.gn -index 7f64198b9f..d29e3466b1 100644 ---- a/build/rust/std/BUILD.gn -+++ b/build/rust/std/BUILD.gn -@@ -89,7 +89,7 @@ if (toolchain_has_rust) { - # These are no longer present in the Windows toolchain. - stdlib_files += [ - "addr2line", -- "adler2", -+ "adler", - "gimli", - "libc", - "memchr", diff --git a/meta-chromium/recipes-browser/chromium/files/0018-third_party-node-update_node_binaries-Update-nodejs-.patch b/meta-chromium/recipes-browser/chromium/files/0018-third_party-node-update_node_binaries-Update-nodejs-.patch deleted file mode 100644 index 30a9206b9..000000000 --- a/meta-chromium/recipes-browser/chromium/files/0018-third_party-node-update_node_binaries-Update-nodejs-.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 6e3d91964a64dbacfddc4c7a38c64fd221fcdd2b Mon Sep 17 00:00:00 2001 -From: Ariel D'Alessandro -Date: Wed, 16 Jul 2025 18:44:44 -0300 -Subject: [PATCH] update_node_binaries: Update nodejs version to v22.15.0 - -Update the NodeJS version to match exactly the one shipped in these -images. - -Upstream-Status: Inappropriate [specific to our build setup] -Signed-off-by: Ariel D'Alessandro ---- - third_party/node/update_node_binaries | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/third_party/node/update_node_binaries b/third_party/node/update_node_binaries -index 4aab805844..5c3714f574 100755 ---- a/third_party/node/update_node_binaries -+++ b/third_party/node/update_node_binaries -@@ -19,7 +19,7 @@ set -eu - cd "$(dirname "$0")" - - BASE_URL="https://nodejs.org/dist" --NODE_VERSION="v22.11.0" -+NODE_VERSION="v22.15.0" - - upload=false # Default value - diff --git a/meta-chromium/recipes-browser/chromium/files/0020-rust-filter-out-arm-specific-flags-from-rust-compile.patch b/meta-chromium/recipes-browser/chromium/files/0020-rust-filter-out-arm-specific-flags-from-rust-compile.patch deleted file mode 100644 index d9107c8f0..000000000 --- a/meta-chromium/recipes-browser/chromium/files/0020-rust-filter-out-arm-specific-flags-from-rust-compile.patch +++ /dev/null @@ -1,29 +0,0 @@ -From f29addf315e55f371c7c9a973002607a628ea3ea Mon Sep 17 00:00:00 2001 -From: Caner Altinbasak -Date: Fri, 25 Jul 2025 13:00:14 +0100 -Subject: [PATCH] rust: filter out arm specific flags from rust compiler - -Upstream-Status: Inappropriate [specific to our build setup] ---- - build/rust/filter_clang_args.py | 5 +++++ - 1 file changed, 5 insertions(+) - -diff --git a/build/rust/filter_clang_args.py b/build/rust/filter_clang_args.py -index 5a1843c0df..7fb4b49516 100644 ---- a/build/rust/filter_clang_args.py -+++ b/build/rust/filter_clang_args.py -@@ -24,6 +24,11 @@ def filter_clang_args(clangargs): - pass - elif args[i].startswith('-plugin-arg'): - i += 2 -+ # Filter out ARM-specific flags that aren't supported on other architectures -+ elif args[i].startswith('-mbranch-protection'): -+ pass # Skip this argument -+ elif args[i].startswith('-mfpu='): -+ pass - else: - yield args[i] - i += 1 --- -2.39.5 - diff --git a/meta-chromium/recipes-browser/chromium/files/23d818d3c7fba4658248f17fd7b8993199242aa9.patch b/meta-chromium/recipes-browser/chromium/files/23d818d3c7fba4658248f17fd7b8993199242aa9.patch new file mode 100644 index 000000000..7df60bef1 --- /dev/null +++ b/meta-chromium/recipes-browser/chromium/files/23d818d3c7fba4658248f17fd7b8993199242aa9.patch @@ -0,0 +1,44 @@ +From 23d818d3c7fba4658248f17fd7b8993199242aa9 Mon Sep 17 00:00:00 2001 +From: Hans Wennborg +Date: Fri, 22 Aug 2025 10:34:47 -0700 +Subject: [PATCH] [rust] Define __rust_alloc_error_handler_should_panic_v2 + +https://github.com/rust-lang/rust/pull/143387 made +__rust_alloc_error_handler_should_panic a function. + +The new definition is needed when rolling Rust past that PR. We can +remove the old symbol afterwards. + +Bug: 440481922 +Change-Id: I3340edd6d96d76de14942af67939978140430424 +Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6875644 +Commit-Queue: Arthur Eubanks +Reviewed-by: Arthur Eubanks +Auto-Submit: Hans Wennborg +Commit-Queue: Hans Wennborg +Cr-Commit-Position: refs/heads/main@{#1505162} + +Upstream-Status: Backport [https://chromiumdash.appspot.com/commit/23d818d3c7fba4658248f17fd7b8993199242aa9] +--- + build/rust/allocator/lib.rs | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/build/rust/allocator/lib.rs b/build/rust/allocator/lib.rs +index 29b3af1274fb36..a7fa7a470f0001 100644 +--- a/build/rust/allocator/lib.rs ++++ b/build/rust/allocator/lib.rs +@@ -90,7 +90,14 @@ mod both_allocators { + #[linkage = "weak"] + fn __rust_no_alloc_shim_is_unstable_v2() {} + ++ #[rustc_std_internal_symbol] ++ #[linkage = "weak"] ++ fn __rust_alloc_error_handler_should_panic_v2() -> u8 { ++ 0 ++ } ++ + // Mangle the symbol name as rustc expects. ++ // TODO(crbug.com/440481922): Remove this after rolling past https://github.com/rust-lang/rust/pull/143387 + #[rustc_std_internal_symbol] + #[allow(non_upper_case_globals)] + #[linkage = "weak"] diff --git a/meta-chromium/recipes-browser/chromium/gn-native_136.0.7103.113.bb b/meta-chromium/recipes-browser/chromium/gn-native_136.0.7103.113.bb deleted file mode 100644 index 5a3225be9..000000000 --- a/meta-chromium/recipes-browser/chromium/gn-native_136.0.7103.113.bb +++ /dev/null @@ -1,48 +0,0 @@ -# gn-native contains the GN binary used to configure Chromium. -# It is not released separately, and each Chromium release is only expected to -# work with the GN version provided with it. - -require chromium.inc - -inherit native - -S = "${WORKDIR}/chromium-${PV}" - -# bootstrap.py --no_clean hardcodes the build location to out_bootstrap. -# Omitting --no_clean causes the script to create a temporary directory with a -# random name outside the build directory, so we choose the lesser of the two -# evils. -B = "${S}/out_bootstrap" - -SRC_URI += " \ - file://0001-Pass-no-static-libstdc-to-gen.py.patch \ -" - -# The build system expects the linker to be invoked via the compiler. If we use -# the default value for BUILD_LD, it will fail because it does not recognize -# some of the arguments passed to it. -BUILD_LD = "${CXX}" - -# Use LLVM's ar rather than binutils'. Depending on the optimizations enabled -# in the build ar(1) may not be enough. -BUILD_AR = "llvm-ar" - -DEPENDS = "clang-native ninja-native" -DEPENDS:append:runtime-llvm = " compiler-rt-native libcxx-native" -# Use libcxx headers for native parts -CXXFLAGS:append:runtime-llvm = " -isysroot=${STAGING_DIR_NATIVE} -stdlib=libc++" -# Use libgcc for native parts -LDFLAGS:append:runtime-llvm = " -rtlib=libgcc -unwindlib=libgcc -stdlib=libc++ -lc++abi -rpath ${STAGING_LIBDIR_NATIVE}" - -do_configure[noexec] = "1" - -do_compile() { - python3 ${S}/tools/gn/bootstrap/bootstrap.py --skip-generate-buildfiles -} - -do_install() { - install -d ${D}${bindir} - install -m 0755 ${S}/out/Release/gn ${D}${bindir}/gn -} - -INSANE_SKIP:${PN} += "already-stripped"