git: 29b83cd3d03e - 2024Q4 - www/qt6-webengine: Address multiple vulnerabilities
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sat, 07 Dec 2024 16:01:00 UTC
The branch 2024Q4 has been updated by jhale:
URL: https://cgit.FreeBSD.org/ports/commit/?id=29b83cd3d03ec3ed8fdd667f1d9f60b459b75e1a
commit 29b83cd3d03ec3ed8fdd667f1d9f60b459b75e1a
Author: Jason E. Hale <jhale@FreeBSD.org>
AuthorDate: 2024-12-07 06:11:51 +0000
Commit: Jason E. Hale <jhale@FreeBSD.org>
CommitDate: 2024-12-07 16:00:23 +0000
www/qt6-webengine: Address multiple vulnerabilities
Includes security patches up to Chromium 131.0.6778.108.
MFH: 2024Q4
Security: c2fd83e4-b450-11ef-b680-4ccc6adda413
(cherry picked from commit 382d7828063a451aed6fdba400cd642c9f1e84df)
---
www/qt6-webengine/Makefile | 2 +-
www/qt6-webengine/files/patch-security-rollup | 1921 ++++++++++++++++++++++++-
2 files changed, 1918 insertions(+), 5 deletions(-)
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
@@ -12,7 +12,7 @@
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-
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,10 +1,12 @@
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
@@ -120,6 +122,360 @@ index 0156b748c38..bed248728cc 100644
// 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
@@ -167,6 +523,524 @@ index ba9be480a81..987963d4bf4 100644
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<RenderWidgetHostImpl*>(
+- render_frame_host_->GetView()->GetRenderWidgetHost())
+- ->StartNewContentRenderingTimeout();
++ auto* rwhi = static_cast<RenderWidgetHostImpl*>(
++ 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<RenderFrameHostImpl> pending_rfh,
+ std::unique_ptr<StoredPage> 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<RenderWidgetHostViewBase*>(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<RenderWidgetHostViewChildFrame*>(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<RenderFrameHostImpl> pending_rfh,
+ std::unique_ptr<StoredPage> 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<int>::max(),
+ std::numeric_limits<int>::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<OverlayStateServiceProvider> {
+ public:
+ virtual bool RegisterObserver(
+ mojo::PendingRemote<gpu::mojom::OverlayStateObserver> pending_remote,
+ const gpu::Mailbox& mailbox) = 0;
++
++ protected:
++ friend class base::RefCountedThreadSafe<OverlayStateServiceProvider>;
++ 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<gpu::GpuChannelHost> channel);
+- ~OverlayStateServiceProviderImpl() override;
+
+ bool RegisterObserver(
+ mojo::PendingRemote<gpu::mojom::OverlayStateObserver> pending_remote,
+@@ -43,6 +50,7 @@ class OverlayStateServiceProviderImpl : public OverlayStateServiceProvider {
+ delete;
+ OverlayStateServiceProviderImpl& operator=(
+ const OverlayStateServiceProviderImpl&) = delete;
++ ~OverlayStateServiceProviderImpl() override;
+
+ scoped_refptr<gpu::GpuChannelHost> 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<DCOMPTextureFactory> RenderThreadImpl::GetDCOMPTextureFactory() {
+ return dcomp_texture_factory_;
+ }
+
+-OverlayStateServiceProvider*
++scoped_refptr<OverlayStateServiceProvider>
+ 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<OverlayStateServiceProviderImpl>(std::move(channel));
++ base::MakeRefCounted<OverlayStateServiceProviderImpl>(
++ 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<OverlayStateServiceProvider> GetOverlayStateServiceProvider();
+ #endif
+
+ blink::WebVideoCaptureImplManager* video_capture_impl_manager() const {
+@@ -530,7 +530,7 @@ class CONTENT_EXPORT RenderThreadImpl
+
+ #if BUILDFLAG(IS_WIN)
+ scoped_refptr<DCOMPTextureFactory> dcomp_texture_factory_;
+- std::unique_ptr<OverlayStateServiceProviderImpl>
++ scoped_refptr<OverlayStateServiceProviderImpl>
+ 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
@@ -195,6 +1069,56 @@ index a2f6aa5f2cf..0878fb2599e 100644
{
"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);
*** 1042 LINES SKIPPED ***