diff --git a/www/qt6-webengine/Makefile b/www/qt6-webengine/Makefile index 352dcaf77694..59ef4d840c56 100644 --- a/www/qt6-webengine/Makefile +++ b/www/qt6-webengine/Makefile @@ -1,184 +1,184 @@ # QtWebEngine itself is a very thin layer of Qt code on top of a large part of # Chromium (everything up to the content/ layer). As such, most of the work in # this port revolves around taming Chromium and getting it to build on FreeBSD. # While it does build at the moment, there are several items that should be # investigated or improved: # - We are using several stub files, especially in Chromium's base/ and net/ # layers. We should look at implementing the missing bits instead. # - We are currently not using any sandboxing mechanism. # - The process of porting QtWebEngine needs to be documented so we can move to # newer releases more easily. # PORTNAME?= webengine DISTVERSION= ${QT6_VERSION} -PORTREVISION?= 2 # Master port for print/qt6-pdf. Please keep this line. +PORTREVISION?= 3 # Master port for print/qt6-pdf. Please keep this line. CATEGORIES?= www PKGNAMEPREFIX= qt6- MAINTAINER= kde@FreeBSD.org COMMENT?= Qt 6 library to render web content BUILD_DEPENDS= ${PYTHON_PKGNAMEPREFIX}html5lib>0:www/py-html5lib@${PY_FLAVOR} \ ${LOCALBASE}/include/vulkan/vulkan.h:graphics/vulkan-headers LIB_DEPENDS= libfreetype.so:print/freetype2 \ libnss3.so:security/nss \ libxkbcommon.so:x11/libxkbcommon USES= bison cmake compiler:c++17-lang gl gperf \ localbase:ldflags ninja:build nodejs:build,lts \ pkgconfig python:build qt-dist:6,webengine USE_GL= opengl USE_QT= base declarative tools USE_XORG= x11 xcb xcomposite xcursor xdamage xext xfixes xi xkbfile \ xrandr xrender xscrnsaver xshmfence xtst CMAKE_ON= QT_FEATURE_webengine_system_ffmpeg \ QT_FEATURE_webengine_proprietary_codecs .if defined(BUILD_QTPDF) LIB_DEPENDS+= libcups.so:print/cups \ libopenjp2.so:graphics/openjpeg CMAKE_ON+= QT_FEATURE_qtpdf_build CMAKE_OFF+= QT_FEATURE_qtwebengine_build SYS_LIBS= freetype .else BUILD_DEPENDS+= ${LOCALBASE}/include/linux/videodev2.h:multimedia/v4l_compat LIB_DEPENDS+= libabsl_base.so:devel/abseil \ libavcodec.so:multimedia/ffmpeg \ libdbus-1.so:devel/dbus \ libdrm.so:graphics/libdrm \ libevent.so:devel/libevent \ libexpat.so:textproc/expat2 \ libfontconfig.so:x11-fonts/fontconfig \ libharfbuzz.so:print/harfbuzz \ libnspr4.so:devel/nspr \ libopenh264.so:multimedia/openh264 \ libopus.so:audio/opus \ libpci.so:devel/libpci \ libpng.so:graphics/png \ libre2.so:devel/re2 \ libsnappy.so:archivers/snappy \ libvpx.so:multimedia/libvpx \ libwebp.so:graphics/webp USES+= gnome jpeg minizip xorg USE_GL+= gbm USE_QT+= positioning quick3d:build webchannel USE_GNOME+= glib20 libxml2 libxslt USE_XORG+= x11 xcb xcomposite xcursor xdamage xext xfixes xi xkbfile \ xrandr xrender xscrnsaver xshmfence xtst CMAKE_ON+= QT_FEATURE_qtwebengine_build CMAKE_OFF+= QT_FEATURE_qtpdf_build SYS_LIBS= freetype harfbuzz-ng libdrm libevent libpng libxml libxslt openh264 opus .endif # The build system reads the environment variable $NINJA_PATH to decide whether # to boostrap ninja or not (and also to invoke it afterwards). CC and CXX are # read by some Chromium code to determine which compiler to invoke when running # some configuration tests. CONFIGURE_ENV+= NINJAFLAGS="-j${MAKE_JOBS_NUMBER}" \ NINJA_PATH="${LOCALBASE}/bin/ninja" \ PATH=${CONFIGURE_WRKSRC}/bin:${LOCALBASE}/bin:${PATH} MAKE_ENV+= CC="${CC}" CXX="${CXX}" \ C_INCLUDE_PATH=${LOCALBASE}/include \ CPLUS_INCLUDE_PATH=${LOCALBASE}/include \ ${CONFIGURE_ENV} # Avoid running multiple make(1) jobs, but only those. Otherwise the build # fails intermittently due race conditions if multiple ninja instances are # running at the same time (mostly for the targets "WebEngineCore" and # "convert_dict"). # # MAKE_JOBS_UNSAFE is too invasive because it also affects the number of jobs # for ninja(1) and would slow everything down which we don't want. We pass the # real number of make jobs via MAKE_JOBS_NUMBER to ninja(1) to CONFIGURE_ENV. DO_MAKE_BUILD= ${SETENV} ${MAKE_ENV} ${MAKE_CMD} ${MAKE_FLAGS} ${MAKEFILE} -j1 ${MAKE_ARGS:N${DESTDIRNAME}=*} BINARY_ALIAS= python3=${PYTHON_CMD} .if !defined(BUILD_QTPDF) OPTIONS_DEFINE= CUPS DRIVER OPTIONS_DEFAULT= ALSA CUPS DRIVER OPTIONS_SINGLE= AUDIO OPTIONS_SINGLE_AUDIO= ALSA PULSEAUDIO SNDIO OPTIONS_SUB= yes AUDIO_DESC= Audio backend # Need the alsa plugins to get sound at runtime, otherwise messages # that the pcm_oss plugin can't be opened. ALSA_LIB_DEPENDS= libasound.so:audio/alsa-lib ALSA_RUN_DEPENDS= alsa-plugins>=0:audio/alsa-plugins ALSA_CMAKE_ON= -DQT_FEATURE_webengine_system_alsa:BOOL=ON ALSA_CMAKE_OFF= -DQT_FEATURE_webengine_system_alsa:BOOL=OFF CUPS_LIB_DEPENDS= libcups.so:print/cups \ liblcms2.so:graphics/lcms2 \ libopenjp2.so:graphics/openjpeg \ libtiff.so:graphics/tiff CUPS_CMAKE_ON= -DQT_FEATURE_webengine_printing_and_pdf:BOOL=ON CUPS_CMAKE_OFF= -DQT_FEATURE_webengine_printing_and_pdf:BOOL=OFF DRIVER_DESC= Install WebEngineDriver DRIVER_CMAKE_ON= -DQT_FEATURE_webenginedriver:BOOL=ON DRIVER_CMAKE_OFF= -DQT_FEATURE_webenginedriver:BOOL=OFF PULSEAUDIO_LIB_DEPENDS= libpulse.so:audio/pulseaudio PULSEAUDIO_CMAKE_ON= -DQT_FEATURE_webengine_system_pulseaudio:BOOL=ON PULSEAUDIO_CMAKE_OFF= -DQT_FEATURE_webengine_system_pulseaudio:BOOL=OFF SNDIO_LIB_DEPENDS= libsndio.so:audio/sndio SNDIO_CMAKE_ON= -DQT_FEATURE_webengine_system_sndio:BOOL=ON SNDIO_CMAKE_OFF= -DQT_FEATURE_webengine_system_sndio:BOOL=OFF .endif .include .if ${ARCH} == i386 || ${ARCH} == armv7 EXTRA_PATCHES+= ${PATCHDIR}/extra-patch-32bit-compress_files_js .endif post-extract: @${MKDIR} ${WRKSRC}/src/3rdparty/chromium/media/audio/sndio \ ${WRKSRC}/src/3rdparty/chromium/sandbox/policy/freebsd \ ${WRKSRC}/src/3rdparty/chromium/sandbox/policy/openbsd post-patch: @${REINPLACE_CMD} -e 's|%%CPPFLAGS%%|${CPPFLAGS}|;s|%%CXXFLAGS%%|${CXXFLAGS}|;s|%%LDFLAGS%%|${LDFLAGS}|' \ ${WRKSRC}/src/host/BUILD.toolchain.gn.in @${REINPLACE_CMD} -e 's|%%LOCALBASE%%|${LOCALBASE}|' \ ${WRKSRC}/src/3rdparty/chromium/third_party/pdfium/core/fxge/linux/fx_linux_impl.cpp \ ${WRKSRC}/src/3rdparty/chromium/ui/events/ozone/layout/xkb/xkb_keyboard_layout_engine.cc pre-configure: # We used to remove bundled libraries to be sure that webengine uses # system libraries and not shipped ones. # # Leads to missing header errors: icu, libvpx, libwebp, re2, snappy, zlib # No-Op: flac # # Don't attempt to unbundle libraries that the Pdf module doesn't use. It # causes configuration errors. # # cd ${WRKSRC} && ${PYTHON_CMD} \ # ./build/linux/unbundle/remove_bundled_libraries.py [list of preserved] cd ${WRKSRC}/src/3rdparty/chromium && ${SETENV} ${CONFIGURE_ENV} ${PYTHON_CMD} \ ./build/linux/unbundle/replace_gn_files.py --system-libraries \ ${SYS_LIBS} || ${FALSE} .if !defined(BUILD_QTPDF) post-install: # Fix for deskutils/calibre, perhaps others, where this empty directory # is created during build causing a fs-violation. ${MKDIR} ${STAGEDIR}${QT_DATADIR}/resources/locales post-install-DRIVER-on: ${STRIP_CMD} ${STAGEDIR}${QT_TOOLDIR}/webenginedriver .endif .include diff --git a/www/qt6-webengine/files/patch-security-rollup b/www/qt6-webengine/files/patch-security-rollup index 651d5dacb2e1..ee21cc53c094 100644 --- a/www/qt6-webengine/files/patch-security-rollup +++ b/www/qt6-webengine/files/patch-security-rollup @@ -1,971 +1,2884 @@ Security fixes applied to the 118-based branch [1] after Qt 6.7.3 release. -Includes fixes between [2] and [3]. +Includes fixes between [2] and [3]. [4] has been redacted, since it disrupts +our main patches, is not a security fix, and only applies to iOS. [1] https://code.qt.io/cgit/qt/qtwebengine-chromium.git/log/chromium?h=118-based [2] https://code.qt.io/cgit/qt/qtwebengine-chromium.git/commit/chromium?h=118-based&id=45bdfbd7721749beea9abd18467465e4c9026559 -[3] https://code.qt.io/cgit/qt/qtwebengine-chromium.git/commit/chromium?h=118-based&id=c30894bf867630a8ffcb56c8817c00f3d673f370 +[3] https://code.qt.io/cgit/qt/qtwebengine-chromium.git/commit/chromium?h=118-based&id=eb31082fcba2380e2cc5789aa707328050531e8d +[4] https://code.qt.io/cgit/qt/qtwebengine-chromium.git/commit/chromium?h=118-based&id=edb5aad8fc938acb291261ec123f5d25f615ddc7 diff --git a/chromium/base/mac/wrap_cg_display.h b/chromium/base/mac/wrap_cg_display.h index a579ef1a900..8645627a3a1 100644 --- src/3rdparty/chromium/base/mac/wrap_cg_display.h +++ src/3rdparty/chromium/base/mac/wrap_cg_display.h @@ -12,6 +12,11 @@ #include +// Build fix for macOS SDK 15 and newer +#if !defined(CG_AVAILABLE_BUT_DEPRECATED) +#define CG_AVAILABLE_BUT_DEPRECATED(a,b,c) +#endif + inline CGDisplayStreamRef __nullable wrapCGDisplayStreamCreate( CGDirectDisplayID display, size_t outputWidth, diff --git a/chromium/base/metrics/field_trial.cc b/chromium/base/metrics/field_trial.cc index 2b67eb59ba1..81243e649e8 100644 --- src/3rdparty/chromium/base/metrics/field_trial.cc +++ src/3rdparty/chromium/base/metrics/field_trial.cc @@ -1020,7 +1020,7 @@ std::string FieldTrialList::SerializeSharedMemoryRegionMetadata( // Tell the child process the name of the inherited HANDLE. uintptr_t uintptr_handle = reinterpret_cast(shm.GetPlatformHandle()); - ss << uintptr_handle << ","; + ss << NumberToString(uintptr_handle) << ","; if (launch_options->elevated) { // Tell the child that it must open its parent and grab the handle. ss << "p,"; @@ -1061,8 +1061,8 @@ std::string FieldTrialList::SerializeSharedMemoryRegionMetadata( #endif UnguessableToken guid = shm.GetGUID(); - ss << guid.GetHighForSerialization() << "," << guid.GetLowForSerialization(); - ss << "," << shm.GetSize(); + ss << NumberToString(guid.GetHighForSerialization()) << "," << NumberToString(guid.GetLowForSerialization()); + ss << "," << NumberToString(shm.GetSize()); return ss.str(); } diff --git a/chromium/base/trace_event/trace_event_etw_export_win.cc b/chromium/base/trace_event/trace_event_etw_export_win.cc index 04e2ab0b350..26f6b168373 100644 --- src/3rdparty/chromium/base/trace_event/trace_event_etw_export_win.cc +++ src/3rdparty/chromium/base/trace_event/trace_event_etw_export_win.cc @@ -426,8 +426,8 @@ bool TraceEventETWExport::IsCategoryGroupEnabled( if (!instance->etw_provider_->IsEnabled()) return false; - CStringTokenizer category_group_tokens(&*category_group_name.begin(), - &*category_group_name.end(), ","); + CStringTokenizer category_group_tokens(category_group_name.data(), + category_group_name.data() + category_group_name.size(), ","); while (category_group_tokens.GetNext()) { StringPiece category_group_token = category_group_tokens.token_piece(); if (instance->IsCategoryEnabled(category_group_token)) { diff --git a/chromium/components/viz/service/gl/gpu_service_impl.cc b/chromium/components/viz/service/gl/gpu_service_impl.cc index 0156b748c38..bed248728cc 100644 --- src/3rdparty/chromium/components/viz/service/gl/gpu_service_impl.cc +++ src/3rdparty/chromium/components/viz/service/gl/gpu_service_impl.cc @@ -143,12 +143,6 @@ namespace viz { namespace { -// Whether to crash the GPU service on context loss when running in-process with -// ANGLE. -BASE_FEATURE(kCrashOnInProcessANGLEContextLoss, - "CrashOnInProcessANGLEContextLoss", - base::FEATURE_DISABLED_BY_DEFAULT); - // The names emitted for GPU initialization trace events. // This code may be removed after the following investigation: // crbug.com/1350257 @@ -671,16 +665,6 @@ void GpuServiceImpl::InitializeWithHost( // initialized. gl::DirectCompositionOverlayCapsMonitor::GetInstance()->AddObserver(this); #endif - - if (in_host_process() && - gpu_channel_manager_->use_passthrough_cmd_decoder()) { - // Check `kCrashOnInProcessANGLEContextLoss` to ensure registration within - // the experiment - the check done at the time of MaybeExitOnContextLost() - // doesn't cause clients in the enabled arm to become registered in the - // experiment due to it being followed by an immediate crash. - [[maybe_unused]] bool unused = - base::FeatureList::IsEnabled(kCrashOnInProcessANGLEContextLoss); - } } void GpuServiceImpl::Bind( @@ -1063,24 +1047,6 @@ void GpuServiceImpl::MaybeExitOnContextLost( DCHECK(main_runner_->BelongsToCurrentThread()); if (in_host_process()) { - // When running with ANGLE, crash on a backend context loss if - // `kCrashOnInProcessANGLEContextLoss` is enabled. This enables evaluation - // of the hypothesis that as ANGLE is currently unable to recover from - // context loss when running within Chrome, it is better to crash in this - // case than enter into a loop of context loss events leading to undefined - // behavior. Note that it *is* possible to recover from a context loss - // event that was generated by Chrome rather than being due to an actual - // backend context loss. In general, this is context losses where - // `synthetic_loss is true - the one exception is if `context_lost_reason` - // is `kMakeCurrentFailed`, which we regard as an unrecoverable context - // loss even though `synthetic_loss` will be set to true. - if (gpu_channel_manager_->use_passthrough_cmd_decoder() && - (!synthetic_loss || - context_lost_reason == gpu::error::kMakeCurrentFailed) && - base::FeatureList::IsEnabled(kCrashOnInProcessANGLEContextLoss)) { - CHECK(false); - } - // We can't restart the GPU process when running in the host process; // instead, just hope for recovery from the context loss. return; +diff --git a/chromium/content/browser/file_system_access/file_system_access_directory_handle_impl.cc b/chromium/content/browser/file_system_access/file_system_access_directory_handle_impl.cc +index ec3216d5f92..bb3602f58b9 100644 +--- src/3rdparty/chromium/content/browser/file_system_access/file_system_access_directory_handle_impl.cc ++++ src/3rdparty/chromium/content/browser/file_system_access/file_system_access_directory_handle_impl.cc +@@ -54,32 +54,6 @@ using UserAction = FileSystemAccessPermissionContext::UserAction; + #endif + + namespace { +-// Returns whether the specified extension receives special handling by the +-// Windows shell. +-bool IsShellIntegratedExtension(const base::FilePath::StringType& extension) { +- base::FilePath::StringType extension_lower = base::ToLowerASCII(extension); +- +- // .lnk and .scf files may be used to execute arbitrary code (see +- // https://nvd.nist.gov/vuln/detail/CVE-2010-2568 and +- // https://crbug.com/1227995, respectively). '.url' files can be used to read +- // arbitrary files (see https://crbug.com/1307930 and +- // https://crbug.com/1354518). +- if (extension_lower == FILE_PATH_LITERAL("lnk") || +- extension_lower == FILE_PATH_LITERAL("scf") || +- extension_lower == FILE_PATH_LITERAL("url")) { +- return true; +- } +- +- // Setting a file's extension to a CLSID may conceal its actual file type on +- // some Windows versions (see https://nvd.nist.gov/vuln/detail/CVE-2004-0420). +- if (!extension_lower.empty() && +- (extension_lower.front() == FILE_PATH_LITERAL('{')) && +- (extension_lower.back() == FILE_PATH_LITERAL('}'))) { +- return true; +- } +- return false; +-} +- + #if BUILDFLAG(IS_POSIX) + base::FilePath ReadSymbolicLink(const base::FilePath& path) { + DCHECK(!path.empty()); +@@ -710,80 +684,13 @@ void FileSystemAccessDirectoryHandleImpl::AllEntriesReady( + file_system_access_error::Ok(), std::move(entries), has_more_entries); + } + +-// static +-bool FileSystemAccessDirectoryHandleImpl::IsSafePathComponent( +- const std::string& name) { +- // This method is similar to net::IsSafePortablePathComponent, with a few +- // notable differences where the net version does not consider names safe +- // while here we do want to allow them. These cases are: +- // - Names starting with a '.'. These would be hidden files in most file +- // managers, but are something we explicitly want to support for the +- // File System Access API, for names like .git. +- // - Names that end in '.local'. For downloads writing to such files is +- // dangerous since it might modify what code is executed when an executable +- // is ran from the same directory. For the File System Access API this +- // isn't really a problem though, since if a website can write to a .local +- // file via a FileSystemDirectoryHandle they can also just modify the +- // executables in the directory directly. +- // +- // TODO(https://crbug.com/1154757): Unify this with +- // net::IsSafePortablePathComponent, with the result probably ending up in +- // base/i18n/file_util_icu.h. +- +- const base::FilePath component = storage::StringToFilePath(name); +- // Empty names, or names that contain path separators are invalid. +- if (component.empty() || component != component.BaseName() || +- component != component.StripTrailingSeparators()) { +- return false; +- } +- +- std::u16string component16; +-#if BUILDFLAG(IS_WIN) +- component16.assign(component.value().begin(), component.value().end()); +-#else +- std::string component8 = component.AsUTF8Unsafe(); +- if (!base::UTF8ToUTF16(component8.c_str(), component8.size(), &component16)) { +- return false; +- } +-#endif +- // base::i18n::IsFilenameLegal blocks names that start with '.', so strip out +- // a leading '.' before passing it to that method. +- // TODO(mek): Consider making IsFilenameLegal more flexible to support this +- // use case. +- if (component16[0] == '.') { +- component16 = component16.substr(1); +- } +- if (!base::i18n::IsFilenameLegal(component16)) { +- return false; +- } +- +- base::FilePath::StringType extension = component.Extension(); +- if (!extension.empty()) { +- extension.erase(extension.begin()); // Erase preceding '.'. +- } +- if (IsShellIntegratedExtension(extension)) { +- return false; +- } +- +- if (base::TrimString(component.value(), FILE_PATH_LITERAL("."), +- base::TRIM_TRAILING) != component.value()) { +- return false; +- } +- +- if (net::IsReservedNameOnWindows(component.value())) { +- return false; +- } +- +- return true; +-} +- + blink::mojom::FileSystemAccessErrorPtr + FileSystemAccessDirectoryHandleImpl::GetChildURL( + const std::string& basename, + storage::FileSystemURL* result) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + +- if (!IsSafePathComponent(basename)) { ++ if (!manager()->IsSafePathComponent(basename)) { + return file_system_access_error::FromStatus( + FileSystemAccessStatus::kInvalidArgument, "Name is not allowed."); + } +diff --git a/chromium/content/browser/file_system_access/file_system_access_directory_handle_impl.h b/chromium/content/browser/file_system_access/file_system_access_directory_handle_impl.h +index 7bbec9a39d9..98452fc1f56 100644 +--- src/3rdparty/chromium/content/browser/file_system_access/file_system_access_directory_handle_impl.h ++++ src/3rdparty/chromium/content/browser/file_system_access/file_system_access_directory_handle_impl.h +@@ -84,14 +84,6 @@ class CONTENT_EXPORT FileSystemAccessDirectoryHandleImpl + const std::string& basename, + storage::FileSystemURL* result); + +- // The File System Access API should not give access to files that might +- // trigger special handling from the operating system. This method is used to +- // validate that all paths passed to GetFileHandle/GetDirectoryHandle are safe +- // to be exposed to the web. +- // TODO(https://crbug.com/1154757): Merge this with +- // net::IsSafePortablePathComponent. +- static bool IsSafePathComponent(const std::string& name); +- + private: + // This method creates the file if it does not currently exists. I.e. it is + // the implementation for passing create=true to GetFile. +diff --git a/chromium/content/browser/file_system_access/file_system_access_handle_base.cc b/chromium/content/browser/file_system_access/file_system_access_handle_base.cc +index 5792ad95e45..44891c0b75c 100644 +--- src/3rdparty/chromium/content/browser/file_system_access/file_system_access_handle_base.cc ++++ src/3rdparty/chromium/content/browser/file_system_access/file_system_access_handle_base.cc +@@ -217,7 +217,7 @@ void FileSystemAccessHandleBase::DoMove( + } + } + +- if (!FileSystemAccessDirectoryHandleImpl::IsSafePathComponent( ++ if (!manager()->IsSafePathComponent( + new_entry_name)) { + std::move(callback).Run(file_system_access_error::FromStatus( + blink::mojom::FileSystemAccessStatus::kInvalidArgument)); +@@ -250,7 +250,7 @@ void FileSystemAccessHandleBase::DoRename( + } + } + +- if (!FileSystemAccessDirectoryHandleImpl::IsSafePathComponent( ++ if (!manager()->IsSafePathComponent( + new_entry_name)) { + std::move(callback).Run(file_system_access_error::FromStatus( + blink::mojom::FileSystemAccessStatus::kInvalidArgument)); +diff --git a/chromium/content/browser/file_system_access/file_system_access_manager_impl.cc b/chromium/content/browser/file_system_access/file_system_access_manager_impl.cc +index faa3f12e452..c0d16224f11 100644 +--- src/3rdparty/chromium/content/browser/file_system_access/file_system_access_manager_impl.cc ++++ src/3rdparty/chromium/content/browser/file_system_access/file_system_access_manager_impl.cc +@@ -15,9 +15,11 @@ + #include "base/functional/bind.h" + #include "base/functional/callback_forward.h" + #include "base/functional/callback_helpers.h" ++#include "base/i18n/file_util_icu.h" + #include "base/notreached.h" + #include "base/ranges/algorithm.h" + #include "base/strings/string_util.h" ++#include "base/strings/utf_string_conversions.h" + #include "base/task/sequenced_task_runner.h" + #include "base/task/task_traits.h" + #include "base/task/thread_pool.h" +@@ -296,6 +298,32 @@ void DidCheckIfDefaultDirectoryExists( + } + } + ++// Returns whether the specified extension receives special handling by the ++// Windows shell. ++bool IsShellIntegratedExtension(const base::FilePath::StringType& extension) { ++ base::FilePath::StringType extension_lower = base::ToLowerASCII(extension); ++ ++ // .lnk and .scf files may be used to execute arbitrary code (see ++ // https://nvd.nist.gov/vuln/detail/CVE-2010-2568 and ++ // https://crbug.com/1227995, respectively). '.url' files can be used to read ++ // arbitrary files (see https://crbug.com/1307930 and ++ // https://crbug.com/1354518). ++ if (extension_lower == FILE_PATH_LITERAL("lnk") || ++ extension_lower == FILE_PATH_LITERAL("scf") || ++ extension_lower == FILE_PATH_LITERAL("url")) { ++ return true; ++ } ++ ++ // Setting a file's extension to a CLSID may conceal its actual file type on ++ // some Windows versions (see https://nvd.nist.gov/vuln/detail/CVE-2004-0420). ++ if (!extension_lower.empty() && ++ (extension_lower.front() == FILE_PATH_LITERAL('{')) && ++ (extension_lower.back() == FILE_PATH_LITERAL('}'))) { ++ return true; ++ } ++ return false; ++} ++ + } // namespace + + FileSystemAccessManagerImpl::SharedHandleState::SharedHandleState( +@@ -1749,4 +1777,69 @@ FileSystemAccessManagerImpl::AsWeakPtr() { + return weak_factory_.GetWeakPtr(); + } + ++bool FileSystemAccessManagerImpl::IsSafePathComponent( ++ const std::string& name) { ++ // This method is similar to net::IsSafePortablePathComponent, with a few ++ // notable differences where the net version does not consider names safe ++ // while here we do want to allow them. These cases are: ++ // - Names starting with a '.'. These would be hidden files in most file ++ // managers, but are something we explicitly want to support for the ++ // File System Access API, for names like .git. ++ // - Names that end in '.local'. For downloads writing to such files is ++ // dangerous since it might modify what code is executed when an executable ++ // is ran from the same directory. For the File System Access API this ++ // isn't really a problem though, since if a website can write to a .local ++ // file via a FileSystemDirectoryHandle they can also just modify the ++ // ++ // TODO(crbug.com/40159607): Unify this with ++ // net::IsSafePortablePathComponent, with the result probably ending up in ++ // base/i18n/file_util_icu.h. ++ ++ const base::FilePath component = storage::StringToFilePath(name); ++ // Empty names, or names that contain path separators are invalid. ++ if (component.empty() || component != component.BaseName() || ++ component != component.StripTrailingSeparators()) { ++ return false; ++ } ++ ++ std::u16string component16; ++#if BUILDFLAG(IS_WIN) ++ component16.assign(component.value().begin(), component.value().end()); ++#else ++ std::string component8 = component.AsUTF8Unsafe(); ++ if (!base::UTF8ToUTF16(component8.c_str(), component8.size(), &component16)) { ++ return false; ++ } ++#endif ++ // base::i18n::IsFilenameLegal blocks names that start with '.', so strip out ++ // a leading '.' before passing it to that method. ++ // TODO(mek): Consider making IsFilenameLegal more flexible to support this ++ // use case. ++ if (component16[0] == '.') { ++ component16 = component16.substr(1); ++ } ++ if (!base::i18n::IsFilenameLegal(component16)) { ++ return false; ++ } ++ ++ base::FilePath::StringType extension = component.Extension(); ++ if (!extension.empty()) { ++ extension.erase(extension.begin()); // Erase preceding '.'. ++ } ++ if (IsShellIntegratedExtension(extension)) { ++ return false; ++ } ++ ++ if (base::TrimString(component.value(), FILE_PATH_LITERAL("."), ++ base::TRIM_TRAILING) != component.value()) { ++ return false; ++ } ++ ++ if (net::IsReservedNameOnWindows(component.value())) { ++ return false; ++ } ++ ++ return true; ++} ++ + } // namespace content +diff --git a/chromium/content/browser/file_system_access/file_system_access_manager_impl.h b/chromium/content/browser/file_system_access/file_system_access_manager_impl.h +index 2b6828054b7..eeda10526b8 100644 +--- src/3rdparty/chromium/content/browser/file_system_access/file_system_access_manager_impl.h ++++ src/3rdparty/chromium/content/browser/file_system_access/file_system_access_manager_impl.h +@@ -359,6 +359,14 @@ class CONTENT_EXPORT FileSystemAccessManagerImpl + + void Shutdown(); + ++ // The File System Access API should not give access to files that might ++ // trigger special handling from the operating system. This method is used to ++ // validate that all paths passed to GetFileHandle/GetDirectoryHandle are safe ++ // to be exposed to the web. ++ // TODO(crbug.com/40159607): Merge this with ++ // net::IsSafePortablePathComponent. ++ bool IsSafePathComponent(const std::string& name); ++ + // Invokes `method` on the correct sequence on the FileSystemOperationRunner, + // passing `args` and a callback to the method. + // The passed in `callback` is wrapped to make sure it is called on the +diff --git a/chromium/content/browser/renderer_host/cross_process_frame_connector.cc b/chromium/content/browser/renderer_host/cross_process_frame_connector.cc +index 00eb0fb1348..2944d939029 100644 +--- src/3rdparty/chromium/content/browser/renderer_host/cross_process_frame_connector.cc ++++ src/3rdparty/chromium/content/browser/renderer_host/cross_process_frame_connector.cc +@@ -60,10 +60,11 @@ CrossProcessFrameConnector::~CrossProcessFrameConnector() { + } + + // Notify the view of this object being destroyed, if the view still exists. +- SetView(nullptr); ++ SetView(nullptr, /*allow_paint_holding=*/false); + } + +-void CrossProcessFrameConnector::SetView(RenderWidgetHostViewChildFrame* view) { ++void CrossProcessFrameConnector::SetView(RenderWidgetHostViewChildFrame* view, ++ bool allow_paint_holding) { + // Detach ourselves from the previous |view_|. + if (view_) { + RenderWidgetHostViewBase* root_view = GetRootRenderWidgetHostView(); +@@ -110,7 +111,7 @@ void CrossProcessFrameConnector::SetView(RenderWidgetHostViewChildFrame* view) { + if (frame_proxy_in_parent_renderer_ && + frame_proxy_in_parent_renderer_->is_render_frame_proxy_live()) { + frame_proxy_in_parent_renderer_->GetAssociatedRemoteFrame() +- ->SetFrameSinkId(view_->GetFrameSinkId()); ++ ->SetFrameSinkId(view_->GetFrameSinkId(), allow_paint_holding); + } + } + } +diff --git a/chromium/content/browser/renderer_host/cross_process_frame_connector.h b/chromium/content/browser/renderer_host/cross_process_frame_connector.h +index 05ecb60aebe..4436cd1fba7 100644 +--- src/3rdparty/chromium/content/browser/renderer_host/cross_process_frame_connector.h ++++ src/3rdparty/chromium/content/browser/renderer_host/cross_process_frame_connector.h +@@ -100,7 +100,7 @@ class CONTENT_EXPORT CrossProcessFrameConnector { + // above. + RenderWidgetHostViewChildFrame* get_view_for_testing() { return view_; } + +- void SetView(RenderWidgetHostViewChildFrame* view); ++ void SetView(RenderWidgetHostViewChildFrame* view, bool allow_paint_holding); + + // Returns the parent RenderWidgetHostView or nullptr if it doesn't have one. + virtual RenderWidgetHostViewBase* GetParentRenderWidgetHostView(); +diff --git a/chromium/content/browser/renderer_host/delegated_frame_host.cc b/chromium/content/browser/renderer_host/delegated_frame_host.cc +index 3ea56e0e536..499a23b5209 100644 +--- src/3rdparty/chromium/content/browser/renderer_host/delegated_frame_host.cc ++++ src/3rdparty/chromium/content/browser/renderer_host/delegated_frame_host.cc +@@ -503,7 +503,10 @@ void DelegatedFrameHost::ContinueDelegatedFrameEviction( + // preventing the FrameTree from being traversed. This could happen during + // navigation involving BFCache. This should not occur with + // features::kEvictSubtree. +- DCHECK(!surface_ids.empty() || ++ // We do allow the surface ids to be empty if we ++ // don't have a local surface id, since that means we don't have memory ++ // allocated in viz. ++ DCHECK(!surface_ids.empty() || !local_surface_id_.is_valid() || + !base::FeatureList::IsEnabled(features::kEvictSubtree)); + if (!surface_ids.empty()) { + DCHECK(host_frame_sink_manager_); diff --git a/chromium/content/browser/renderer_host/navigation_controller_impl.cc b/chromium/content/browser/renderer_host/navigation_controller_impl.cc index db818eb83e9..084fd00eeae 100644 --- src/3rdparty/chromium/content/browser/renderer_host/navigation_controller_impl.cc +++ src/3rdparty/chromium/content/browser/renderer_host/navigation_controller_impl.cc @@ -1826,6 +1826,7 @@ void NavigationControllerImpl::UpdateNavigationEntryDetails( params.method, params.post_id, nullptr /* blob_url_loader_factory */, ComputePolicyContainerPoliciesForFrameEntry( rfh, request && request->IsSameDocument(), + request ? request->DidEncounterError() : false, request ? request->common_params().url : params.url)); if (rfh->GetParent()) { @@ -2288,6 +2289,7 @@ void NavigationControllerImpl::RendererDidNavigateNewSubframe( } std::unique_ptr policy_container_policies = ComputePolicyContainerPoliciesForFrameEntry(rfh, is_same_document, + request->DidEncounterError(), request->GetURL()); bool protect_url_in_navigation_api = false; if (is_same_document) { @@ -4474,7 +4476,14 @@ std::unique_ptr NavigationControllerImpl::ComputePolicyContainerPoliciesForFrameEntry( RenderFrameHostImpl* rfh, bool is_same_document, + bool navigation_encountered_error, const GURL& url) { + if (navigation_encountered_error) { + // We should never reload the policy container of an error page from + // history, see https://crbug.com/364773822. + return nullptr; + } + if (is_same_document) { DCHECK(GetLastCommittedEntry()); FrameNavigationEntry* previous_frame_entry = diff --git a/chromium/content/browser/renderer_host/navigation_controller_impl.h b/chromium/content/browser/renderer_host/navigation_controller_impl.h index ba9be480a81..987963d4bf4 100644 --- src/3rdparty/chromium/content/browser/renderer_host/navigation_controller_impl.h +++ src/3rdparty/chromium/content/browser/renderer_host/navigation_controller_impl.h @@ -835,6 +835,7 @@ class CONTENT_EXPORT NavigationControllerImpl : public NavigationController { std::unique_ptr ComputePolicyContainerPoliciesForFrameEntry(RenderFrameHostImpl* rfh, bool is_same_document, + bool navigation_encountered_error, const GURL& url); // Adds details from a committed navigation to `entry` and the +diff --git a/chromium/content/browser/renderer_host/navigator.cc b/chromium/content/browser/renderer_host/navigator.cc +index e4cdb82d559..fd5e2eb26c3 100644 +--- src/3rdparty/chromium/content/browser/renderer_host/navigator.cc ++++ src/3rdparty/chromium/content/browser/renderer_host/navigator.cc +@@ -32,6 +32,7 @@ + #include "content/browser/web_package/prefetched_signed_exchange_cache.h" + #include "content/browser/webui/web_ui_controller_factory_registry.h" + #include "content/browser/webui/web_ui_impl.h" ++#include "content/common/features.h" + #include "content/common/navigation_params_utils.h" + #include "content/public/browser/browser_context.h" + #include "content/public/browser/content_browser_client.h" +@@ -516,17 +517,56 @@ void Navigator::DidNavigate( + // Store this information before DidNavigateFrame() potentially swaps RFHs. + url::Origin old_frame_origin = old_frame_host->GetLastCommittedOrigin(); + ++ // RenderFrameHostImpl::DidNavigate will update the url, and may cause the ++ // node to consider itself no longer on the initial empty document. Record ++ // whether we're leaving the initial empty document before that. ++ bool was_on_initial_empty_document = ++ frame_tree_node->is_on_initial_empty_document(); ++ ++ // Allow main frame paint holding in the following cases: ++ // - We don't have an animated transition. See crbug.com/360844863. ++ // - At least one of the following conditions is true: ++ // - This is a navigation from the initial document. This part helps with ++ // tests. See crbug.com/367623929. ++ // - This is a same origin navigation (or we're not limiting cross-origin ++ // paint holding) ++ // - There is a user activation. This means that the user interacted with ++ // the page. Commonly used attacks are done without user activation -- ++ // which will not enable paint holding. However, if the user interacts ++ // with the page, we treat it as a valid case for paint holding. ++ // - The client allows non-activated cross origin paintholding, which is ++ // currently the case with webview. ++ // ++ // See https://issues.chromium.org/40942531 for reasons we limit paint ++ // holding. ++ ContentBrowserClient* client = GetContentClient()->browser(); ++ const bool allow_main_frame_paint_holding = ++ (was_on_initial_empty_document || ++ old_frame_origin.IsSameOriginWith(params.origin) || ++ old_frame_host->HasStickyUserActivation() || ++ client->AllowNonActivatedCrossOriginPaintHolding() || ++ !base::FeatureList::IsEnabled( ++ kLimitCrossOriginNonActivatedPaintHolding)); ++ ++ // Only allow subframe paint holding for same origin. ++ const bool allow_subframe_paint_holding = ++ old_frame_origin.IsSameOriginWith(params.origin); ++ + // DidNavigateFrame() must be called before replicating the new origin and + // other properties to proxies. This is because it destroys the subframes of + // the frame we're navigating from, which might trigger those subframes to + // run unload handlers. Those unload handlers should still see the old + // frame's origin. See https://crbug.com/825283. ++ const bool allow_paint_holding = frame_tree_node->IsMainFrame() ++ ? allow_main_frame_paint_holding ++ : allow_subframe_paint_holding; ++ + frame_tree_node->render_manager()->DidNavigateFrame( + render_frame_host, navigation_request->common_params().has_user_gesture, + was_within_same_document, + navigation_request->browsing_context_group_swap() + .ShouldClearProxiesOnCommit(), +- navigation_request->commit_params().frame_policy); ++ navigation_request->commit_params().frame_policy, allow_paint_holding); + + // The main frame, same site, and cross-site navigation checks for user + // activation mirror the checks in DocumentLoader::CommitNavigation() (note: +@@ -593,12 +633,6 @@ void Navigator::DidNavigate( + render_frame_host->GetPage().SetContentsMimeType(params.contents_mime_type); + } + +- // RenderFrameHostImpl::DidNavigate will update the url, and may cause the +- // node to consider itself no longer on the initial empty document. Record +- // whether we're leaving the initial empty document before that. +- bool was_on_initial_empty_document = +- frame_tree_node->is_on_initial_empty_document(); +- + render_frame_host->DidNavigate(params, navigation_request.get(), + was_within_same_document); + +diff --git a/chromium/content/browser/renderer_host/render_frame_host_impl.cc b/chromium/content/browser/renderer_host/render_frame_host_impl.cc +index d1d0efb398b..a45f586a3c4 100644 +--- src/3rdparty/chromium/content/browser/renderer_host/render_frame_host_impl.cc ++++ src/3rdparty/chromium/content/browser/renderer_host/render_frame_host_impl.cc +@@ -8546,7 +8546,8 @@ void RenderFrameHostImpl::AdoptPortal( + ->render_manager() + ->GetRenderWidgetHostView() + ->GetFrameSinkId(); +- proxy_host->GetAssociatedRemoteFrame()->SetFrameSinkId(frame_sink_id); ++ // generally disallow paint holding for security reasons ++ proxy_host->GetAssociatedRemoteFrame()->SetFrameSinkId(frame_sink_id, /*allow_paint_holding*/ false); + + std::move(callback).Run( + proxy_host->frame_tree_node()->current_replication_state().Clone(), +diff --git a/chromium/content/browser/renderer_host/render_frame_host_manager.cc b/chromium/content/browser/renderer_host/render_frame_host_manager.cc +index 9f5cddd99a0..91114140ea4 100644 +--- src/3rdparty/chromium/content/browser/renderer_host/render_frame_host_manager.cc ++++ src/3rdparty/chromium/content/browser/renderer_host/render_frame_host_manager.cc +@@ -731,10 +731,11 @@ void RenderFrameHostManager::DidNavigateFrame( + bool was_caused_by_user_gesture, + bool is_same_document_navigation, + bool clear_proxies_on_commit, +- const blink::FramePolicy& frame_policy) { ++ const blink::FramePolicy& frame_policy, ++ bool allow_paint_holding) { + CommitPendingIfNecessary(render_frame_host, was_caused_by_user_gesture, +- is_same_document_navigation, +- clear_proxies_on_commit); ++ is_same_document_navigation, clear_proxies_on_commit, ++ allow_paint_holding); + + // Make sure any dynamic changes to this frame's sandbox flags and permissions + // policy that were made prior to navigation take effect. This should only +@@ -770,7 +771,8 @@ void RenderFrameHostManager::CommitPendingIfNecessary( + RenderFrameHostImpl* render_frame_host, + bool was_caused_by_user_gesture, + bool is_same_document_navigation, +- bool clear_proxies_on_commit) { ++ bool clear_proxies_on_commit, ++ bool allow_paint_holding) { + if (!speculative_render_frame_host_) { + // There's no speculative RenderFrameHost so it must be that the current + // RenderFrameHost completed a navigation. +@@ -784,7 +786,8 @@ void RenderFrameHostManager::CommitPendingIfNecessary( + if (render_frame_host == speculative_render_frame_host_.get()) { + // A cross-RenderFrameHost navigation completed, so show the new renderer. + CommitPending(std::move(speculative_render_frame_host_), +- std::move(stored_page_to_restore_), clear_proxies_on_commit); ++ std::move(stored_page_to_restore_), clear_proxies_on_commit, ++ allow_paint_holding); + + if (GetNavigationQueueingFeatureLevel() >= + NavigationQueueingFeatureLevel::kAvoidRedundantCancellations) { +@@ -841,9 +844,26 @@ void RenderFrameHostManager::CommitPendingIfNecessary( + // output on prerender activation. + if (render_frame_host_->lifecycle_state() != + LifecycleStateImpl::kPrerendering) { +- static_cast( +- render_frame_host_->GetView()->GetRenderWidgetHost()) +- ->StartNewContentRenderingTimeout(); ++ auto* rwhi = static_cast( ++ render_frame_host_->GetView()->GetRenderWidgetHost()); ++ ++ rwhi->StartNewContentRenderingTimeout(); ++ // Force the timer to expire immediately if we don't allow main frame ++ // paint holding. ++ if (frame_tree_node_->IsMainFrame() && !allow_paint_holding) { ++ // We post task here, since this evicts a surface but the embedding of a ++ // new surface would be done in the same stack as this call. The ++ // ordering of whether the new surface has or has not yet been embedded ++ // differs for different platforms, and we always want the new surface ++ // to be embedded before we evict. Hence, we post a task. In practice ++ // this still disables paint holding unless this task is delayed for a ++ // long time. ++ GetUIThreadTaskRunner({})->PostTask( ++ FROM_HERE, ++ base::BindOnce( ++ &RenderWidgetHostImpl::ForceFirstFrameAfterNavigationTimeout, ++ rwhi->GetWeakPtr())); ++ } + } + } + +@@ -1467,7 +1487,8 @@ void RenderFrameHostManager::PerformEarlyRenderFrameHostSwapIfNeeded( + + CommitPending( + std::move(speculative_render_frame_host_), nullptr, +- request->browsing_context_group_swap().ShouldClearProxiesOnCommit()); ++ request->browsing_context_group_swap().ShouldClearProxiesOnCommit(), ++ /* allow_paint_holding */ false); + request->SetAssociatedRFHType( + NavigationRequest::AssociatedRenderFrameHostType::CURRENT); + +@@ -4028,7 +4049,8 @@ void RenderFrameHostManager::SetRWHViewForInnerFrameTree( + RenderWidgetHostViewChildFrame* child_rwhv) { + DCHECK(IsMainFrameForInnerDelegate()); + DCHECK(GetProxyToOuterDelegate()); +- GetProxyToOuterDelegate()->SetChildRWHView(child_rwhv, nullptr); ++ GetProxyToOuterDelegate()->SetChildRWHView(child_rwhv, nullptr, ++ /*allow_paint_holding=*/false); + } + + bool RenderFrameHostManager::InitRenderView( +@@ -4340,7 +4362,8 @@ RenderFrameHostManager::GetFrameTokenForSiteInstanceGroup( + void RenderFrameHostManager::CommitPending( + std::unique_ptr pending_rfh, + std::unique_ptr pending_stored_page, +- bool clear_proxies_on_commit) { ++ bool clear_proxies_on_commit, ++ bool allow_paint_holding) { + TRACE_EVENT1("navigation", "RenderFrameHostManager::CommitPending", + "FrameTreeNode id", frame_tree_node_->frame_tree_node_id()); + CHECK(pending_rfh); +@@ -4593,9 +4616,10 @@ void RenderFrameHostManager::CommitPending( + // valid surface id, because it already has that surface embedded through + // `RenderFrameHostImpl::WillLeaveBackForwardCache` and the timeout that + // would be set here will clear that frame (incorrectly). +- if (is_main_frame && old_view && old_view != new_view) { +- // We should take the fallback if we're not coming from BFCache or if we +- // don't have a valid surface id to display. ++ if (is_main_frame && allow_paint_holding && old_view && old_view != new_view) { ++ // If allowed, we should take the fallback in any of the following cases: ++ // - We're not coming from BFCache ++ // - We don't have a valid surface id to display. + auto* render_widget_host_view_base = + static_cast(render_frame_host_->GetView()); + should_take_fallback_content = +@@ -4730,7 +4754,7 @@ void RenderFrameHostManager::CommitPending( + if (proxy_to_parent_or_outer_delegate) { + proxy_to_parent_or_outer_delegate->SetChildRWHView( + static_cast(new_view), +- old_size ? &*old_size : nullptr); ++ old_size ? &*old_size : nullptr, allow_paint_holding); + } + + if (render_frame_host_->is_local_root()) { +@@ -5136,8 +5160,10 @@ void RenderFrameHostManager::CreateNewFrameForInnerDelegateAttachIfNecessary() { + // Swap in the speculative frame. It will later be replaced when + // WebContents::AttachToOuterWebContentsFrame is called. + speculative_render_frame_host_->SwapIn(); ++ + CommitPending(std::move(speculative_render_frame_host_), nullptr, +- false /* clear_proxies_on_commit */); ++ false /* clear_proxies_on_commit */, ++ /* allow_paint_holding */ false); + NotifyPrepareForInnerDelegateAttachComplete(true /* success */); + } + +diff --git a/chromium/content/browser/renderer_host/render_frame_host_manager.h b/chromium/content/browser/renderer_host/render_frame_host_manager.h +index 9257b8c5f93..46acf6a9380 100644 +--- src/3rdparty/chromium/content/browser/renderer_host/render_frame_host_manager.h ++++ src/3rdparty/chromium/content/browser/renderer_host/render_frame_host_manager.h +@@ -322,7 +322,8 @@ class CONTENT_EXPORT RenderFrameHostManager { + bool was_caused_by_user_gesture, + bool is_same_document_navigation, + bool clear_proxies_on_commit, +- const blink::FramePolicy& frame_policy); ++ const blink::FramePolicy& frame_policy, ++ bool allow_paint_holding); + + // Called when this frame's opener is changed to the frame specified by + // |opener_frame_token| in |source_site_instance_group|'s process. This +@@ -971,15 +972,18 @@ class CONTENT_EXPORT RenderFrameHostManager { + // |clear_proxies_on_commit| Indicates if the proxies and opener must be + // removed during the commit. This can happen following some BrowsingInstance + // swaps, such as those for COOP. ++ // |allow_paint_holding| Indicates whether paint holding is allowed. + void CommitPending(std::unique_ptr pending_rfh, + std::unique_ptr pending_stored_page, +- bool clear_proxies_on_commit); ++ bool clear_proxies_on_commit, ++ bool allow_paint_holding); + + // Helper to call CommitPending() in all necessary cases. + void CommitPendingIfNecessary(RenderFrameHostImpl* render_frame_host, + bool was_caused_by_user_gesture, + bool is_same_document_navigation, +- bool clear_proxies_on_commit); ++ bool clear_proxies_on_commit, ++ bool allow_paint_holding); + + // Runs the unload handler in the old RenderFrameHost, after the new + // RenderFrameHost has committed. |old_render_frame_host| will either be +diff --git a/chromium/content/browser/renderer_host/render_frame_proxy_host.cc b/chromium/content/browser/renderer_host/render_frame_proxy_host.cc +index 2ac59af2958..6ac750e7155 100644 +--- src/3rdparty/chromium/content/browser/renderer_host/render_frame_proxy_host.cc ++++ src/3rdparty/chromium/content/browser/renderer_host/render_frame_proxy_host.cc +@@ -192,10 +192,10 @@ RenderFrameProxyHost::~RenderFrameProxyHost() { + TRACE_EVENT_END("navigation", perfetto::Track::FromPointer(this)); + } + +-void RenderFrameProxyHost::SetChildRWHView( +- RenderWidgetHostViewChildFrame* view, +- const gfx::Size* initial_frame_size) { +- cross_process_frame_connector_->SetView(view); ++void RenderFrameProxyHost::SetChildRWHView(RenderWidgetHostViewChildFrame* view, ++ const gfx::Size* initial_frame_size, ++ bool allow_paint_holding) { ++ cross_process_frame_connector_->SetView(view, allow_paint_holding); + if (initial_frame_size) + cross_process_frame_connector_->SetLocalFrameSize(*initial_frame_size); + } +diff --git a/chromium/content/browser/renderer_host/render_frame_proxy_host.h b/chromium/content/browser/renderer_host/render_frame_proxy_host.h +index 08c1d72af90..c63589a7c31 100644 +--- src/3rdparty/chromium/content/browser/renderer_host/render_frame_proxy_host.h ++++ src/3rdparty/chromium/content/browser/renderer_host/render_frame_proxy_host.h +@@ -164,7 +164,8 @@ class CONTENT_EXPORT RenderFrameProxyHost + // receives its size from the parent via FrameHostMsg_UpdateResizeParams + // before it begins parsing the content. + void SetChildRWHView(RenderWidgetHostViewChildFrame* view, +- const gfx::Size* initial_frame_size); ++ const gfx::Size* initial_frame_size, ++ bool allow_paint_holding); + + RenderViewHostImpl* GetRenderViewHost(); + +diff --git a/chromium/content/browser/renderer_host/render_widget_host_impl.cc b/chromium/content/browser/renderer_host/render_widget_host_impl.cc +index f27648e12c1..a337dd6a96b 100644 +--- src/3rdparty/chromium/content/browser/renderer_host/render_widget_host_impl.cc ++++ src/3rdparty/chromium/content/browser/renderer_host/render_widget_host_impl.cc +@@ -117,6 +117,7 @@ + #include "third_party/blink/public/common/input/synthetic_web_input_event_builders.h" + #include "third_party/blink/public/common/storage_key/storage_key.h" + #include "third_party/blink/public/common/web_preferences/web_preferences.h" ++#include "third_party/blink/public/common/widget/constants.h" + #include "third_party/blink/public/common/widget/visual_properties.h" + #include "third_party/blink/public/mojom/drag/drag.mojom.h" + #include "third_party/blink/public/mojom/frame/intrinsic_sizing_info.mojom.h" +@@ -165,10 +166,6 @@ using blink::WebMouseWheelEvent; + namespace content { + namespace { + +-// How long to wait for newly loaded content to send a compositor frame +-// before clearing previously displayed graphics. +-constexpr base::TimeDelta kNewContentRenderingDelay = base::Seconds(4); +- + constexpr gfx::Rect kInvalidScreenRect(std::numeric_limits::max(), + std::numeric_limits::max(), + 0, +@@ -438,7 +435,7 @@ RenderWidgetHostImpl::RenderWidgetHostImpl( + switches::kDisableHangMonitor)), + latency_tracker_(delegate_), + hung_renderer_delay_(kHungRendererDelay), +- new_content_rendering_delay_(kNewContentRenderingDelay), ++ new_content_rendering_delay_(blink::kNewContentRenderingDelay), + frame_token_message_queue_(std::move(frame_token_message_queue)), + render_frame_metadata_provider_( + #if BUILDFLAG(IS_MAC) +diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_child_frame.cc b/chromium/content/browser/renderer_host/render_widget_host_view_child_frame.cc +index b190c86708d..632973c779e 100644 +--- src/3rdparty/chromium/content/browser/renderer_host/render_widget_host_view_child_frame.cc ++++ src/3rdparty/chromium/content/browser/renderer_host/render_widget_host_view_child_frame.cc +@@ -406,7 +406,7 @@ void RenderWidgetHostViewChildFrame::Destroy() { + // have already been cleared when RenderWidgetHostViewBase notified its + // observers of our impending destruction. + if (frame_connector_) { +- frame_connector_->SetView(nullptr); ++ frame_connector_->SetView(nullptr, /*allow_paint_holding=*/false); + SetFrameConnector(nullptr); + } + +diff --git a/chromium/content/common/features.cc b/chromium/content/common/features.cc +index 52443a0118c..e80454c2edd 100644 +--- src/3rdparty/chromium/content/common/features.cc ++++ src/3rdparty/chromium/content/common/features.cc +@@ -59,6 +59,11 @@ BASE_FEATURE(kWindowOpenFileSelectFix, + "WindowOpenFileSelectFix", + base::FEATURE_ENABLED_BY_DEFAULT); + ++// Flag guard for fix for crbug.com/40942531. ++BASE_FEATURE(kLimitCrossOriginNonActivatedPaintHolding, ++ "LimitCrossOriginNonActivatedPaintHolding", ++ base::FEATURE_ENABLED_BY_DEFAULT); ++ + // Please keep features in alphabetical order. + + } // namespace content +diff --git a/chromium/content/common/features.h b/chromium/content/common/features.h +index 5b5feb19663..92d7b515f86 100644 +--- src/3rdparty/chromium/content/common/features.h ++++ src/3rdparty/chromium/content/common/features.h +@@ -72,6 +72,8 @@ CONTENT_EXPORT BASE_DECLARE_FEATURE(kSpeculativeServiceWorkerStartup); + // Flag guard for fix for crbug.com/1414936. + CONTENT_EXPORT BASE_DECLARE_FEATURE(kWindowOpenFileSelectFix); + ++CONTENT_EXPORT BASE_DECLARE_FEATURE(kLimitCrossOriginNonActivatedPaintHolding); ++ + // Please keep features in alphabetical order. + + } // namespace content +diff --git a/chromium/content/public/browser/content_browser_client.cc b/chromium/content/public/browser/content_browser_client.cc +index f30e5094533..59d3cc16e25 100644 +--- src/3rdparty/chromium/content/public/browser/content_browser_client.cc ++++ src/3rdparty/chromium/content/public/browser/content_browser_client.cc +@@ -1593,4 +1593,8 @@ bool ContentBrowserClient:: + return true; + } + ++bool ContentBrowserClient::AllowNonActivatedCrossOriginPaintHolding() { ++ return false; ++} ++ + } // namespace content +diff --git a/chromium/content/public/browser/content_browser_client.h b/chromium/content/public/browser/content_browser_client.h +index 3ae26ba017f..ded95892ab6 100644 +--- src/3rdparty/chromium/content/public/browser/content_browser_client.h ++++ src/3rdparty/chromium/content/public/browser/content_browser_client.h +@@ -2619,6 +2619,10 @@ class CONTENT_EXPORT ContentBrowserClient { + // "Cache-control: no-store" header in BFCache. + virtual bool ShouldAllowBackForwardCacheForCacheControlNoStorePage( + content::BrowserContext* browser_context); ++ ++ // Indicates whether this client allows paint holding in cross-origin ++ // navigations even if there was no user activation. ++ virtual bool AllowNonActivatedCrossOriginPaintHolding(); + }; + + } // namespace content +diff --git a/chromium/content/renderer/media/media_factory.cc b/chromium/content/renderer/media/media_factory.cc +index a6859aa3532..3316f1aaedc 100644 +--- src/3rdparty/chromium/content/renderer/media/media_factory.cc ++++ src/3rdparty/chromium/content/renderer/media/media_factory.cc +@@ -690,7 +690,7 @@ MediaFactory::CreateRendererFactorySelector( + + media::ObserveOverlayStateCB observe_overlay_state_cb = + base::BindRepeating(&OverlayStateObserverImpl::Create, +- render_thread->GetOverlayStateServiceProvider()); ++ base::RetainedRef(render_thread->GetOverlayStateServiceProvider())); + + factory_selector->AddFactory( + RendererType::kMediaFoundation, +diff --git a/chromium/content/renderer/media/win/overlay_state_observer_impl.cc b/chromium/content/renderer/media/win/overlay_state_observer_impl.cc +index 7cb6729a1e2..1de0ddc46ab 100644 +--- src/3rdparty/chromium/content/renderer/media/win/overlay_state_observer_impl.cc ++++ src/3rdparty/chromium/content/renderer/media/win/overlay_state_observer_impl.cc +@@ -16,7 +16,7 @@ OverlayStateObserverImpl::Create( + StateChangedCB state_changed_cb) { + if (overlay_state_service_provider) { + return base::WrapUnique(new OverlayStateObserverImpl( +- overlay_state_service_provider, mailbox, state_changed_cb)); ++ overlay_state_service_provider, mailbox, std::move(state_changed_cb))); + } + return nullptr; + } +diff --git a/chromium/content/renderer/media/win/overlay_state_service_provider.h b/chromium/content/renderer/media/win/overlay_state_service_provider.h +index a1b97b4429f..491a44ba2ea 100644 +--- src/3rdparty/chromium/content/renderer/media/win/overlay_state_service_provider.h ++++ src/3rdparty/chromium/content/renderer/media/win/overlay_state_service_provider.h +@@ -15,11 +15,19 @@ class GpuChannelHost; + + namespace content { + +-class OverlayStateServiceProvider { ++class OverlayStateServiceProvider ++ : public base::RefCountedThreadSafe { + public: + virtual bool RegisterObserver( + mojo::PendingRemote pending_remote, + const gpu::Mailbox& mailbox) = 0; ++ ++ protected: ++ friend class base::RefCountedThreadSafe; ++ OverlayStateServiceProvider() = default; ++ OverlayStateServiceProvider(const OverlayStateServiceProvider&) = delete; ++ OverlayStateServiceProvider& operator=(const OverlayStateServiceProvider&) = ++ delete; + virtual ~OverlayStateServiceProvider() = default; + }; + +@@ -29,7 +37,6 @@ class OverlayStateServiceProviderImpl : public OverlayStateServiceProvider { + public: + explicit OverlayStateServiceProviderImpl( + scoped_refptr channel); +- ~OverlayStateServiceProviderImpl() override; + + bool RegisterObserver( + mojo::PendingRemote pending_remote, +@@ -43,6 +50,7 @@ class OverlayStateServiceProviderImpl : public OverlayStateServiceProvider { + delete; + OverlayStateServiceProviderImpl& operator=( + const OverlayStateServiceProviderImpl&) = delete; ++ ~OverlayStateServiceProviderImpl() override; + + scoped_refptr channel_; + }; +diff --git a/chromium/content/renderer/render_thread_impl.cc b/chromium/content/renderer/render_thread_impl.cc +index 328ed025f6b..f44428ecb13 100644 +--- src/3rdparty/chromium/content/renderer/render_thread_impl.cc ++++ src/3rdparty/chromium/content/renderer/render_thread_impl.cc +@@ -1268,7 +1268,7 @@ scoped_refptr RenderThreadImpl::GetDCOMPTextureFactory() { + return dcomp_texture_factory_; + } + +-OverlayStateServiceProvider* ++scoped_refptr + RenderThreadImpl::GetOverlayStateServiceProvider() { + DCHECK(IsMainThread()); + // Only set 'overlay_state_service_provider_' if Media Foundation for clear +@@ -1282,11 +1282,12 @@ RenderThreadImpl::GetOverlayStateServiceProvider() { + return nullptr; + } + overlay_state_service_provider_ = +- std::make_unique(std::move(channel)); ++ base::MakeRefCounted( ++ std::move(channel)); + } + } + +- return overlay_state_service_provider_.get(); ++ return overlay_state_service_provider_; + } + #endif // BUILDFLAG(IS_WIN) + +diff --git a/chromium/content/renderer/render_thread_impl.h b/chromium/content/renderer/render_thread_impl.h +index 0d91d61008a..1e3a986f9e7 100644 +--- src/3rdparty/chromium/content/renderer/render_thread_impl.h ++++ src/3rdparty/chromium/content/renderer/render_thread_impl.h +@@ -265,7 +265,7 @@ class CONTENT_EXPORT RenderThreadImpl + // The OverlayStateService is only available where Media Foundation for + // clear is supported, otherwise GetOverlayStateServiceProvider will return + // nullptr. +- OverlayStateServiceProvider* GetOverlayStateServiceProvider(); ++ scoped_refptr GetOverlayStateServiceProvider(); + #endif + + blink::WebVideoCaptureImplManager* video_capture_impl_manager() const { +@@ -530,7 +530,7 @@ class CONTENT_EXPORT RenderThreadImpl + + #if BUILDFLAG(IS_WIN) + scoped_refptr dcomp_texture_factory_; +- std::unique_ptr ++ scoped_refptr + overlay_state_service_provider_; + #endif + diff --git a/chromium/gpu/config/software_rendering_list.json b/chromium/gpu/config/software_rendering_list.json index a2f6aa5f2cf..0878fb2599e 100644 --- src/3rdparty/chromium/gpu/config/software_rendering_list.json +++ src/3rdparty/chromium/gpu/config/software_rendering_list.json @@ -1396,23 +1396,6 @@ "accelerated_webgl2" ] }, - { - "id": 158, - "description": "Canvas rendering issues with Intel drivers on Windows since 94-based: https://bugreports.qt.io/browse/QTBUG-104065", - "cr_bugs": [1316442], - "os": { - "type": "win" - }, - "exceptions": [ - { - "gl_renderer": "ANGLE.*" - } - ], - "vendor_id": "0x8086", - "features": [ - "accelerated_2d_canvas" - ] - }, { "id": 159, "cr_bugs": [902247], +diff --git a/chromium/third_party/blink/common/widget/constants.cc b/chromium/third_party/blink/common/widget/constants.cc +index 212050c1221..2b27ca8d7e9 100644 +--- src/3rdparty/chromium/third_party/blink/common/widget/constants.cc ++++ src/3rdparty/chromium/third_party/blink/common/widget/constants.cc +@@ -8,4 +8,6 @@ namespace blink { + + const int kMinimumWindowSize = 100; + ++const base::TimeDelta kNewContentRenderingDelay = base::Seconds(4); ++ + } // namespace blink +diff --git a/chromium/third_party/blink/public/common/widget/constants.h b/chromium/third_party/blink/public/common/widget/constants.h +index 95749573237..69aedfbc137 100644 +--- src/3rdparty/chromium/third_party/blink/public/common/widget/constants.h ++++ src/3rdparty/chromium/third_party/blink/public/common/widget/constants.h +@@ -5,6 +5,7 @@ + #ifndef THIRD_PARTY_BLINK_PUBLIC_COMMON_WIDGET_CONSTANTS_H_ + #define THIRD_PARTY_BLINK_PUBLIC_COMMON_WIDGET_CONSTANTS_H_ + ++#include "base/time/time.h" + #include "third_party/blink/public/common/common_export.h" + + namespace blink { +@@ -13,6 +14,9 @@ namespace blink { + // window object + BLINK_COMMON_EXPORT extern const int kMinimumWindowSize; + ++// The timeout for clearing old paint for a cross-document navigation. ++BLINK_COMMON_EXPORT extern const base::TimeDelta kNewContentRenderingDelay; ++ + } // namespace blink + + #endif // THIRD_PARTY_BLINK_PUBLIC_COMMON_WIDGET_CONSTANTS_H_ +diff --git a/chromium/third_party/blink/public/mojom/frame/remote_frame.mojom b/chromium/third_party/blink/public/mojom/frame/remote_frame.mojom +index 4d891d46b67..e3c22c2059b 100644 +--- src/3rdparty/chromium/third_party/blink/public/mojom/frame/remote_frame.mojom ++++ src/3rdparty/chromium/third_party/blink/public/mojom/frame/remote_frame.mojom +@@ -404,7 +404,11 @@ interface RemoteFrame { + + // Notifies this remote frame that its associated compositing + // destination (RenderWidgetHostView) has changed. +- SetFrameSinkId(viz.mojom.FrameSinkId frame_sink_id); ++ // ++ // The embedder can keep using the painted content from the previous frame ++ // sink until the new frame sink produces a new frame, i.e., paint holding. ++ // `allow_paint_holding` is used to limit this to same-origin navigations. ++ SetFrameSinkId(viz.mojom.FrameSinkId frame_sink_id, bool allow_paint_holding); + + // Notifies the remote frame that the process rendering the child frame's + // contents has terminated. diff --git a/chromium/third_party/blink/renderer/core/dom/element_rare_data_vector.cc b/chromium/third_party/blink/renderer/core/dom/element_rare_data_vector.cc index 5680187326b..66abc46ca6a 100644 --- src/3rdparty/chromium/third_party/blink/renderer/core/dom/element_rare_data_vector.cc +++ src/3rdparty/chromium/third_party/blink/renderer/core/dom/element_rare_data_vector.cc @@ -45,12 +45,21 @@ ElementRareDataVector::~ElementRareDataVector() { unsigned ElementRareDataVector::GetFieldIndex(FieldId field_id) const { unsigned field_id_int = static_cast(field_id); DCHECK(fields_bitfield_ & (static_cast(1) << field_id_int)); -#ifdef _MSC_VER - return __popcnt(fields_bitfield_ & - ~(~static_cast(0) << field_id_int)); -#else +#if defined(__GNUC__) || defined(__clang__) return __builtin_popcount(fields_bitfield_ & ~(~static_cast(0) << field_id_int)); +#elif _MSVC_LANG >= 202002L // C++20 + return std::popcount(fields_bitfield_ & + ~(~static_cast(0) << field_id_int)); +#else + uint32_t v = (fields_bitfield_ & + ~(~static_cast(0) << field_id_int)); + uint32_t c = v - ((v >> 1) & 0x55555555); + c = ((c >> 2) & 0x33333333) + (c & 0x33333333); + c = ((c >> 4) + c) & 0x0F0F0F0F; + c = ((c >> 8) + c) & 0x00FF00FF; + c = ((c >> 16) + c) & 0x0000FFFF; + return c; #endif } +diff --git a/chromium/third_party/blink/renderer/core/frame/child_frame_compositing_helper.cc b/chromium/third_party/blink/renderer/core/frame/child_frame_compositing_helper.cc +index 632bc8d5aa3..d5afeae18a8 100644 +--- src/3rdparty/chromium/third_party/blink/renderer/core/frame/child_frame_compositing_helper.cc ++++ src/3rdparty/chromium/third_party/blink/renderer/core/frame/child_frame_compositing_helper.cc +@@ -12,7 +12,10 @@ + #include "cc/paint/paint_image.h" + #include "cc/paint/paint_image_builder.h" + #include "skia/ext/image_operations.h" ++#include "third_party/blink/public/common/widget/constants.h" + #include "third_party/blink/renderer/core/frame/child_frame_compositor.h" ++#include "third_party/blink/renderer/platform/runtime_enabled_features.h" ++#include "third_party/blink/renderer/platform/wtf/functional.h" + #include "third_party/skia/include/core/SkBitmap.h" + #include "third_party/skia/include/core/SkImage.h" + #include "ui/gfx/geometry/point_f.h" +@@ -46,11 +49,14 @@ void ChildFrameCompositingHelper::ChildFrameGone(float device_scale_factor) { + + void ChildFrameCompositingHelper::SetSurfaceId( + const viz::SurfaceId& surface_id, +- bool capture_sequence_number_changed) { ++ CaptureSequenceNumberChanged capture_sequence_number_changed, ++ AllowPaintHolding allow_paint_holding) { + if (surface_id_ == surface_id) + return; + ++ const auto current_surface_id = surface_id_; + surface_id_ = surface_id; ++ paint_holding_timer_.Stop(); + + surface_layer_ = cc::SurfaceLayer::Create(); + surface_layer_->SetMasksToBounds(true); +@@ -59,10 +65,12 @@ void ChildFrameCompositingHelper::SetSurfaceId( + + // If we're synchronizing surfaces, then use an infinite deadline to ensure + // everything is synchronized. +- cc::DeadlinePolicy deadline = capture_sequence_number_changed +- ? cc::DeadlinePolicy::UseInfiniteDeadline() +- : cc::DeadlinePolicy::UseDefaultDeadline(); ++ cc::DeadlinePolicy deadline = ++ capture_sequence_number_changed == CaptureSequenceNumberChanged::kYes ++ ? cc::DeadlinePolicy::UseInfiniteDeadline() ++ : cc::DeadlinePolicy::UseDefaultDeadline(); + surface_layer_->SetSurfaceId(surface_id, deadline); ++ MaybeSetUpPaintHolding(current_surface_id, allow_paint_holding); + + // TODO(lfg): Investigate if it's possible to propagate the information + // about the child surface's opacity. https://crbug.com/629851. +@@ -72,6 +80,33 @@ void ChildFrameCompositingHelper::SetSurfaceId( + UpdateVisibility(true); + } + ++void ChildFrameCompositingHelper::MaybeSetUpPaintHolding( ++ const viz::SurfaceId& fallback_id, ++ AllowPaintHolding allow_paint_holding) { ++ if (!RuntimeEnabledFeatures::PaintHoldingForIframesEnabled()) { ++ return; ++ } ++ ++ if (fallback_id.is_valid() && ++ allow_paint_holding == AllowPaintHolding::kYes) { ++ surface_layer_->SetOldestAcceptableFallback(fallback_id); ++ ++ paint_holding_timer_.Start( ++ FROM_HERE, kNewContentRenderingDelay, ++ WTF::BindOnce(&ChildFrameCompositingHelper::PaintHoldingTimerFired, ++ base::Unretained(this))); ++ } else { ++ surface_layer_->SetOldestAcceptableFallback(viz::SurfaceId()); ++ } ++} ++ ++void ChildFrameCompositingHelper::PaintHoldingTimerFired() { ++ CHECK(RuntimeEnabledFeatures::PaintHoldingForIframesEnabled()); ++ if (surface_layer_) { ++ surface_layer_->SetOldestAcceptableFallback(viz::SurfaceId()); ++ } ++} ++ + void ChildFrameCompositingHelper::UpdateVisibility(bool visible) { + const scoped_refptr& layer = child_frame_compositor_->GetCcLayer(); + if (layer) { +diff --git a/chromium/third_party/blink/renderer/core/frame/child_frame_compositing_helper.h b/chromium/third_party/blink/renderer/core/frame/child_frame_compositing_helper.h +index 2717a66a18d..4f870564916 100644 +--- src/3rdparty/chromium/third_party/blink/renderer/core/frame/child_frame_compositing_helper.h ++++ src/3rdparty/chromium/third_party/blink/renderer/core/frame/child_frame_compositing_helper.h +@@ -7,6 +7,7 @@ + + #include + ++#include "base/timer/timer.h" + #include "cc/layers/content_layer_client.h" + #include "cc/layers/surface_layer.h" + #include "components/viz/common/surfaces/surface_id.h" +@@ -29,8 +30,12 @@ class CORE_EXPORT ChildFrameCompositingHelper : public cc::ContentLayerClient { + delete; + ~ChildFrameCompositingHelper() override; + +- void SetSurfaceId(const viz::SurfaceId& surface_id, +- bool capture_sequence_number_changed); ++ enum class CaptureSequenceNumberChanged { kYes, kNo }; ++ enum class AllowPaintHolding { kYes, kNo }; ++ void SetSurfaceId( ++ const viz::SurfaceId& surface_id, ++ CaptureSequenceNumberChanged capture_sequence_number_changed, ++ AllowPaintHolding allow_paint_holding); + void UpdateVisibility(bool visible); + void ChildFrameGone(float device_scale_factor); + +@@ -43,10 +48,15 @@ class CORE_EXPORT ChildFrameCompositingHelper : public cc::ContentLayerClient { + scoped_refptr PaintContentsToDisplayList() override; + bool FillsBoundsCompletely() const override; + ++ void MaybeSetUpPaintHolding(const viz::SurfaceId& fallback_id, ++ AllowPaintHolding allow_paint_holding); ++ void PaintHoldingTimerFired(); ++ + ChildFrameCompositor* const child_frame_compositor_; + viz::SurfaceId surface_id_; + scoped_refptr surface_layer_; + scoped_refptr crash_ui_layer_; ++ base::OneShotTimer paint_holding_timer_; + float device_scale_factor_ = 1.f; + }; + +diff --git a/chromium/third_party/blink/renderer/core/frame/child_frame_compositing_helper_test.cc b/chromium/third_party/blink/renderer/core/frame/child_frame_compositing_helper_test.cc +index 47d094c4e8d..cb961013332 100644 +--- src/3rdparty/chromium/third_party/blink/renderer/core/frame/child_frame_compositing_helper_test.cc ++++ src/3rdparty/chromium/third_party/blink/renderer/core/frame/child_frame_compositing_helper_test.cc +@@ -4,6 +4,7 @@ + + #include "third_party/blink/renderer/core/frame/child_frame_compositing_helper.h" + ++#include "base/test/task_environment.h" + #include "cc/layers/layer.h" + #include "testing/gtest/include/gtest/gtest.h" + #include "third_party/blink/renderer/core/frame/child_frame_compositor.h" +@@ -61,6 +62,9 @@ class ChildFrameCompositingHelperTest : public testing::Test { + ChildFrameCompositingHelper* compositing_helper() { + return &compositing_helper_; + } ++ const cc::SurfaceLayer& GetSurfaceLayer() { ++ return *static_cast(compositor_.GetCcLayer().get()); ++ } + + private: + MockChildFrameCompositor compositor_; +@@ -74,7 +78,10 @@ TEST_F(ChildFrameCompositingHelperTest, ChildFrameGoneClearsFallback) { + EXPECT_FALSE(compositing_helper()->surface_id().is_valid()); + + const viz::SurfaceId surface_id = MakeSurfaceId(viz::FrameSinkId(1, 1), 1); +- compositing_helper()->SetSurfaceId(surface_id, false); ++ compositing_helper()->SetSurfaceId( ++ surface_id, ++ ChildFrameCompositingHelper::CaptureSequenceNumberChanged::kNo, ++ ChildFrameCompositingHelper::AllowPaintHolding::kNo); + EXPECT_EQ(surface_id, compositing_helper()->surface_id()); + + // Reporting that the child frame is gone should clear the surface id. +@@ -82,4 +89,33 @@ TEST_F(ChildFrameCompositingHelperTest, ChildFrameGoneClearsFallback) { + EXPECT_FALSE(compositing_helper()->surface_id().is_valid()); + } + ++TEST_F(ChildFrameCompositingHelperTest, PaintHoldingTimeout) { ++ base::test::SingleThreadTaskEnvironment task_environment{ ++ base::test::TaskEnvironment::MainThreadType::UI, ++ base::test::TaskEnvironment::TimeSource::MOCK_TIME}; ++ EXPECT_FALSE(compositing_helper()->surface_id().is_valid()); ++ ++ const viz::SurfaceId surface_id = MakeSurfaceId(viz::FrameSinkId(1, 1), 1); ++ compositing_helper()->SetSurfaceId( ++ surface_id, ++ ChildFrameCompositingHelper::CaptureSequenceNumberChanged::kNo, ++ ChildFrameCompositingHelper::AllowPaintHolding::kNo); ++ EXPECT_EQ(surface_id, GetSurfaceLayer().surface_id()); ++ EXPECT_FALSE(GetSurfaceLayer().oldest_acceptable_fallback()); ++ ++ const viz::SurfaceId new_surface_id = ++ MakeSurfaceId(viz::FrameSinkId(1, 1), 2); ++ compositing_helper()->SetSurfaceId( ++ new_surface_id, ++ ChildFrameCompositingHelper::CaptureSequenceNumberChanged::kNo, ++ ChildFrameCompositingHelper::AllowPaintHolding::kYes); ++ EXPECT_EQ(new_surface_id, GetSurfaceLayer().surface_id()); ++ ASSERT_TRUE(GetSurfaceLayer().oldest_acceptable_fallback()); ++ EXPECT_EQ(surface_id, GetSurfaceLayer().oldest_acceptable_fallback().value()); ++ ++ task_environment.FastForwardUntilNoTasksRemain(); ++ EXPECT_EQ(new_surface_id, GetSurfaceLayer().surface_id()); ++ EXPECT_FALSE(GetSurfaceLayer().oldest_acceptable_fallback()); ++} ++ + } // namespace blink +diff --git a/chromium/third_party/blink/renderer/core/frame/location_report_body.cc b/chromium/third_party/blink/renderer/core/frame/location_report_body.cc +index ccd47126403..6aa5c56f92b 100644 +--- src/3rdparty/chromium/third_party/blink/renderer/core/frame/location_report_body.cc ++++ src/3rdparty/chromium/third_party/blink/renderer/core/frame/location_report_body.cc +@@ -3,7 +3,10 @@ + // found in the LICENSE file. + + #include "third_party/blink/renderer/core/frame/location_report_body.h" ++ ++#include "third_party/blink/public/common/scheme_registry.h" + #include "third_party/blink/renderer/bindings/core/v8/capture_source_location.h" ++#include "third_party/blink/renderer/platform/weborigin/kurl.h" + #include "third_party/blink/renderer/platform/wtf/hash_functions.h" + + namespace blink { +@@ -49,4 +52,16 @@ unsigned LocationReportBody::MatchId() const { + return hash; + } + ++bool LocationReportBody::IsExtensionSource() const { ++ // TODO(crbug.com/356098278): Either remove this KURL instantiation completely ++ // or store `source_file_` as a KURL and only convert to string when sending ++ // reports. ++ KURL source_file_url(source_file_); ++ if (!source_file_url.IsValid()) { ++ return false; ++ } ++ return CommonSchemeRegistry::IsExtensionScheme( ++ source_file_url.Protocol().Utf8()); ++} ++ + } // namespace blink +diff --git a/chromium/third_party/blink/renderer/core/frame/location_report_body.h b/chromium/third_party/blink/renderer/core/frame/location_report_body.h +index dea5e9232f4..8dd27eed8f5 100644 +--- src/3rdparty/chromium/third_party/blink/renderer/core/frame/location_report_body.h ++++ src/3rdparty/chromium/third_party/blink/renderer/core/frame/location_report_body.h +@@ -59,6 +59,8 @@ class CORE_EXPORT LocationReportBody : public ReportBody { + + unsigned MatchId() const override; + ++ bool IsExtensionSource() const override; ++ + protected: + const String source_file_; + const absl::optional line_number_; +diff --git a/chromium/third_party/blink/renderer/core/frame/location_report_body_test.cc b/chromium/third_party/blink/renderer/core/frame/location_report_body_test.cc +index 19eea3f8c71..c5ada318dbc 100644 +--- src/3rdparty/chromium/third_party/blink/renderer/core/frame/location_report_body_test.cc ++++ src/3rdparty/chromium/third_party/blink/renderer/core/frame/location_report_body_test.cc +@@ -8,6 +8,7 @@ + #include + + #include "testing/gtest/include/gtest/gtest.h" ++#include "third_party/blink/public/common/scheme_registry.h" + + namespace blink { + namespace { +@@ -89,5 +90,24 @@ TEST(LocationReportBodyMatchIdTest, + } + } + ++TEST(LocationReportBodyTest, ExtensionURLsAreIdentified) { ++ const char* kExtensionUrl = ++ "chrome-extension://abcdefghijklmnopabcdefghijklmnop/scripts/" ++ "script.js"; ++ const char* kAboutBlankUrl = "about:blank"; ++ const char* kHttpsUrl = "https://example.com/"; ++ ++ EXPECT_FALSE(TestLocationReportBody(kExtensionUrl, 1, 1).IsExtensionSource()); ++ EXPECT_FALSE( ++ TestLocationReportBody(kAboutBlankUrl, 1, 1).IsExtensionSource()); ++ EXPECT_FALSE(TestLocationReportBody(kHttpsUrl, 1, 1).IsExtensionSource()); ++ ++ CommonSchemeRegistry::RegisterURLSchemeAsExtension("chrome-extension"); ++ EXPECT_TRUE(TestLocationReportBody(kExtensionUrl, 1, 1).IsExtensionSource()); ++ EXPECT_FALSE( ++ TestLocationReportBody(kAboutBlankUrl, 1, 1).IsExtensionSource()); ++ EXPECT_FALSE(TestLocationReportBody(kHttpsUrl, 1, 1).IsExtensionSource()); ++} ++ + } // namespace + } // namespace blink +diff --git a/chromium/third_party/blink/renderer/core/frame/remote_frame.cc b/chromium/third_party/blink/renderer/core/frame/remote_frame.cc +index 7f3f457261d..3d744cda68d 100644 +--- src/3rdparty/chromium/third_party/blink/renderer/core/frame/remote_frame.cc ++++ src/3rdparty/chromium/third_party/blink/renderer/core/frame/remote_frame.cc +@@ -28,7 +28,6 @@ + #include "third_party/blink/renderer/core/accessibility/ax_object_cache.h" + #include "third_party/blink/renderer/core/events/message_event.h" + #include "third_party/blink/renderer/core/exported/web_view_impl.h" +-#include "third_party/blink/renderer/core/frame/child_frame_compositing_helper.h" + #include "third_party/blink/renderer/core/frame/local_dom_window.h" + #include "third_party/blink/renderer/core/frame/local_frame.h" + #include "third_party/blink/renderer/core/frame/local_frame_client.h" +@@ -860,7 +859,8 @@ viz::FrameSinkId RemoteFrame::GetFrameSinkId() { + return frame_sink_id_; + } + +-void RemoteFrame::SetFrameSinkId(const viz::FrameSinkId& frame_sink_id) { ++void RemoteFrame::SetFrameSinkId(const viz::FrameSinkId& frame_sink_id, ++ bool allow_paint_holding) { + remote_process_gone_ = false; + + // The same ParentLocalSurfaceIdAllocator cannot provide LocalSurfaceIds for +@@ -873,7 +873,10 @@ void RemoteFrame::SetFrameSinkId(const viz::FrameSinkId& frame_sink_id) { + + // Resend the FrameRects and allocate a new viz::LocalSurfaceId when the view + // changes. +- ResendVisualProperties(); ++ ResendVisualPropertiesInternal( ++ allow_paint_holding ++ ? ChildFrameCompositingHelper::AllowPaintHolding::kYes ++ : ChildFrameCompositingHelper::AllowPaintHolding::kNo); + } + + void RemoteFrame::ChildProcessGone() { +@@ -922,14 +925,18 @@ void RemoteFrame::ApplyReplicatedPermissionsPolicyHeader() { + permissions_policy_header_, container_policy, parent_permissions_policy); + } + +-bool RemoteFrame::SynchronizeVisualProperties(bool propagate) { ++bool RemoteFrame::SynchronizeVisualProperties( ++ bool propagate, ++ ChildFrameCompositingHelper::AllowPaintHolding allow_paint_holding) { + if (!GetFrameSinkId().is_valid() || remote_process_gone_) + return false; + +- bool capture_sequence_number_changed = +- sent_visual_properties_ && +- sent_visual_properties_->capture_sequence_number != +- pending_visual_properties_.capture_sequence_number; ++ auto capture_sequence_number_changed = ++ (sent_visual_properties_ && ++ sent_visual_properties_->capture_sequence_number != ++ pending_visual_properties_.capture_sequence_number) ++ ? ChildFrameCompositingHelper::CaptureSequenceNumberChanged::kYes ++ : ChildFrameCompositingHelper::CaptureSequenceNumberChanged::kNo; + + if (view_) { + pending_visual_properties_.compositor_viewport = +@@ -981,8 +988,8 @@ bool RemoteFrame::SynchronizeVisualProperties(bool propagate) { + DCHECK(surface_id.is_valid()); + DCHECK(!remote_process_gone_); + +- compositing_helper_->SetSurfaceId(surface_id, +- capture_sequence_number_changed); ++ compositing_helper_->SetSurfaceId(surface_id, capture_sequence_number_changed, ++ allow_paint_holding); + + bool rect_changed = !sent_visual_properties_ || + sent_visual_properties_->rect_in_local_root != +@@ -1011,8 +1018,14 @@ void RemoteFrame::RecordSentVisualProperties() { + } + + void RemoteFrame::ResendVisualProperties() { ++ ResendVisualPropertiesInternal( ++ ChildFrameCompositingHelper::AllowPaintHolding::kNo); ++} ++ ++void RemoteFrame::ResendVisualPropertiesInternal( ++ ChildFrameCompositingHelper::AllowPaintHolding allow_paint_holding) { + sent_visual_properties_ = absl::nullopt; +- SynchronizeVisualProperties(); ++ SynchronizeVisualProperties(/*propagate=*/true, allow_paint_holding); + } + + void RemoteFrame::DidUpdateVisualProperties( +diff --git a/chromium/third_party/blink/renderer/core/frame/remote_frame.h b/chromium/third_party/blink/renderer/core/frame/remote_frame.h +index 9585ac3d502..2209822b702 100644 +--- src/3rdparty/chromium/third_party/blink/renderer/core/frame/remote_frame.h ++++ src/3rdparty/chromium/third_party/blink/renderer/core/frame/remote_frame.h +@@ -16,6 +16,7 @@ + #include "third_party/blink/public/mojom/security_context/insecure_request_policy.mojom-blink-forward.h" + #include "third_party/blink/renderer/core/core_export.h" + #include "third_party/blink/renderer/core/execution_context/remote_security_context.h" ++#include "third_party/blink/renderer/core/frame/child_frame_compositing_helper.h" + #include "third_party/blink/renderer/core/frame/child_frame_compositor.h" + #include "third_party/blink/renderer/core/frame/frame.h" + #include "third_party/blink/renderer/core/frame/remote_frame_view.h" +@@ -129,7 +130,13 @@ class CORE_EXPORT RemoteFrame final : public Frame, + void InitializeFrameVisualProperties(const FrameVisualProperties& properties); + // If 'propagate' is true, updated properties will be sent to the browser. + // Returns true if visual properties have changed. +- bool SynchronizeVisualProperties(bool propagate = true); ++ // If 'allow_paint_holding' is yes, the remote frame will display stale paint ++ // (for a timeout) until a frame with the newly synchronized visual properties ++ // has been produced by the child. ++ bool SynchronizeVisualProperties( ++ bool propagate = true, ++ ChildFrameCompositingHelper::AllowPaintHolding allow_paint_holding = ++ ChildFrameCompositingHelper::AllowPaintHolding::kNo); + void ResendVisualProperties(); + void SetViewportIntersection(const mojom::blink::ViewportIntersectionState&); + void UpdateCompositedLayerBounds(); +@@ -208,7 +215,8 @@ class CORE_EXPORT RemoteFrame final : public Frame, + void DisableAutoResize() override; + void DidUpdateVisualProperties( + const cc::RenderFrameMetadata& metadata) override; +- void SetFrameSinkId(const viz::FrameSinkId& frame_sink_id) override; ++ void SetFrameSinkId(const viz::FrameSinkId& frame_sink_id, ++ bool allow_paint_holding) override; + void ChildProcessGone() override; + void CreateRemoteChild( + const RemoteFrameToken& token, +@@ -274,6 +282,9 @@ class CORE_EXPORT RemoteFrame final : public Frame, + void ApplyReplicatedPermissionsPolicyHeader(); + void RecordSentVisualProperties(); + ++ void ResendVisualPropertiesInternal( ++ ChildFrameCompositingHelper::AllowPaintHolding allow_paint_holding); ++ + Member view_; + RemoteSecurityContext security_context_; + absl::optional sent_visual_properties_; +diff --git a/chromium/third_party/blink/renderer/core/frame/report.cc b/chromium/third_party/blink/renderer/core/frame/report.cc +index f854ddfdc18..4106efeba4a 100644 +--- src/3rdparty/chromium/third_party/blink/renderer/core/frame/report.cc ++++ src/3rdparty/chromium/third_party/blink/renderer/core/frame/report.cc +@@ -30,4 +30,11 @@ unsigned Report::MatchId() const { + return hash; + } + ++bool Report::ShouldSendReport() const { ++ // Don't report any URLs from extension code. ++ // TODO(356098278): Investigate whether extension URLs should be reported to ++ // an extension-defined endpoint, if the extension opts in to reporting. ++ return !body()->IsExtensionSource(); ++} ++ + } // namespace blink +diff --git a/chromium/third_party/blink/renderer/core/frame/report.h b/chromium/third_party/blink/renderer/core/frame/report.h +index 2dcc85fe99a..0e97c298e1d 100644 +--- src/3rdparty/chromium/third_party/blink/renderer/core/frame/report.h ++++ src/3rdparty/chromium/third_party/blink/renderer/core/frame/report.h +@@ -50,6 +50,12 @@ class CORE_EXPORT Report : public ScriptWrappable { + // Collision of match id is possible. + unsigned MatchId() const; + ++ // Determines whether this report is allowed to be sent to observers or the ++ // reporting endpoints. This should return false if the report should not be ++ // sent, for example, if the body of the report would reveal private ++ // information, such as extension URLs. ++ bool ShouldSendReport() const; ++ + private: + const String type_; + const String url_; +diff --git a/chromium/third_party/blink/renderer/core/frame/report_body.h b/chromium/third_party/blink/renderer/core/frame/report_body.h +index 73a07fa7355..ea19d190b71 100644 +--- src/3rdparty/chromium/third_party/blink/renderer/core/frame/report_body.h ++++ src/3rdparty/chromium/third_party/blink/renderer/core/frame/report_body.h +@@ -25,6 +25,10 @@ class CORE_EXPORT ReportBody : public ScriptWrappable { + // Provides a hash-like value for identifying reports with same content. + // Collision of match id is possible. + virtual unsigned MatchId() const { return 0; } ++ ++ // Returns true if this report body would contain an extension URL as the ++ // report source. ++ virtual bool IsExtensionSource() const { return false; } + }; + + } // namespace blink +diff --git a/chromium/third_party/blink/renderer/core/frame/report_test.cc b/chromium/third_party/blink/renderer/core/frame/report_test.cc +index 1fbaa2bfa3f..2d14342315a 100644 +--- src/3rdparty/chromium/third_party/blink/renderer/core/frame/report_test.cc ++++ src/3rdparty/chromium/third_party/blink/renderer/core/frame/report_test.cc +@@ -7,6 +7,7 @@ + #include + + #include "testing/gtest/include/gtest/gtest.h" ++#include "third_party/blink/public/common/scheme_registry.h" + #include "third_party/blink/renderer/core/frame/document_policy_violation_report_body.h" + #include "third_party/blink/renderer/core/frame/location_report_body.h" + #include "third_party/blink/renderer/core/frame/permissions_policy_violation_report_body.h" +@@ -87,5 +88,32 @@ TEST(ReportMatchIdTest, MatchIdGeneratedShouldNotBeZero) { + } + } + ++TEST(ReportTest, ExtensionURLsAreNotReported) { ++ CommonSchemeRegistry::RegisterURLSchemeAsExtension("chrome-extension"); ++ EXPECT_TRUE(Report(ReportType::kDocumentPolicyViolation, ++ "https://example.com/", ++ MakeGarbageCollected( ++ "feature", "message", "disposition", ++ "https://example.com/script.js")) ++ .ShouldSendReport()); ++ EXPECT_FALSE(Report(ReportType::kDocumentPolicyViolation, ++ "https://example.com/", ++ MakeGarbageCollected( ++ "feature", "message", "disposition", ++ "chrome-extension://abcdefghijklmnopabcdefghijklmnop/" ++ "scripts/script.js")) ++ .ShouldSendReport()); ++ // This is false for now; all reports from extension scripts are blocked, even ++ // if the report comes from the extension itself. ++ EXPECT_FALSE(Report(ReportType::kDocumentPolicyViolation, ++ "chrome-extension://abcdefghijklmnopabcdefghijklmnop/" ++ "background_page.html", ++ MakeGarbageCollected( ++ "feature", "message", "disposition", ++ "chrome-extension://abcdefghijklmnopabcdefghijklmnop/" ++ "scripts/script.js")) ++ .ShouldSendReport()); ++} ++ + } // namespace + } // namespace blink +diff --git a/chromium/third_party/blink/renderer/core/frame/reporting_context.cc b/chromium/third_party/blink/renderer/core/frame/reporting_context.cc +index dc32fd90d94..c4ade3b35c8 100644 +--- src/3rdparty/chromium/third_party/blink/renderer/core/frame/reporting_context.cc ++++ src/3rdparty/chromium/third_party/blink/renderer/core/frame/reporting_context.cc +@@ -76,6 +76,10 @@ void ReportingContext::Bind( + + void ReportingContext::QueueReport(Report* report, + const Vector& endpoints) { ++ if (!report->ShouldSendReport()) { ++ return; ++ } ++ + CountReport(report); + + NotifyInternal(report); +diff --git a/chromium/third_party/blink/renderer/core/html/parser/html_srcset_parser.cc b/chromium/third_party/blink/renderer/core/html/parser/html_srcset_parser.cc +index 1767d68d92f..06a51f5e1a6 100644 +--- src/3rdparty/chromium/third_party/blink/renderer/core/html/parser/html_srcset_parser.cc ++++ src/3rdparty/chromium/third_party/blink/renderer/core/html/parser/html_srcset_parser.cc +@@ -413,7 +413,7 @@ static unsigned AvoidDownloadIfHigherDensityResourceIsInCache( + KURL url = document->CompleteURL( + StripLeadingAndTrailingHTMLSpaces(image_candidates[i]->Url())); + if (MemoryCache::Get()->ResourceForURL( +- url, document->Fetcher()->GetCacheIdentifier(url)) || ++ url, document->Fetcher()->GetCacheIdentifier(url, /*skip_service_worker=*/false)) || + url.ProtocolIsData()) + return i; + } +diff --git a/chromium/third_party/blink/renderer/core/inspector/inspector_network_agent.cc b/chromium/third_party/blink/renderer/core/inspector/inspector_network_agent.cc +index fb7a567f9f5..e9863d53647 100644 +--- src/3rdparty/chromium/third_party/blink/renderer/core/inspector/inspector_network_agent.cc ++++ src/3rdparty/chromium/third_party/blink/renderer/core/inspector/inspector_network_agent.cc +@@ -2315,7 +2315,8 @@ bool InspectorNetworkAgent::FetchResourceContent(Document* document, + Resource* cached_resource = document->Fetcher()->CachedResource(url); + if (!cached_resource) { + cached_resource = MemoryCache::Get()->ResourceForURL( +- url, document->Fetcher()->GetCacheIdentifier(url)); ++ url, document->Fetcher()->GetCacheIdentifier( ++ url, /*skip_service_worker=*/false)); + } + if (cached_resource && InspectorPageAgent::CachedResourceContent( + cached_resource, content, base64_encoded)) { +diff --git a/chromium/third_party/blink/renderer/core/inspector/inspector_page_agent.cc b/chromium/third_party/blink/renderer/core/inspector/inspector_page_agent.cc +index 0767cdd734f..809aa7ceda5 100644 +--- src/3rdparty/chromium/third_party/blink/renderer/core/inspector/inspector_page_agent.cc ++++ src/3rdparty/chromium/third_party/blink/renderer/core/inspector/inspector_page_agent.cc +@@ -167,7 +167,8 @@ Resource* CachedResource(LocalFrame* frame, + Resource* cached_resource = document->Fetcher()->CachedResource(url); + if (!cached_resource) { + cached_resource = MemoryCache::Get()->ResourceForURL( +- url, document->Fetcher()->GetCacheIdentifier(url)); ++ url, document->Fetcher()->GetCacheIdentifier( ++ url, /*skip_service_worker=*/false)); + } + if (!cached_resource) + cached_resource = loader->ResourceForURL(url); +diff --git a/chromium/third_party/blink/renderer/core/loader/image_loader.cc b/chromium/third_party/blink/renderer/core/loader/image_loader.cc +index c647f154a13..76d72a7bc49 100644 +--- src/3rdparty/chromium/third_party/blink/renderer/core/loader/image_loader.cc ++++ src/3rdparty/chromium/third_party/blink/renderer/core/loader/image_loader.cc +@@ -741,7 +741,8 @@ bool ImageLoader::ShouldLoadImmediately(const KURL& url) const { + // content when style recalc is over and DOM mutation is allowed again. + if (!url.IsNull()) { + Resource* resource = MemoryCache::Get()->ResourceForURL( +- url, element_->GetDocument().Fetcher()->GetCacheIdentifier(url)); ++ url, element_->GetDocument().Fetcher()->GetCacheIdentifier( ++ url, /*skip_service_worker=*/false)); + + if (resource && !resource->ErrorOccurred() && + CanReuseFromListOfAvailableImages( diff --git a/chromium/third_party/blink/renderer/core/loader/modulescript/module_script_loader.cc b/chromium/third_party/blink/renderer/core/loader/modulescript/module_script_loader.cc index e6138a68698..1bd0a69801d 100644 --- src/3rdparty/chromium/third_party/blink/renderer/core/loader/modulescript/module_script_loader.cc +++ src/3rdparty/chromium/third_party/blink/renderer/core/loader/modulescript/module_script_loader.cc @@ -116,11 +116,18 @@ void ModuleScriptLoader::FetchInternal( url_ = module_request.Url(); #endif + DOMWrapperWorld& request_world = modulator_->GetScriptState()->World(); + // Prevents web service workers from intercepting isolated world dynamic + // script imports requests and responding with different contents. + // TODO(crbug.com/1296102): Link to documentation that describes the criteria + // where module imports are handled by service worker fetch handler. + resource_request.SetSkipServiceWorker(request_world.IsIsolatedWorld()); + // ... destination is destination, ... resource_request.SetRequestContext(module_request.ContextType()); resource_request.SetRequestDestination(module_request.Destination()); - ResourceLoaderOptions options(&modulator_->GetScriptState()->World()); + ResourceLoaderOptions options(&request_world); // Set up the module script request given request and // options. diff --git a/chromium/third_party/blink/renderer/core/paint/sparse_vector.h b/chromium/third_party/blink/renderer/core/paint/sparse_vector.h index 983d49f249e..ebc1c2a17bc 100644 --- src/3rdparty/chromium/third_party/blink/renderer/core/paint/sparse_vector.h +++ src/3rdparty/chromium/third_party/blink/renderer/core/paint/sparse_vector.h @@ -108,10 +108,18 @@ class CORE_EXPORT SparseVector { // Then count the total population of field IDs lower than that one we // are looking for. The target field ID should be located at the index of // of the total population. -#ifdef _MSC_VER - return __popcnt(fields_bitfield_ & mask); -#else +#if defined(__GNUC__) || defined(__clang__) return __builtin_popcount(fields_bitfield_ & mask); +#elif _MSVC_LANG >= 202002L // C++20 + return std::popcount(fields_bitfield_ & mask); +#else + uint32_t v = (fields_bitfield_ & mask); + uint32_t c = v - ((v >> 1) & 0x55555555); + c = ((c >> 2) & 0x33333333) + (c & 0x33333333); + c = ((c >> 4) + c) & 0x0F0F0F0F; + c = ((c >> 8) + c) & 0x00FF00FF; + c = ((c >> 16) + c) & 0x0000FFFF; + return c; #endif } +diff --git a/chromium/third_party/blink/renderer/core/testing/internals.cc b/chromium/third_party/blink/renderer/core/testing/internals.cc +index e3bda97e583..a56b6d8fbb3 100644 +--- src/3rdparty/chromium/third_party/blink/renderer/core/testing/internals.cc ++++ src/3rdparty/chromium/third_party/blink/renderer/core/testing/internals.cc +@@ -883,8 +883,8 @@ bool Internals::isLoading(const String& url) { + if (!document_) + return false; + const KURL full_url = document_->CompleteURL(url); +- const String cache_identifier = +- document_->Fetcher()->GetCacheIdentifier(full_url); ++ const String cache_identifier = document_->Fetcher()->GetCacheIdentifier( ++ full_url, /*skip_service_worker=*/false); + Resource* resource = + MemoryCache::Get()->ResourceForURL(full_url, cache_identifier); + // We check loader() here instead of isLoading(), because a multipart +@@ -896,8 +896,8 @@ bool Internals::isLoadingFromMemoryCache(const String& url) { + if (!document_) + return false; + const KURL full_url = document_->CompleteURL(url); +- const String cache_identifier = +- document_->Fetcher()->GetCacheIdentifier(full_url); ++ const String cache_identifier = document_->Fetcher()->GetCacheIdentifier( ++ full_url, /*skip_service_worker=*/false); + Resource* resource = + MemoryCache::Get()->ResourceForURL(full_url, cache_identifier); + return resource && resource->GetStatus() == ResourceStatus::kCached; diff --git a/chromium/third_party/blink/renderer/modules/serial/serial_port_underlying_sink.cc b/chromium/third_party/blink/renderer/modules/serial/serial_port_underlying_sink.cc index 136f27f1ab0..97bb637e329 100644 --- src/3rdparty/chromium/third_party/blink/renderer/modules/serial/serial_port_underlying_sink.cc +++ src/3rdparty/chromium/third_party/blink/renderer/modules/serial/serial_port_underlying_sink.cc @@ -266,4 +266,10 @@ void SerialPortUnderlyingSink::PipeClosed() { abort_handle_.Clear(); } +void SerialPortUnderlyingSink::Dispose() { + // Ensure that `watcher_` is disarmed so that `OnHandleReady()` is not called + // after this object becomes garbage. + PipeClosed(); +} + } // namespace blink diff --git a/chromium/third_party/blink/renderer/modules/serial/serial_port_underlying_sink.h b/chromium/third_party/blink/renderer/modules/serial/serial_port_underlying_sink.h index 0b2070f01aa..a3ff78fc45c 100644 --- src/3rdparty/chromium/third_party/blink/renderer/modules/serial/serial_port_underlying_sink.h +++ src/3rdparty/chromium/third_party/blink/renderer/modules/serial/serial_port_underlying_sink.h @@ -20,6 +20,8 @@ class SerialPort; class WritableStreamDefaultController; class SerialPortUnderlyingSink final : public UnderlyingSinkBase { + USING_PRE_FINALIZER(SerialPortUnderlyingSink, Dispose); + public: SerialPortUnderlyingSink(SerialPort*, mojo::ScopedDataPipeProducerHandle); @@ -46,6 +48,7 @@ class SerialPortUnderlyingSink final : public UnderlyingSinkBase { void OnFlushOrDrain(); void WriteData(); void PipeClosed(); + void Dispose(); mojo::ScopedDataPipeProducerHandle data_pipe_; mojo::SimpleWatcher watcher_; diff --git a/chromium/third_party/blink/renderer/modules/serial/serial_port_underlying_source.cc b/chromium/third_party/blink/renderer/modules/serial/serial_port_underlying_source.cc index 1f4440001bf..c7d17260ddb 100644 --- src/3rdparty/chromium/third_party/blink/renderer/modules/serial/serial_port_underlying_source.cc +++ src/3rdparty/chromium/third_party/blink/renderer/modules/serial/serial_port_underlying_source.cc @@ -225,4 +225,10 @@ void SerialPortUnderlyingSource::Close() { data_pipe_.reset(); } +void SerialPortUnderlyingSource::Dispose() { + // Ensure that `watcher_` is disarmed so that `OnHandleReady()` is not called + // after this object becomes garbage. + Close(); +} + } // namespace blink diff --git a/chromium/third_party/blink/renderer/modules/serial/serial_port_underlying_source.h b/chromium/third_party/blink/renderer/modules/serial/serial_port_underlying_source.h index 2ca0f471f54..eed40684716 100644 --- src/3rdparty/chromium/third_party/blink/renderer/modules/serial/serial_port_underlying_source.h +++ src/3rdparty/chromium/third_party/blink/renderer/modules/serial/serial_port_underlying_source.h @@ -11,6 +11,7 @@ #include "third_party/blink/renderer/bindings/core/v8/script_value.h" #include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h" #include "third_party/blink/renderer/core/streams/underlying_byte_source_base.h" +#include "third_party/blink/renderer/platform/heap/prefinalizer.h" namespace blink { @@ -20,6 +21,8 @@ class SerialPort; class SerialPortUnderlyingSource : public UnderlyingByteSourceBase, ExecutionContextLifecycleObserver { + USING_PRE_FINALIZER(SerialPortUnderlyingSource, Dispose); + public: SerialPortUnderlyingSource(ScriptState*, SerialPort*, @@ -46,6 +49,7 @@ class SerialPortUnderlyingSource : public UnderlyingByteSourceBase, void OnFlush(ScriptPromiseResolver*); void PipeClosed(); void Close(); + void Dispose(); // TODO(crbug.com/1457493) : Remove when debugging is done. MojoResult invalid_data_pipe_read_result_ = MOJO_RESULT_OK; +diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc +index 5bfbe590f32..248c049c62c 100644 +--- src/3rdparty/chromium/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc ++++ src/3rdparty/chromium/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc +@@ -860,7 +860,8 @@ Resource* ResourceFetcher::CreateResourceForStaticData( + if (!archive_ && factory.GetType() == ResourceType::kRaw) + return nullptr; + +- const String cache_identifier = GetCacheIdentifier(url); ++ const String cache_identifier = GetCacheIdentifier( ++ url, params.GetResourceRequest().GetSkipServiceWorker()); + // Most off-main-thread resource fetches use Resource::kRaw and don't reach + // this point, but off-main-thread module fetches might. + if (IsMainThread()) { +@@ -1347,7 +1348,10 @@ Resource* ResourceFetcher::RequestResource(FetchParameters& params, + resource = nullptr; + } else { + resource = MemoryCache::Get()->ResourceForURL( +- params.Url(), GetCacheIdentifier(params.Url())); ++ params.Url(), ++ GetCacheIdentifier( ++ params.Url(), ++ params.GetResourceRequest().GetSkipServiceWorker())); + } + if (resource) { + policy = DetermineRevalidationPolicy(resource_type, params, *resource, +@@ -1604,7 +1608,8 @@ Resource* ResourceFetcher::CreateResourceForLoading( + const FetchParameters& params, + const ResourceFactory& factory) { + const String cache_identifier = +- GetCacheIdentifier(params.GetResourceRequest().Url()); ++ GetCacheIdentifier(params.GetResourceRequest().Url(), ++ params.GetResourceRequest().GetSkipServiceWorker()); + if (!base::FeatureList::IsEnabled( + blink::features::kScopeMemoryCachePerContext)) { + DCHECK(!IsMainThread() || params.IsStaleRevalidation() || +@@ -2605,9 +2610,11 @@ void ResourceFetcher::UpdateAllImageResourcePriorities() { + to_be_removed.clear(); + } + +-String ResourceFetcher::GetCacheIdentifier(const KURL& url) const { +- if (properties_->GetControllerServiceWorkerMode() != +- mojom::ControllerServiceWorkerMode::kNoController) { ++String ResourceFetcher::GetCacheIdentifier(const KURL& url, ++ bool skip_service_worker) const { ++ if (!skip_service_worker && ++ properties_->GetControllerServiceWorkerMode() != ++ mojom::ControllerServiceWorkerMode::kNoController) { + return String::Number(properties_->ServiceWorkerId()); + } + +diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h +index c437d854203..31e9774c178 100644 +--- src/3rdparty/chromium/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h ++++ src/3rdparty/chromium/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h +@@ -260,7 +260,11 @@ class PLATFORM_EXPORT ResourceFetcher + uint32_t inflight_keepalive_bytes); + blink::mojom::ControllerServiceWorkerMode IsControlledByServiceWorker() const; + +- String GetCacheIdentifier(const KURL& url) const; ++ // Returns a cache identifier for MemoryCache. ++ // `url` is used for finding a matching WebBundle. ++ // If `skip_service_worker` is true, the identifier won't be a ServiceWorker's ++ // identifier to keep the cache separated. ++ String GetCacheIdentifier(const KURL& url, bool skip_service_worker) const; + + // If `url` exists as a resource in a subresource bundle in this frame, + // returns its UnguessableToken; otherwise, returns absl::nullopt. +diff --git a/chromium/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/chromium/third_party/blink/renderer/platform/runtime_enabled_features.json5 +index c8c9459fad4..ff8dbd47b82 100644 +--- src/3rdparty/chromium/third_party/blink/renderer/platform/runtime_enabled_features.json5 ++++ src/3rdparty/chromium/third_party/blink/renderer/platform/runtime_enabled_features.json5 +@@ -2749,6 +2749,10 @@ + base_feature: "none", + settable_from_internals: true, + }, ++ { ++ name: "PaintHoldingForIframes", ++ status: "test", ++ }, + { + // PARAKEET ad serving runtime flag/JS API. + name: "Parakeet", +diff --git a/chromium/third_party/dawn/src/tint/lang/wgsl/ast/transform/packed_vec3.cc b/chromium/third_party/dawn/src/tint/lang/wgsl/ast/transform/packed_vec3.cc +index c6f47805657..53ac72c89fb 100644 +--- src/3rdparty/chromium/third_party/dawn/src/tint/lang/wgsl/ast/transform/packed_vec3.cc ++++ src/3rdparty/chromium/third_party/dawn/src/tint/lang/wgsl/ast/transform/packed_vec3.cc +@@ -66,6 +66,14 @@ struct PackedVec3::State { + /// A map from type to the name of a helper function used to unpack that type. + Hashmap unpack_helpers; + ++ /// @returns true if @p addrspace requires vec3 types to be packed ++ bool AddressSpaceNeedsPacking(core::AddressSpace addrspace) { ++ // Host-shareable address spaces need to be packed to match the memory layout on the host. ++ // The workgroup address space needs to be packed so that the size of generated threadgroup ++ // variables matches the size of the original WGSL declarations. ++ return core::IsHostShareable(addrspace) || addrspace == core::AddressSpace::kWorkgroup; ++ } ++ + /// @param ty the type to test + /// @returns true if `ty` is a vec3, false otherwise + bool IsVec3(const core::type::Type* ty) { +@@ -342,7 +350,7 @@ struct PackedVec3::State { + // if the transform is necessary. + for (auto* decl : src->AST().GlobalVariables()) { + auto* var = sem.Get(decl); +- if (var && core::IsHostShareable(var->AddressSpace()) && ++ if (var && AddressSpaceNeedsPacking(var->AddressSpace()) && + ContainsVec3(var->Type()->UnwrapRef())) { + return true; + } +@@ -379,7 +387,7 @@ struct PackedVec3::State { + [&](const sem::TypeExpression* type) { + // Rewrite pointers to types that contain vec3s. + auto* ptr = type->Type()->As(); +- if (ptr && core::IsHostShareable(ptr->AddressSpace())) { ++ if (ptr && AddressSpaceNeedsPacking(ptr->AddressSpace())) { + auto new_store_type = RewriteType(ptr->StoreType()); + if (new_store_type) { + auto access = ptr->AddressSpace() == core::AddressSpace::kStorage +@@ -392,7 +400,7 @@ struct PackedVec3::State { + } + }, + [&](const sem::Variable* var) { +- if (!core::IsHostShareable(var->AddressSpace())) { ++ if (!AddressSpaceNeedsPacking(var->AddressSpace())) { + return; + } + +@@ -408,7 +416,7 @@ struct PackedVec3::State { + auto* lhs = sem.GetVal(assign->lhs); + auto* rhs = sem.GetVal(assign->rhs); + if (!ContainsVec3(rhs->Type()) || +- !core::IsHostShareable( ++ !AddressSpaceNeedsPacking( + lhs->Type()->As()->AddressSpace())) { + // Skip assignments to address spaces that are not host-shareable, or + // that do not contain vec3 types. +@@ -436,7 +444,7 @@ struct PackedVec3::State { + [&](const sem::Load* load) { + // Unpack loads of types that contain vec3s in host-shareable address spaces. + if (ContainsVec3(load->Type()) && +- core::IsHostShareable(load->ReferenceType()->AddressSpace())) { ++ AddressSpaceNeedsPacking(load->ReferenceType()->AddressSpace())) { + to_unpack.Add(load); + } + }, +@@ -446,7 +454,7 @@ struct PackedVec3::State { + // struct. + if (auto* ref = accessor->Type()->As()) { + if (IsVec3(ref->StoreType()) && +- core::IsHostShareable(ref->AddressSpace())) { ++ AddressSpaceNeedsPacking(ref->AddressSpace())) { + ctx.Replace(node, b.MemberAccessor(ctx.Clone(accessor->Declaration()), + kStructMemberName)); + } diff --git a/chromium/third_party/dawn/src/tint/lang/wgsl/resolver/validator.cc b/chromium/third_party/dawn/src/tint/lang/wgsl/resolver/validator.cc -index 42f7e840d1d..78e83769803 100644 +index 42f7e840d1d..f15bb8095f4 100644 --- src/3rdparty/chromium/third_party/dawn/src/tint/lang/wgsl/resolver/validator.cc +++ src/3rdparty/chromium/third_party/dawn/src/tint/lang/wgsl/resolver/validator.cc -@@ -518,6 +518,22 @@ bool Validator::AddressSpaceLayout(const core::type::Type* store_ty, +@@ -438,10 +438,6 @@ bool Validator::AddressSpaceLayout(const core::type::Type* store_ty, + return true; + } + +- if (!core::IsHostShareable(address_space)) { +- return true; +- } +- + auto note_usage = [&] { + AddNote("'" + store_ty->FriendlyName() + "' used in address space '" + + tint::ToString(address_space) + "' here", +@@ -518,6 +514,22 @@ bool Validator::AddressSpaceLayout(const core::type::Type* store_ty, return false; } } + + // If an alignment was explicitly specified, we need to validate that it satisfies the + // alignment requirement of the address space. + auto* align_attr = + ast::GetAttribute(m->Declaration()->attributes); + if (align_attr && !enabled_extensions_.Contains( + wgsl::Extension::kChromiumInternalRelaxedUniformLayout)) { + auto align = sem_.GetVal(align_attr->expr)->ConstantValue()->ValueAs(); + if (align % required_align != 0) { + AddError(align_attr->expr->source) + << "alignment must be a multiple of " << style::Literal(required_align) + << " bytes for the " << style::Enum(address_space) << " address space"; + note_usage(); + return false; + } + } } } diff --git a/chromium/third_party/dawn/third_party/dxc/lib/Transforms/Scalar/DxilConditionalMem2Reg.cpp b/chromium/third_party/dawn/third_party/dxc/lib/Transforms/Scalar/DxilConditionalMem2Reg.cpp index 79a250de94f..026d2aacd0c 100644 --- src/3rdparty/chromium/third_party/dawn/third_party/dxc/lib/Transforms/Scalar/DxilConditionalMem2Reg.cpp +++ src/3rdparty/chromium/third_party/dawn/third_party/dxc/lib/Transforms/Scalar/DxilConditionalMem2Reg.cpp @@ -257,14 +257,17 @@ class DxilConditionalMem2Reg : public FunctionPass { static bool ScalarizePreciseVectorAlloca(Function &F) { BasicBlock *Entry = &*F.begin(); - bool Changed = false; + SmallVector PreciseAllocaInsts; for (auto it = Entry->begin(); it != Entry->end();) { Instruction *I = &*(it++); AllocaInst *AI = dyn_cast(I); if (!AI || !AI->getAllocatedType()->isVectorTy()) continue; if (!HLModule::HasPreciseAttributeWithMetadata(AI)) continue; + PreciseAllocaInsts.push_back(AI); + } - + bool Changed = false; + for (auto AI : PreciseAllocaInsts) { IRBuilder<> B(AI); VectorType *VTy = cast(AI->getAllocatedType()); Type *ScalarTy = VTy->getVectorElementType(); diff --git a/chromium/third_party/devtools-frontend/src/front_end/panels/network/NetworkLogView.ts b/chromium/third_party/devtools-frontend/src/front_end/panels/network/NetworkLogView.ts index f2cc8ca2ef3..73d6e02d1fe 100644 --- src/3rdparty/chromium/third_party/devtools-frontend/src/front_end/panels/network/NetworkLogView.ts +++ src/3rdparty/chromium/third_party/devtools-frontend/src/front_end/panels/network/NetworkLogView.ts @@ -2184,8 +2184,7 @@ export class NetworkLogView extends Common.ObjectWrapper.eventMixin(['accept-encoding', 'host', 'method', 'path', 'scheme', 'version']); function escapeStringWin(str: string): string { - /* If there are no new line characters do not escape the " characters - since it only uglifies the command. + /* Always escape the " characters so that we can use caret escaping. Because cmd.exe parser and MS Crt arguments parsers use some of the same escape characters, they can interact with each other in @@ -2211,11 +2210,11 @@ export class NetworkLogView extends Common.ObjectWrapper.eventMixinm_errorCode = XML_ERROR_INVALID_ARGUMENT; + return XML_STATUS_ERROR; + } + switch (parser->m_parsingStatus.parsing) { case XML_SUSPENDED: parser->m_errorCode = XML_ERROR_SUSPENDED; @@ -6886,6 +6892,16 @@ dtdCopy(XML_Parser oldParser, DTD *newDtd, const DTD *oldDtd, if (! newE) return 0; if (oldE->nDefaultAtts) { + /* Detect and prevent integer overflow. + * The preprocessor guard addresses the "always false" warning + * from -Wtype-limits on platforms where + * sizeof(int) < sizeof(size_t), e.g. on x86_64. */ +#if UINT_MAX >= SIZE_MAX + if ((size_t)oldE->nDefaultAtts + > ((size_t)(-1) / sizeof(DEFAULT_ATTRIBUTE))) { + return 0; + } +#endif newE->defaultAtts = ms->malloc_fcn(oldE->nDefaultAtts * sizeof(DEFAULT_ATTRIBUTE)); if (! newE->defaultAtts) { @@ -7428,6 +7444,15 @@ nextScaffoldPart(XML_Parser parser) { int next; if (! dtd->scaffIndex) { + /* Detect and prevent integer overflow. + * The preprocessor guard addresses the "always false" warning + * from -Wtype-limits on platforms where + * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */ +#if UINT_MAX >= SIZE_MAX + if (parser->m_groupSize > ((size_t)(-1) / sizeof(int))) { + return -1; + } +#endif dtd->scaffIndex = (int *)MALLOC(parser, parser->m_groupSize * sizeof(int)); if (! dtd->scaffIndex) return -1; diff --git a/chromium/third_party/ipcz/src/ipcz/node_link.cc b/chromium/third_party/ipcz/src/ipcz/node_link.cc index 2fe981a9a2e..fc7b186eda0 100644 --- src/3rdparty/chromium/third_party/ipcz/src/ipcz/node_link.cc +++ src/3rdparty/chromium/third_party/ipcz/src/ipcz/node_link.cc @@ -36,21 +36,6 @@ namespace ipcz { -namespace { - -template -FragmentRef MaybeAdoptFragmentRef(NodeLinkMemory& memory, - const FragmentDescriptor& descriptor) { - if (descriptor.is_null() || descriptor.size() < sizeof(T) || - descriptor.offset() % 8 != 0) { - return {}; - } - - return memory.AdoptFragmentRef(memory.GetFragment(descriptor)); -} - -} // namespace - // static Ref NodeLink::CreateActive(Ref node, LinkSide link_side, @@ -702,8 +687,8 @@ bool NodeLink::OnAcceptBypassLink(msg::AcceptBypassLink& accept) { return true; } - auto link_state = MaybeAdoptFragmentRef( - memory(), accept.params().new_link_state_fragment); + auto link_state = memory().AdoptFragmentRefIfValid( + accept.params().new_link_state_fragment); if (link_state.is_null()) { // Bypass links must always come with a valid fragment for their // RouterLinkState. If one has not been provided, that's a validation @@ -745,8 +730,8 @@ bool NodeLink::OnBypassPeerWithLink(msg::BypassPeerWithLink& bypass) { return true; } - auto link_state = MaybeAdoptFragmentRef( - memory(), bypass.params().new_link_state_fragment); + auto link_state = memory().AdoptFragmentRefIfValid( + bypass.params().new_link_state_fragment); if (link_state.is_null()) { return false; } diff --git a/chromium/third_party/ipcz/src/ipcz/node_link_memory.h b/chromium/third_party/ipcz/src/ipcz/node_link_memory.h index df8010b595f..ba04a7c03da 100644 --- src/3rdparty/chromium/third_party/ipcz/src/ipcz/node_link_memory.h +++ src/3rdparty/chromium/third_party/ipcz/src/ipcz/node_link_memory.h @@ -86,14 +86,29 @@ class NodeLinkMemory : public RefCounted { // with the same BufferId and dimensions as `descriptor`. Fragment GetFragment(const FragmentDescriptor& descriptor); - // Adopts an existing reference to a RefCountedFragment within `fragment`. - // This does NOT increment the ref count of the RefCountedFragment. + // Adopts an existing reference to a RefCountedFragment within `fragment`, + // which must be a valid, properly aligned, and sufficiently sized fragment to + // hold a T. This does NOT increment the ref count of the RefCountedFragment. template FragmentRef AdoptFragmentRef(const Fragment& fragment) { ABSL_ASSERT(sizeof(T) <= fragment.size()); return FragmentRef(kAdoptExistingRef, WrapRefCounted(this), fragment); } + // Attempts to adopt an existing reference to a RefCountedFragment located at + // `fragment`. Returns null if the fragment descriptor is null, misaligned, + // or of insufficient size. This does NOT increment the ref count of the + // RefCountedFragment. + template + FragmentRef AdoptFragmentRefIfValid(const FragmentDescriptor& descriptor) { + if (descriptor.is_null() || descriptor.size() < sizeof(T) || + descriptor.offset() % 8 != 0) { + return {}; + } + + return AdoptFragmentRef(GetFragment(descriptor)); + } + // Adds a new buffer to the underlying BufferPool to use as additional // allocation capacity for blocks of size `block_size`. Note that the // contents of the mapped region must already be initialized as a diff --git a/chromium/third_party/ipcz/src/ipcz/router.cc b/chromium/third_party/ipcz/src/ipcz/router.cc index 09988c04fe9..45ab0135459 100644 --- src/3rdparty/chromium/third_party/ipcz/src/ipcz/router.cc +++ src/3rdparty/chromium/third_party/ipcz/src/ipcz/router.cc @@ -764,12 +764,17 @@ Ref Router::Deserialize(const RouterDescriptor& descriptor, ? descriptor.decaying_incoming_sequence_length : descriptor.next_incoming_sequence_number); + auto link_state = + from_node_link.memory().AdoptFragmentRefIfValid( + descriptor.new_link_state_fragment); + if (link_state.is_null()) { + // Central links require a valid link state fragment. + return nullptr; + } new_outward_link = from_node_link.AddRemoteRouterLink( context, descriptor.new_sublink, - from_node_link.memory().AdoptFragmentRef( - from_node_link.memory().GetFragment( - descriptor.new_link_state_fragment)), - LinkType::kCentral, LinkSide::kB, router); + std::move(link_state), LinkType::kCentral, + LinkSide::kB, router); if (!new_outward_link) { return nullptr; } diff --git a/chromium/third_party/perfetto/include/perfetto/base/compiler.h b/chromium/third_party/perfetto/include/perfetto/base/compiler.h index 85678cc768c..ae7bf0aa10a 100644 --- src/3rdparty/chromium/third_party/perfetto/include/perfetto/base/compiler.h +++ src/3rdparty/chromium/third_party/perfetto/include/perfetto/base/compiler.h @@ -76,9 +76,31 @@ #if defined(__GNUC__) || defined(__clang__) #define PERFETTO_POPCOUNT(x) __builtin_popcountll(x) -#else +#elif defined(__AVX__) || defined(__SSE4_2__) || defined(__POPCNT__) #include #define PERFETTO_POPCOUNT(x) __popcnt64(x) +#else +#if _MSVC_LANG >= 202002L || (__cplusplus > 201703L && __has_include()) // C++20 +#include +#endif +template , int> = 0> +inline uint32_t qPopulationCount(ValueType v) noexcept +{ +#if defined(__cpp_lib_bitops) + return std::popcount(v); +#else + // we static_cast these bit patterns in order to truncate them to the correct size + v = static_cast(v - ((v >> 1) & static_cast(0x5555'5555'5555'5555ull))); + v = static_cast((v & static_cast(0x3333'3333'3333'3333ull)) + + ((v >> 2) & static_cast(0x3333'3333'3333'3333ull))); + v = static_cast((v + (v >> 4)) & static_cast(0x0F0F'0F0F'0F0F'0F0Full)); + // Multiply by one in each byte, so that it will have the sum of all source bytes in the highest byte + v = static_cast(v * static_cast(0x0101'0101'0101'0101ull)); + // Extract highest byte + return static_cast(v >> (sizeof(ValueType) * CHAR_BIT - 8)); +#endif +} +#define PERFETTO_POPCOUNT(x) qPopulationCount(x) #endif #if defined(__clang__) diff --git a/chromium/third_party/skia/src/gpu/ganesh/ops/DrawAtlasOp.cpp b/chromium/third_party/skia/src/gpu/ganesh/ops/DrawAtlasOp.cpp index a3d7e4ddabb..7faa16de5df 100644 --- src/3rdparty/chromium/third_party/skia/src/gpu/ganesh/ops/DrawAtlasOp.cpp +++ src/3rdparty/chromium/third_party/skia/src/gpu/ganesh/ops/DrawAtlasOp.cpp @@ -112,6 +112,7 @@ DrawAtlasOpImpl::DrawAtlasOpImpl(GrProcessorSet* processorSet, const SkPMColor4f : GrMeshDrawOp(ClassID()), fHelper(processorSet, aaType), fColor(color) { SkASSERT(xforms); SkASSERT(rects); + SkASSERT(spriteCount >= 0); fViewMatrix = viewMatrix; Geometry& installedGeo = fGeoData.push_back(); @@ -127,6 +128,11 @@ DrawAtlasOpImpl::DrawAtlasOpImpl(GrProcessorSet* processorSet, const SkPMColor4f vertexStride += sizeof(GrColor); } + // Bail out if we'd overflow from a really large draw + if (spriteCount > SK_MaxS32 / static_cast(4 * vertexStride)) { + return; + } + // Compute buffer size and alloc buffer fQuadCount = spriteCount; int allocSize = static_cast(4 * vertexStride * spriteCount); diff --git a/chromium/third_party/webrtc/modules/desktop_capture/mac/screen_capturer_mac.mm b/chromium/third_party/webrtc/modules/desktop_capture/mac/screen_capturer_mac.mm index 8f0c68d48b4..1cf029186b0 100644 --- src/3rdparty/chromium/third_party/webrtc/modules/desktop_capture/mac/screen_capturer_mac.mm +++ src/3rdparty/chromium/third_party/webrtc/modules/desktop_capture/mac/screen_capturer_mac.mm @@ -20,6 +20,11 @@ #include "rtc_base/trace_event.h" #include "sdk/objc/helpers/scoped_cftyperef.h" +// Build fix for macOS SDK 15 and newer +#if !defined(CG_AVAILABLE_BUT_DEPRECATED) +#define CG_AVAILABLE_BUT_DEPRECATED(a,b,c) +#endif + // All these symbols have incorrect availability annotations in the 13.3 SDK. // These have the correct annotation. See https://crbug.com/1431897. // TODO(thakis): Remove this once FB12109479 is fixed and we updated to an SDK +diff --git a/chromium/ui/views/views_features.cc b/chromium/ui/views/views_features.cc +index 9c296ba65e0..2641a68539b 100644 +--- src/3rdparty/chromium/ui/views/views_features.cc ++++ src/3rdparty/chromium/ui/views/views_features.cc +@@ -17,6 +17,14 @@ BASE_FEATURE(kEnablePlatformHighContrastInkDrop, + "EnablePlatformHighContrastInkDrop", + base::FEATURE_DISABLED_BY_DEFAULT); + ++// Handle mouse cursor being out sync with a touch drag operation. If mouse ++// cursor is over different window, drag will not start, and cursor will be ++// moved to the window where the touch drag started. This is a kill switch ++// for this new logic, crbug.com/370856871. ++BASE_FEATURE(kEnableTouchDragCursorSync, ++ "EnableTouchDragCursorSync", ++ base::FEATURE_ENABLED_BY_DEFAULT); ++ + // Only paint views that are invalidated/dirty (i.e. a paint was directly + // scheduled on those views) as opposed to painting all views that intersect + // an invalid rectangle on the layer. +diff --git a/chromium/ui/views/views_features.h b/chromium/ui/views/views_features.h +index 3aa4134a57b..682a2cec4df 100644 +--- src/3rdparty/chromium/ui/views/views_features.h ++++ src/3rdparty/chromium/ui/views/views_features.h +@@ -13,6 +13,7 @@ namespace views::features { + + // Please keep alphabetized. + VIEWS_EXPORT BASE_DECLARE_FEATURE(kEnablePlatformHighContrastInkDrop); ++VIEWS_EXPORT BASE_DECLARE_FEATURE(kEnableTouchDragCursorSync); + VIEWS_EXPORT BASE_DECLARE_FEATURE(kEnableViewPaintOptimization); + VIEWS_EXPORT BASE_DECLARE_FEATURE(kWidgetLayering); + +diff --git a/chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_win.cc b/chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_win.cc +index da61095385f..450530b6058 100644 +--- src/3rdparty/chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_win.cc ++++ src/3rdparty/chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_win.cc +@@ -8,6 +8,7 @@ + + #include "base/metrics/histogram_macros.h" + #include "base/threading/hang_watcher.h" ++#include "ui/aura/env.h" + #include "ui/base/dragdrop/drag_drop_types.h" + #include "ui/base/dragdrop/drag_source_win.h" + #include "ui/base/dragdrop/drop_target_event.h" +@@ -15,6 +16,7 @@ + #include "ui/base/dragdrop/os_exchange_data_provider_win.h" + #include "ui/base/win/event_creation_utils.h" + #include "ui/display/win/screen_win.h" ++#include "ui/views/views_features.h" + #include "ui/views/widget/desktop_aura/desktop_drop_target_win.h" + #include "ui/views/widget/desktop_aura/desktop_window_tree_host_win.h" + +@@ -42,12 +44,34 @@ ui::mojom::DragOperation DesktopDragDropClientWin::StartDragAndDrop( + const gfx::Point& screen_location, + int allowed_operations, + ui::mojom::DragEventSource source) { +- drag_drop_in_progress_ = true; + gfx::Point touch_screen_point; + if (source == ui::mojom::DragEventSource::kTouch) { ++ display::Screen* screen = display::Screen::GetScreen(); ++ CHECK(screen); ++ aura::Window* window = ++ screen->GetWindowAtScreenPoint(screen->GetCursorScreenPoint()); + touch_screen_point = + screen_location + source_window->GetBoundsInScreen().OffsetFromOrigin(); + source_window->GetHost()->ConvertDIPToPixels(&touch_screen_point); ++ bool touch_down = aura::Env::GetInstance()->is_touch_down(); ++ bool touch_over_other_window = ++ !window || window->GetRootWindow() != root_window; ++ bool touch_drag_cursor_sync = ++ base::FeatureList::IsEnabled(features::kEnableTouchDragCursorSync); ++ // If attempting to start a touch drag with the cursor over another window, ++ // move cursor to this window so the next drag attempt will succeed. ++ // TODO(crbug.com/40312079): Mouse cursor needs to follow long press touch ++ // events for this to be smoother, but ::SetCursorPos needs to be called ++ // well before calling ::DoDragDrop. ++ if (touch_drag_cursor_sync && touch_down && touch_over_other_window) { ++ ::SetCursorPos(touch_screen_point.x(), touch_screen_point.y()); ++ } ++ // Check that the cursor is over the window being dragged from. If not, ++ // don't start the drag because ::DoDragDrop will not do the drag. ++ if (touch_drag_cursor_sync && (!touch_down || touch_over_other_window)) { ++ return ui::PreferredDragOperation( ++ ui::DragDropTypes::DropEffectToDragOperation(DROPEFFECT_NONE)); ++ } + desktop_host_->StartTouchDrag(touch_screen_point); + // Gesture state gets left in a state where you can't start + // another drag, unless it's cleaned up. Cleaning it up before starting +@@ -57,6 +81,7 @@ ui::mojom::DragOperation DesktopDragDropClientWin::StartDragAndDrop( + } + base::WeakPtr alive(weak_factory_.GetWeakPtr()); + ++ drag_drop_in_progress_ = true; + drag_source_ = ui::DragSourceWin::Create(); + Microsoft::WRL::ComPtr drag_source_copy = drag_source_; + drag_source_copy->set_data(data.get()); +diff --git a/chromium/ui/views/widget/root_view.cc b/chromium/ui/views/widget/root_view.cc +index ace679c7cc9..1dd799a55c2 100644 +--- src/3rdparty/chromium/ui/views/widget/root_view.cc ++++ src/3rdparty/chromium/ui/views/widget/root_view.cc +@@ -60,37 +60,6 @@ class MouseEnterExitEvent : public ui::MouseEvent { + } + }; + +-// TODO(crbug.com/1295290): This class is for debug purpose only. +-// Remove it after resolving the issue. +-class DanglingMouseMoveHandlerOnViewDestroyingChecker +- : public views::ViewObserver { +- public: +- explicit DanglingMouseMoveHandlerOnViewDestroyingChecker( +- const raw_ptr& +- mouse_move_handler) +- : mouse_move_handler_(mouse_move_handler) { +- scoped_observation.Observe(mouse_move_handler_); +- } +- +- // views::ViewObserver: +- void OnViewIsDeleting(views::View* view) override { +- // `mouse_move_handler_` should be nulled before `view` dies. Otherwise +- // `mouse_move_handler_` will become a dangling pointer. +- CHECK(!mouse_move_handler_); +- scoped_observation.Reset(); +- } +- +- private: +- base::ScopedObservation scoped_observation{ +- this}; +- // Excluded from `raw_ref` rewriter which would otherwise turn this +- // into a `raw_ref>`. The current `raw_ptr&` setup is +- // intentional and used to observe the pointer without counting as a +- // live reference to the underlying memory. +- RAW_PTR_EXCLUSION const raw_ptr& +- mouse_move_handler_; +-}; +- + } // namespace + + // Used by RootView to create a hidden child that can be used to make screen +@@ -667,16 +636,21 @@ void RootView::ViewHierarchyChanged( + widget_->ViewHierarchyChanged(details); + + if (!details.is_add && !details.move_view) { +- if (!explicit_mouse_handler_ && mouse_pressed_handler_ == details.child) +- mouse_pressed_handler_ = nullptr; +- if (mouse_move_handler_ == details.child) ++ if (mouse_pressed_handler_ == details.child) { ++ SetMouseHandler(nullptr); ++ } ++ if (mouse_move_handler_ == details.child) { + mouse_move_handler_ = nullptr; +- if (gesture_handler_ == details.child) ++ } ++ if (gesture_handler_ == details.child) { + gesture_handler_ = nullptr; +- if (event_dispatch_target_ == details.child) ++ } ++ if (event_dispatch_target_ == details.child) { + event_dispatch_target_ = nullptr; +- if (old_dispatch_target_ == details.child) ++ } ++ if (old_dispatch_target_ == details.child) { + old_dispatch_target_ = nullptr; ++ } + } + } + +@@ -779,8 +753,6 @@ void RootView::HandleMouseEnteredOrMoved(const ui::MouseEvent& event) { + mouse_move_handler_ = v; + // TODO(crbug.com/1295290): This is for debug purpose only. + // Remove it after resolving the issue. +- DanglingMouseMoveHandlerOnViewDestroyingChecker +- mouse_move_handler_dangling_checker(mouse_move_handler_); + if (!mouse_move_handler_->GetNotifyEnterExitOnChild() || + !mouse_move_handler_->Contains(old_handler)) { + MouseEnterExitEvent entered(event, ui::ET_MOUSE_ENTERED); +diff --git a/chromium/ui/views/widget/root_view.h b/chromium/ui/views/widget/root_view.h +index 80fc491f87a..4daee866abf 100644 +--- src/3rdparty/chromium/ui/views/widget/root_view.h ++++ src/3rdparty/chromium/ui/views/widget/root_view.h +@@ -132,6 +132,9 @@ class VIEWS_EXPORT RootView : public View, + const views::View* gesture_handler_for_testing() const { + return gesture_handler_; + } ++ const views::View* mouse_pressed_handler_for_testing() const { ++ return mouse_pressed_handler_.get(); ++ } + + protected: + // View: +@@ -205,7 +208,7 @@ class VIEWS_EXPORT RootView : public View, + // ViewTargeter / RootViewTargeter. + + // The view currently handing down - drag - up +- raw_ptr mouse_pressed_handler_ = nullptr; ++ raw_ptr mouse_pressed_handler_ = nullptr; + + // The view currently handling enter / exit + raw_ptr mouse_move_handler_ = nullptr; +diff --git a/chromium/ui/views/widget/root_view_unittest.cc b/chromium/ui/views/widget/root_view_unittest.cc +index 388dd6f1125..68a691b348a 100644 +--- src/3rdparty/chromium/ui/views/widget/root_view_unittest.cc ++++ src/3rdparty/chromium/ui/views/widget/root_view_unittest.cc +@@ -228,10 +228,12 @@ TEST_F(RootViewTest, EventHandlersResetWhenDeleted) { + View* event_handler = state.AddChildView(std::make_unique()); + root_view->SetMouseAndGestureHandler(event_handler); + ASSERT_EQ(event_handler, root_view->gesture_handler_for_testing()); ++ ASSERT_EQ(event_handler, root_view->mouse_pressed_handler_for_testing()); + + // Delete the child and expect that there is no longer a mouse handler. + root_view->GetContentsView()->RemoveChildViewT(event_handler); + EXPECT_EQ(nullptr, root_view->gesture_handler_for_testing()); ++ EXPECT_EQ(nullptr, root_view->mouse_pressed_handler_for_testing()); + } + + TEST_F(RootViewTest, EventHandlersNotResetWhenReparented) { diff --git a/chromium/v8/src/compiler/access-info.cc b/chromium/v8/src/compiler/access-info.cc index 92405188f28..ac19b0a2178 100644 --- src/3rdparty/chromium/v8/src/compiler/access-info.cc +++ src/3rdparty/chromium/v8/src/compiler/access-info.cc @@ -919,6 +919,7 @@ PropertyAccessInfo AccessInfoFactory::ComputePropertyAccessInfo( return PropertyAccessInfo::NotFound(zone(), receiver_map, holder); } + CHECK(prototype.IsJSObject()); holder = prototype.AsJSObject(); map = map_prototype_map; diff --git a/chromium/v8/src/compiler/heap-refs.cc b/chromium/v8/src/compiler/heap-refs.cc index 932f0be7872..4c7d00d6a4d 100644 --- src/3rdparty/chromium/v8/src/compiler/heap-refs.cc +++ src/3rdparty/chromium/v8/src/compiler/heap-refs.cc @@ -1610,6 +1610,7 @@ HolderLookupResult FunctionTemplateInfoRef::LookupHolderOfExpectedType( if (!expected_receiver_type->IsTemplateFor(prototype.object()->map())) { return not_found; } + CHECK(prototype.IsJSObject()); return HolderLookupResult(CallOptimization::kHolderFound, prototype.AsJSObject()); } diff --git a/chromium/v8/src/compiler/js-call-reducer.cc b/chromium/v8/src/compiler/js-call-reducer.cc index caec49b87c5..e7f89542a46 100644 --- src/3rdparty/chromium/v8/src/compiler/js-call-reducer.cc +++ src/3rdparty/chromium/v8/src/compiler/js-call-reducer.cc @@ -3715,14 +3715,13 @@ bool CanInlineJSToWasmCall(const wasm::FunctionSig* wasm_signature) { return false; } - wasm::ValueType externRefNonNull = wasm::kWasmExternRef.AsNonNull(); for (auto type : wasm_signature->all()) { #if defined(V8_TARGET_ARCH_32_BIT) if (type == wasm::kWasmI64) return false; #endif if (type != wasm::kWasmI32 && type != wasm::kWasmI64 && type != wasm::kWasmF32 && type != wasm::kWasmF64 && - type != wasm::kWasmExternRef && type != externRefNonNull) { + type != wasm::kWasmExternRef) { return false; } } diff --git a/chromium/v8/src/compiler/js-native-context-specialization.cc b/chromium/v8/src/compiler/js-native-context-specialization.cc index 8f37860aefe..089b6410528 100644 --- src/3rdparty/chromium/v8/src/compiler/js-native-context-specialization.cc +++ src/3rdparty/chromium/v8/src/compiler/js-native-context-specialization.cc @@ -878,7 +878,9 @@ JSNativeContextSpecialization::InferHasInPrototypeChain( // might be a different object each time, so it's much simpler to include // {prototype}. That does, however, mean that we must check {prototype}'s // map stability. - if (!prototype.map(broker()).is_stable()) return kMayBeInPrototypeChain; + if (!prototype.IsJSObject() || !prototype.map(broker()).is_stable()) { + return kMayBeInPrototypeChain; + } last_prototype = prototype.AsJSObject(); } WhereToStart start = result == NodeProperties::kUnreliableMaps diff --git a/chromium/v8/src/execution/local-isolate.cc b/chromium/v8/src/execution/local-isolate.cc index ca5ed58ae63..568a6fe0cf9 100644 --- src/3rdparty/chromium/v8/src/execution/local-isolate.cc +++ src/3rdparty/chromium/v8/src/execution/local-isolate.cc @@ -64,8 +64,7 @@ bool StackLimitCheck::HasOverflowed(LocalIsolate* local_isolate) { #ifdef V8_INTL_SUPPORT // WARNING: This might be out-of-sync with the main-thread. const std::string& LocalIsolate::DefaultLocale() { - const std::string& res = - is_main_thread() ? isolate_->DefaultLocale() : default_locale_; + const std::string& res = isolate_->DefaultLocale(); DCHECK(!res.empty()); return res; } diff --git a/chromium/v8/src/execution/local-isolate.h b/chromium/v8/src/execution/local-isolate.h index b9cdec9e703..08aa92d712d 100644 --- src/3rdparty/chromium/v8/src/execution/local-isolate.h +++ src/3rdparty/chromium/v8/src/execution/local-isolate.h @@ -185,9 +185,6 @@ class V8_EXPORT_PRIVATE LocalIsolate final : private HiddenLocalFactory { base::Optional rcs_scope_; RuntimeCallStats* runtime_call_stats_; #endif -#ifdef V8_INTL_SUPPORT - std::string default_locale_; -#endif }; template diff --git a/chromium/v8/src/maglev/maglev-graph-builder.cc b/chromium/v8/src/maglev/maglev-graph-builder.cc index 2e7756703f4..406f436a44c 100644 --- src/3rdparty/chromium/v8/src/maglev/maglev-graph-builder.cc +++ src/3rdparty/chromium/v8/src/maglev/maglev-graph-builder.cc @@ -5080,15 +5080,21 @@ void MaglevGraphBuilder::VisitDeletePropertySloppy() { void MaglevGraphBuilder::VisitGetSuperConstructor() { ValueNode* active_function = GetAccumulatorTagged(); - ValueNode* map_proto; + // TODO(victorgomes): Maybe BuildLoadTaggedField should support constants + // instead. if (compiler::OptionalHeapObjectRef constant = TryGetConstant(active_function)) { - map_proto = GetConstant(constant->map(broker()).prototype(broker())); - } else { - ValueNode* map = - AddNewNode({active_function}, HeapObject::kMapOffset); - map_proto = AddNewNode({map}, Map::kPrototypeOffset); + compiler::MapRef map = constant->map(broker()); + if (map.is_stable()) { + broker()->dependencies()->DependOnStableMap(map); + ValueNode* map_proto = GetConstant(map.prototype(broker())); + StoreRegister(iterator_.GetRegisterOperand(0), map_proto); + return; + } } + ValueNode* map = + AddNewNode({active_function}, HeapObject::kMapOffset); + ValueNode* map_proto = AddNewNode({map}, Map::kPrototypeOffset); StoreRegister(iterator_.GetRegisterOperand(0), map_proto); } diff --git a/chromium/v8/src/runtime/runtime-wasm.cc b/chromium/v8/src/runtime/runtime-wasm.cc index 34851fe10da..6d4d445bc60 100644 --- src/3rdparty/chromium/v8/src/runtime/runtime-wasm.cc +++ src/3rdparty/chromium/v8/src/runtime/runtime-wasm.cc @@ -468,7 +468,16 @@ RUNTIME_FUNCTION(Runtime_TierUpWasmToJSWrapper) { isolate); if (IsTuple2(*origin)) { Handle tuple = Handle::cast(origin); - instance = handle(WasmInstanceObject::cast(tuple->value1()), isolate); + Handle call_origin_instance(handle(WasmInstanceObject::cast(tuple->value1()), isolate)); + if (call_origin_instance->module() != instance->module()) { + for (wasm::ValueType type : sig.all()) { + if (type.has_index()) { + ref->set_wrapper_budget(Smi::kMaxValue); + return ReadOnlyRoots(isolate).undefined_value(); + } + } + } + instance = call_origin_instance; origin = handle(tuple->value2(), isolate); } +diff --git a/chromium/v8/src/wasm/baseline/x64/liftoff-assembler-x64.h b/chromium/v8/src/wasm/baseline/x64/liftoff-assembler-x64.h +index 46a756bbae2..1d4fc72fe50 100644 +--- src/3rdparty/chromium/v8/src/wasm/baseline/x64/liftoff-assembler-x64.h ++++ src/3rdparty/chromium/v8/src/wasm/baseline/x64/liftoff-assembler-x64.h +@@ -66,7 +66,7 @@ inline Operand GetMemOp(LiftoffAssembler* assm, Register addr, + : Operand(addr, offset_reg, scale_factor, offset_imm32); + } + // Offset immediate does not fit in 31 bits. +- Register scratch = kScratchRegister; ++ Register scratch = kScratchRegister2; + assm->MacroAssembler::Move(scratch, offset_imm); + if (offset_reg != no_reg) assm->addq(scratch, offset_reg); + return Operand(addr, scratch, scale_factor, 0); diff --git a/chromium/v8/src/wasm/streaming-decoder.cc b/chromium/v8/src/wasm/streaming-decoder.cc index 786c5aa250f..9eb2d2fb9f1 100644 --- src/3rdparty/chromium/v8/src/wasm/streaming-decoder.cc +++ src/3rdparty/chromium/v8/src/wasm/streaming-decoder.cc @@ -294,6 +294,10 @@ void AsyncStreamingDecoder::Finish(bool can_use_compiled_module) { if (!full_wire_bytes_.back().empty()) { size_t total_length = 0; for (auto& bytes : full_wire_bytes_) total_length += bytes.size(); + if (ok()) { + // {DecodeSectionLength} enforces this with graceful error reporting. + CHECK_LE(total_length, max_module_size()); + } auto all_bytes = base::OwnedVector::NewForOverwrite(total_length); uint8_t* ptr = all_bytes.begin(); for (auto& bytes : full_wire_bytes_) { @@ -627,6 +631,18 @@ std::unique_ptr AsyncStreamingDecoder::DecodeSectionLength::NextWithValue( AsyncStreamingDecoder* streaming) { TRACE_STREAMING("DecodeSectionLength(%zu)\n", value_); + // Check if this section fits into the overall module length limit. + // Note: {this->module_offset_} is the position of the section ID byte, + // {streaming->module_offset_} is the start of the section's payload (i.e. + // right after the just-decoded section length varint). + // The latter can already exceed the max module size, when the previous + // section barely fit into it, and this new section's ID or length crossed + // the threshold. + uint32_t payload_start = streaming->module_offset(); + size_t max_size = max_module_size(); + if (payload_start > max_size || max_size - payload_start < value_) { + return streaming->ToErrorState(); + } SectionBuffer* buf = streaming->CreateNewBuffer(module_offset_, section_id_, value_, buffer().SubVector(0, bytes_consumed_)); diff --git a/chromium/v8/src/wasm/wasm-engine.cc b/chromium/v8/src/wasm/wasm-engine.cc index 688a0741cb6..6898538c9e4 100644 --- src/3rdparty/chromium/v8/src/wasm/wasm-engine.cc +++ src/3rdparty/chromium/v8/src/wasm/wasm-engine.cc @@ -1855,10 +1855,11 @@ uint32_t max_table_init_entries() { // {max_module_size} is declared in wasm-limits.h. size_t max_module_size() { - // Clamp the value of --wasm-max-module-size between 16 and just below 2GB. + // Clamp the value of --wasm-max-module-size between 16 and the maximum + // that the implementation supports. constexpr size_t kMin = 16; - constexpr size_t kMax = RoundDown(size_t{kMaxInt}); - static_assert(kMin <= kV8MaxWasmModuleSize && kV8MaxWasmModuleSize <= kMax); + constexpr size_t kMax = kV8MaxWasmModuleSize; + static_assert(kMin <= kV8MaxWasmModuleSize); return std::clamp(v8_flags.wasm_max_module_size.value(), kMin, kMax); } diff --git a/chromium/v8/src/wasm/wasm-js.cc b/chromium/v8/src/wasm/wasm-js.cc index 8710727207a..5e2427cde30 100644 --- src/3rdparty/chromium/v8/src/wasm/wasm-js.cc +++ src/3rdparty/chromium/v8/src/wasm/wasm-js.cc @@ -189,8 +189,8 @@ GET_FIRST_ARGUMENT_AS(Tag) #undef GET_FIRST_ARGUMENT_AS i::wasm::ModuleWireBytes GetFirstArgumentAsBytes( - const v8::FunctionCallbackInfo& info, ErrorThrower* thrower, - bool* is_shared) { + const v8::FunctionCallbackInfo& info, size_t max_length, + ErrorThrower* thrower, bool* is_shared) { DCHECK(i::ValidateCallbackInfo(info)); const uint8_t* start = nullptr; size_t length = 0; @@ -221,7 +221,6 @@ i::wasm::ModuleWireBytes GetFirstArgumentAsBytes( if (length == 0) { thrower->CompileError("BufferSource argument is empty"); } - size_t max_length = i::wasm::max_module_size(); if (length > max_length) { // The spec requires a CompileError for implementation-defined limits, see // https://webassembly.github.io/spec/js-api/index.html#limits. @@ -534,7 +533,8 @@ void WebAssemblyCompile(const v8::FunctionCallbackInfo& info) { new AsyncCompilationResolver(isolate, context, promise_resolver)); bool is_shared = false; - auto bytes = GetFirstArgumentAsBytes(info, &thrower, &is_shared); + auto bytes = GetFirstArgumentAsBytes(info, i::wasm::max_module_size(), + &thrower, &is_shared); if (thrower.error()) { resolver->OnCompilationFailed(thrower.Reify()); return; @@ -559,8 +559,11 @@ void WasmStreamingCallbackForTesting( v8::WasmStreaming::Unpack(info.GetIsolate(), info.Data()); bool is_shared = false; + // We don't check the buffer length up front, to allow d8 to test that the + // streaming decoder implementation handles overly large inputs correctly. + size_t unlimited = std::numeric_limits::max(); i::wasm::ModuleWireBytes bytes = - GetFirstArgumentAsBytes(info, &thrower, &is_shared); + GetFirstArgumentAsBytes(info, unlimited, &thrower, &is_shared); if (thrower.error()) { streaming->Abort(Utils::ToLocal(thrower.Reify())); return; @@ -653,7 +656,8 @@ void WebAssemblyValidate(const v8::FunctionCallbackInfo& info) { ScheduledErrorThrower thrower(i_isolate, "WebAssembly.validate()"); bool is_shared = false; - auto bytes = GetFirstArgumentAsBytes(info, &thrower, &is_shared); + auto bytes = GetFirstArgumentAsBytes(info, i::wasm::max_module_size(), + &thrower, &is_shared); v8::ReturnValue return_value = info.GetReturnValue(); @@ -725,7 +729,8 @@ void WebAssemblyModule(const v8::FunctionCallbackInfo& info) { } bool is_shared = false; - auto bytes = GetFirstArgumentAsBytes(info, &thrower, &is_shared); + auto bytes = GetFirstArgumentAsBytes(info, i::wasm::max_module_size(), + &thrower, &is_shared); if (thrower.error()) { return; @@ -1023,7 +1028,8 @@ void WebAssemblyInstantiate(const v8::FunctionCallbackInfo& info) { } bool is_shared = false; - auto bytes = GetFirstArgumentAsBytes(info, &thrower, &is_shared); + auto bytes = GetFirstArgumentAsBytes(info, i::wasm::max_module_size(), + &thrower, &is_shared); if (thrower.error()) { resolver->OnInstantiationFailed(thrower.Reify()); return; @@ -1155,9 +1161,10 @@ i::Handle DefaultReferenceValue(i::Isolate* isolate, DCHECK(type.is_object_reference()); // Use undefined for JS type (externref) but null for wasm types as wasm does // not know undefined. - if (type.heap_representation() == i::wasm::HeapType::kExtern || - type.heap_representation() == i::wasm::HeapType::kNoExtern) { + if (type.heap_representation() == i::wasm::HeapType::kExtern) { return isolate->factory()->undefined_value(); + } else if (type.heap_representation() == i::wasm::HeapType::kNoExtern) { + return isolate->factory()->null_value(); } return isolate->factory()->wasm_null(); } diff --git a/chromium/v8/src/wasm/wasm-objects.cc b/chromium/v8/src/wasm/wasm-objects.cc index 4c5050a56b8..5698a8f49de 100644 --- src/3rdparty/chromium/v8/src/wasm/wasm-objects.cc +++ src/3rdparty/chromium/v8/src/wasm/wasm-objects.cc @@ -1850,8 +1850,8 @@ Handle WasmTagObject::New(Isolate* isolate, } bool WasmTagObject::MatchesSignature(uint32_t expected_canonical_type_index) { - return wasm::GetWasmEngine()->type_canonicalizer()->IsCanonicalSubtype( - this->canonical_type_index(), expected_canonical_type_index); + return static_cast(this->canonical_type_index()) == + expected_canonical_type_index; } const wasm::FunctionSig* WasmCapiFunction::GetSignature(Zone* zone) const {