diff --git a/.cmake.conf b/.cmake.conf
index f5b3715d7bc..504f5f93c3a 100644
--- a/.cmake.conf
+++ b/.cmake.conf
@@ -1,4 +1,4 @@
-set(QT_REPO_MODULE_VERSION "6.9.0")
+set(QT_REPO_MODULE_VERSION "6.9.2")
 set(QT_REPO_MODULE_PRERELEASE_VERSION_SEGMENT "alpha1")
 set(QT_SUPPORTED_MIN_CMAKE_VERSION_FOR_BUILDING_WEBENGINE "3.19")
 set(QT_EXTRA_INTERNAL_TARGET_DEFINES "QT_NO_AS_CONST=1")
diff --git a/.gitreview b/.gitreview
new file mode 100644
index 00000000000..a17ec896fca
--- /dev/null
+++ b/.gitreview
@@ -0,0 +1,4 @@
+[gerrit]
+host=codereview.qt-project.org
+project=qt/qtwebengine
+defaultbranch=dev
diff --git a/CHROMIUM_VERSION b/CHROMIUM_VERSION
index 7f98334efb0..c5799d9850f 100644
--- a/CHROMIUM_VERSION
+++ b/CHROMIUM_VERSION
@@ -1,3 +1,3 @@
 
-Based on Chromium version:                                      122.0.6261.171
-Patched with security patches up to Chromium version:           129.0.6668.58
+Based on Chromium version:                                      130.0.6723.192
+Patched with security patches up to Chromium version:           139.0.7258.67
diff --git a/CMakeLists.txt b/CMakeLists.txt
index c600f450154..90b90053c56 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -12,6 +12,8 @@ include(cmake/Functions.cmake)
 include(cmake/QtGnTargetHelpers.cmake)
 include(cmake/QtGnConfigHelpers.cmake)
 include(cmake/QtConfigureHelpers.cmake)
+include(cmake/QtWebEngineSbomHelpers.cmake)
+include(cmake/QtToolchainHelpers.cmake)
 
 project(QtWebEngineDummy)
 find_package(Qt6 6.5 CONFIG REQUIRED COMPONENTS BuildInternals Core)
@@ -35,7 +37,7 @@ find_package(Qt6 ${PROJECT_VERSION} CONFIG QUIET OPTIONAL_COMPONENTS
     WebChannel WebChannelQuick Positioning QuickControls2
     Test QuickWidgets QuickTest WebSockets Designer
     JpegPrivate PngPrivate HarfbuzzPrivate FreetypePrivate ZlibPrivate
-    HttpServer
+    HttpServer Svg
 )
 
 if(MATRIX_BUILD AND NOT MATRIX_SUBBUILD AND NOT QT_SUPERBUILD)
@@ -48,4 +50,14 @@ if(MATRIX_BUILD AND NOT MATRIX_SUBBUILD AND NOT QT_SUPERBUILD)
     return()
 endif()
 
+# Don't auto create the SBOM projects, they will be manually created
+# for each sub-project.
+set(QT_SKIP_SBOM_AUTO_PROJECT TRUE)
 qt_build_repo()
+
+# Coin sanity check after qt_build_repo report is printed
+
+qt_webengine_configure_check_coin(coin.nodes
+    "${QT_CONFIGURE_CHECK_qtwebengine_build}"
+    "${QT_CONFIGURE_CHECK_qtpdf_build}"
+)
diff --git a/REUSE.toml b/REUSE.toml
index 9474f351661..faaa2093da1 100644
--- a/REUSE.toml
+++ b/REUSE.toml
@@ -11,7 +11,8 @@ path = ["src/core/doc/QtWebEngineDoc",
         "src/process/QtWebEngineProcess.exe.manifest",
         "src/webenginequick/ui/information.png",
         "src/webenginequick/ui/question.png",
-        "src/webenginewidgets/plugins/qwebengineview/images/qwebengineview.png"]
+        "src/webenginewidgets/plugins/qwebengineview/images/qwebengineview.png",
+        "src/pdf/plugins/imageformats/pdf/pdf.json"]
 precedence = "closest"
 comment = "module and plugin"
 SPDX-FileCopyrightText = "Copyright (C) 2024 The Qt Company Ltd."
@@ -70,29 +71,30 @@ SPDX-FileCopyrightText = "Copyright (C) 2024 The Qt Company Ltd."
 SPDX-License-Identifier = "LicenseRef-Qt-Commercial OR GPL-3.0-only"
 
 [[annotations]]
-path = ["**.pro", "**.qrc", "**CMakeLists.txt", ".cmake.conf", "**.yaml", "**.json",
-        "**.cfg", "**BLACKLIST", "**.plist", "**.plist.in", "**BUILD**.in"]
+path = ["**.pro", "**.qrc", "**CMakeLists.txt", ".cmake.conf", "**.yaml",
+        "**.cfg", "**BLACKLIST", "**.plist", "**.plist.in", "**BUILD**.in", "coin.nodes",
+        "coin/qt-installer-package-config.json", ".tag"]
 precedence = "closest"
 comment = "build system"
 SPDX-FileCopyrightText = "Copyright (C) 2024 The Qt Company Ltd."
 SPDX-License-Identifier = "BSD-3-Clause"
 
 [[annotations]]
-path = [".tag", "**/.gitattributes", "**.gitignore"]
+path = ["**/.gitattributes", "**.gitignore", ".gitmodules", "**.gitreview"]
 precedence = "closest"
-comment = "version control system. Licensed as build system"
+comment = "version control system. Infrastructure"
 SPDX-FileCopyrightText = "Copyright (C) 2024 The Qt Company Ltd."
-SPDX-License-Identifier = "BSD-3-Clause"
+SPDX-License-Identifier = "LicenseRef-Qt-Commercial OR BSD-3-Clause"
 
 [[annotations]]
-path = ["**/doc/images/**", "examples/**", "tests/manual/examples/**", "**/doc/snippets/**"]
+path = ["examples/**", "tests/manual/examples/**", "**/doc/snippets/**"]
 comment = "this must be after the build system table because example and snippets take precedence over build system"
 precedence = "closest"
 SPDX-FileCopyrightText = "Copyright (C) 2024 The Qt Company Ltd."
 SPDX-License-Identifier = "LicenseRef-Qt-Commercial OR BSD-3-Clause"
 
 [[annotations]]
-path = ["**.qdocconf", "config_help.txt", ".gitmodules"]
+path = ["**/doc/images/**", "**.qdocconf", "config_help.txt"]
 comment = "documentation"
 precedence = "closest"
 SPDX-FileCopyrightText = "Copyright (C) 2024 The Qt Company Ltd."
@@ -100,10 +102,10 @@ SPDX-License-Identifier = "LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-on
 
 [[annotations]]
 path = ["**.toml", "licenseRule.json"]
-comment = "documentation"
+comment = "infrastructure"
 precedence = "override"
 SPDX-FileCopyrightText = "Copyright (C) 2024 The Qt Company Ltd."
-SPDX-License-Identifier = "LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only"
+SPDX-License-Identifier = "LicenseRef-Qt-Commercial OR BSD-3-Clause"
 
 [[annotations]]
 path = ["**/qt_attribution.json"]
diff --git a/cmake/Functions.cmake b/cmake/Functions.cmake
index ca4ce729286..c3294142958 100644
--- a/cmake/Functions.cmake
+++ b/cmake/Functions.cmake
@@ -40,39 +40,6 @@ function(get_forward_declaration_macro result)
     endif()
 endfunction()
 
-function(get_darwin_sdk_version result)
-    if(APPLE)
-        if(IOS)
-            set(sdk_name "iphoneos")
-        elseif(TVOS)
-            set(sdk_name "appletvos")
-        elseif(WATCHOS)
-            set(sdk_name "watchos")
-        else()
-            # Default to macOS
-            set(sdk_name "macosx")
-        endif()
-        set(xcrun_version_arg "--show-sdk-version")
-        execute_process(COMMAND /usr/bin/xcrun --sdk ${sdk_name} ${xcrun_version_arg}
-                        OUTPUT_VARIABLE sdk_version
-                        ERROR_VARIABLE xcrun_error)
-        if(NOT sdk_version)
-            message(FATAL_ERROR
-                    "Can't determine darwin ${sdk_name} SDK version. Error: ${xcrun_error}")
-        endif()
-        string(STRIP "${sdk_version}" sdk_version)
-        set(${result} "${sdk_version}" PARENT_SCOPE)
-    endif()
-endfunction()
-
-function(get_ios_target_triple_and_sysroot result arch)
-    get_ios_sysroot(sysroot ${arch})
-    set(${result}
-        -target ${arch}-apple-ios${CMAKE_OSX_DEPLOYMENT_TARGET}
-        -isysroot ${sysroot} PARENT_SCOPE
-    )
-endfunction()
-
 function(add_ninja_target)
     cmake_parse_arguments(PARSE_ARGV 0 arg
         "" "TARGET;CMAKE_TARGET;NINJA_TARGET;BUILDDIR;NINJA_STAMP;NINJA_DATA_STAMP;CONFIG;ARCH" ""
@@ -335,521 +302,16 @@ function(qt_internal_add_external_project_dependency_to_root_project name)
     cmake_policy(POP)
 endfunction()
 
-# Function maps TEST_architecture_arch or CMAKE_SYSTEM_PROCESSOR into gn architecture
-function(get_gn_arch result arch)
-    set(armList arm armv7-a)
-    set(arm64List arm64 ARM64 aarch64)
-    set(mips64List mips64 mipsel64)
-    set(x86List i386 i686)
-    set(x64List x86_64 AMD64 x86_64h)
-    if(arch IN_LIST x86List)
-        set(${result} "x86" PARENT_SCOPE)
-    elseif(arch IN_LIST x64List)
-        set(${result} "x64" PARENT_SCOPE)
-    elseif(arch IN_LIST armList)
-        set(${result} "arm" PARENT_SCOPE)
-    elseif(arch IN_LIST arm64List)
-        set(${result} "arm64" PARENT_SCOPE)
-    elseif(arch STREQUAL "mipsel")
-        set(${result} "mipsel" PARENT_SCOPE)
-    elseif(arch IN_LIST mipsList)
-        set(${result} "mips64el" PARENT_SCOPE)
-    elseif(arch STREQUAL "riscv64")
-        set(${result} "riscv64" PARENT_SCOPE)
-    else()
-        message(FATAL_ERROR "Unknown architecture: ${arch}")
-    endif()
-endfunction()
-
-# Function maps gn architecture for v8
-function(get_v8_arch result targetArch hostArch)
-    set(list32 x86 arm mipsel riscv32)
-    if(hostArch STREQUAL targetArch)
-        set(${result} "${targetArch}" PARENT_SCOPE)
-    elseif(targetArch IN_LIST list32)
-        # 32bit target which needs a 32bit compatible host
-        if(hostArch STREQUAL "x64")
-            set(${result} "x86" PARENT_SCOPE)
-        elseif(hostArch STREQUAL "arm64")
-            set(${result} "arm" PARENT_SCOPE)
-        elseif(hostArch STREQUAL "mips64el")
-            set(${result} "mipsel" PARENT_SCOPE)
-        elseif(hostArch STREQUAL "riscv64")
-            set(${result} "riscv32" PARENT_SCOPE)
-        elseif(hostArch IN_LIST list32)
-            set(${result} "${hostArch}" PARENT_SCOPE)
-        else()
-            message(FATAL_ERROR "Unknown architecture: ${hostArch}")
-        endif()
-    else()
-        # assume 64bit target which matches 64bit host
-        set(${result} "${hostArch}" PARENT_SCOPE)
-    endif()
-endfunction()
-
-function(get_gn_os result)
-    if(WIN32)
-        set(${result} "win" PARENT_SCOPE)
-    elseif(LINUX)
-        set(${result} "linux" PARENT_SCOPE)
-    elseif(MACOS)
-        set(${result} "mac" PARENT_SCOPE)
-    elseif(IOS)
-        set(${result} "ios" PARENT_SCOPE)
-    else()
-        message(DEBUG "Unrecognized OS")
-    endif()
-endfunction()
-
-function(get_gn_is_clang result)
-    if(CLANG)
-        set(${result} "true" PARENT_SCOPE)
-    else()
-        set(${result} "false" PARENT_SCOPE)
-    endif()
-endfunction()
-
-
-function(get_gn_is_mingw result)
-    if(MINGW)
-        set(${result} "true" PARENT_SCOPE)
-    else()
-        set(${result} "false" PARENT_SCOPE)
-    endif()
-endfunction()
-
-function(get_ios_sysroot result arch)
-    if(NOT CMAKE_APPLE_ARCH_SYSROOTS)
-      message(FATAL_ERROR "CMAKE_APPLE_ARCH_SYSROOTS not set.")
-    endif()
-    get_architectures(archs)
-    list(FIND archs ${arch} known_arch)
-    if (known_arch EQUAL "-1")
-        message(FATAL_ERROR "Unknown iOS architecture ${arch}.")
-    endif()
-    list(GET CMAKE_APPLE_ARCH_SYSROOTS ${known_arch} sysroot)
-    set(${result} ${sysroot} PARENT_SCOPE)
-endfunction()
-
-function(configure_gn_toolchain name cpu v8Cpu toolchainIn toolchainOut)
-    set(GN_TOOLCHAIN ${name})
-    get_gn_os(GN_OS)
-    get_gn_is_clang(GN_IS_CLANG)
-    get_gn_is_mingw(GN_IS_MINGW)
-    set(GN_CPU ${cpu})
-    set(GN_V8_CPU ${v8Cpu})
-    configure_file(${toolchainIn} ${toolchainOut}/BUILD.gn @ONLY)
-endfunction()
-
-function(create_pkg_config_wrapper wrapperName wrapperCmd)
-    file(WRITE ${wrapperName}
-        "#!/bin/sh\n"
-        "unset PKG_CONFIG_LIBDIR\n"
-        "unset PKG_CONFIG_PATH\n"
-        "unset PKG_CONFIG_SYSROOT_DIR\n"
-        "exec ${wrapperCmd} \"$@\""
-    )
-    file(CHMOD ${wrapperName} PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE)
-endfunction()
-
-function(extract_cflag result cflag)
-    set(i 1)
-    while(NOT "x${CMAKE_CXX_COMPILER_ARG${i}}" STREQUAL "x")
-        list(APPEND cflags ${CMAKE_CXX_COMPILER_ARG${i}})
-        math(EXPR i "${i} + 1")
-    endwhile()
-    list(APPEND cflags ${CMAKE_C_FLAGS} ${CMAKE_CXX_FLAGS})
-    string(REPLACE ";" " " cflags "${cflags}")
-    message(DEBUG "Found cflags: ${cflags}")
-    if(cflags MATCHES "-${cflag}=([^ ]+)")
-        set(${result} ${CMAKE_MATCH_1} PARENT_SCOPE)
-        return()
-    endif()
-    if(cflags MATCHES "-${cflag}")
-       set(${result} ON PARENT_SCOPE)
-    else()
-       set(${result} OFF PARENT_SCOPE)
-    endif()
-endfunction()
-
-function(extend_gn_list_cflag outList)
-    cmake_parse_arguments(PARSE_ARGV 1 GN "" "" "ARG;CFLAG")
-    _qt_internal_validate_all_args_are_parsed(GN)
-
-    extract_cflag(cflag "${GN_CFLAG}")
-    if(cflag)
-        set(${outList} "${${outList}}" "${GN_ARG}=\"${cflag}\"" PARENT_SCOPE)
-    endif()
-endfunction()
-
-function(get_arm_version result cflag)
-    if(cflag MATCHES "^armv([0-9])")
-        set(${result} ${CMAKE_MATCH_1} PARENT_SCOPE)
-    endif()
-endfunction()
-
-function(check_thumb result)
-    extract_cflag(thumb "mthumb")
-    if(thumb)
-        set(${result} TRUE PARENT_SCOPE)
-        return()
-    else()
-        extract_cflag(marm "marm")
-        if(marm)
-            set(${result} FALSE PARENT_SCOPE)
-            return()
-        else()
-            extract_cflag(march "march")
-            get_arm_version(arm_version ${march})
-            if(arm_version GREATER_EQUAL 7)
-                set(${result} TRUE PARENT_SCOPE)
-                return()
-            endif()
-        endif()
-    endif()
-    set(${result} FALSE PARENT_SCOPE)
-endfunction()
-
-macro(create_pkg_config_host_wrapper buildDir)
-    find_package(PkgConfigHost)
-        if(CMAKE_CROSSCOMPILING)
-            create_pkg_config_wrapper("${buildDir}/pkg-config-host_wrapper.sh" "${PKG_CONFIG_HOST_EXECUTABLE}")
-            set(PKG_CONFIG_HOST_EXECUTABLE "${buildDir}/pkg-config-host_wrapper.sh")
-        endif()
-endmacro()
-
-macro(setup_toolchains)
-    get_gn_arch(gn_arch ${TEST_architecture_arch})
-    if(NOT CMAKE_CROSSCOMPILING) # delivered by hostBuild project
-        configure_gn_toolchain(host ${gn_arch} ${gn_arch}
-            ${WEBENGINE_ROOT_SOURCE_DIR}/src/host/BUILD.toolchain.gn.in
-            ${buildDir}/host_toolchain)
-        configure_gn_toolchain(v8 ${gn_arch} ${gn_arch}
-            ${WEBENGINE_ROOT_SOURCE_DIR}/src/host/BUILD.toolchain.gn.in
-            ${buildDir}/v8_toolchain)
-    endif()
-    configure_gn_toolchain(target ${gn_arch} ${gn_arch}
-        ${WEBENGINE_ROOT_SOURCE_DIR}/src/host/BUILD.toolchain.gn.in
-        ${buildDir}/target_toolchain)
-    unset(gn_arch)
-endmacro()
-
-macro(append_build_type_setup)
-    list(APPEND gnArgArg
-        is_qtwebengine=true
-        init_stack_vars=false
-        is_component_build=false
-        is_shared=true
-        use_sysroot=false
-        forbid_non_component_debug_builds=false
-        treat_warnings_as_errors=false
-        use_allocator_shim=false
-        use_partition_alloc=true
-        use_partition_alloc_as_malloc=false
-        use_custom_libcxx=false
-        enable_rust=false # We do not yet support rust
-        enable_chromium_prelude=false
-        build_tflite_with_xnnpack=false
-        assert_cpp20=false
-    )
-    if(${config} STREQUAL "Debug")
-        list(APPEND gnArgArg is_debug=true symbol_level=2)
-        if(WIN32)
-            list(APPEND gnArgArg enable_iterator_debugging=true)
-        endif()
-    elseif(${config} STREQUAL "Release")
-        list(APPEND gnArgArg is_debug=false symbol_level=0)
-    elseif(${config} STREQUAL "RelWithDebInfo")
-        list(APPEND gnArgArg is_debug=false)
-        if(WIN32 AND NOT CLANG)
-            list(APPEND gnArgArg symbol_level=2)
-        else()
-            list(APPEND gnArgArg symbol_level=1)
-        endif()
-    elseif(${config} STREQUAL "MinSizeRel")
-        list(APPEND gnArgArg is_debug=false symbol_level=0 optimize_for_size=true)
-    endif()
-    if(FEATURE_developer_build OR (${config} STREQUAL "Debug") OR QT_FEATURE_webengine_sanitizer)
-        list(APPEND gnArgArg
-             is_official_build=false
-             use_viz_debugger=false
-        )
-    else()
-        list(APPEND gnArgArg is_official_build=true)
-        if(NOT CLANG OR NOT QT_FEATURE_use_lld_linker)
-            list(APPEND gnArgArg
-                use_thin_lto=false
-            )
-        endif()
-    endif()
-    extend_gn_list(gnArgArg
-        ARGS is_unsafe_developer_build
-        CONDITION FEATURE_developer_build
-    )
-
-    #TODO: refactor to not check for IOS here
-    if(NOT QT_FEATURE_webengine_full_debug_info AND NOT IOS)
-        list(APPEND gnArgArg blink_symbol_level=0 v8_symbol_level=0)
-    endif()
-
-    extend_gn_list(gnArgArg ARGS use_jumbo_build CONDITION QT_FEATURE_webengine_jumbo_build)
-    if(QT_FEATURE_webengine_jumbo_build)
-        list(APPEND gnArgArg jumbo_file_merge_limit=${QT_FEATURE_webengine_jumbo_file_merge_limit})
-        if(QT_FEATURE_webengine_jumbo_file_merge_limit LESS_EQUAL 8)
-            list(APPEND gnArgArg "jumbo_build_excluded=[\"browser\"]")
-        endif()
-    endif()
-
-    extend_gn_list(gnArgArg
-        ARGS enable_precompiled_headers
-        CONDITION BUILD_WITH_PCH AND NOT LINUX
-    )
-    extend_gn_list(gnArgArg
-        ARGS dcheck_always_on
-        CONDITION QT_FEATURE_force_asserts
-    )
-endmacro()
-
-macro(append_compiler_linker_sdk_setup)
-    if(CMAKE_CXX_COMPILER_LAUNCHER)
-        list(APPEND gnArgArg cc_wrapper="${CMAKE_CXX_COMPILER_LAUNCHER}")
-    endif()
-
-    extend_gn_list(gnArgArg ARGS is_clang CONDITION CLANG)
-    extend_gn_list(gnArgArg ARGS is_mingw CONDITION MINGW)
-    extend_gn_list(gnArgArg ARGS is_msvc CONDITION MSVC)
-    extend_gn_list(gnArgArg ARGS is_gcc CONDITION LINUX AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
-
-    if(CLANG)
-        if(MACOS)
-            get_darwin_sdk_version(macSdkVersion)
-            # macOS needs to use the objcxx compiler as the cxx compiler is just a link
-            get_filename_component(clangBasePath ${CMAKE_OBJCXX_COMPILER} DIRECTORY)
-            get_filename_component(clangBasePath ${clangBasePath} DIRECTORY)
-        else()
-            get_filename_component(clangBasePath ${CMAKE_CXX_COMPILER} DIRECTORY)
-            get_filename_component(clangBasePath ${clangBasePath} DIRECTORY)
-        endif()
-
-        string(REGEX MATCH "[0-9]+" clangVersion ${CMAKE_CXX_COMPILER_VERSION})
-        list(APPEND gnArgArg
-            clang_base_path="${clangBasePath}"
-            clang_use_chrome_plugins=false
-            clang_version=${clangVersion}
-            fatal_linker_warnings=false
-        )
-
-        if(MACOS)
-            list(APPEND gnArgArg
-                use_system_xcode=true
-                mac_deployment_target="${CMAKE_OSX_DEPLOYMENT_TARGET}"
-                mac_sdk_min="${macSdkVersion}"
-                use_libcxx=true
-            )
-            _qt_internal_get_apple_sdk_version(apple_sdk_version)
-            if (apple_sdk_version LESS 13.2)
-                list(APPEND gnArgArg
-                    use_sck=false
-                )
-            endif()
-        endif()
-        if(IOS)
-            list(APPEND gnArgArg
-                use_system_xcode=true
-                enable_ios_bitcode=true
-                ios_deployment_target="${CMAKE_OSX_DEPLOYMENT_TARGET}"
-                ios_enable_code_signing=false
-                use_libcxx=true
-            )
-        endif()
-        if(DEFINED QT_FEATURE_stdlib_libcpp AND LINUX)
-            extend_gn_list(gnArgArg ARGS use_libcxx
-                CONDITION QT_FEATURE_stdlib_libcpp
-            )
-        endif()
-        if(ANDROID)
-            list(APPEND gnArgArg
-                android_ndk_root="${CMAKE_ANDROID_NDK}"
-                android_ndk_version="${CMAKE_ANDROID_NDK_VERSION}"
-                clang_use_default_sample_profile=false
-                #android_ndk_major_version=22
-            )
-        endif()
-    else()
-        if(QT_FEATURE_use_lld_linker)
-            get_filename_component(clangBasePath ${CMAKE_LINKER} DIRECTORY)
-            get_filename_component(clangBasePath ${clangBasePath} DIRECTORY)
-            list(APPEND gnArgArg
-                clang_base_path="${clangBasePath}"
-                fatal_linker_warnings=false
-            )
-        endif()
-    endif()
-
-    if(MSVC)
-        get_filename_component(windows_sdk_path $ENV{WINDOWSSDKDIR} ABSOLUTE)
-        get_filename_component(visual_studio_path $ENV{VSINSTALLDIR} ABSOLUTE)
-        qt_webengine_get_windows_sdk_version(windows_sdk_version sdk_minor)
-        list(APPEND gnArgArg
-            win_linker_timing=true
-            use_incremental_linking=false
-            visual_studio_version=2022
-            visual_studio_path=\"${visual_studio_path}\"
-            windows_sdk_version=\"${windows_sdk_version}\"
-            windows_sdk_path=\"${windows_sdk_path}\"
-        )
-    endif()
-    get_gn_arch(cpu ${TEST_architecture_arch})
-    if(LINUX AND CMAKE_CROSSCOMPILING AND cpu STREQUAL "arm")
-
-        extend_gn_list_cflag(gnArgArg
-            ARG arm_tune
-            CFLAG mtune
-        )
-        extend_gn_list_cflag(gnArgArg
-            ARG arm_float_abi
-            CFLAG mfloat-abi
-        )
-        extend_gn_list_cflag(gnArgArg
-            ARG arm_arch
-            CFLAG march
-        )
-        extend_gn_list_cflag(gnArgArg
-            ARG arm_cpu
-            CFLAG mcpu
-        )
-        extract_cflag(cflag "mfpu")
-        get_arm_version(arm_version "${cflag}")
-        extend_gn_list(gnArgArg
-            ARGS arm_use_neon
-            CONDITION (arm_version GREATER_EQUAL 8) OR ("${cflag}" MATCHES ".*neon.*")
-        )
-        if(arm_version EQUAL 7 AND NOT "${cflag}" MATCHES ".*neon.*")
-            # If the toolchain does not explicitly specify to use NEON instructions
-            # we use arm_neon_optional for ARMv7
-            list(APPEND gnArgArg arm_optionally_use_neon=true)
-        endif()
-        extract_cflag(march "march")
-        get_arm_version(arm_version ${march})
-        if(arm_version EQUAL 7)
-            list(APPEND gnArgArg use_arm_crc32=false)
-        endif()
-        check_thumb(armThumb)
-        extend_gn_list(gnArgArg
-            ARGS arm_use_thumb
-            CONDITION armThumb
-        )
-    endif()
-    extend_gn_list(gnArgArg
-        ARGS use_gold
-        CONDITION QT_FEATURE_use_gold_linker
-    )
-    extend_gn_list(gnArgArg
-        ARGS use_lld
-        CONDITION QT_FEATURE_use_lld_linker
-    )
-    unset(cpu)
-endmacro()
-
-macro(append_sanitizer_setup)
-    if(QT_FEATURE_webengine_sanitizer)
-        extend_gn_list(gnArgArg
-            ARGS is_asan
-            CONDITION address IN_LIST ECM_ENABLE_SANITIZERS
-        )
-        extend_gn_list(gnArgArg
-            ARGS is_tsan
-            CONDITION thread IN_LIST ECM_ENABLE_SANITIZERS
-        )
-        extend_gn_list(gnArgArg
-            ARGS is_msan
-            CONDITION memory IN_LIST ECM_ENABLE_SANITIZERS
-        )
-        extend_gn_list(gnArgArg
-            ARGS is_ubsan is_ubsan_vptr
-            CONDITION undefined IN_LIST ECM_ENABLE_SANITIZERS
-        )
-        if(APPLE)
-            list(APPEND gnArgArg
-                clang_version=\"${QT_COMPILER_VERSION_MAJOR}.${QT_COMPILER_VERSION_MINOR}.${QT_COMPILER_VERSION_PATCH}\"
-            )
-        endif()
-    endif()
-endmacro()
-
-macro(append_toolchain_setup)
-    if(WIN32)
-        get_gn_arch(cpu ${arch})
-        list(APPEND gnArgArg target_cpu="${cpu}")
-        if(MINGW)
-            get_gn_arch(cpu ${TEST_architecture_arch})
-            list(APPEND gnArgArg
-                # note '/' prefix
-                custom_toolchain="/${buildDir}/target_toolchain:target"
-                host_toolchain="/${buildDir}/host_toolchain:host"
-                host_cpu="${cpu}"
-            )
-        endif()
-    elseif(LINUX)
-        get_gn_arch(cpu ${TEST_architecture_arch})
-        list(APPEND gnArgArg
-            custom_toolchain="${buildDir}/target_toolchain:target"
-            host_toolchain="${buildDir}/host_toolchain:host"
-        )
-        if(CMAKE_CROSSCOMPILING)
-            list(APPEND gnArgArg
-                v8_snapshot_toolchain="${buildDir}/v8_toolchain:v8"
-                target_cpu="${cpu}"
-            )
-        else()
-            list(APPEND gnArgArg host_cpu="${cpu}")
-        endif()
-        if(CMAKE_SYSROOT)
-            list(APPEND gnArgArg target_sysroot="${CMAKE_SYSROOT}")
-        endif()
-    elseif(MACOS)
-        get_gn_arch(cpu ${arch})
-        list(APPEND gnArgArg target_cpu="${cpu}")
-    elseif(IOS)
-        get_gn_arch(cpu ${arch})
-        get_ios_sysroot(sysroot ${arch})
-        list(APPEND gnArgArg target_cpu="${cpu}" target_sysroot="${sysroot}" target_os="ios")
-    elseif(ANDROID)
-        get_gn_arch(cpu ${TEST_architecture_arch})
-        list(APPEND gnArgArg target_os="android" target_cpu="${cpu}")
-        if(CMAKE_HOST_WIN32)
-            list(APPEND gnArgArg
-                host_toolchain="/${buildDir}/host_toolchain:host"
-                host_cpu="x64"
-                v8_snapshot_toolchain="/${buildDir}/v8_toolchain:v8"
-            )
-        endif()
-    endif()
-    unset(cpu)
-endmacro()
-
-
-macro(append_pkg_config_setup)
-    if(PkgConfig_FOUND)
-        list(APPEND gnArgArg
-            pkg_config="${PKG_CONFIG_EXECUTABLE}"
-            host_pkg_config="${PKG_CONFIG_HOST_EXECUTABLE}"
-        )
-        if(NOT "$ENV{PKG_CONFIG_LIBDIR}" STREQUAL "")
-            list(APPEND gnArgArg
-                system_libdir="$ENV{PKG_CONFIG_LIBDIR}"
-            )
-        endif()
-    endif()
-endmacro()
-
 function(add_ninja_command)
     cmake_parse_arguments(PARSE_ARGV 0 arg
-        "" "TARGET;BUILDDIR;MODULE" "OUTPUT;BYPRODUCTS"
+        "" "TARGET;BUILDDIR;MODULE" "OUTPUT;BYPRODUCTS;DEPENDS"
     )
     _qt_internal_validate_all_args_are_parsed(arg)
 
-    string(REPLACE " " ";" NINJAFLAGS "$ENV{NINJAFLAGS}")
+    string(REPLACE " " ";" ninja_flags "$ENV{NINJAFLAGS}")
+    if(CMAKE_VERBOSE_MAKEFILE)
+        list(APPEND ninja_flags -v)
+    endif()
     list(TRANSFORM arg_OUTPUT PREPEND "${arg_BUILDDIR}/")
     list(TRANSFORM arg_BYPRODUCTS PREPEND "${arg_BUILDDIR}/")
     add_custom_command(
@@ -859,43 +321,19 @@ function(add_ninja_command)
         BYPRODUCTS ${arg_BYPRODUCTS}
         COMMENT "Running ninja for ${arg_TARGET} in ${arg_BUILDDIR}"
         COMMAND Ninja::ninja
-            ${NINJAFLAGS}
+            ${ninja_flags}
             -C ${arg_BUILDDIR}
             ${arg_TARGET}
         USES_TERMINAL
         VERBATIM
         COMMAND_EXPAND_LISTS
-        DEPENDS run_${arg_MODULE}_NinjaReady
+        DEPENDS run_${arg_MODULE}_NinjaReady ${arg_DEPENDS}
     )
 endfunction()
 
-function(get_configs result)
-    if(QT_GENERATOR_IS_MULTI_CONFIG)
-        set(${result} ${CMAKE_CONFIGURATION_TYPES})
-    else()
-        set(${result} ${CMAKE_BUILD_TYPE})
-    endif()
-    if(NOT ${result})
-        message(FATAL_ERROR "No valid configurations found !")
-    endif()
-    set(${result} ${${result}} PARENT_SCOPE)
-endfunction()
-
-function(get_architectures result)
-    if(CMAKE_OSX_ARCHITECTURES)
-        set(${result} ${CMAKE_OSX_ARCHITECTURES})
-    else()
-        set(${result} ${CMAKE_SYSTEM_PROCESSOR})
-    endif()
-    if(NOT ${result})
-    message(FATAL_ERROR "No valid architectures found. In case of cross-compiling make sure you have CMAKE_SYSTEM_PROCESSOR in your toolchain file.")
-    endif()
-    set(${result} ${${result}} PARENT_SCOPE)
-endfunction()
-
 function(add_gn_build_artifacts_to_target)
     cmake_parse_arguments(PARSE_ARGV 0 arg
-        "" "CMAKE_TARGET;NINJA_TARGET;BUILDDIR;MODULE;COMPLETE_STATIC;NINJA_STAMP;NINJA_DATA_STAMP" ""
+        "" "CMAKE_TARGET;NINJA_TARGET;BUILDDIR;MODULE;COMPLETE_STATIC;NINJA_STAMP;NINJA_DATA_STAMP;DEPENDS" ""
     )
     _qt_internal_validate_all_args_are_parsed(arg)
 
@@ -908,12 +346,16 @@ function(add_gn_build_artifacts_to_target)
         foreach(arch ${archs})
             set(target ${arg_NINJA_TARGET}_${config}_${arch})
             set(stamps ${arg_NINJA_STAMP} ${arg_NINJA_DATA_STAMP})
+            set(data_stamp_option "")
+            if(arg_NINJA_DATA_STAMP)
+                set(data_stamp_option NINJA_DATA_STAMP ${arg_NINJA_DATA_STAMP})
+            endif()
             add_ninja_target(
                 TARGET ${target}
                 NINJA_TARGET ${arg_NINJA_TARGET}
                 CMAKE_TARGET ${arg_CMAKE_TARGET}
                 NINJA_STAMP ${arg_NINJA_STAMP}
-                NINJA_DATA_STAMP ${arg_NINJA_DATA_STAMP}
+                ${data_stamp_option}
                 CONFIG ${config}
                 ARCH ${arch}
                 BUILDDIR ${arg_BUILDDIR}
@@ -923,7 +365,10 @@ function(add_gn_build_artifacts_to_target)
                 OUTPUT ${stamps}
                 BUILDDIR ${arg_BUILDDIR}/${config}/${arch}
                 MODULE ${arg_MODULE}
+                DEPENDS ${arg_DEPENDS}
             )
+            qt_webengine_add_gn_target_to_sbom(${arg_NINJA_TARGET} ${arg_BUILDDIR}/${config}/${arch})
+            qt_webengine_add_gn_artifact_relationship_to_sbom(${arg_NINJA_TARGET} ${arg_CMAKE_TARGET})
             add_dependencies(run_${arg_MODULE}_NinjaDone ${target})
             set_target_properties(${arg_CMAKE_TARGET} PROPERTIES
                 LINK_DEPENDS ${arg_BUILDDIR}/${config}/${arch}/${arg_NINJA_STAMP}
@@ -1002,6 +447,7 @@ function(add_gn_command)
             run_${arg_MODULE}_GnReady
             "${WEBENGINE_ROOT_SOURCE_DIR}/src/${arg_MODULE}/configure/BUILD.root.gn.in"
             "${WEBENGINE_ROOT_SOURCE_DIR}/cmake/QtGnGen.cmake"
+            "${WEBENGINE_ROOT_SOURCE_DIR}/cmake/QtBuildGnHelpers.cmake"
     )
     add_custom_target(runGn_${arg_GN_TARGET}
         DEPENDS #TODO this is fixed in cmake 3.20 so we could simply use GN_TARGET and not create new one
@@ -1033,7 +479,6 @@ function(addCopyCommand target src dst)
         COMMAND ${CMAKE_COMMAND} -E make_directory ${dst}
         COMMAND ${CMAKE_COMMAND} -E copy ${src} ${dst}
         TARGET ${target}
-        DEPENDS ${src}
         USES_TERMINAL
     )
 endfunction()
@@ -1100,8 +545,11 @@ macro(qt_webengine_externalproject_add)
                    -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>
                    -DCMAKE_PREFIX_PATH:PATH=<INSTALL_DIR>
                    -DCMAKE_OSX_ARCHITECTURES=${OSX_ARCH_STR}
+                   -DCMAKE_VERBOSE_MAKEFILE=${CMAKE_VERBOSE_MAKEFILE}
                    -DWEBENGINE_ROOT_BUILD_DIR=${PROJECT_BINARY_DIR}
                    -DQT_ALLOW_SYMLINK_IN_PATHS=${QT_ALLOW_SYMLINK_IN_PATHS}
+                   -DPython3_EXECUTABLE=${Python3_EXECUTABLE}
+                   -DGCC_LEGACY_SUPPORT=${QT_FEATURE_webengine_gcc_legacy_support}
     )
     unset(OSX_ARCH_STR)
 endmacro()
diff --git a/cmake/QtBuildGnHelpers.cmake b/cmake/QtBuildGnHelpers.cmake
index d838b8662c7..135219fcff5 100644
--- a/cmake/QtBuildGnHelpers.cmake
+++ b/cmake/QtBuildGnHelpers.cmake
@@ -41,6 +41,25 @@ function(recover_framework_build includeDirs compilerFlags)
     set(${compilerFlags} ${${compilerFlags}} ${frameworkDirs} PARENT_SCOPE)
 endfunction()
 
+# CMake uses a "SHELL:" prefix to group options and avoid unwanted option de-duplication; we
+# need to strip these after manually de-duplicating, but before passing to GN.
+# See https://cmake.org/cmake/help/latest/command/target_compile_options.html#option-de-duplication
+function(transform_cmake_compile_options_for_gn out_var compile_options_var)
+    get_property(flags_var DIRECTORY PROPERTY ${compile_options_var})
+
+    list(REMOVE_DUPLICATES flags_var)
+    set(out_flags "")
+    foreach(elem IN LISTS flags_var)
+        if(elem MATCHES "^SHELL:(.*)")
+            # Split on spaces and enclose each argument with quotes.
+            string(REPLACE " " "\";\"" elem "${CMAKE_MATCH_1}")
+        endif()
+        list(APPEND out_flags "\"${elem}\"")
+    endforeach()
+
+    set(${out_var} ${out_flags} PARENT_SCOPE)
+endfunction()
+
 function(configure_gn_target source_dir in_file_path out_file_path path_mode)
 
     # GN_SOURCES GN_HEADERS
@@ -76,18 +95,10 @@ function(configure_gn_target source_dir in_file_path out_file_path path_mode)
     set(GN_ARGS_MOC_BIN \"${moc_file_path}\")
 
     # GN_CFLAGS_CC
-    get_property(gn_cxx_compile_options DIRECTORY PROPERTY GN_CXX_COMPILE_OPTIONS)
-    foreach(gn_cxx_compile_option ${gn_cxx_compile_options})
-        list(APPEND GN_CFLAGS_CC \"${gn_cxx_compile_option}\")
-    endforeach()
-    list(REMOVE_DUPLICATES GN_CFLAGS_CC)
+    transform_cmake_compile_options_for_gn(GN_CFLAGS_CC GN_CXX_COMPILE_OPTIONS)
 
     # GN_CFLAGS_C
-    get_property(gn_c_compile_options DIRECTORY PROPERTY GN_C_COMPILE_OPTIONS)
-    foreach(gn_c_compile_option ${gn_c_compile_options})
-        list(APPEND GN_CFLAGS_C \"${gn_c_compile_option}\")
-    endforeach()
-    list(REMOVE_DUPLICATES GN_CFLAGS_C)
+    transform_cmake_compile_options_for_gn(GN_CFLAGS_C GN_C_COMPILE_OPTIONS)
 
     # GN_SOURCE_ROOT
     get_filename_component(GN_SOURCE_ROOT "${source_dir}" ${path_mode})
diff --git a/cmake/QtConfigureHelpers.cmake b/cmake/QtConfigureHelpers.cmake
index e7c555a8caf..e469fc67a0b 100644
--- a/cmake/QtConfigureHelpers.cmake
+++ b/cmake/QtConfigureHelpers.cmake
@@ -36,8 +36,8 @@ endmacro()
 
 macro(qt_webengine_check_support)
     foreach(module_checked ${configure_checks})
-        set(error_message "\n -- The following configure errors were found:")
-        set(warning_message "\n -- The following configure warnings were found:")
+        set(error_message "The following configure errors were found:")
+        set(warning_message "The following configure warnings were found:")
         string(TOLOWER ${module_checked} module)
         set(QT_CONFIGURE_CHECK_${module}_build ON CACHE BOOL "Build ${module_checked} Modules" FORCE)
         if(${configure_checks_${module}_error} OR ${configure_checks_${module}_warning})
@@ -257,8 +257,52 @@ endfunction()
 
 function(qt_webengine_get_windows_sdk_version result_sdk_full result_sdk_minor)
     set(windows_sdk_version $ENV{WindowsSDKVersion})
-    String(REGEX REPLACE "([0-9.]+).*" "\\1" windows_sdk_version "${windows_sdk_version}")
+    string(REGEX REPLACE "([0-9.]+).*" "\\1" windows_sdk_version "${windows_sdk_version}")
     string(REGEX REPLACE "^[0-9]+\\.[0-9]+\\.([0-9]+)\\.[0-9]+" "\\1" sdk_minor "${windows_sdk_version}")
     set(${result_sdk_full} "${windows_sdk_version}" PARENT_SCOPE)
     set(${result_sdk_minor} "${sdk_minor}" PARENT_SCOPE)
 endfunction()
+
+function(qt_webengine_configure_check_coin white_list_file webengine_check pdf_check)
+    if("${webengine_check}" STREQUAL "" OR "${pdf_check}" STREQUAL "")
+        return()
+    endif()
+    set(coin_id $ENV{COIN_PLATFORM_ID})
+    if(coin_id)
+        set(res OFF)
+        file(READ ${white_list_file} white_list)
+        string(REPLACE "\n" ";" white_list "${white_list}")
+        foreach(line IN LISTS white_list)
+            string(REPLACE " " ";" line "${line}")
+            list(REMOVE_ITEM line "")
+            if(NOT line)
+                continue()
+            endif()
+            list(POP_FRONT line id)
+            if(id MATCHES "^#") # skip comments
+                continue()
+            endif()
+            if(id)
+               set(${id} ${line})
+            endif()
+        endforeach()
+        if(DEFINED ${coin_id})
+            list(POP_FRONT ${coin_id} webengine_build)
+            list(POP_FRONT ${coin_id} pdf_build)
+            set(res ON)
+            if(webengine_build AND NOT webengine_check)
+                set(res OFF)
+            endif()
+            if(pdf_build AND NOT pdf_check)
+                set(res OFF)
+            endif()
+        else()
+            message(WARNING "Undefined coin sanity check for ${coin_id} platform")
+            return()
+        endif()
+        if(NOT res)
+            message(FATAL_ERROR "!!! Coin sanity check failed for ${coin_id} platform with:
+           (qtwebegine=${QT_CONFIGURE_CHECK_qtwebengine_build} qtpdf=${QT_CONFIGURE_CHECK_qtpdf_build}), but expected: (qtwebengine=${webengine_build} qtpdf=${pdf_build})")
+        endif()
+    endif()
+endfunction()
diff --git a/cmake/QtGnConfigHelpers.cmake b/cmake/QtGnConfigHelpers.cmake
index bee08a96745..62469c09828 100644
--- a/cmake/QtGnConfigHelpers.cmake
+++ b/cmake/QtGnConfigHelpers.cmake
@@ -62,7 +62,7 @@ endfunction()
 function(create_c_config cmake_target arch config_file_name)
     file(GENERATE
           OUTPUT $<CONFIG>/${arch}/${config_file_name}
-          CONTENT "set(GN_C_COMPILE_OPTIONS $<TARGET_PROPERTY:COMPILE_OPTIONS>)"
+          CONTENT "set(GN_C_COMPILE_OPTIONS \"$<TARGET_PROPERTY:COMPILE_OPTIONS>\")"
           CONDITION $<COMPILE_LANGUAGE:C>
           TARGET ${cmake_target})
 endfunction()
diff --git a/cmake/QtGnCredits.cmake b/cmake/QtGnCredits.cmake
index 87cdd7d24e3..499698cb906 100644
--- a/cmake/QtGnCredits.cmake
+++ b/cmake/QtGnCredits.cmake
@@ -18,7 +18,7 @@ set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR})
 
 find_package(Gn ${QT_REPO_MODULE_VERSION} EXACT)
 if(NOT Python3_EXECUTABLE)
-    find_package(Python3 3.6 REQUIRED)
+    message(FATAL_ERROR "\nPython3_EXECUTABLE not set.\n")
 endif()
 
 set(extra_third_party_dirs "")
diff --git a/cmake/QtGnGen.cmake b/cmake/QtGnGen.cmake
index 3ad41ef8cfe..a961330744f 100644
--- a/cmake/QtGnGen.cmake
+++ b/cmake/QtGnGen.cmake
@@ -29,7 +29,7 @@ set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR})
 
 find_package(Gn ${QT_REPO_MODULE_VERSION} EXACT)
 if(NOT Python3_EXECUTABLE)
-    find_package(Python3 3.6 REQUIRED)
+    message(FATAL_ERROR "\nPython3_EXECUTABLE not set.\n")
 endif()
 
 set(gn_command ${Gn_EXECUTABLE})
diff --git a/cmake/QtGnSbom.cmake b/cmake/QtGnSbom.cmake
new file mode 100644
index 00000000000..905efed1370
--- /dev/null
+++ b/cmake/QtGnSbom.cmake
@@ -0,0 +1,53 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+# This is a wrapper around sbom.py which creates an SBOM document for a GN-based target.
+
+if(NOT CMAKE_SCRIPT_MODE_FILE)
+    message(FATAL_ERROR "This file should run only in script mode")
+    return()
+endif()
+
+foreach(variable
+        Python3_EXECUTABLE SCRIPT_PATH GN_TARGET_LIST BUILD_DIR_LIST
+        PACKAGE_ID DOC_NAMESPACE OUTPUT)
+    if(NOT DEFINED ${variable} OR "${${variable}}" STREQUAL "")
+        message(FATAL_ERROR "\n${variable} not set (${${variable}})\n")
+    endif()
+endforeach()
+
+set(path_mode REALPATH)
+if(APPLE AND QT_ALLOW_SYMLINK_IN_PATHS)
+    set(path_mode ABSOLUTE)
+endif()
+
+get_filename_component(WEBENGINE_ROOT_SOURCE_DIR "${CMAKE_CURRENT_LIST_DIR}/.." ${path_mode})
+get_filename_component(WEBENGINE_ROOT_BUILD_DIR "${CMAKE_CURRENT_BINARY_DIR}" ${path_mode})
+
+include(${WEBENGINE_ROOT_SOURCE_DIR}/.cmake.conf)
+include(${WEBENGINE_ROOT_SOURCE_DIR}/cmake/QtBuildGnHelpers.cmake)
+
+set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR})
+
+find_package(Gn ${QT_REPO_MODULE_VERSION} EXACT MODULE REQUIRED)
+
+execute_process(
+    COMMAND "${Python3_EXECUTABLE}" "${SCRIPT_PATH}"
+        --gn-binary "${Gn_EXECUTABLE}"
+        --gn-target-list "${GN_TARGET_LIST}"
+        --build-dir-list "${BUILD_DIR_LIST}"
+        --gn-version ${Gn_VERSION}
+        --package-id ${PACKAGE_ID}
+        --namespace "${DOC_NAMESPACE}"
+        "${OUTPUT}"
+    RESULT_VARIABLE gn_result
+    OUTPUT_VARIABLE gn_output
+    ERROR_VARIABLE gn_error
+    TIMEOUT 600
+)
+
+if(NOT gn_result EQUAL 0)
+    string(REGEX REPLACE "\n$" "" gn_output "${gn_output}")
+    string(REGEX REPLACE "\n$" "" gn_error "${gn_error}")
+    message(FATAL_ERROR "\n-- SBOM generation FAILED\n${gn_output}\n${gn_error}\n-- Exit code: ${gn_result}\n")
+endif()
diff --git a/cmake/QtToolchainHelpers.cmake b/cmake/QtToolchainHelpers.cmake
new file mode 100644
index 00000000000..a34c0d06efa
--- /dev/null
+++ b/cmake/QtToolchainHelpers.cmake
@@ -0,0 +1,638 @@
+# Copyright (C) 2025 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+function(get_darwin_sdk_version result)
+    if(APPLE)
+        if(IOS)
+            set(sdk_name "iphoneos")
+        elseif(TVOS)
+            set(sdk_name "appletvos")
+        elseif(WATCHOS)
+            set(sdk_name "watchos")
+        else()
+            # Default to macOS
+            set(sdk_name "macosx")
+        endif()
+        set(xcrun_version_arg "--show-sdk-version")
+        execute_process(COMMAND /usr/bin/xcrun --sdk ${sdk_name} ${xcrun_version_arg}
+                        OUTPUT_VARIABLE sdk_version
+                        ERROR_VARIABLE xcrun_error)
+        if(NOT sdk_version)
+            message(FATAL_ERROR
+                    "Can't determine darwin ${sdk_name} SDK version. Error: ${xcrun_error}")
+        endif()
+        string(STRIP "${sdk_version}" sdk_version)
+        set(${result} "${sdk_version}" PARENT_SCOPE)
+    endif()
+endfunction()
+
+function(get_ios_target_triple_and_sysroot result arch)
+    get_ios_sysroot(sysroot ${arch})
+    set(${result}
+        -target ${arch}-apple-ios${CMAKE_OSX_DEPLOYMENT_TARGET}
+        -isysroot ${sysroot} PARENT_SCOPE
+    )
+endfunction()
+
+# Function maps TEST_architecture_arch or CMAKE_SYSTEM_PROCESSOR into gn architecture
+function(get_gn_arch result arch)
+    set(armList arm armv7-a)
+    set(arm64List arm64 ARM64 aarch64)
+    set(mips64List mips64 mipsel64)
+    set(x86List i386 i686)
+    set(x64List x86_64 AMD64 x86_64h)
+    if(arch IN_LIST x86List)
+        set(${result} "x86" PARENT_SCOPE)
+    elseif(arch IN_LIST x64List)
+        set(${result} "x64" PARENT_SCOPE)
+    elseif(arch IN_LIST armList)
+        set(${result} "arm" PARENT_SCOPE)
+    elseif(arch IN_LIST arm64List)
+        set(${result} "arm64" PARENT_SCOPE)
+    elseif(arch STREQUAL "mipsel")
+        set(${result} "mipsel" PARENT_SCOPE)
+    elseif(arch IN_LIST mipsList)
+        set(${result} "mips64el" PARENT_SCOPE)
+    elseif(arch STREQUAL "riscv64")
+        set(${result} "riscv64" PARENT_SCOPE)
+    else()
+        message(FATAL_ERROR "Unknown architecture: ${arch}")
+    endif()
+endfunction()
+
+# Function maps gn architecture for v8
+function(get_v8_arch result targetArch hostArch)
+    set(list32 x86 arm mipsel riscv32)
+    if(hostArch STREQUAL targetArch)
+        set(${result} "${targetArch}" PARENT_SCOPE)
+    elseif(targetArch IN_LIST list32)
+        # 32bit target which needs a 32bit compatible host
+        if(hostArch STREQUAL "x64")
+            set(${result} "x86" PARENT_SCOPE)
+        elseif(hostArch STREQUAL "arm64")
+            set(${result} "arm" PARENT_SCOPE)
+        elseif(hostArch STREQUAL "mips64el")
+            set(${result} "mipsel" PARENT_SCOPE)
+        elseif(hostArch STREQUAL "riscv64")
+            set(${result} "riscv32" PARENT_SCOPE)
+        elseif(hostArch IN_LIST list32)
+            set(${result} "${hostArch}" PARENT_SCOPE)
+        else()
+            message(FATAL_ERROR "Unknown architecture: ${hostArch}")
+        endif()
+    else()
+        # assume 64bit target which matches 64bit host
+        set(${result} "${hostArch}" PARENT_SCOPE)
+    endif()
+endfunction()
+
+function(get_gn_os result)
+    if(WIN32)
+        set(${result} "win" PARENT_SCOPE)
+    elseif(LINUX)
+        set(${result} "linux" PARENT_SCOPE)
+    elseif(MACOS)
+        set(${result} "mac" PARENT_SCOPE)
+    elseif(IOS)
+        set(${result} "ios" PARENT_SCOPE)
+    else()
+        message(DEBUG "Unrecognized OS")
+    endif()
+endfunction()
+
+function(get_gn_is_clang result)
+    if(CLANG)
+        set(${result} "true" PARENT_SCOPE)
+    else()
+        set(${result} "false" PARENT_SCOPE)
+    endif()
+endfunction()
+
+function(get_gn_is_mingw result)
+    if(MINGW)
+        set(${result} "true" PARENT_SCOPE)
+    else()
+        set(${result} "false" PARENT_SCOPE)
+    endif()
+endfunction()
+
+function(get_ios_sysroot result arch)
+    if(NOT CMAKE_APPLE_ARCH_SYSROOTS)
+      message(FATAL_ERROR "CMAKE_APPLE_ARCH_SYSROOTS not set.")
+    endif()
+    get_architectures(archs)
+    list(FIND archs ${arch} known_arch)
+    if (known_arch EQUAL "-1")
+        message(FATAL_ERROR "Unknown iOS architecture ${arch}.")
+    endif()
+    list(GET CMAKE_APPLE_ARCH_SYSROOTS ${known_arch} sysroot)
+    set(${result} ${sysroot} PARENT_SCOPE)
+endfunction()
+
+function(configure_gn_toolchain name cpu v8Cpu toolchainIn toolchainOut)
+    set(GN_TOOLCHAIN ${name})
+    get_gn_os(GN_OS)
+    get_gn_is_clang(GN_IS_CLANG)
+    get_gn_is_mingw(GN_IS_MINGW)
+    set(GN_CPU ${cpu})
+    set(GN_V8_CPU ${v8Cpu})
+    configure_file(${toolchainIn} ${toolchainOut}/BUILD.gn @ONLY)
+endfunction()
+
+function(create_pkg_config_wrapper wrapperName wrapperCmd)
+    file(WRITE ${wrapperName}
+        "#!/bin/sh\n"
+        "unset PKG_CONFIG_LIBDIR\n"
+        "unset PKG_CONFIG_PATH\n"
+        "unset PKG_CONFIG_SYSROOT_DIR\n"
+        "exec ${wrapperCmd} \"$@\""
+    )
+    file(CHMOD ${wrapperName} PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE)
+endfunction()
+
+function(extract_cflag result cflag)
+    set(i 1)
+    while(NOT "x${CMAKE_CXX_COMPILER_ARG${i}}" STREQUAL "x")
+        list(APPEND cflags ${CMAKE_CXX_COMPILER_ARG${i}})
+        math(EXPR i "${i} + 1")
+    endwhile()
+    list(APPEND cflags ${CMAKE_C_FLAGS} ${CMAKE_CXX_FLAGS})
+    string(REPLACE ";" " " cflags "${cflags}")
+    message(DEBUG "Found cflags: ${cflags}")
+    if(cflags MATCHES "-${cflag}=([^ ]+)")
+        set(${result} ${CMAKE_MATCH_1} PARENT_SCOPE)
+        return()
+    endif()
+    if(cflags MATCHES "-${cflag}")
+       set(${result} ON PARENT_SCOPE)
+    else()
+       set(${result} OFF PARENT_SCOPE)
+    endif()
+endfunction()
+
+function(extend_gn_list_cflag outList)
+    cmake_parse_arguments(PARSE_ARGV 1 GN "" "" "ARG;CFLAG")
+    _qt_internal_validate_all_args_are_parsed(GN)
+
+    extract_cflag(cflag "${GN_CFLAG}")
+    if(cflag)
+        set(${outList} "${${outList}}" "${GN_ARG}=\"${cflag}\"" PARENT_SCOPE)
+    endif()
+endfunction()
+
+function(get_arm_version result cflag)
+    if(cflag MATCHES "^armv([0-9])")
+        set(${result} ${CMAKE_MATCH_1} PARENT_SCOPE)
+    endif()
+endfunction()
+
+function(check_thumb result)
+    extract_cflag(thumb "mthumb")
+    if(thumb)
+        set(${result} TRUE PARENT_SCOPE)
+        return()
+    else()
+        extract_cflag(marm "marm")
+        if(marm)
+            set(${result} FALSE PARENT_SCOPE)
+            return()
+        else()
+            extract_cflag(march "march")
+            get_arm_version(arm_version ${march})
+            if(arm_version GREATER_EQUAL 7)
+                set(${result} TRUE PARENT_SCOPE)
+                return()
+            endif()
+        endif()
+    endif()
+    set(${result} FALSE PARENT_SCOPE)
+endfunction()
+
+macro(create_pkg_config_host_wrapper buildDir)
+    find_package(PkgConfigHost)
+        if(CMAKE_CROSSCOMPILING)
+            create_pkg_config_wrapper("${buildDir}/pkg-config-host_wrapper.sh" "${PKG_CONFIG_HOST_EXECUTABLE}")
+            set(PKG_CONFIG_HOST_EXECUTABLE "${buildDir}/pkg-config-host_wrapper.sh")
+        endif()
+endmacro()
+
+macro(setup_toolchains)
+    if(MSVC)
+        if(CLANG)
+            set(toolchain_in_file "BUILD.clang-cl.toolchain.gn.in")
+        else()
+            set(toolchain_in_file "BUILD.msvc.toolchain.gn.in")
+        endif()
+    else()
+        set(toolchain_in_file "BUILD.toolchain.gn.in")
+    endif()
+    get_gn_arch(gn_arch ${TEST_architecture_arch})
+    if(NOT CMAKE_CROSSCOMPILING) # delivered by hostBuild project
+        configure_gn_toolchain(host ${gn_arch} ${gn_arch}
+            ${WEBENGINE_ROOT_SOURCE_DIR}/src/host/${toolchain_in_file}
+            ${buildDir}/host_toolchain)
+        configure_gn_toolchain(v8 ${gn_arch} ${gn_arch}
+            ${WEBENGINE_ROOT_SOURCE_DIR}/src/host/${toolchain_in_file}
+            ${buildDir}/v8_toolchain)
+    endif()
+    configure_gn_toolchain(target ${gn_arch} ${gn_arch}
+        ${WEBENGINE_ROOT_SOURCE_DIR}/src/host/${toolchain_in_file}
+        ${buildDir}/target_toolchain)
+    unset(gn_arch)
+    unset(toolchain_in_file)
+endmacro()
+
+macro(append_build_type_setup)
+    list(APPEND gnArgArg
+        use_ml=false
+        init_stack_vars=false
+        is_component_build=false
+        is_shared=true
+        use_sysroot=false
+        forbid_non_component_debug_builds=false
+        treat_warnings_as_errors=false
+        use_allocator_shim=false
+        use_freelist_dispatcher=false
+        use_partition_alloc=true
+        use_partition_alloc_as_malloc=false
+        use_custom_libcxx=false
+        enable_rust=false # We do not yet support rust
+        enable_chromium_prelude=false
+        assert_cpp20=false
+    )
+    if(${config} STREQUAL "Debug")
+        list(APPEND gnArgArg
+            is_debug=true
+            symbol_level=2
+            enable_mojom_message_id_scrambling=false
+        )
+        if(WIN32)
+            list(APPEND gnArgArg enable_iterator_debugging=true)
+        endif()
+    elseif(${config} STREQUAL "Release")
+        list(APPEND gnArgArg
+            is_debug=false
+            symbol_level=0
+            enable_mojom_message_id_scrambling=true
+        )
+    elseif(${config} STREQUAL "RelWithDebInfo")
+        list(APPEND gnArgArg is_debug=false enable_mojom_message_id_scrambling=true)
+        if(WIN32 AND NOT CLANG)
+            list(APPEND gnArgArg symbol_level=2)
+        else()
+            list(APPEND gnArgArg symbol_level=1)
+        endif()
+    elseif(${config} STREQUAL "MinSizeRel")
+        list(APPEND gnArgArg
+            is_debug=false
+            symbol_level=0
+            optimize_for_size=true
+            enable_mojom_message_id_scrambling=true
+        )
+    endif()
+    if(FEATURE_developer_build OR (${config} STREQUAL "Debug") OR QT_FEATURE_webengine_sanitizer)
+        list(APPEND gnArgArg
+             is_official_build=false
+             use_viz_debugger=false
+        )
+    else()
+        list(APPEND gnArgArg is_official_build=true)
+        if(NOT CLANG OR NOT QT_FEATURE_use_lld_linker)
+            list(APPEND gnArgArg
+                use_thin_lto=false
+            )
+        endif()
+    endif()
+    extend_gn_list(gnArgArg
+        ARGS is_unsafe_developer_build
+        CONDITION FEATURE_developer_build
+    )
+
+    #TODO: refactor to not check for IOS here
+    if(NOT QT_FEATURE_webengine_full_debug_info AND NOT IOS)
+        list(APPEND gnArgArg blink_symbol_level=0 v8_symbol_level=0)
+    endif()
+
+    extend_gn_list(gnArgArg ARGS use_jumbo_build CONDITION QT_FEATURE_webengine_jumbo_build)
+    if(QT_FEATURE_webengine_jumbo_build)
+        list(APPEND gnArgArg jumbo_file_merge_limit=${QT_FEATURE_webengine_jumbo_file_merge_limit})
+        if(QT_FEATURE_webengine_jumbo_file_merge_limit LESS_EQUAL 8)
+            list(APPEND gnArgArg "jumbo_build_excluded=[\"browser\"]")
+        endif()
+    endif()
+
+    extend_gn_list(gnArgArg
+        ARGS enable_precompiled_headers
+        CONDITION BUILD_WITH_PCH AND NOT LINUX
+    )
+    extend_gn_list(gnArgArg
+        ARGS dcheck_always_on
+        CONDITION QT_FEATURE_force_asserts
+    )
+endmacro()
+
+function(get_clang_version_from_runtime_path result)
+if(CLANG AND CMAKE_CXX_COMPILER)
+    if(NOT DEFINED CLANG_RUNTIME_PATH)
+        set(CLANG_PRINT_RUNTIME_DIR_COMMAND -print-runtime-dir)
+        if (MSVC)
+            # clang-cl does not accept the argument unless it's piped via /clang:
+            set(CLANG_PRINT_RUNTIME_DIR_COMMAND /clang:-print-runtime-dir)
+        endif()
+        execute_process(
+           COMMAND ${CMAKE_CXX_COMPILER} ${CLANG_PRINT_RUNTIME_DIR_COMMAND}
+           OUTPUT_VARIABLE clang_output
+           ERROR_QUIET
+           OUTPUT_STRIP_TRAILING_WHITESPACE
+        )
+        cmake_path(CONVERT "${clang_output}" TO_CMAKE_PATH_LIST clang_output NORMALIZE)
+        set(CLANG_RUNTIME_PATH "${clang_output}" CACHE INTERNAL "internal")
+        mark_as_advanced(CLANG_RUNTIME_PATH)
+     endif()
+     string(REGEX MATCH "\\/([0-9.]+)\\/" clang_run_time_path_version "${CLANG_RUNTIME_PATH}")
+     if(clang_run_time_path_version)
+         string(REPLACE "/" "" clang_run_time_path_version ${clang_run_time_path_version})
+     else()
+         string(REGEX MATCH "[0-9]+" clang_run_time_path_version ${CMAKE_CXX_COMPILER_VERSION})
+     endif()
+     set(${result} ${clang_run_time_path_version} PARENT_SCOPE)
+endif()
+endfunction()
+
+macro(append_compiler_linker_sdk_setup)
+    if(CMAKE_CXX_COMPILER_LAUNCHER)
+        list(APPEND gnArgArg cc_wrapper="${CMAKE_CXX_COMPILER_LAUNCHER}")
+    endif()
+
+    extend_gn_list(gnArgArg ARGS is_clang CONDITION CLANG)
+    extend_gn_list(gnArgArg ARGS is_mingw CONDITION MINGW)
+    extend_gn_list(gnArgArg ARGS is_msvc CONDITION MSVC)
+    extend_gn_list(gnArgArg ARGS is_gcc CONDITION LINUX AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
+
+    if(CLANG)
+        if(MACOS)
+            get_darwin_sdk_version(macSdkVersion)
+            # macOS needs to use the objcxx compiler as the cxx compiler is just a link
+            get_filename_component(clangBasePath ${CMAKE_OBJCXX_COMPILER} DIRECTORY)
+            get_filename_component(clangBasePath ${clangBasePath} DIRECTORY)
+        else()
+            get_filename_component(clangBasePath ${CMAKE_CXX_COMPILER} DIRECTORY)
+            get_filename_component(clangBasePath ${clangBasePath} DIRECTORY)
+        endif()
+            get_clang_version_from_runtime_path(clang_version)
+        if (NOT DEFINED clang_version)
+            message(FATAL_ERROR "Clang version for runtime is missing."
+                    "Please open bug report.Found clang runtime path: ${CLANG_RUNTIME_PATH}"
+            )
+        endif()
+        list(APPEND gnArgArg
+            clang_base_path="${clangBasePath}"
+            clang_version="${clang_version}"
+            clang_use_chrome_plugins=false
+            fatal_linker_warnings=false
+        )
+
+        if(MACOS)
+            list(APPEND gnArgArg
+                use_system_xcode=true
+                mac_deployment_target="${CMAKE_OSX_DEPLOYMENT_TARGET}"
+                mac_sdk_min="${macSdkVersion}"
+                use_libcxx=true
+            )
+            _qt_internal_get_apple_sdk_version(apple_sdk_version)
+            if (apple_sdk_version LESS 13.2)
+                list(APPEND gnArgArg
+                    use_sck=false
+                )
+            endif()
+        endif()
+        if(IOS)
+            list(APPEND gnArgArg
+                use_system_xcode=true
+                enable_ios_bitcode=true
+                ios_deployment_target="${CMAKE_OSX_DEPLOYMENT_TARGET}"
+                ios_enable_code_signing=false
+                use_libcxx=true
+            )
+        endif()
+        if(DEFINED QT_FEATURE_stdlib_libcpp AND LINUX)
+            extend_gn_list(gnArgArg ARGS use_libcxx
+                CONDITION QT_FEATURE_stdlib_libcpp
+            )
+        endif()
+        if(ANDROID)
+            list(APPEND gnArgArg
+                android_ndk_root="${CMAKE_ANDROID_NDK}"
+                android_ndk_version="${CMAKE_ANDROID_NDK_VERSION}"
+                clang_use_default_sample_profile=false
+                #android_ndk_major_version=22
+            )
+        endif()
+    else()
+        if(QT_FEATURE_use_lld_linker)
+            get_filename_component(clangBasePath ${CMAKE_LINKER} DIRECTORY)
+            get_filename_component(clangBasePath ${clangBasePath} DIRECTORY)
+            list(APPEND gnArgArg
+                clang_base_path="${clangBasePath}"
+                fatal_linker_warnings=false
+            )
+        endif()
+    endif()
+
+    if(MSVC)
+        get_filename_component(windows_sdk_path $ENV{WINDOWSSDKDIR} ABSOLUTE)
+        get_filename_component(visual_studio_path $ENV{VSINSTALLDIR} ABSOLUTE)
+        get_filename_component(wdk_path $ENV{WINDOWSSDKDIR} ABSOLUTE)
+        qt_webengine_get_windows_sdk_version(windows_sdk_version sdk_minor)
+        list(APPEND gnArgArg
+            win_linker_timing=true
+            use_incremental_linking=false
+            visual_studio_version=2022
+            visual_studio_path=\"${visual_studio_path}\"
+            windows_sdk_version=\"${windows_sdk_version}\"
+            windows_sdk_path=\"${windows_sdk_path}\"
+            wdk_path=\"${windows_sdk_path}\"
+            setup_toolchain_script=\"//build/toolchain/win/qwe_setup_toolchain.py\"
+        )
+    endif()
+    get_gn_arch(cpu ${TEST_architecture_arch})
+    if(LINUX AND CMAKE_CROSSCOMPILING AND cpu STREQUAL "arm")
+
+        extend_gn_list_cflag(gnArgArg
+            ARG arm_tune
+            CFLAG mtune
+        )
+        extend_gn_list_cflag(gnArgArg
+            ARG arm_float_abi
+            CFLAG mfloat-abi
+        )
+        extend_gn_list_cflag(gnArgArg
+            ARG arm_arch
+            CFLAG march
+        )
+        extend_gn_list_cflag(gnArgArg
+            ARG arm_cpu
+            CFLAG mcpu
+        )
+        extract_cflag(cflag "mfpu")
+        get_arm_version(arm_version "${cflag}")
+        extend_gn_list(gnArgArg
+            ARGS arm_use_neon
+            CONDITION (arm_version GREATER_EQUAL 8) OR ("${cflag}" MATCHES ".*neon.*")
+        )
+        if(arm_version EQUAL 7 AND NOT "${cflag}" MATCHES ".*neon.*")
+            # If the toolchain does not explicitly specify to use NEON instructions
+            # we use arm_neon_optional for ARMv7
+            list(APPEND gnArgArg arm_optionally_use_neon=true)
+        endif()
+        extract_cflag(march "march")
+        get_arm_version(arm_version ${march})
+        if(arm_version EQUAL 7)
+            list(APPEND gnArgArg use_arm_crc32=false)
+        endif()
+        check_thumb(armThumb)
+        extend_gn_list(gnArgArg
+            ARGS arm_use_thumb
+            CONDITION armThumb
+        )
+    endif()
+    extend_gn_list(gnArgArg
+        ARGS use_gold
+        CONDITION QT_FEATURE_use_gold_linker
+    )
+    extend_gn_list(gnArgArg
+        ARGS use_lld
+        CONDITION QT_FEATURE_use_lld_linker OR (MSVC AND CLANG)
+    )
+    unset(cpu)
+endmacro()
+
+macro(append_sanitizer_setup)
+    if(QT_FEATURE_webengine_sanitizer)
+        extend_gn_list(gnArgArg
+            ARGS is_asan
+            CONDITION address IN_LIST ECM_ENABLE_SANITIZERS
+        )
+        extend_gn_list(gnArgArg
+            ARGS is_tsan
+            CONDITION thread IN_LIST ECM_ENABLE_SANITIZERS
+        )
+        extend_gn_list(gnArgArg
+            ARGS is_msan
+            CONDITION memory IN_LIST ECM_ENABLE_SANITIZERS
+        )
+        extend_gn_list(gnArgArg
+            ARGS is_ubsan is_ubsan_vptr
+            CONDITION undefined IN_LIST ECM_ENABLE_SANITIZERS
+        )
+        if(APPLE)
+            list(APPEND gnArgArg
+                clang_version=\"${QT_COMPILER_VERSION_MAJOR}.${QT_COMPILER_VERSION_MINOR}.${QT_COMPILER_VERSION_PATCH}\"
+            )
+        endif()
+    endif()
+endmacro()
+
+macro(append_toolchain_setup)
+    if(WIN32)
+        if(CMAKE_CROSSCOMPILING)
+           #TODO: fetch this from HOST QT or gn
+           set(host_cpu "x64")
+           get_gn_arch(target_cpu ${TEST_architecture_arch})
+        else()
+           get_gn_arch(host_cpu ${TEST_architecture_arch})
+           set(target_cpu ${host_cpu})
+        endif()
+        list(APPEND gnArgArg target_cpu="${target_cpu}")
+        if(MINGW)
+            list(APPEND gnArgArg
+                # note '/' prefix
+                custom_toolchain="/${buildDir}/target_toolchain:target"
+                host_toolchain="/${buildDir}/host_toolchain:host"
+                host_cpu="${host_cpu}"
+            )
+        else()
+            #TODO: no point genrete this in buildDir, it is a fixed set of toolchain afterall
+            list(APPEND gnArgArg
+                # note '/' prefix
+                custom_toolchain="/${buildDir}/target_toolchain:${target_cpu}"
+                host_toolchain="/${buildDir}/target_toolchain:${host_cpu}"
+            )
+        endif()
+        unset(host_cpu)
+        unset(target_cpu)
+    elseif(LINUX)
+        get_gn_arch(cpu ${TEST_architecture_arch})
+        list(APPEND gnArgArg
+            custom_toolchain="${buildDir}/target_toolchain:target"
+            host_toolchain="${buildDir}/host_toolchain:host"
+        )
+        if(CMAKE_CROSSCOMPILING)
+            list(APPEND gnArgArg
+                v8_snapshot_toolchain="${buildDir}/v8_toolchain:v8"
+                target_cpu="${cpu}"
+            )
+        else()
+            list(APPEND gnArgArg host_cpu="${cpu}")
+        endif()
+        if(CMAKE_SYSROOT)
+            list(APPEND gnArgArg target_sysroot="${CMAKE_SYSROOT}")
+        endif()
+    elseif(MACOS)
+        get_gn_arch(cpu ${arch})
+        list(APPEND gnArgArg target_cpu="${cpu}")
+    elseif(IOS)
+        get_gn_arch(cpu ${arch})
+        get_ios_sysroot(sysroot ${arch})
+        list(APPEND gnArgArg target_cpu="${cpu}" target_sysroot="${sysroot}" target_os="ios")
+    elseif(ANDROID)
+        get_gn_arch(cpu ${TEST_architecture_arch})
+        list(APPEND gnArgArg target_os="android" target_cpu="${cpu}")
+        if(CMAKE_HOST_WIN32)
+            list(APPEND gnArgArg
+                host_toolchain="/${buildDir}/host_toolchain:host"
+                host_cpu="x64"
+                v8_snapshot_toolchain="/${buildDir}/v8_toolchain:v8"
+            )
+        endif()
+    endif()
+    unset(cpu)
+endmacro()
+
+macro(append_pkg_config_setup)
+    if(PkgConfig_FOUND)
+        list(APPEND gnArgArg
+            pkg_config="${PKG_CONFIG_EXECUTABLE}"
+            host_pkg_config="${PKG_CONFIG_HOST_EXECUTABLE}"
+        )
+        if(NOT "$ENV{PKG_CONFIG_LIBDIR}" STREQUAL "")
+            list(APPEND gnArgArg
+                system_libdir="$ENV{PKG_CONFIG_LIBDIR}"
+            )
+        endif()
+    endif()
+endmacro()
+
+function(get_configs result)
+    if(QT_GENERATOR_IS_MULTI_CONFIG)
+        set(${result} ${CMAKE_CONFIGURATION_TYPES})
+    else()
+        set(${result} ${CMAKE_BUILD_TYPE})
+    endif()
+    if(NOT ${result})
+        message(FATAL_ERROR "No valid configurations found !")
+    endif()
+    set(${result} ${${result}} PARENT_SCOPE)
+endfunction()
+
+function(get_architectures result)
+    if(CMAKE_OSX_ARCHITECTURES)
+        set(${result} ${CMAKE_OSX_ARCHITECTURES})
+    else()
+        set(${result} ${CMAKE_SYSTEM_PROCESSOR})
+    endif()
+    if(NOT ${result})
+    message(FATAL_ERROR "No valid architectures found. In case of cross-compiling make sure you have CMAKE_SYSTEM_PROCESSOR in your toolchain file.")
+    endif()
+    set(${result} ${${result}} PARENT_SCOPE)
+endfunction()
diff --git a/cmake/QtWebEngineSbomHelpers.cmake b/cmake/QtWebEngineSbomHelpers.cmake
new file mode 100644
index 00000000000..c16b5af39a7
--- /dev/null
+++ b/cmake/QtWebEngineSbomHelpers.cmake
@@ -0,0 +1,145 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+# Helper functions for SBOM generation. We defer setting up targets until the end of build setup
+# because we only want to generate e.g. one SBOM document for WebEngine. This in turn requires
+# us to only call sbom.py once for WebEngine.
+
+# Setup data structures used in other calls
+function(qt_webengine_sbom_project_begin project_name cmake_target_name)
+    if(NOT QT_GENERATE_SBOM)
+        return()
+    endif()
+
+    set_property(GLOBAL PROPERTY QTWEBENGINE_SBOM_PROJECT_NAME ${project_name})
+    set_property(GLOBAL PROPERTY QTWEBENGINE_SBOM_CMAKE_TARGET_NAME ${cmake_target_name})
+    set_property(GLOBAL PROPERTY QTWEBENGINE_SBOM_GN_TARGETS "")
+    set_property(GLOBAL PROPERTY QTWEBENGINE_SBOM_BUILD_DIRS "")
+    set_property(GLOBAL PROPERTY QTWEBENGINE_SBOM_CMAKE_TO_GN_DEPENDENCY_PAIRS "")
+endfunction()
+
+# Add a GN target to the list of components contained in an SBOM document
+function(qt_webengine_add_gn_target_to_sbom gn_target build_dir)
+    if(NOT QT_GENERATE_SBOM)
+        return()
+    endif()
+
+    get_property(project_name GLOBAL PROPERTY QTWEBENGINE_SBOM_PROJECT_NAME)
+    if(NOT DEFINED project_name)
+        message(FATAL_ERROR "Call qt_webengine_sbom_project_begin first")
+        return()
+    endif()
+
+    set_property(GLOBAL APPEND PROPERTY QTWEBENGINE_SBOM_GN_TARGETS ":${gn_target}")
+    set_property(GLOBAL APPEND PROPERTY QTWEBENGINE_SBOM_BUILD_DIRS "${build_dir}")
+endfunction()
+
+function(qt_webengine_add_gn_artifact_relationship_to_sbom ninja_target cmake_target)
+    if(NOT QT_GENERATE_SBOM)
+        return()
+    endif()
+
+    set_property(GLOBAL APPEND PROPERTY QTWEBENGINE_SBOM_CMAKE_TO_GN_DEPENDENCY_PAIRS
+        "${cmake_target};${ninja_target}")
+endfunction()
+
+# Join all the targets into (at most) two documents for Pdf / WebEngine
+function(qt_webengine_sbom_project_end)
+    if(NOT QT_GENERATE_SBOM)
+        return()
+    endif()
+
+    # We have the situation that qtbase by default does not generate JSON files if the required
+    # python dependency spdx-tools is not found.
+    # But QtWebEngine requires the spdx-tools package to be available, otherwise we can't generate
+    # a tag/value document from the Chromium-generated json file, and then link the Chromium
+    # SBOM document to the qtwebengine one.
+    # Skip the Chromium SBOM generation if the dependency is not found.
+    # A warning or skip message should have already been shown at general configure check time.
+    qt_internal_sbom_verify_deps_for_generate_tag_value_spdx_document(
+        OUT_VAR_DEPS_FOUND sbom_deps_found
+    )
+    if(NOT sbom_deps_found)
+        return()
+    endif()
+
+    get_property(project_name GLOBAL PROPERTY QTWEBENGINE_SBOM_PROJECT_NAME)
+    get_property(gn_target_list GLOBAL PROPERTY QTWEBENGINE_SBOM_GN_TARGETS)
+    get_property(build_dir_list GLOBAL PROPERTY QTWEBENGINE_SBOM_BUILD_DIRS)
+    get_property(cmake_target_name GLOBAL PROPERTY QTWEBENGINE_SBOM_CMAKE_TARGET_NAME)
+    get_property(cmake_to_gn_dep_pairs GLOBAL PROPERTY
+        QTWEBENGINE_SBOM_CMAKE_TO_GN_DEPENDENCY_PAIRS)
+
+    string(TOLOWER ${project_name} project_name_lower)
+    set(chromium_project_name QtWebEngine-Chromium-${project_name})
+    string(TOLOWER ${chromium_project_name} chromium_project_name_lower)
+    qt_internal_sbom_get_project_supplier_url(supplier_url)
+    qt_internal_sbom_compute_project_namespace(doc_namespace SUPPLIER_URL ${supplier_url}
+        PROJECT_NAME ${chromium_project_name_lower})
+    qt_internal_sbom_compute_project_file_name(output_file_name EXTENSION_JSON
+        PROJECT_NAME ${chromium_project_name_lower})
+    set(output_file_path ${WEBENGINE_ROOT_BUILD_DIR}/qt_sbom/${output_file_name})
+
+    set(generate_sbom_script_path
+        "${CMAKE_CURRENT_BINARY_DIR}/gen_qtwebengine_chromium_sbom_${project_name}-$<CONFIG>.cmake")
+    set(chromium_sbom_script
+        "${WEBENGINE_ROOT_SOURCE_DIR}/src/3rdparty/chromium/tools/licenses/sbom.py")
+    set(generate_sbom_script_contents "
+message(STATUS \"Generating Chromium SBOM for ${project_name}...\")
+execute_process(
+    COMMAND \"${CMAKE_COMMAND}\"
+        \"-DSCRIPT_PATH=${chromium_sbom_script}\"
+        \"-DGN_TARGET_LIST=${gn_target_list}\"
+        \"-DBUILD_DIR_LIST=${build_dir_list}\"
+        \"-DQT_HOST_PATH=${QT_HOST_PATH}\"
+        \"-DQT6_HOST_INFO_LIBEXECDIR=${QT6_HOST_INFO_LIBEXECDIR}\"
+        \"-DQT6_HOST_INFO_BINDIR=${QT6_HOST_INFO_BINDIR}\"
+        -DPACKAGE_ID=${project_name}
+        -DDOC_NAMESPACE=${doc_namespace}
+        \"-DOUTPUT=${output_file_path}\"
+        \"-DPython3_EXECUTABLE=${Python3_EXECUTABLE}\"
+        -P \"${WEBENGINE_ROOT_SOURCE_DIR}/cmake/QtGnSbom.cmake\"
+    WORKING_DIRECTORY \"${WEBENGINE_ROOT_BUILD_DIR}\"
+    COMMAND_ERROR_IS_FATAL ANY
+)
+file(INSTALL \"${output_file_path}\" DESTINATION \"${QT6_INSTALL_PREFIX}/${INSTALL_SBOMDIR}\")
+message(STATUS \"Done generating Chromium SBOM for ${project_name}.\")
+")
+    file(GENERATE OUTPUT "${generate_sbom_script_path}" CONTENT "${generate_sbom_script_contents}")
+    qt_internal_sbom_add_cmake_include_step(STEP BEGIN INCLUDE_PATH "${generate_sbom_script_path}")
+    qt_internal_sbom_generate_tag_value_spdx_document(
+        OPERATION_ID ${chromium_project_name_lower}
+        INPUT_JSON_FILE_PATH "${output_file_path}"
+        OUT_VAR_OUTPUT_FILE_NAME external_output_file_name
+    )
+    # Reference to external document.
+    qt_internal_sbom_get_external_document_ref_spdx_id(${chromium_project_name_lower} document_ref_spdx_id)
+    set(external_package_spdx_id "SPDXRef-${chromium_project_name}-Internal-Components")
+    qt_internal_sbom_add_external_reference(
+        EXTERNAL_DOCUMENT_FILE_PATH "sbom/${external_output_file_name}"
+        EXTERNAL_DOCUMENT_SPDX_ID "${document_ref_spdx_id}"
+        EXTERNAL_PACKAGE_SPDX_ID "${external_package_spdx_id}"
+    )
+
+    while(NOT "${cmake_to_gn_dep_pairs}" STREQUAL "")
+        list(POP_FRONT cmake_to_gn_dep_pairs cmake_target gn_target)
+        qt_internal_sbom_get_target_spdx_id("${cmake_target}" cmake_spdx_id)
+        qt_internal_sbom_get_sanitized_spdx_id(gn_spdx_id
+            "SPDXRef-${chromium_project_name}-${gn_target}")
+        set(relationship "${cmake_spdx_id} CONTAINS ${document_ref_spdx_id}:${gn_spdx_id}")
+        qt_internal_extend_target(${cmake_target}
+            SBOM_RELATIONSHIPS
+            "${relationship}"
+        )
+    endwhile()
+endfunction()
+
+# Shims for SBOM commands that may be missing < 6.9
+if(NOT COMMAND qt_internal_sbom_begin_qt_repo_project)
+    function(qt_internal_sbom_begin_qt_repo_project)
+    endfunction()
+    function(qt_internal_sbom_end_qt_repo_project)
+    endfunction()
+    function(qt_internal_sbom_add_files)
+    endfunction()
+endif()
diff --git a/coin.nodes b/coin.nodes
new file mode 100644
index 00000000000..a556e9ed1a7
--- /dev/null
+++ b/coin.nodes
@@ -0,0 +1,50 @@
+#      coin-platofrm-id               # builds-webengine # builds-pdf #
+android-arm64-on-macos                        OFF             ON
+android-armv7-on-windows                      OFF             ON
+android-9-x86-on-linux                        OFF             ON
+android-15-x86_64-on-linux                    OFF             ON
+android-14-x86_64-on-linux                    OFF             ON
+ios-universal                                 OFF             ON
+macos-14-arm64-developer-build                ON              ON
+macos-14-x86_64-developer-build               ON              ON
+macos-universal-on-arm64                      ON              ON
+macos-universal-on-x86_64                     ON              ON
+qemu-arm64-developer-build                    ON              ON
+qemu-armv7-developer-build                    ON              ON
+qemu-mips64-developer-build                   OFF             OFF
+qnx-710-arm64-on-linux                        OFF             OFF
+qnx-710-armv7-on-linux                        OFF             OFF
+qnx-710-x86_64-developer-build-on-linux       OFF             OFF
+qnx-710-arm64-on-windows                      OFF             OFF
+qnx-800-arm64-on-linux                        OFF             OFF
+qnx-800-x86_64-developer-build-on-linux       OFF             OFF
+rhel-8.10                                     ON              ON
+rhel-9.4                                      ON              ON
+sles-15_sp5-static                            OFF             ON
+sles-15_sp6-static                            OFF             ON
+ubuntu-22.04                                  ON              ON
+ubuntu-22.04-developer-build                  ON              ON
+ubuntu-24.04-arm64                            ON              ON
+ubuntu-24.04-arm64-developer-build            ON              ON
+ubuntu-24.04-x64-developer-build              ON              ON
+ubuntu-24.04-x64                              ON              ON
+webassembly-windows                           OFF             OFF
+webassembly-linux-thread                      OFF             OFF
+webassembly-linux-shared                      OFF             OFF
+webassembly-linux-thread-asyncify             OFF             OFF
+windows-10_22h2-msvc2022                      ON              ON
+windows-10_22h2-mingw13                       OFF             ON
+windows-11_22h2-arm64-msvc2022                OFF             ON
+windows-11_23h2-arm64-msvc2022                OFF             ON
+windows-11_23H2-llvm                          OFF             ON
+windows-11_23H2-msvc2022-arm64                OFF             ON
+windows-11_23H2-msvc2022                      ON              ON
+windows-11_23H2-msvc2022-developer-build      ON              ON
+windows-11_23H2-mingw13-developer-build       OFF             ON
+opensuse-15.6-host-asan                       OFF             ON
+opensuse-15.6-developer-build                 OFF             ON
+jammy-arm64-debian-pkg-packaging              ON              ON
+jammy-amd64-debian-pkg-packaging              ON              ON
+documentation-warnings                        ON              ON
+offline-documentation                         ON              ON
+visionos-developer-build                      OFF             OFF
diff --git a/coin/module_config.yaml b/coin/module_config.yaml
index 9c6e1d003e5..b30b231fb00 100644
--- a/coin/module_config.yaml
+++ b/coin/module_config.yaml
@@ -7,12 +7,62 @@ accept_configuration:
 
 machine_type:
   Build:
-    cores: 8
+    # Run Windows cross-compilation on larger VM, due to extreme length.
+    - cores: 32
+      enable_if:
+        condition: and
+        conditions:
+          - condition: property
+            property: host.os
+            equals_value: Windows
+          - condition: property
+            property: host
+            not_equals_property: target
+          - condition: property
+            property: target.os
+            not_equals_value: Android
+    - cores: 16
+      enable_if:
+        condition: and
+        conditions:
+          - condition: property
+            property: host.os
+            equals_value: Windows
+          - condition: property
+            property: host.compiler
+            contains_value: MSVC
+          - condition: property
+            property: host.arch
+            equals_value: X86_64
+    - cores: 8
+
   Test:
     cores: 4
 
 instructions:
   Build:
+    - type: AppendToEnvironmentVariable
+      variableName: COMMON_NON_QTBASE_CMAKE_ARGS
+      variableValue: " -DFEATURE_qtwebengine_build=OFF"
+      enable_if:
+        condition: or
+        conditions:
+          - condition: runtime
+            env_var: COIN_PLATFORM_ID
+            contains_value: "windows-11_22h2-arm64-msvc2022"
+          - condition: runtime
+            env_var: COIN_PLATFORM_ID
+            contains_value: "windows-11_23h2-arm64-msvc2022"
+    - type: AppendToEnvironmentVariable
+      variableName: COMMON_NON_QTBASE_CMAKE_ARGS
+      variableValue: " -DFEATURE_webengine_system_libxml=OFF -DFEATURE_webengine_system_libtiff=OFF"
+      enable_if:
+        condition: property
+        property: features
+        contains_value: Packaging
+    - type: EnvironmentVariable
+      variableName: VERIFY_SOURCE_SBOM
+      variableValue: "ON"
     - type: EnvironmentVariable
       variableName: CMAKE_BUILD_TIMEOUT
       variableValue: "36000"
diff --git a/coin/qt-installer-package-config.json b/coin/qt-installer-package-config.json
index aec45688b39..433ddfd824a 100644
--- a/coin/qt-installer-package-config.json
+++ b/coin/qt-installer-package-config.json
@@ -3,6 +3,7 @@
     "module-split": {
         "qtpdf": [
             "**/bin/*Pdf*",
+            "**/sbom/qtpdf*",
             "**/include/*QtPdf*/**/*",
             "**/lib/cmake/Qt*Gui/*Pdf*",
             "**/lib/cmake/Qt*Pdf*/*",
diff --git a/configure.cmake b/configure.cmake
index c4acca20c99..6b3b5f7705e 100644
--- a/configure.cmake
+++ b/configure.cmake
@@ -12,6 +12,7 @@ qt_webengine_set_version(python3 3.8)
 qt_webengine_set_version(nodejs 14.9)
 qt_webengine_set_version(nss 3.26)
 qt_webengine_set_version(gcc 10.0)
+qt_webengine_set_version(gcc-pdf 9.0)
 qt_webengine_set_version(glib 2.32.0)
 qt_webengine_set_version(glibc 2.16)
 qt_webengine_set_version(harfbuzz 4.3.0)
@@ -24,6 +25,7 @@ qt_webengine_set_version(vpx 1.10.0)
 qt_webengine_set_version(libavutil 58.29.100)
 qt_webengine_set_version(libavcodec 60.31.102)
 qt_webengine_set_version(libavformat 60.16.100)
+qt_webengine_set_version(windows_sdk 26100) # we only care about minor number "10.0.26100.0"
 
 if(QT_CONFIGURE_RUNNING)
     function(qt_webengine_configure_check)
@@ -35,10 +37,9 @@ if(QT_CONFIGURE_RUNNING)
 else()
     find_package(Ninja ${QT_CONFIGURE_CHECK_ninja_version})
     find_package(Gn ${QT_REPO_MODULE_VERSION} EXACT)
-    find_program(Python3_EXECUTABLE NAMES python3 python HINTS $ENV{PYTHON3_PATH})
-    if(NOT Python3_EXECUTABLE)
-        find_package(Python3 ${QT_CONFIGURE_CHECK_python3_version})
-    endif()
+    set(Python3_ROOT_DIR $ENV{PYTHON3_PATH})
+    find_package(Python3 ${QT_CONFIGURE_CHECK_python3_version})
+    unset(Python3_ROOT_DIR)
     find_package(GPerf)
     find_package(BISON)
     find_package(FLEX)
@@ -46,6 +47,10 @@ else()
     find_package(PkgConfig)
     find_package(Snappy)
     find_package(Nodejs ${QT_CONFIGURE_CHECK_nodejs_version})
+    _qt_internal_sbom_verify_deps_for_generate_tag_value_spdx_document(
+        OUT_VAR_DEPS_FOUND sbom_deps_found
+        OUT_VAR_REASON_FAILURE_MESSAGE sbom_missing_deps_message
+    )
 endif()
 
 if(PkgConfig_FOUND)
@@ -87,6 +92,7 @@ if(PkgConfig_FOUND)
     pkg_check_modules(XKBCOMMON xkbcommon)
     pkg_check_modules(XKBFILE xkbfile)
     pkg_check_modules(XCBDRI3 xcb-dri3)
+    pkg_check_modules(LIBUDEV libudev)
 endif()
 
 if(Python3_EXECUTABLE)
@@ -156,31 +162,20 @@ int main() {
 }"
 )
 
-qt_config_compile_test(snappy
+qt_config_compile_test(webengine_system_snappy
     LABEL "snappy"
     LIBRARIES
         Snappy::Snappy
     CODE
 "
 #include \"snappy.h\"
+#include <string>
 int main() {
     snappy::Source *src = 0;
     snappy::Sink *sink = 0;
-    return 0;
-}"
-)
-
-qt_config_compile_test(libxml2
-    LABEL "compatible libxml2 and libxslt"
-    LIBRARIES
-        PkgConfig::LIBXML2
-    CODE
-"
-#include \"libxml/xmlversion.h\"
-#if !defined(LIBXML_ICU_ENABLED)
-#error libxml icu not enabled
-#endif
-int main() {
+    const char *str = \"string\";
+    std::string compressed;
+    snappy::Compress(str, 7, &compressed);
     return 0;
 }"
 )
@@ -270,7 +265,9 @@ qt_webengine_configure_check("compiler-cxx20"
     MODULES QtWebEngine QtPdf
     CONDITION TEST_cxx20
     MESSAGE "Missing C++20 compiler support."
+
     DOCUMENTATION "C++20 compiler support"
+
 )
 
 qt_webengine_configure_check("cmake"
@@ -292,22 +289,14 @@ foreach(target_to_check ${targets_to_check})
 endforeach()
 unset(targets_to_check)
 
-if(WIN32 AND (CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64" OR
-         CMAKE_SYSTEM_PROCESSOR STREQUAL "ARM64" OR
-         CMAKE_CROSSCOMPILING))
-    set(WIN_ARM_64 ON)
-else()
-    set(WIN_ARM_64 OFF)
-endif()
-
 qt_webengine_configure_check("supported-platform"
     MODULES QtWebEngine
-    CONDITION LINUX OR (WIN32 AND NOT WIN_ARM_64) OR MACOS
+    CONDITION LINUX OR WIN32 OR MACOS
     MESSAGE "Build can be done only on Linux, Windows or macOS."
 )
 qt_webengine_configure_check("supported-platform"
     MODULES QtPdf
-    CONDITION LINUX OR (WIN32 AND NOT WIN_ARM_64) OR MACOS OR IOS OR ANDROID
+    CONDITION LINUX OR WIN32 OR MACOS OR IOS OR ANDROID
     MESSAGE "Build can be done only on Linux, Windows, macO, iOS and Android."
 )
 
@@ -328,7 +317,7 @@ qt_webengine_configure_check("static-build"
 )
 
 qt_webengine_configure_check("nodejs"
-    MODULES QtWebEngine QtPdf
+    MODULES QtWebEngine
     CONDITION TARGET Nodejs::Nodejs AND
         NOT (Nodejs_ARCH STREQUAL "ia32") AND
         NOT (Nodejs_ARCH STREQUAL "x86") AND
@@ -338,29 +327,37 @@ qt_webengine_configure_check("nodejs"
 )
 qt_webengine_configure_check("python3"
     MODULES QtWebEngine QtPdf
-    CONDITION Python3_EXECUTABLE
-    MESSAGE "Python ${QT_CONFIGURE_CHECK_python3_version} or later is required."
+    CONDITION Python3_FOUND
+    MESSAGE "Python ${QT_CONFIGURE_CHECK_python3_version} or later is required. Please use -DPython3_EXECUTABLE for custom path to interpreter."
     DOCUMENTATION "Python ${QT_CONFIGURE_CHECK_python3_version} version or later."
 )
+if(QT_GENERATE_SBOM AND QT_SBOM_GENERATE_JSON AND QT_SBOM_REQUIRE_GENERATE_JSON)
+    qt_webengine_configure_check("sbom-generate-json"
+        MODULES QtWebEngine QtPdf
+        CONDITION sbom_deps_found
+        MESSAGE
+            "SBOM JSON file generation requirements missing, but JSON files were explicitly required. ${sbom_missing_deps_message}"
+    )
+endif()
 qt_webengine_configure_check("python3-html5lib"
-    MODULES QtWebEngine QtPdf
+    MODULES QtWebEngine
     CONDITION Python3_EXECUTABLE AND NOT html5lib_NOT_FOUND
-    MESSAGE "Python3 html5lib is missing."
+    MESSAGE "Python3 html5lib is missing (${Python3_EXECUTABLE})."
     DOCUMENTATION "Python3 html5lib module.")
 qt_webengine_configure_check("gperf"
-    MODULES QtWebEngine QtPdf
+    MODULES QtWebEngine
     CONDITION GPerf_FOUND
     MESSAGE "Tool gperf is required."
     DOCUMENTATION "GNU gperf binary."
 )
 qt_webengine_configure_check("bison"
-    MODULES QtWebEngine QtPdf
+    MODULES QtWebEngine
     CONDITION BISON_FOUND
     MESSAGE "Tool bison is required."
     DOCUMENTATION "GNU bison binary."
 )
 qt_webengine_configure_check("flex"
-    MODULES QtWebEngine QtPdf
+    MODULES QtWebEngine
     CONDITION FLEX_FOUND
     MESSAGE "Tool flex is required."
     DOCUMENTATION "GNU flex binary."
@@ -373,14 +370,14 @@ qt_webengine_configure_check("pkg-config"
     TAGS LINUX_PLATFORM
 )
 qt_webengine_configure_check("glibc"
-    MODULES QtWebEngine QtPdf
+    MODULES QtWebEngine
     CONDITION NOT LINUX OR TEST_glibc
     MESSAGE "A suitable version >= ${QT_CONFIGURE_CHECK_glibc_version} of glibc is required."
     DOCUMENTATION "glibc library at least ${QT_CONFIGURE_CHECK_glibc_version} version or later."
     TAGS LINUX_PLATFORM
 )
 qt_webengine_configure_check("glib"
-    MODULES QtWebEngine QtPdf
+    MODULES QtWebEngine
     CONDITION NOT UNIX OR GLIB_FOUND
     MESSAGE "No glib library at least ${QT_CONFIGURE_CHECK_glib_version} version or later. Using build-in one"
     DOCUMENTATION "glib library at least ${QT_CONFIGURE_CHECK_glib_version} version or later."
@@ -396,7 +393,7 @@ qt_webengine_configure_check("harfbuzz"
     OPTIONAL
 )
 qt_webengine_configure_check("mesa-headers"
-    MODULES QtWebEngine QtPdf
+    MODULES QtWebEngine
     CONDITION NOT LINUX OR TEST_khr
     MESSAGE "Build requires Khronos development headers for build - see mesa/libegl1-mesa-dev"
     DOCUMENTATION "Mesa development headers."
@@ -423,6 +420,14 @@ qt_webengine_configure_check("dbus"
     DOCUMENTATION "Dbus"
     TAGS LINUX_PKG_CONFIG
 )
+qt_webengine_configure_check("libudev"
+    MODULES QtWebEngine
+    CONDITION NOT UNIX OR LIBUDEV_FOUND
+    MESSAGE "No libudev found."
+    DOCUMENTATION "libudev library."
+    TAGS PLATFROM_MACOS PLATFORM_LINUX
+    OPTIONAL
+)
 
 # Only check for the 'xcb' feature if the Gui targets exists, aka Qt was not configured with
 # -no-gui.
@@ -489,7 +494,7 @@ qt_webengine_configure_check("msvc-2022"
 )
 
 qt_webengine_configure_check("gcc"
-    MODULES QtWebEngine QtPdf
+    MODULES QtWebEngine
     CONDITION NOT (LINUX OR MINGW) OR NOT CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR
               NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS ${QT_CONFIGURE_CHECK_gcc_version}
     MESSAGE "GCC version must be at least ${QT_CONFIGURE_CHECK_gcc_version}"
@@ -497,6 +502,15 @@ qt_webengine_configure_check("gcc"
     TAGS LINUX_PLATFORM
 )
 
+qt_webengine_configure_check("gcc-pdf"
+    MODULES QtPdf
+    CONDITION NOT (LINUX OR MINGW) OR NOT CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR
+              NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS ${QT_CONFIGURE_CHECK_gcc-pdf_version}
+    MESSAGE "GCC version must be at least ${QT_CONFIGURE_CHECK_gcc-pdf_version}"
+    DOCUMENTATION "GCC version must be at least ${QT_CONFIGURE_CHECK_gcc-pdf_version}"
+    TAGS LINUX_PLATFORM
+)
+
 if(WIN32)
     qt_webengine_get_windows_sdk_version(windows_sdk_version sdk_minor)
     message("-- Windows 10 SDK version: ${windows_sdk_version}")
@@ -505,9 +519,9 @@ endif()
 
 qt_webengine_configure_check("windows-sdk"
     MODULES QtWebEngine
-    CONDITION NOT WIN32 OR sdk_minor GREATER_EQUAL 22621
-    MESSAGE "Build requires Windows 11 SDK at least version 10.0.22621.0"
-    DOCUMENTATION "Windows 11 SDK at least version 10.0.22621.0"
+    CONDITION NOT WIN32 OR sdk_minor GREATER_EQUAL ${QT_CONFIGURE_CHECK_windows_sdk_version}
+    MESSAGE "Build requires Windows 11 SDK at least version 10.0.${QT_CONFIGURE_CHECK_windows_sdk_version}.0"
+    DOCUMENTATION "Windows 11 SDK at least version 10.0.${QT_CONFIGURE_CHECK_windows_sdk_version}.0"
     TAGS WINDOWS_PLATFORM
 )
 unset(sdk_minor)
@@ -619,7 +633,7 @@ qt_feature("webengine-system-libvpx" PRIVATE
 )
 qt_feature("webengine-system-snappy" PRIVATE
     LABEL "snappy"
-    CONDITION UNIX AND TEST_snappy
+    CONDITION UNIX AND TEST_webengine_system_snappy
 )
 qt_feature("webengine-system-glib" PRIVATE
     LABEL "glib"
@@ -645,7 +659,7 @@ qt_feature("webengine-system-libevent" PRIVATE
 )
 qt_feature("webengine-system-libxml" PRIVATE
     LABEL "libxml2 and libxslt"
-    CONDITION UNIX AND TEST_libxml2
+    CONDITION UNIX AND LIBXML2_FOUND
 )
 qt_feature("webengine-system-lcms2" PRIVATE
     LABEL "lcms2"
@@ -704,6 +718,11 @@ qt_feature("webengine-system-libpci" PRIVATE
     CONDITION UNIX AND LIBPCI_FOUND
 )
 
+qt_feature("webengine-system-libudev" PRIVATE
+    LABEL "libudev"
+    CONDITION UNIX AND LIBUDEV_FOUND
+)
+
 qt_feature("webengine-ozone-x11" PRIVATE
     LABEL "Support X11 on qpa-xcb"
     CONDITION LINUX
@@ -712,6 +731,12 @@ qt_feature("webengine-ozone-x11" PRIVATE
         AND qpa_xcb_support_check
 )
 
+qt_feature("webengine-gcc-legacy-support" PRIVATE
+    LABEL "gcc-legacy-support"
+    CONDITION UNIX AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU"
+        AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 10.0
+        AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL ${QT_CONFIGURE_CHECK_gcc-pdf_version}
+)
 
 #### Summary
 
@@ -752,6 +777,7 @@ if(UNIX)
     qt_configure_add_summary_entry(ARGS "webengine-system-harfbuzz")
     qt_configure_add_summary_entry(ARGS "webengine-system-freetype")
     qt_configure_add_summary_entry(ARGS "webengine-system-libpci")
+    qt_configure_add_summary_entry(ARGS "webengine-system-libudev")
     qt_configure_end_summary_section()
 endif()
 
@@ -811,4 +837,12 @@ if(NOT QT_SUPERBUILD)
         CONDITION QT_SHOW_EXTRA_IDE_SOURCES OR (NOT DEFINED QT_SHOW_EXTRA_IDE_SOURCES AND CMAKE_VERSION VERSION_GREATER_EQUAL 3.20)
     )
 endif()
-
+# Only show the warning if JSON generation is not required. For the case when it is required,
+# there's an extra configure check.
+if(QT_GENERATE_SBOM AND NOT QT_SBOM_REQUIRE_GENERATE_JSON)
+    qt_configure_add_report_entry(
+        TYPE WARNING
+        MESSAGE "Qt WebEngine And Qt Pdf SBOM generation will be skipped due to missing dependencies. ${sbom_missing_deps_message}"
+        CONDITION NOT sbom_deps_found
+    )
+endif()
diff --git a/dependencies.yaml b/dependencies.yaml
index 6283dc1146f..b1d08d8a063 100644
--- a/dependencies.yaml
+++ b/dependencies.yaml
@@ -1,13 +1,13 @@
 dependencies:
   ../qtdeclarative:
-    ref: f5673f1e0e139fab33a456275b015fe4e5ca3986
+    ref: 4e29e04ddb6dba0a029a40110abe9bb5b55cd89f
     required: true
   ../qtpositioning:
-    ref: 7db6885dce399ad7ef47493c612127b71d3b229d
+    ref: e0a2f577baee911de24a750d07d8ad982223ce26
     required: false
   ../qttools:
-    ref: 3557f0897aa2624b633a0bb83f1970245de37e1f
+    ref: 09bd648b8c60c7cf66622fea0c216359643d1332
     required: false
   ../qtwebchannel:
-    ref: a13deb0fbd2f0af0c23311b83c3783ab27140a56
+    ref: f12a626f2a39f7ca2e0149979b3bfe7d26bb980b
     required: false
diff --git a/examples/pdf/CMakeLists.txt b/examples/pdf/CMakeLists.txt
index bdc1d0f0524..7255752b814 100644
--- a/examples/pdf/CMakeLists.txt
+++ b/examples/pdf/CMakeLists.txt
@@ -3,6 +3,3 @@
 
 qt_internal_add_example(singlepage)
 qt_internal_add_example(multipage)
-if(NOT TARGET Qt::Svg)
-    message(WARNING "QtSvg is required as runtime dependency for qtpdfquick examples.")
-endif()
diff --git a/examples/pdf/multipage/CMakeLists.txt b/examples/pdf/multipage/CMakeLists.txt
index 8f8111c826d..fb4e449fd7a 100644
--- a/examples/pdf/multipage/CMakeLists.txt
+++ b/examples/pdf/multipage/CMakeLists.txt
@@ -12,7 +12,10 @@ endif()
 
 set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/pdf/multipage")
 
-find_package(Qt6 REQUIRED COMPONENTS Gui Qml)
+find_package(Qt6 REQUIRED COMPONENTS Gui Qml OPTIONAL_COMPONENTS Svg)
+if(NOT TARGET Qt::Svg)
+    message(WARNING "QtSvg is required as runtime dependency for qtpdfquick examples.")
+endif()
 
 qt_add_executable(multipage
     main.cpp
diff --git a/examples/pdf/multipage/viewer.qrc b/examples/pdf/multipage/viewer.qrc
index e786ae4ce6c..b8ec1c8c68e 100644
--- a/examples/pdf/multipage/viewer.qrc
+++ b/examples/pdf/multipage/viewer.qrc
@@ -1,5 +1,5 @@
 <RCC>
-    <qresource prefix="/singlepage">
+    <qresource prefix="/multipage">
         <file>viewer.qml</file>
         <file>resources/document-open.svg</file>
         <file>resources/edit-clear.svg</file>
diff --git a/examples/pdf/singlepage/CMakeLists.txt b/examples/pdf/singlepage/CMakeLists.txt
index fac95f54a98..647a30f8d4d 100644
--- a/examples/pdf/singlepage/CMakeLists.txt
+++ b/examples/pdf/singlepage/CMakeLists.txt
@@ -12,7 +12,10 @@ endif()
 
 set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/pdf/singlepage")
 
-find_package(Qt6 REQUIRED COMPONENTS Gui Qml)
+find_package(Qt6 REQUIRED COMPONENTS Gui Qml OPTIONAL_COMPONENTS Svg)
+if(NOT TARGET Qt::Svg)
+    message(WARNING "QtSvg is required as runtime dependency for qtpdfquick examples.")
+endif()
 
 qt_add_executable(pdfviewerquick
     main.cpp
diff --git a/examples/webenginequick/lifecycle/CMakeLists.txt b/examples/webenginequick/lifecycle/CMakeLists.txt
index 46478b622cf..2da4246c07b 100644
--- a/examples/webenginequick/lifecycle/CMakeLists.txt
+++ b/examples/webenginequick/lifecycle/CMakeLists.txt
@@ -30,14 +30,20 @@ target_link_libraries(lifecycle PUBLIC
     Qt::WebEngineQuick
 )
 
-# Resources:
+qt_add_qml_module(lifecycle
+    URI LifecycleUtils
+    VERSION 1.0
+    QML_FILES
+        "WebBrowser.qml"
+        "WebTab.qml"
+        "WebTabBar.qml"
+        "WebTabButton.qml"
+        "WebTabStack.qml"
+        "WebToolButton.qml"
+    RESOURCE_PREFIX /
+)
+
 set(resources_resource_files
-    "WebBrowser.qml"
-    "WebTab.qml"
-    "WebTabBar.qml"
-    "WebTabButton.qml"
-    "WebTabStack.qml"
-    "WebToolButton.qml"
     "qtquickcontrols2.conf"
 )
 
diff --git a/examples/webenginequick/lifecycle/main.cpp b/examples/webenginequick/lifecycle/main.cpp
index 1f45ad0ee03..185dc460c9b 100644
--- a/examples/webenginequick/lifecycle/main.cpp
+++ b/examples/webenginequick/lifecycle/main.cpp
@@ -16,6 +16,6 @@ int main(int argc, char *argv[])
     QQmlApplicationEngine engine;
     Utils utils;
     engine.rootContext()->setContextProperty("utils", &utils);
-    engine.load(QUrl(QStringLiteral("qrc:/WebBrowser.qml")));
+    engine.load(QUrl(QStringLiteral("qrc:/LifecycleUtils/WebBrowser.qml")));
     return app.exec();
 }
diff --git a/examples/webenginequick/quicknanobrowser/CMakeLists.txt b/examples/webenginequick/quicknanobrowser/CMakeLists.txt
index 7efb6112761..058f345d75e 100644
--- a/examples/webenginequick/quicknanobrowser/CMakeLists.txt
+++ b/examples/webenginequick/quicknanobrowser/CMakeLists.txt
@@ -43,27 +43,17 @@ target_link_libraries(quicknanobrowser PUBLIC
 qt_add_qml_module(quicknanobrowser
     URI BrowserUtils
     VERSION 1.0
+    QML_FILES
+        "ApplicationRoot.qml"
+        "BrowserDialog.qml"
+        "BrowserWindow.qml"
+        "DownloadView.qml"
+        "FindBar.qml"
+        "FullScreenNotification.qml"
+        "WebAuthDialog.qml"
     RESOURCE_PREFIX /
 )
 
-# Resources:
-set(resources_resource_files
-    "ApplicationRoot.qml"
-    "BrowserDialog.qml"
-    "BrowserWindow.qml"
-    "DownloadView.qml"
-    "FindBar.qml"
-    "FullScreenNotification.qml"
-    "WebAuthDialog.qml"
-)
-
-qt_add_resources(quicknanobrowser "resources"
-    PREFIX
-        "/"
-    FILES
-        ${resources_resource_files}
-)
-
 set(resources1_resource_files
     "icons/3rdparty/go-next.png"
     "icons/3rdparty/go-previous.png"
diff --git a/examples/webenginequick/quicknanobrowser/main.cpp b/examples/webenginequick/quicknanobrowser/main.cpp
index 1e693cbcd26..1267986a4f9 100644
--- a/examples/webenginequick/quicknanobrowser/main.cpp
+++ b/examples/webenginequick/quicknanobrowser/main.cpp
@@ -41,7 +41,7 @@ int main(int argc, char **argv)
     parser.process(app);
 
     QQmlApplicationEngine appEngine;
-    appEngine.load(QUrl("qrc:/ApplicationRoot.qml"));
+    appEngine.load(QUrl("qrc:/BrowserUtils/ApplicationRoot.qml"));
     if (appEngine.rootObjects().isEmpty())
         qFatal("Failed to load sources");
 
diff --git a/examples/webenginewidgets/clientcertificate/CMakeLists.txt b/examples/webenginewidgets/clientcertificate/CMakeLists.txt
index 97c9393ffce..ef1f9a6d415 100644
--- a/examples/webenginewidgets/clientcertificate/CMakeLists.txt
+++ b/examples/webenginewidgets/clientcertificate/CMakeLists.txt
@@ -14,20 +14,20 @@ set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/webenginewidgets/clientcertificat
 
 find_package(Qt6 REQUIRED COMPONENTS Core Gui WebEngineWidgets)
 
-qt_add_executable(server
+qt_add_executable(example_cert_server
     server.cpp
 )
 
-qt_add_executable(client
+qt_add_executable(example_cert_client
     client.cpp
 )
 
-set_target_properties(client PROPERTIES
+set_target_properties(example_cert_client PROPERTIES
     WIN32_EXECUTABLE TRUE
     MACOSX_BUNDLE TRUE
 )
 
-qt_add_resources(client "client"
+qt_add_resources(example_cert_client "client"
     PREFIX
         "/"
     FILES
@@ -35,7 +35,7 @@ qt_add_resources(client "client"
        "resources/client.key"
 )
 
-qt_add_resources(server "server"
+qt_add_resources(example_cert_server "server"
     PREFIX
         "/"
     FILES
@@ -44,16 +44,16 @@ qt_add_resources(server "server"
        "resources/ca.pem"
 )
 
-target_link_libraries(client PUBLIC
+target_link_libraries(example_cert_client PUBLIC
     Qt::WebEngineWidgets
 )
 
-target_link_libraries(server PUBLIC
+target_link_libraries(example_cert_server PUBLIC
     Qt::Core
     Qt::Network
 )
 
-install(TARGETS server client
+install(TARGETS example_cert_server example_cert_client
     RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
     BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
     LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
diff --git a/examples/webenginewidgets/clientcertificate/client.cpp b/examples/webenginewidgets/clientcertificate/client.cpp
index 1227fa28e8a..c10cff24769 100644
--- a/examples/webenginewidgets/clientcertificate/client.cpp
+++ b/examples/webenginewidgets/clientcertificate/client.cpp
@@ -21,11 +21,17 @@ int main(int argc, char *argv[])
     QApplication app(argc, argv);
 
     QFile certFile(":/resources/client.pem");
-    certFile.open(QIODevice::ReadOnly);
+    if (!certFile.open(QIODevice::ReadOnly)) {
+        qFatal("Failed to read cert file %s: %s", qPrintable(certFile.fileName()),
+               qPrintable(certFile.errorString()));
+    }
     const QSslCertificate cert(certFile.readAll(), QSsl::Pem);
 
     QFile keyFile(":/resources/client.key");
-    keyFile.open(QIODevice::ReadOnly);
+    if (!keyFile.open(QIODevice::ReadOnly)) {
+        qFatal("Failed to read key file %s: %s", qPrintable(keyFile.fileName()),
+               qPrintable(keyFile.errorString()));
+    }
     const QSslKey sslKey(keyFile.readAll(), QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey, "");
 
     QWebEngineProfile::defaultProfile()->clientCertificateStore()->add(cert, sslKey);
@@ -36,7 +42,7 @@ int main(int argc, char *argv[])
 
     QObject::connect(
             &page, &QWebEnginePage::selectClientCertificate, &page,
-            [&cert](QWebEngineClientCertificateSelection selection) {
+            [](QWebEngineClientCertificateSelection selection) {
                 QDialog dialog;
                 QVBoxLayout *layout = new QVBoxLayout;
                 QLabel *label = new QLabel(QLatin1String("Select certificate"));
diff --git a/examples/webenginewidgets/clientcertificate/server.cpp b/examples/webenginewidgets/clientcertificate/server.cpp
index ee83dab8a59..0d1bf771030 100644
--- a/examples/webenginewidgets/clientcertificate/server.cpp
+++ b/examples/webenginewidgets/clientcertificate/server.cpp
@@ -38,7 +38,10 @@ int main(int argc, char *argv[])
     configuration.setPeerVerifyMode(QSslSocket::VerifyPeer);
 
     QFile keyFile(":/resources/server.key");
-    keyFile.open(QIODevice::ReadOnly);
+    if (!keyFile.open(QIODevice::ReadOnly)) {
+        qFatal("Failed to read key file %s: %s", qPrintable(keyFile.fileName()),
+               qPrintable(keyFile.errorString()));
+    }
 
     QSslKey key(keyFile.readAll(), QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey);
     configuration.setPrivateKey(key);
diff --git a/examples/webenginewidgets/contentmanipulation/mainwindow.cpp b/examples/webenginewidgets/contentmanipulation/mainwindow.cpp
index 3990be2b8a7..4e661f4d825 100644
--- a/examples/webenginewidgets/contentmanipulation/mainwindow.cpp
+++ b/examples/webenginewidgets/contentmanipulation/mainwindow.cpp
@@ -12,7 +12,10 @@ MainWindow::MainWindow(const QUrl& url)
 
     QFile file;
     file.setFileName(":/jquery.min.js");
-    file.open(QIODevice::ReadOnly);
+    if (!file.open(QIODevice::ReadOnly)) {
+        qFatal("Failed to read jQuery file %s: %s", qPrintable(file.fileName()),
+               qPrintable(file.errorString()));
+    }
     jQuery = file.readAll();
     jQuery.append("\nvar qt = { 'jQuery': jQuery.noConflict(true) };");
     file.close();
diff --git a/examples/webenginewidgets/maps/mainwindow.cpp b/examples/webenginewidgets/maps/mainwindow.cpp
index 07b8d8ab3da..31cc0bbf0cb 100644
--- a/examples/webenginewidgets/maps/mainwindow.cpp
+++ b/examples/webenginewidgets/maps/mainwindow.cpp
@@ -13,8 +13,7 @@ MainWindow::MainWindow(QWidget *parent)
 
     QWebEnginePage *page = m_view->page();
 
-    connect(page, &QWebEnginePage::permissionRequested,
-            [this, page](QWebEnginePermission permission) {
+    connect(page, &QWebEnginePage::permissionRequested, [this](QWebEnginePermission permission) {
         if (permission.permissionType() != QWebEnginePermission::PermissionType::Geolocation)
             return;
 
diff --git a/examples/webenginewidgets/permissionbrowser/CMakeLists.txt b/examples/webenginewidgets/permissionbrowser/CMakeLists.txt
index c4d8f9cd43e..c7d241d8f67 100644
--- a/examples/webenginewidgets/permissionbrowser/CMakeLists.txt
+++ b/examples/webenginewidgets/permissionbrowser/CMakeLists.txt
@@ -1,7 +1,7 @@
 # Copyright (C) 2024 The Qt Company Ltd.
 # SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
 
-cmake_minimum_required(VERSION 3.5)
+cmake_minimum_required(VERSION 3.16)
 project(permissionbrowser LANGUAGES CXX)
 
 set(CMAKE_AUTOMOC ON)
diff --git a/examples/webenginewidgets/permissionbrowser/doc/src/permissionbrowser.qdoc b/examples/webenginewidgets/permissionbrowser/doc/src/permissionbrowser.qdoc
index fd01cf42da6..6a71d5da8cc 100644
--- a/examples/webenginewidgets/permissionbrowser/doc/src/permissionbrowser.qdoc
+++ b/examples/webenginewidgets/permissionbrowser/doc/src/permissionbrowser.qdoc
@@ -193,7 +193,7 @@
     \list
         \li \l QWebEngineProfile::StoreOnDisk is the default, and it ensures
         that any permissions that have been granted in the current application run will be
-        loaded back up at next startup. A permission onlycneeds to be granted once, and
+        loaded back up at next startup. A permission only needs to be granted once, and
         subsequent uses of the API that triggered the request will automatically be granted,
         until the application calls QWebEnginePermission::reset().
         \li \l QWebEngineProfile::StoreInMemory Has the same behavior as above,
diff --git a/examples/webenginewidgets/permissionbrowser/mainwindow.cpp b/examples/webenginewidgets/permissionbrowser/mainwindow.cpp
index 8fd811e8383..1cc9b74efd6 100644
--- a/examples/webenginewidgets/permissionbrowser/mainwindow.cpp
+++ b/examples/webenginewidgets/permissionbrowser/mainwindow.cpp
@@ -9,30 +9,23 @@
 #include <QUrl>
 
 PermissionDialog::PermissionDialog(const QWebEngineProfile *profile, QWidget *parent)
-    : QDialog(parent)
-    , m_profile(profile)
-    , m_permission(nullptr)
+    : QDialog(parent), m_profile(profile)
 {
     setupUi(this);
 
     auto metaEnum = QMetaEnum::fromType<QWebEnginePermission::PermissionType>();
-    Q_ASSERT(metaEnum.value((quint8)QWebEnginePermission::PermissionType::Unsupported) == 0);
-    for (int i = 1; i < metaEnum.keyCount(); ++i) {
-        QWebEnginePermission::PermissionType permissionType = QWebEnginePermission::PermissionType(metaEnum.value(i));
+    for (int i = 0; i < metaEnum.keyCount(); ++i) {
+        auto permissionType = QWebEnginePermission::PermissionType(metaEnum.value(i));
         if (QWebEnginePermission::isPersistent(permissionType))
-            m_permissionTypeComboBox->addItem(metaEnum.valueToKey((quint8)permissionType), QVariant::fromValue(permissionType));
+            m_permissionTypeComboBox->addItem(metaEnum.key(i), QVariant::fromValue(permissionType));
     }
 }
 
-PermissionDialog::~PermissionDialog()
+QWebEnginePermission PermissionDialog::permission() const
 {
-    delete m_permission;
-}
-
-QWebEnginePermission PermissionDialog::permission()
-{
-    return m_profile->queryPermission(QUrl(m_originLineEdit->text()),
-        QWebEnginePermission::PermissionType(m_permissionTypeComboBox->itemData(m_permissionTypeComboBox->currentIndex()).toInt()));
+    return m_profile->queryPermission(
+            QUrl(m_originLineEdit->text()),
+            m_permissionTypeComboBox->currentData().value<QWebEnginePermission::PermissionType>());
 }
 
 PermissionWidget::PermissionWidget(const QWebEnginePermission &permission, QWidget *parent)
@@ -92,6 +85,13 @@ MainWindow::MainWindow(const QUrl &url)
     , m_pendingWidget(nullptr)
 {
     setupUi(this);
+
+    auto metaEnum = QMetaEnum::fromType<QWebEngineProfile::PersistentPermissionsPolicy>();
+    for (int i = 0; i < metaEnum.keyCount(); ++i) {
+        auto policy = QWebEngineProfile::PersistentPermissionsPolicy(metaEnum.value(i));
+        m_policyComboBox->addItem(metaEnum.key(i), QVariant::fromValue(policy));
+    }
+
     m_urlLineEdit->setText(url.toString());
 
     m_layout->addItem(new QSpacerItem(0,0, QSizePolicy::Minimum, QSizePolicy::Expanding));
@@ -204,21 +204,10 @@ void MainWindow::handleForwardClicked()
     m_webview->triggerPageAction(QWebEnginePage::Forward);
 }
 
-void MainWindow::handlePolicyComboBoxIndexChanged(int index)
+void MainWindow::handlePolicyComboBoxIndexChanged(int)
 {
-    QWebEngineProfile::PersistentPermissionsPolicy policy;
-    switch (index) {
-    case 0:
-        policy = QWebEngineProfile::PersistentPermissionsPolicy::AskEveryTime;
-        break;
-    case 1:
-        policy = QWebEngineProfile::PersistentPermissionsPolicy::StoreInMemory;
-        break;
-    case 2:
-        policy = QWebEngineProfile::PersistentPermissionsPolicy::StoreOnDisk;
-        break;
-    }
-
+    auto policy =
+            m_policyComboBox->currentData().value<QWebEngineProfile::PersistentPermissionsPolicy>();
     if (policy == m_profile->persistentPermissionsPolicy())
         return;
 
diff --git a/examples/webenginewidgets/permissionbrowser/mainwindow.h b/examples/webenginewidgets/permissionbrowser/mainwindow.h
index 8f7a0945035..ce239be8250 100644
--- a/examples/webenginewidgets/permissionbrowser/mainwindow.h
+++ b/examples/webenginewidgets/permissionbrowser/mainwindow.h
@@ -20,12 +20,10 @@ class PermissionDialog : public QDialog, public Ui_PermissionDialog
     Q_OBJECT
 public:
     PermissionDialog(const QWebEngineProfile *profile, QWidget *parent = nullptr);
-    ~PermissionDialog();
-    QWebEnginePermission permission();
+    QWebEnginePermission permission() const;
 
 private:
     const QWebEngineProfile *m_profile;
-    QWebEnginePermission *m_permission;
 };
 
 class PermissionWidget : public QWidget, public Ui_PermissionWidget
@@ -60,7 +58,7 @@ private slots:
     void handleRefreshClicked();
     void handleBackClicked();
     void handleForwardClicked();
-    void handlePolicyComboBoxIndexChanged(int index);
+    void handlePolicyComboBoxIndexChanged(int);
 
 private:
     bool containsPermission(const QWebEnginePermission &permission);
diff --git a/examples/webenginewidgets/permissionbrowser/mainwindow.ui b/examples/webenginewidgets/permissionbrowser/mainwindow.ui
index 4496b8c0782..2cef35130ab 100644
--- a/examples/webenginewidgets/permissionbrowser/mainwindow.ui
+++ b/examples/webenginewidgets/permissionbrowser/mainwindow.ui
@@ -215,21 +215,6 @@
             <property name="sizeAdjustPolicy">
              <enum>QComboBox::AdjustToContents</enum>
             </property>
-            <item>
-             <property name="text">
-              <string>Persist on disk</string>
-             </property>
-            </item>
-            <item>
-             <property name="text">
-              <string>Persist in memory</string>
-             </property>
-            </item>
-            <item>
-             <property name="text">
-              <string>Do not persist</string>
-             </property>
-            </item>
            </widget>
           </item>
          </layout>
diff --git a/examples/webenginewidgets/simplebrowser/CMakeLists.txt b/examples/webenginewidgets/simplebrowser/CMakeLists.txt
index cbaffa6d91e..d99a8088105 100644
--- a/examples/webenginewidgets/simplebrowser/CMakeLists.txt
+++ b/examples/webenginewidgets/simplebrowser/CMakeLists.txt
@@ -4,17 +4,10 @@
 cmake_minimum_required(VERSION 3.16)
 project(simplebrowser LANGUAGES CXX)
 
-set(CMAKE_AUTOMOC ON)
-set(CMAKE_AUTOUIC ON)
-
-if(NOT DEFINED INSTALL_EXAMPLESDIR)
-    set(INSTALL_EXAMPLESDIR "examples")
-endif()
-
-set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/webenginewidgets/simplebrowser")
-
 find_package(Qt6 REQUIRED COMPONENTS Core Gui WebEngineWidgets)
 
+qt_standard_project_setup()
+
 qt_add_executable(simplebrowser
     browser.cpp browser.h
     browserwindow.cpp browserwindow.h
@@ -103,7 +96,14 @@ if (APPLE)
 endif()
 
 install(TARGETS simplebrowser
-    RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
-    BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
-    LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
+    BUNDLE DESTINATION .
+    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
+    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
+)
+
+qt_generate_deploy_app_script(
+    TARGET simplebrowser
+    OUTPUT_SCRIPT deploy_script
+    NO_UNSUPPORTED_PLATFORM_ERROR
 )
+install(SCRIPT ${deploy_script})
diff --git a/examples/webenginewidgets/simplebrowser/doc/src/simplebrowser.qdoc b/examples/webenginewidgets/simplebrowser/doc/src/simplebrowser.qdoc
index a312da3ad1e..8523ed6896f 100644
--- a/examples/webenginewidgets/simplebrowser/doc/src/simplebrowser.qdoc
+++ b/examples/webenginewidgets/simplebrowser/doc/src/simplebrowser.qdoc
@@ -180,7 +180,7 @@
 
     We add a menu item to the context menu, so that users can right-click to have an inspector
     opened in a new window. We override QWebEngineView::contextMenuEvent and use
-    QWebEnginePage::createStandardContextMenu to create a default QMenu with a
+    QWebEngineView::createStandardContextMenu to create a default QMenu with a
     default list of QWebEnginePage::WebAction actions.
 
     The default name for QWebEnginePage::InspectElement action is
diff --git a/licenseRule.json b/licenseRule.json
index 5f78a7dc8c1..4ae4a4e8453 100644
--- a/licenseRule.json
+++ b/licenseRule.json
@@ -1,6 +1,6 @@
 [
     {
-        "comment" : ["file_pattern_ending: strings matched against the end of a file name.",
+        "comment": ["file_pattern_ending: strings matched against the end of a file name.",
                      "location keys: regular expression matched against the beginning of",
                      "the file path (relative to the git submodule root).",
                      "spdx: list of SPDX-License-Expression's allowed in the matching files.",
@@ -9,95 +9,152 @@
                      "unless they are examples",
                      "Files with other endings can also be build system files"
                      ],
-        "file_pattern_ending" : ["CMakeLists.txt", ".cmake", ".pro", ".pri", ".prf",
-                     "configure", "configure.bat", "cmake.in", "plist.in", "CMakeLists.txt.in", ".clang-format"],
-        "location" : {
-            "" : {
-                "comment" : "Default",
-                "file type" : "build system",
-                "spdx"      : ["BSD-3-Clause"]
-            },
-            "(.*)(examples/|snippets/)" : {
-                "comment" : "Example takes precedence",
-                "file type" : "examples and snippets",
-                "spdx" : ["LicenseRef-Qt-Commercial OR BSD-3-Clause"]
+        "file_pattern_ending": ["CMakeLists.txt", ".cmake", ".pro", ".pri", ".prf",
+                     "configure", "configure.bat", "cmake.in", "plist.in", "CMakeLists.txt.in",
+                     ".clang-format", ".plist", ".qrc", "BLACKLIST",
+                     ".tag", ".cmake.conf", ".yaml", "coin/qt-installer-package-config.json",
+                     "BUILD.root.gn.in", "BUILD.toolchain.gn.in", "BUILD.msvc.toolchain.gn.in",
+                     "BUILD.clang-cl.toolchain.gn.in", ".cfg", "coin.nodes"],
+        "location": {
+            "": {
+                "comment": "Default",
+                "file type": "build system",
+                "spdx": ["BSD-3-Clause"]
+            },
+            "(.*)(examples/|snippets/)": {
+                "comment": "Example takes precedence",
+                "file type": "examples and snippets",
+                "spdx": ["LicenseRef-Qt-Commercial OR BSD-3-Clause"]
+            }
+        }
+    },
+    {
+        "comments": ["Files with the following endings are infrastructure licensed"],
+        "file_pattern_ending": [".gitattributes", ".gitignore", ".gitmodules", ".gitreview",
+                                "clang-format", "licenseRule.json", "REUSE.toml"],
+        "location":{
+            "": {
+                "comment": "Default",
+                "file type": "infrastructure",
+                "spdx": ["LicenseRef-Qt-Commercial OR BSD-3-Clause"]
             }
         }
     },
     {
-        "comments" : ["Files with the following endings are Tool licensed,",
+        "comments": ["Files with the following endings are Tool licensed,",
                       "unless they are examples.",
                       "Files with other endings can also be tool files."],
-        "file_pattern_ending" : [".sh", ".py", ".pl", ".bat", ".ps1"],
-        "location" :{
-            "" : {
-                "comment" : "Default",
-                "file type" : "tools and utils",
-                "spdx"      : ["LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0"]
-            },
-            "(.*)(examples/|snippets/)" : {
-                "comment" : "Example takes precedence",
-                "file type" : "examples and snippets",
-                "spdx" : ["LicenseRef-Qt-Commercial OR BSD-3-Clause"]
+        "file_pattern_ending": [".sh", ".py", ".pl", ".bat", ".ps1"],
+        "location":{
+            "": {
+                "comment": "Default",
+                "file type": "tools and utils",
+                "spdx": ["LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0"]
+            },
+            "(.*)(examples/|snippets/)": {
+                "comment": "Example takes precedence",
+                "file type": "examples and snippets",
+                "spdx": ["LicenseRef-Qt-Commercial OR BSD-3-Clause"]
             }
         }
     },
     {
-        "comment" : "Files with the following endings are Documentation licensed.",
-        "file_pattern_ending" : [".qdoc", ".qdoc.in", ".qdocinc" , ".qdocconf", ".txt", "README", "qt_attribution.json"],
-        "location" :{
-            "" : {
-                "comment" : "",
-                "file type" : "documentation",
-                "spdx"      : ["LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only"]
+        "comment": "Files with the following endings are Documentation licensed.",
+        "file_pattern_ending": [".qdoc", ".qdoc.in", ".qdocinc" , ".qdocconf", "README", "qt_attribution.json",
+                                 "config_help.txt"],
+        "location":{
+            "": {
+                "comment": "",
+                "file type": "documentation",
+                "spdx": ["LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only"]
             }
         }
     },
     {
-        "comment" : ["All other files",
+        "comment": ["All other files",
                      "The licensing is defined only by the file location in the Qt module repository.",
                      "NO <file_pattern_ending> key for this case!",
                      "This needs to be the last entry of the file."],
-        "location" : {
-            "" : {
-                "comment" : "Default",
-                "file type" : "module and plugin",
-                "spdx"      : ["LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only"]
-            },
-            "src/" : {
-                "comment" : "Default",
-                "file type" : "module and plugin",
-                "spdx"      : ["LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only"]
-            },
-            "tests/" : {
-                "comment" : "Default",
-                "file type" : "test",
-                "spdx" : ["LicenseRef-Qt-Commercial OR GPL-3.0-only"]
-            },
-            "(.*)(examples/|snippets/)" : {
-                "comment" : "Default",
-                "file type" : "examples and snippets",
-                "spdx" : ["LicenseRef-Qt-Commercial OR BSD-3-Clause"]
-            },
-            "src/host/config\\.tests/" : {
-                "comment" : "Default",
-                "file type" : "build system",
-                "spdx" : ["BSD-3-Clause"]
-            },
-            "src/core/clipboard_util_win.cpp" : {
-                "comment" : "Partially from Chromium",
-                "file type" : "module and plugin",
-                "spdx" : ["BSD-3-Clause"]
-            },
-            "src/core/common/qt_messages.*" : {
-                "comment" : "Partially from Chromium",
-                "file type" : "module and plugin",
-                "spdx" : ["BSD-3-Clause"]
-            },
-            "src/core/tools/qwebengine_convert_dict/main.cpp" : {
-                "comment" : "Partially from Chromium",
-                "file type" : "module and plugin",
-                "spdx" : ["BSD-3-Clause"]
+        "location": {
+            "": {
+                "comment": "Default",
+                "file type": "module and plugin",
+                "spdx": ["LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only"]
+            },
+            "dist/": {
+                "comment": "Default",
+                "file type": "documentation",
+                "spdx": ["LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only"]
+            },
+            "src/": {
+                "comment": "Default",
+                "file type": "module and plugin",
+                "spdx": ["LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only"]
+            },
+            "tests/": {
+                "comment": "Default",
+                "file type": "test",
+                "spdx": ["LicenseRef-Qt-Commercial OR GPL-3.0-only"]
+            },
+            "(.*)(examples/|snippets/)": {
+                "comment": "Default",
+                "file type": "examples and snippets",
+                "spdx": ["LicenseRef-Qt-Commercial OR BSD-3-Clause"]
+            },
+            "(.*|examples).*doc/images/": {
+                "comment": "Default",
+                "file type": "documentation",
+                "spdx": ["LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only"]
+            },
+            "src/host/config\\.tests/": {
+                "comment": "Default",
+                "file type": "build system",
+                "spdx": ["BSD-3-Clause"]
+            },
+            "src/core/clipboard_util_win.cpp": {
+                "comment": "Partially from Chromium",
+                "file type": "module and plugin",
+                "spdx": ["BSD-3-Clause"]
+            },
+            "src/core/common/qt_messages.*": {
+                "comment": "Partially from Chromium",
+                "file type": "module and plugin",
+                "spdx": ["BSD-3-Clause"]
+            },
+            "src/core/tools/qwebengine_convert_dict/main.cpp": {
+                "comment": "Partially from Chromium",
+                "file type": "module and plugin",
+                "spdx": ["BSD-3-Clause"]
+            },
+            "tests/auto/widgets/qwebengine(view|script|page|history)/tst_qwebengine.*.cpp": {
+                "comment": "exception",
+                "file type": "test",
+                "spdx": ["LGPL-2.0-or-later"]
+            },
+            "tests/auto/widgets/accessibility/tst_accessibility.cpp": {
+                "comment": "exception",
+                "file type": "test",
+                "spdx": ["LGPL-2.0-or-later"]
+            },
+            "tests/auto/core/qwebengine(settings|frame)/tst_qwebengine.*.cpp": {
+                "comment": "exception",
+                "file type": "test",
+                "spdx": ["LGPL-2.0-or-later"]
+            },
+            "examples/webenginewidgets/contentmanipulation/jquery.min.js": {
+                "comment": "",
+                "file type": "3rd party",
+                "spdx": ["MIT"]
+            },
+            "src/core/ozone/(ozone_extra.gni|BUILD.gn)": {
+                "comment": "Chrominum",
+                "file type": "3rd party",
+                "spdx": ["BSD-3-Clause"]
+            },
+            "CHROMIUM_VERSION": {
+                "comment": "Chrominum",
+                "file type": "3rd party",
+                "spdx": ["CC0-1.0"]
             }
         }
     }
diff --git a/src/3rdparty b/src/3rdparty
index b7c46a2abb5..136d7fe8aa4 160000
--- a/src/3rdparty
+++ b/src/3rdparty
@@ -1 +1 @@
-Subproject commit b7c46a2abb5b3cdc37250f9c3006aa6228acdc9e
+Subproject commit 136d7fe8aa41c9d4cd764a6b890af9699f5141dd
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index cfe2721c995..96cd1fb5a4f 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -22,6 +22,11 @@ endif()
 #  MODULES
 ##
 
+if(QT_FEATURE_qtwebengine_build)
+    # Use implicit PROJECT_NAME.
+    qt_internal_sbom_begin_qt_repo_project()
+    qt_webengine_sbom_project_begin(WebEngine WebEngineCore)
+endif()
 if(QT_FEATURE_qtwebengine_core_build)
     add_subdirectory(core)
     add_subdirectory(process)
@@ -36,8 +41,14 @@ endif()
 if(QT_FEATURE_qtwebengine_quick_build)
     add_subdirectory(webenginequick)
 endif()
+if(QT_FEATURE_qtwebengine_build)
+    qt_webengine_sbom_project_end()
+    qt_internal_sbom_end_qt_repo_project()
+endif()
 
 if(QT_FEATURE_qtpdf_build)
+    qt_internal_sbom_begin_qt_repo_project(SBOM_PROJECT_NAME QtPdf)
+    qt_webengine_sbom_project_begin(Pdf Pdf)
     add_subdirectory(pdf)
 endif()
 if(QT_FEATURE_qtpdf_widgets_build)
@@ -61,6 +72,14 @@ if(QT_FEATURE_qtpdf_build)
     endif()
 endif()
 
+# No SBOM information will be generated for any targets created past this point in the file
+# or any add_subdirectory calls. For the external project GN, we'll have to come up with some
+# additional API.
+if(QT_FEATURE_qtpdf_build)
+    qt_webengine_sbom_project_end()
+    qt_internal_sbom_end_qt_repo_project()
+endif()
+
 set(installDir ${PROJECT_BINARY_DIR}/install)
 
 ##
@@ -95,7 +114,7 @@ endif()
 #  HOST PROJECT
 ##
 
-if(CMAKE_CROSSCOMPILING AND NOT IOS AND NOT MACOS)
+if(CMAKE_CROSSCOMPILING AND NOT IOS AND NOT MACOS AND NOT WIN32)
 
     if(NOT Gn_FOUND)
         message(FATAL_ERROR "\nHost gn not found - cross compilation not possible")
@@ -116,6 +135,7 @@ if(CMAKE_CROSSCOMPILING AND NOT IOS AND NOT MACOS)
                    -DCMAKE_CXX_FLAGS=
                    -DQT_FEATURE_qtwebengine_build=${QT_FEATURE_qtwebengine_build}
                    -DQT_FEATURE_qtpdf_build=${QT_FEATURE_qtpdf_build}
+                   -DGCC_LEGACY_SUPPORT=${QT_FEATURE_webengine_gcc_legacy_support}
     )
     if(QT_FEATURE_qtwebengine_build)
         add_dependencies(run_core_GnReady hostBuild)
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index d24513fae14..2b71f80f4b6 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -21,7 +21,7 @@ add_subdirectory(tools/qwebengine_convert_dict)
 #   TOOLCHAIN SETUP
 ##
 
-if(LINUX)
+if(LINUX OR WIN32)
     setup_toolchains()
 endif()
 
@@ -195,6 +195,11 @@ foreach(arch ${archs})
                 authenticator_request_dialog_controller.cpp authenticator_request_dialog_controller.h authenticator_request_dialog_controller_p.h
         )
 
+        extend_gn_target(${buildGn} CONDITION config STREQUAL "Debug"
+            DEFINES
+                QT_USE_DEBUG_RESOURCES
+        )
+
         extend_gn_target(${buildGn} CONDITION QT_FEATURE_accessibility
             SOURCES
                 accessibility_activation_observer.cpp accessibility_activation_observer.h
@@ -213,7 +218,7 @@ foreach(arch ${archs})
                 ozone/gl_helper.cpp ozone/gl_helper.h
         )
 
-        extend_gn_target(${buildGn} CONDITION LINUX AND QT_FEATURE_opengl AND QT_FEATURE_webengine_ozone_x11
+        extend_gn_target(${buildGn} CONDITION LINUX AND QT_FEATURE_opengl AND QT_FEATURE_webengine_ozone_x11 AND QT_FEATURE_xcb_glx_plugin
             SOURCES
                 ozone/glx_helper.cpp ozone/glx_helper.h
         )
@@ -322,11 +327,17 @@ foreach(arch ${archs})
             qtwebengine_target="${buildDir}/${config}/${arch}:QtWebEngineCore"
             build_dawn_tests=false
             build_with_tflite_lib=false
+            is_qtwebengine=true
+            is_qtpdf=false
+            chrome_pgo_phase=0
+            disable_fieldtrial_testing_config=true
             enable_background_contents=false
             enable_background_mode=false
+            enable_bluetooth_emulation=false
             enable_ipc_fuzzer=false
             enable_ipc_logging=false
             enable_java_templates=false
+            enable_library_cdms=true
             enable_media_remoting=false
             enable_message_center=false
             enable_nacl=false
@@ -339,29 +350,29 @@ foreach(arch ${archs})
             enable_supervised_users=false
             enable_swiftshader=false
             enable_swiftshader_vulkan=false
+            enable_nocompile_tests=false
             angle_enable_swiftshader=false
             dawn_use_swiftshader=false
+            pdf_enable_fontations=false
             enable_vr=false
             enable_web_speech=false
             enable_widevine=true
-            enable_library_cdms=true
+            enable_bound_session_credentials=false
             fatal_linker_warnings=false
             has_native_accessibility=false
-            safe_browsing_mode=0
-            toolkit_views=false
-            chrome_pgo_phase=0
             optimize_webui=false
+            safe_browsing_mode=0
             strip_absolute_paths_from_debug_symbols=false
+            toolkit_views=false
             pdf_use_skia=true
             use_cups=false
             use_dawn=false
             skia_use_dawn=false
+            use_static_angle=true
             devtools_fast_bundle=false
             devtools_skip_typecheck=false
-            use_static_angle=true
             content_enable_legacy_ipc=true
-            enable_bound_session_credentials=false
-            webnn_use_tflite=false
+            headless_use_policy=false
         )
         extend_gn_list(gnArgArg
             ARGS use_v8_context_snapshot v8_use_external_startup_data
@@ -413,7 +424,7 @@ foreach(arch ${archs})
             CONDITION QT_FEATURE_webengine_kerberos
         )
         extend_gn_list(gnArgArg
-            ARGS proprietary_codecs
+            ARGS proprietary_codecs rtc_use_h264
             CONDITION QT_FEATURE_webengine_proprietary_codecs
         )
         if(QT_FEATURE_webengine_proprietary_codecs)
@@ -441,7 +452,6 @@ foreach(arch ${archs})
                 use_bundled_fontconfig=false
                 use_glib=false
                 use_bluez=false
-                use_udev=true
                 is_cfi=false
                 use_ozone=true
                 ozone_auto_platforms=false
@@ -517,6 +527,10 @@ foreach(arch ${archs})
                 ARGS rtc_use_x11
                 CONDITION QT_FEATURE_webengine_ozone_x11 AND QT_FEATURE_webengine_webrtc
             )
+            extend_gn_list(gnArgArg
+                ARGS use_udev
+                CONDITION QT_FEATURE_webengine_system_libudev
+            )
 
             if(QT_FEATURE_webengine_kerberos)
                 list(APPEND gnArgArg
@@ -524,11 +538,24 @@ foreach(arch ${archs})
                 )
             endif()
             get_gn_arch(cpu ${TEST_architecture_arch})
-            if(CMAKE_CROSSCOMPILING AND cpu STREQUAL "arm")
+
+            if(cpu STREQUAL "arm" AND
+               CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND
+               CMAKE_CXX_COMPILER_VERSION VERSION_LESS "11.0.0")
+                list(APPEND gnArgArg libyuv_use_neon=false)
+                #TODO check if libyuv really uses udot in case of arm32
+            endif()
+            if(cpu STREQUAL "arm64" AND NOT QT_FEATURE_webengine_arm64_udot_support)
+                list(APPEND gnArgArg libyuv_use_neon=false)
+            endif()
+            if(cpu STREQUAL "arm")
                 check_thumb(armThumb)
                 if(NOT armThumb AND NOT QT_FEATURE_webengine_system_ffmpeg)
                     list(APPEND gnArgArg media_use_ffmpeg=false use_webaudio_ffmpeg=false)
                 endif()
+                # sme and sve depend on armv9
+                list(APPEND gnArgArg libyuv_use_sme=false
+                                     libyuv_use_sve=false)
             endif()
 
             if(CMAKE_CROSSCOMPILING AND cpu STREQUAL "arm64")
@@ -540,6 +567,14 @@ foreach(arch ${archs})
                     )
                 endif()
             endif()
+            if(cpu STREQUAL "arm64")
+                if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS "14.0.0")
+                    list(APPEND gnArgArg libyuv_use_sme=false)
+                endif()
+                if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS "12.0.0")
+                    list(APPEND gnArgArg libyuv_use_sve=false)
+                endif()
+            endif()
             unset(cpu)
         endif()
 
@@ -552,7 +587,6 @@ foreach(arch ${archs})
 
         if(WIN32)
             list(APPEND gnArgArg
-                ninja_use_custom_environment_files=false
                 com_init_check_hook_disabled=true
                 heterogeneous_executables=true
             )
@@ -585,18 +619,20 @@ target_include_directories(WebEngineCore PRIVATE
 )
 
 set(stamps QtWebEngineCore.stamp)
+set(dataStampOption "")
 if(QT_FEATURE_webengine_v8_context_snapshot)
-    set(dataStamp obj/tools/v8_context_snapshot/v8_context_snapshot.stamp)
+    set(dataStampOption NINJA_DATA_STAMP obj/tools/v8_context_snapshot/v8_context_snapshot.stamp)
 endif()
 
 add_gn_build_artifacts_to_target(
     CMAKE_TARGET WebEngineCore
     NINJA_TARGET QtWebEngineCore
     MODULE core
+    DEPENDS WebEngineCore_sync_headers
     BUILDDIR ${buildDir}
     COMPLETE_STATIC FALSE
     NINJA_STAMP QtWebEngineCore.stamp
-    NINJA_DATA_STAMP ${dataStamp}
+    ${dataStampOption}
 )
 add_dependencies(WebEngineCore run_core_NinjaDone)
 if(COIN_BUG_699)
@@ -615,8 +651,10 @@ if(WIN32)
             TARGET QtWebEngineCoreSandbox
             OUTPUT QtWebEngineCoreSandbox.lib
             BUILDDIR ${buildDir}/${config}/${arch}
+            DEPENDS WebEngineCore_sync_headers
             MODULE core
         )
+        qt_webengine_add_gn_target_to_sbom(QtWebEngineCoreSandbox ${buildDir}/${config}/${arch})
         set(sandboxLibraryPath ${buildDir}/${config}/${arch}/QtWebEngineCoreSandbox.lib)
         set_property(TARGET WebEngineCoreSandbox
             PROPERTY IMPORTED_LOCATION_${cfg} ${sandboxLibraryPath}
@@ -664,6 +702,7 @@ if(QT_FEATURE_webenginedriver)
         BUILDDIR ${buildDir}/$<CONFIG>/${arch}
         MODULE core
     )
+    qt_webengine_add_gn_target_to_sbom(webenginedriver_group ${buildDir}/$<CONFIG>/${arch})
     add_custom_target(webenginedriver
         DEPENDS
             ${buildDir}/$<CONFIG>/${arch}/${WEBENGINEDRIVER_EXECUTABLE})
diff --git a/src/core/accessibility_activation_observer.cpp b/src/core/accessibility_activation_observer.cpp
index 4f25a35ffed..4e90b9b3b38 100644
--- a/src/core/accessibility_activation_observer.cpp
+++ b/src/core/accessibility_activation_observer.cpp
@@ -5,6 +5,8 @@
 
 #include "content/browser/accessibility/browser_accessibility_state_impl.h"
 
+using namespace Qt::StringLiterals;
+
 namespace QtWebEngineCore {
 
 namespace {
@@ -14,9 +16,8 @@ bool isAccessibilityEnabled() {
     // QTWEBENGINE_ENABLE_LINUX_ACCESSIBILITY environment variable to 0. For details,
     // see QTBUG-59922.
 #ifdef Q_OS_LINUX
-    static bool accessibility_enabled
-            = qEnvironmentVariable("QTWEBENGINE_ENABLE_LINUX_ACCESSIBILITY", QLatin1String("1"))
-                == QLatin1String("1");
+    static bool accessibility_enabled =
+            qEnvironmentVariable("QTWEBENGINE_ENABLE_LINUX_ACCESSIBILITY", u"1"_s) == "1"_L1;
 #else
     const bool accessibility_enabled = true;
 #endif
diff --git a/src/core/accessibility_tree_formatter_qt.cpp b/src/core/accessibility_tree_formatter_qt.cpp
index a86727a4415..481c188c93a 100644
--- a/src/core/accessibility_tree_formatter_qt.cpp
+++ b/src/core/accessibility_tree_formatter_qt.cpp
@@ -1,9 +1,9 @@
 // Copyright (C) 2018 The Qt Company Ltd.
 // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
 
-#include "content/browser/accessibility/browser_accessibility_manager.h"
 #include "content/browser/accessibility/accessibility_tree_formatter_blink.h"
 #include "content/public/browser/ax_inspect_factory.h"
+#include "ui/accessibility/platform/browser_accessibility_manager.h"
 #include "ui/accessibility/platform/inspect/ax_event_recorder.h"
 
 #include <QtGui/qtguiglobal.h>
@@ -17,7 +17,7 @@
 
 #include "base/strings/stringprintf.h"
 #include "base/values.h"
-#include "content/browser/accessibility/browser_accessibility.h"
+#include "ui/accessibility/platform/browser_accessibility.h"
 #include "ui/accessibility/platform/inspect/ax_tree_formatter_base.h"
 
 #include <QtGui/qaccessible.h>
@@ -26,7 +26,8 @@
 namespace content {
 
 #if QT_CONFIG(accessibility)
-class AccessibilityTreeFormatterQt : public ui::AXTreeFormatterBase {
+class AccessibilityTreeFormatterQt : public ui::AXTreeFormatterBase
+{
 public:
     explicit AccessibilityTreeFormatterQt();
     ~AccessibilityTreeFormatterQt() override;
@@ -38,8 +39,9 @@ class AccessibilityTreeFormatterQt : public ui::AXTreeFormatterBase {
    }
 
 private:
-    void RecursiveBuildAccessibilityTree(const BrowserAccessibility &node, base::Value::Dict *dict) const;
-    void AddProperties(const BrowserAccessibility &node, base::Value::Dict *dict) const;
+    void RecursiveBuildAccessibilityTree(const ui::BrowserAccessibility &node,
+                                         base::Value::Dict *dict) const;
+    void AddProperties(const ui::BrowserAccessibility &node, base::Value::Dict *dict) const;
     std::string ProcessTreeForOutput(const base::Value::Dict &node) const override;
 };
 
@@ -53,14 +55,15 @@ AccessibilityTreeFormatterQt::~AccessibilityTreeFormatterQt()
 
 base::Value::Dict AccessibilityTreeFormatterQt::BuildTree(ui::AXPlatformNodeDelegate *start) const
 {
-    BrowserAccessibility *root_internal =
-        BrowserAccessibility::FromAXPlatformNodeDelegate(start);
+    ui::BrowserAccessibility *root_internal =
+            ui::BrowserAccessibility::FromAXPlatformNodeDelegate(start);
     base::Value::Dict dict;
     RecursiveBuildAccessibilityTree(*root_internal, &dict);
     return dict;
 }
 
-void AccessibilityTreeFormatterQt::RecursiveBuildAccessibilityTree(const BrowserAccessibility &node, base::Value::Dict *dict) const
+void AccessibilityTreeFormatterQt::RecursiveBuildAccessibilityTree(
+        const ui::BrowserAccessibility &node, base::Value::Dict *dict) const
 {
     AddProperties(node, dict);
 
@@ -68,7 +71,7 @@ void AccessibilityTreeFormatterQt::RecursiveBuildAccessibilityTree(const Browser
     for (size_t i = 0; i < node.PlatformChildCount(); ++i) {
         base::Value::Dict child_dict;
 
-        content::BrowserAccessibility *child_node = node.PlatformGetChild(i);
+        ui::BrowserAccessibility *child_node = node.PlatformGetChild(i);
 
         RecursiveBuildAccessibilityTree(*child_node, &child_dict);
         children.Append(std::move(child_dict));
@@ -76,10 +79,11 @@ void AccessibilityTreeFormatterQt::RecursiveBuildAccessibilityTree(const Browser
     dict->Set(kChildrenDictAttr, std::move(children));
 }
 
-void AccessibilityTreeFormatterQt::AddProperties(const BrowserAccessibility &node, base::Value::Dict *dict) const
+void AccessibilityTreeFormatterQt::AddProperties(const ui::BrowserAccessibility &node,
+                                                 base::Value::Dict *dict) const
 {
     dict->Set("id", node.GetId());
-    const QAccessibleInterface *iface = toQAccessibleInterface(&node);
+    const QAccessibleInterface *iface = ui::toQAccessibleInterface(&node);
 
     dict->Set("role", qAccessibleRoleString(iface->role()));
 
@@ -196,7 +200,7 @@ std::unique_ptr<ui::AXTreeFormatter> AXInspectFactory::CreateFormatter(ui::AXApi
     // Developer mode: crash immediately on any accessibility fatal error.
     // This only runs during integration tests, or if a developer is
     // using an inspection tool, e.g. chrome://accessibility.
-    BrowserAccessibilityManager::AlwaysFailFast();
+    ui::BrowserAccessibilityManager::AlwaysFailFast();
 
     switch (type) {
     case ui::AXApiType::kBlink:
diff --git a/src/core/api/CMakeLists.txt b/src/core/api/CMakeLists.txt
index f148afee14b..34a467d16b0 100644
--- a/src/core/api/CMakeLists.txt
+++ b/src/core/api/CMakeLists.txt
@@ -46,6 +46,7 @@ qt_internal_add_module(WebEngineCore
         qwebengineprofilebuilder.cpp qwebengineprofilebuilder.h qwebengineprofilebuilder_p.h
     DEFINES
         BUILDING_CHROMIUM
+        TOOLKIT_QT
     INCLUDE_DIRECTORIES
         ../
         ../../3rdparty/chromium
@@ -136,10 +137,10 @@ set(localeList am ar bg bn ca cs da de el en-GB en-US es-419 es et fa fi fil fr
     gu he hi hr hu id it ja kn ko lt lv ml mr ms nb nl pl pt-BR pt-PT ro ru sk
     sl sr sv sw ta te th tr uk vi zh-CN zh-TW)
 
-set(resourceList qtwebengine_resources.pak
-    qtwebengine_resources_100p.pak
-    qtwebengine_resources_200p.pak
-    qtwebengine_devtools_resources.pak)
+set(resourceList qtwebengine_resources
+    qtwebengine_resources_100p
+    qtwebengine_resources_200p
+    qtwebengine_devtools_resources)
 
 set(stamps ${buildDir}/${config}/${arch}/QtWebEngineCore.stamp)
 
@@ -176,9 +177,16 @@ foreach(loc ${localeList})
     list(APPEND localeFiles ${locSourcePath})
 endforeach()
 
-foreach(res ${resourceList})
-    get_filename_component(resSourcePath ${buildDir}/${config}/${arch}/${res} ${path_mode})
-    list(APPEND resourceFiles ${resSourcePath})
+foreach(config ${configs})
+    if("${config}" STREQUAL "Debug")
+        set(ext_debug ".debug")
+    else()
+        unset(ext_debug)
+    endif()
+    foreach(res ${resourceList})
+        get_filename_component(resSourcePath ${buildDir}/${config}/${arch}/${res}${ext_debug}.pak ${path_mode})
+        list(APPEND resourceFiles ${resSourcePath})
+    endforeach()
 endforeach()
 
 
@@ -214,14 +222,28 @@ if(QT_FEATURE_framework)
     )
 
 else()
+    set(locale_install_path "${INSTALL_TRANSLATIONSDIR}/qtwebengine_locales")
     install(FILES ${localeFiles}
-        DESTINATION ${INSTALL_TRANSLATIONSDIR}/qtwebengine_locales
+        DESTINATION ${locale_install_path}
         CONFIGURATIONS ${config}
     )
+    qt_internal_sbom_add_files(WebEngineCore
+        FILES "${localeFiles}"
+        FILE_TYPE "TRANSLATIONS"
+        INSTALL_PATH "${locale_install_path}"
+    )
+
+    qt_path_join(resource_install_path "${INSTALL_DATADIR}" "resources")
     install(FILES ${resourceFiles}
-        DESTINATION ${INSTALL_DATADIR}/resources
+        DESTINATION ${resource_install_path}
         CONFIGURATIONS ${config}
     )
+    qt_internal_sbom_add_files(WebEngineCore
+        FILES "${resourceFiles}"
+        FILE_TYPE "RESOURCES"
+        INSTALL_PATH "${resource_install_path}"
+    )
+
     if(QT_SUPERBUILD OR NOT QT_WILL_INSTALL)
         addCopyCommand(WebEngineCore "${localeFiles}"
             ${QT_BUILD_DIR}/${INSTALL_TRANSLATIONSDIR}/qtwebengine_locales
diff --git a/src/core/api/Qt6WebEngineCoreDeploySupport.cmake b/src/core/api/Qt6WebEngineCoreDeploySupport.cmake
index e67eb212b3d..2ff3d9e70de 100644
--- a/src/core/api/Qt6WebEngineCoreDeploySupport.cmake
+++ b/src/core/api/Qt6WebEngineCoreDeploySupport.cmake
@@ -74,37 +74,77 @@ function(_qt_internal_deploy_webenginecore_binary)
         endif()
     endforeach()
 
-    set(install_destination "${QT_DEPLOY_PREFIX}/")
+    # CMAKE_INSTALL_PREFIX does not contain $ENV{DESTDIR}, whereas QT_DEPLOY_PREFIX does.
+    # The install_ variant should be used in file(INSTALL) to avoid double DESTDIR in paths.
+    # Other code should reference the destdir_ variant instead.
+    set(install_destination "${CMAKE_INSTALL_PREFIX}/")
+    set(destdir_destination "${QT_DEPLOY_PREFIX}/")
+
     if(__QT_DEPLOY_SYSTEM_NAME STREQUAL "Windows")
         string(APPEND install_destination "${QT_DEPLOY_BIN_DIR}")
+        string(APPEND destdir_destination "${QT_DEPLOY_BIN_DIR}")
     else()
         string(APPEND install_destination "${QT_DEPLOY_LIBEXEC_DIR}")
+        string(APPEND destdir_destination "${QT_DEPLOY_LIBEXEC_DIR}")
     endif()
     file(INSTALL "${process_path}" DESTINATION "${install_destination}")
 
     get_filename_component(process_file_name "${process_path}" NAME)
     if(CMAKE_VERSION GREATER_EQUAL "3.19")
-        file(CHMOD "${install_destination}/${process_file_name}"
+        file(CHMOD "${destdir_destination}/${process_file_name}"
             PERMISSIONS OWNER_EXECUTE OWNER_READ OWNER_WRITE
                         GROUP_EXECUTE GROUP_READ
                         WORLD_EXECUTE WORLD_READ
         )
     else()
         execute_process(
-            COMMAND chmod 0755 "${install_destination}/${process_file_name}"
+            COMMAND chmod 0755 "${destdir_destination}/${process_file_name}"
+        )
+    endif()
+
+    if(NOT __QT_DEPLOY_SYSTEM_NAME STREQUAL "Windows")
+        qt6_deploy_qt_conf("${install_destination}/qt.conf"
+            PREFIX "${QT_DEPLOY_PREFIX}"
+            BIN_DIR "${QT_DEPLOY_BIN_DIR}"
+            LIB_DIR "${QT_DEPLOY_LIB_DIR}"
+            PLUGINS_DIR "${QT_DEPLOY_PLUGINS_DIR}"
+            QML_DIR "${QT_DEPLOY_QML_DIR}"
+        )
+    endif()
+    # Checking for __QT_DEPLOY_MUST_ADJUST_PLUGINS_RPATH is a bit strange because this is not a
+    # plugin, but it gives a single common way to detect when the rpath adjustment must be done,
+    # because the lib dir is different than the original Qt configured one.
+    if(__QT_DEPLOY_MUST_ADJUST_PLUGINS_RPATH)
+        _qt_internal_get_rpath_origin(rpath_origin)
+        file(RELATIVE_PATH rel_lib_dir "${destdir_destination}"
+            "${QT_DEPLOY_PREFIX}/${QT_DEPLOY_LIB_DIR}")
+        _qt_internal_set_rpath(
+            FILE "${destdir_destination}/${process_file_name}"
+            NEW_RPATH "${rpath_origin}/${rel_lib_dir}"
         )
     endif()
 endfunction()
 
 function(_qt_internal_deploy_webenginecore_data)
+    # used for deployment on Linux, using the CMake deployment API.
     _qt_internal_webenginecore_status_message("Deploying the WebEngineCore data files")
-    set(data_files
-        icudtl.dat
-        qtwebengine_devtools_resources.pak
-        qtwebengine_resources.pak
-        qtwebengine_resources_100p.pak
-        qtwebengine_resources_200p.pak
-    )
+    if(__QT_DEPLOY_ACTIVE_CONFIG STREQUAL "Debug")
+        set(data_files
+            icudtl.dat
+            qtwebengine_devtools_resources.debug.pak
+            qtwebengine_resources.debug.pak
+            qtwebengine_resources_100p.debug.pak
+            qtwebengine_resources_200p.debug.pak
+        )
+    else()
+        set(data_files
+            icudtl.dat
+            qtwebengine_devtools_resources.pak
+            qtwebengine_resources.pak
+            qtwebengine_resources_100p.pak
+            qtwebengine_resources_200p.pak
+        )
+    endif()
     get_filename_component(resources_dir "resources" ABSOLUTE
         BASE_DIR "${__QT_DEPLOY_QT_INSTALL_PREFIX}/${__QT_DEPLOY_QT_INSTALL_DATA}"
     )
@@ -117,8 +157,9 @@ function(_qt_internal_deploy_webenginecore_data)
         list(APPEND data_files "${snapshot_file}")
     endif()
 
+    # See comment above why we use CMAKE_INSTALL_PREFIX instead of QT_DEPLOY_PREFIX.
     get_filename_component(install_destination "${QT_DEPLOY_WEBENGINECORE_RESOURCES_DIR}" ABSOLUTE
-        BASE_DIR "${QT_DEPLOY_PREFIX}/${QT_DEPLOY_DATA_DIR}"
+        BASE_DIR "${CMAKE_INSTALL_PREFIX}/${QT_DEPLOY_DATA_DIR}"
     )
     foreach(data_file IN LISTS data_files)
         file(INSTALL "${resources_dir}/${data_file}" DESTINATION "${install_destination}")
@@ -163,8 +204,9 @@ function(_qt_internal_deploy_webenginecore_translations)
     get_filename_component(locales_dir "qtwebengine_locales" ABSOLUTE
         BASE_DIR "${__QT_DEPLOY_QT_INSTALL_PREFIX}/${__QT_DEPLOY_QT_INSTALL_TRANSLATIONS}"
     )
+    # See comment above why we use CMAKE_INSTALL_PREFIX instead of QT_DEPLOY_PREFIX.
     get_filename_component(install_destination "qtwebengine_locales" ABSOLUTE
-        BASE_DIR "${QT_DEPLOY_PREFIX}/${QT_DEPLOY_TRANSLATIONS_DIR}"
+        BASE_DIR "${CMAKE_INSTALL_PREFIX}/${QT_DEPLOY_TRANSLATIONS_DIR}"
     )
     file(GLOB locale_files "${locales_dir}/*.pak")
     foreach(locale_file IN LISTS locale_files)
diff --git a/src/core/api/configure.cmake b/src/core/api/configure.cmake
index 44dd38d5594..4a556656efb 100644
--- a/src/core/api/configure.cmake
+++ b/src/core/api/configure.cmake
@@ -36,6 +36,20 @@ qt_config_compile_test(alsa
 int main(){};
 ")
 
+qt_config_compile_test(udot
+    LABEL "udot on arm64"
+    CODE
+"
+static_assert(__aarch64__);
+static void test_dot_prod(){
+asm volatile (
+\"udot v0.4s, v4.16b, v16.16b\"
+:
+:
+: \"v0\",\"v4\",\"v16\");
+}
+")
+
 #### Features
 
 qt_feature("webengine-embedded-build" PRIVATE
@@ -168,6 +182,10 @@ qt_feature("webenginedriver" PUBLIC
               AND NOT (CMAKE_OSX_ARCHITECTURES AND osx_arch_count GREATER 1)
     DISABLE CMAKE_BUILD_TYPE STREQUAL Debug
 )
+qt_feature("webengine-arm64-udot-support" PRIVATE
+    LABEL "Use libyuv on neon64"
+    CONDITION UNIX AND TEST_udot
+)
 qt_configure_add_summary_section(NAME "Qt WebEngineCore")
 qt_configure_add_summary_entry(ARGS "webengine-embedded-build")
 qt_configure_add_summary_entry(ARGS "webengine-full-debug-info")
diff --git a/src/core/api/qwebenginecertificateerror.cpp b/src/core/api/qwebenginecertificateerror.cpp
index 85c5d512752..60ec3c95b19 100644
--- a/src/core/api/qwebenginecertificateerror.cpp
+++ b/src/core/api/qwebenginecertificateerror.cpp
@@ -42,6 +42,7 @@ QWebEngineCertificateError::~QWebEngineCertificateError() = default;
     QSslError::SslError values are not used directly, because the Qt error
     categories cannot be mapped to the Chromium error categories.
 
+    \value Ok There was no actual certificate error.
     \value SslPinnedKeyNotInCertificateChain The certificate did not match the built-in public keys
             pinned for the host name.
     \value CertificateCommonNameInvalid The certificate's common name did not match the host name.
@@ -74,7 +75,9 @@ QWebEngineCertificateError::~QWebEngineCertificateError() = default;
 */
 bool QWebEngineCertificateError::isOverridable() const
 {
-    return d->overridable();
+    if (Q_LIKELY(d))
+        return d->overridable();
+    return false;
 }
 
 /*!
@@ -84,7 +87,9 @@ bool QWebEngineCertificateError::isOverridable() const
 */
 QUrl QWebEngineCertificateError::url() const
 {
-    return d->url();
+    if (Q_LIKELY(d))
+        return d->url();
+    return QUrl();
 }
 
 /*!
@@ -97,7 +102,9 @@ QUrl QWebEngineCertificateError::url() const
 */
 bool QWebEngineCertificateError::isMainFrame() const
 {
-    return d->isMainFrame();
+    if (Q_LIKELY(d))
+        return d->isMainFrame();
+    return false;
 }
 
 /*!
@@ -107,7 +114,9 @@ bool QWebEngineCertificateError::isMainFrame() const
 */
 QWebEngineCertificateError::Type QWebEngineCertificateError::type() const
 {
-    return d->error();
+    if (Q_LIKELY(d))
+        return d->error();
+    return Ok;
 }
 
 /*!
@@ -117,7 +126,9 @@ QWebEngineCertificateError::Type QWebEngineCertificateError::type() const
 */
 QString QWebEngineCertificateError::description() const
 {
-    return d->errorString();
+    if (Q_LIKELY(d))
+        return d->errorString();
+    return QString();
 }
 
 /*!
@@ -135,7 +146,8 @@ QString QWebEngineCertificateError::description() const
 */
 void QWebEngineCertificateError::defer()
 {
-    d->defer();
+    if (Q_LIKELY(d))
+        d->defer();
 }
 
 /*!
@@ -145,7 +157,8 @@ void QWebEngineCertificateError::defer()
 */
 void QWebEngineCertificateError::acceptCertificate()
 {
-    d->ignoreCertificateError();
+    if (Q_LIKELY(d))
+        d->ignoreCertificateError();
 }
 
 /*!
@@ -155,7 +168,8 @@ void QWebEngineCertificateError::acceptCertificate()
 */
 void QWebEngineCertificateError::rejectCertificate()
 {
-    d->rejectCertificate();
+    if (Q_LIKELY(d))
+        d->rejectCertificate();
 }
 
 /*!
@@ -167,7 +181,9 @@ void QWebEngineCertificateError::rejectCertificate()
 */
 QList<QSslCertificate> QWebEngineCertificateError::certificateChain() const
 {
-    return d->certificateChain();
+    if (Q_LIKELY(d))
+        return d->certificateChain();
+    return QList<QSslCertificate>();
 }
 
 QT_END_NAMESPACE
diff --git a/src/core/api/qwebenginecertificateerror.h b/src/core/api/qwebenginecertificateerror.h
index 3eef3dcca58..73a3ac09099 100644
--- a/src/core/api/qwebenginecertificateerror.h
+++ b/src/core/api/qwebenginecertificateerror.h
@@ -27,12 +27,15 @@ class Q_WEBENGINECORE_EXPORT QWebEngineCertificateError
     Q_PROPERTY(bool isMainFrame READ isMainFrame CONSTANT FINAL REVISION(6, 8))
 
 public:
+    QWebEngineCertificateError() = default;
     QWebEngineCertificateError(const QWebEngineCertificateError &other);
     QWebEngineCertificateError &operator=(const QWebEngineCertificateError &other);
     ~QWebEngineCertificateError();
 
     // Keep this identical to NET_ERROR in net_error_list.h, or add mapping layer.
     enum Type {
+        Ok = 0, // No actual error. See net_errors.h for that one
+
         SslPinnedKeyNotInCertificateChain = -150,
         CertificateCommonNameInvalid = -200,
         CertificateDateInvalid = -201,
diff --git a/src/core/api/qwebenginedownloadrequest.cpp b/src/core/api/qwebenginedownloadrequest.cpp
index 107549f7efe..536d193b7f8 100644
--- a/src/core/api/qwebenginedownloadrequest.cpp
+++ b/src/core/api/qwebenginedownloadrequest.cpp
@@ -56,8 +56,7 @@ static inline QWebEngineDownloadRequest::DownloadState toDownloadState(int state
     case ProfileAdapterClient::DownloadInterrupted:
         return QWebEngineDownloadRequest::DownloadInterrupted;
     default:
-        Q_UNREACHABLE();
-        return QWebEngineDownloadRequest::DownloadCancelled;
+        Q_UNREACHABLE_RETURN(QWebEngineDownloadRequest::DownloadCancelled);
     }
 }
 
@@ -146,17 +145,13 @@ void QWebEngineDownloadRequestPrivate::update(const ProfileAdapterClient::Downlo
         downloadState = toDownloadState(info.state);
         Q_EMIT q->stateChanged(downloadState);
     }
-
-    if (info.receivedBytes != receivedBytes || info.totalBytes != totalBytes) {
-
-      if (info.receivedBytes != receivedBytes) {
-          receivedBytes = info.receivedBytes;
-          Q_EMIT q->receivedBytesChanged();
-      }
-      if (info.totalBytes != totalBytes) {
-          totalBytes = info.totalBytes;
-          Q_EMIT q->totalBytesChanged();
-      }
+    if (info.receivedBytes != receivedBytes) {
+        receivedBytes = info.receivedBytes;
+        Q_EMIT q->receivedBytesChanged();
+    }
+    if (info.totalBytes != totalBytes) {
+        totalBytes = info.totalBytes;
+        Q_EMIT q->totalBytesChanged();
     }
 
     if (info.done)
@@ -183,7 +178,7 @@ void QWebEngineDownloadRequestPrivate::answer()
         return;
 
     if (profileAdapter) {
-        QString path = QDir(downloadDirectory).filePath(downloadFileName);
+        const QString path = QDir(downloadDirectory).filePath(downloadFileName);
         bool accepted = downloadState != QWebEngineDownloadRequest::DownloadCancelled
                 && downloadState != QWebEngineDownloadRequest::DownloadRequested;
         profileAdapter->acceptDownload(downloadId, accepted, useDownloadTargetCallback, path, savePageFormat);
@@ -480,7 +475,7 @@ void QWebEngineDownloadRequest::setDownloadDirectory(const QString &directory)
                                                                                  d->suggestedFileName,
                                                                                  d->startTime)).fileName();
         if (d->downloadFileName != newFileName) {
-            d->downloadFileName = newFileName;
+            d->downloadFileName = std::move(newFileName);
             Q_EMIT downloadFileNameChanged();
         }
     }
diff --git a/src/core/api/qwebenginefilesystemaccessrequest.cpp b/src/core/api/qwebenginefilesystemaccessrequest.cpp
index 3f901b671cf..0834468f659 100644
--- a/src/core/api/qwebenginefilesystemaccessrequest.cpp
+++ b/src/core/api/qwebenginefilesystemaccessrequest.cpp
@@ -72,7 +72,8 @@ QWebEngineFileSystemAccessRequest::QWebEngineFileSystemAccessRequest(
 */
 void QWebEngineFileSystemAccessRequest::reject()
 {
-    d_ptr->reject();
+    if (Q_LIKELY(d_ptr))
+        d_ptr->reject();
 }
 
 /*!
@@ -80,7 +81,8 @@ void QWebEngineFileSystemAccessRequest::reject()
 */
 void QWebEngineFileSystemAccessRequest::accept()
 {
-    d_ptr->accept();
+    if (Q_LIKELY(d_ptr))
+        d_ptr->accept();
 }
 
 /*!
@@ -90,7 +92,9 @@ void QWebEngineFileSystemAccessRequest::accept()
 
 QUrl QWebEngineFileSystemAccessRequest::origin() const
 {
-    return d_ptr->origin();
+    if (Q_LIKELY(d_ptr))
+        return d_ptr->origin();
+    return QUrl();
 }
 
 /*!
@@ -100,7 +104,9 @@ QUrl QWebEngineFileSystemAccessRequest::origin() const
 
 QUrl QWebEngineFileSystemAccessRequest::filePath() const
 {
-    return d_ptr->filePath();
+    if (Q_LIKELY(d_ptr))
+        return d_ptr->filePath();
+    return QUrl();
 }
 
 /*!
@@ -109,7 +115,9 @@ QUrl QWebEngineFileSystemAccessRequest::filePath() const
  */
 HandleType QWebEngineFileSystemAccessRequest::handleType() const
 {
-    return d_ptr->handleType();
+    if (Q_LIKELY(d_ptr))
+        return d_ptr->handleType();
+    return File;
 }
 
 /*!
@@ -118,7 +126,9 @@ HandleType QWebEngineFileSystemAccessRequest::handleType() const
  */
 AccessFlags QWebEngineFileSystemAccessRequest::accessFlags() const
 {
-    return d_ptr->accessFlags();
+    if (Q_LIKELY(d_ptr))
+        return d_ptr->accessFlags();
+    return {};
 }
 
 QT_END_NAMESPACE
diff --git a/src/core/api/qwebenginefilesystemaccessrequest.h b/src/core/api/qwebenginefilesystemaccessrequest.h
index 37b1e186111..7707c607c8c 100644
--- a/src/core/api/qwebenginefilesystemaccessrequest.h
+++ b/src/core/api/qwebenginefilesystemaccessrequest.h
@@ -24,6 +24,7 @@ class Q_WEBENGINECORE_EXPORT QWebEngineFileSystemAccessRequest
     Q_PROPERTY(AccessFlags accessFlags READ accessFlags CONSTANT FINAL)
 
 public:
+    QWebEngineFileSystemAccessRequest() = default;
     QWebEngineFileSystemAccessRequest(const QWebEngineFileSystemAccessRequest &other);
     QWebEngineFileSystemAccessRequest &operator=(const QWebEngineFileSystemAccessRequest &other);
     QWebEngineFileSystemAccessRequest(QWebEngineFileSystemAccessRequest &&other) noexcept = default;
diff --git a/src/core/api/qwebenginefullscreenrequest.h b/src/core/api/qwebenginefullscreenrequest.h
index 8e25286b64f..b07d158fd35 100644
--- a/src/core/api/qwebenginefullscreenrequest.h
+++ b/src/core/api/qwebenginefullscreenrequest.h
@@ -23,6 +23,7 @@ class Q_WEBENGINECORE_EXPORT QWebEngineFullScreenRequest
     Q_PROPERTY(QUrl origin READ origin CONSTANT)
 
 public:
+    QWebEngineFullScreenRequest() : QWebEngineFullScreenRequest(QUrl(), false, [](bool){}) {}
     QWebEngineFullScreenRequest(const QWebEngineFullScreenRequest &other);
     QWebEngineFullScreenRequest &operator=(const QWebEngineFullScreenRequest &other);
     QWebEngineFullScreenRequest(QWebEngineFullScreenRequest &&other);
diff --git a/src/core/api/qwebenginehttprequest.cpp b/src/core/api/qwebenginehttprequest.cpp
index 050213d1e2d..0039533d687 100644
--- a/src/core/api/qwebenginehttprequest.cpp
+++ b/src/core/api/qwebenginehttprequest.cpp
@@ -148,8 +148,8 @@ QWebEngineHttpRequest QWebEngineHttpRequest::postRequest(const QUrl &url,
 
     QByteArray buffer;
     for (QMap<QString, QString>::const_iterator it = postData.begin(); it != postData.end(); it++) {
-        QByteArray key = QUrl::toPercentEncoding(it.key());
-        QByteArray value = QUrl::toPercentEncoding(it.value());
+        const QByteArray key = QUrl::toPercentEncoding(it.key());
+        const QByteArray value = QUrl::toPercentEncoding(it.value());
 
         if (buffer.size() > 0)
             buffer += '&';
diff --git a/src/core/api/qwebengineloadinginfo.h b/src/core/api/qwebengineloadinginfo.h
index a268f888ff6..16da45a2adb 100644
--- a/src/core/api/qwebengineloadinginfo.h
+++ b/src/core/api/qwebengineloadinginfo.h
@@ -28,7 +28,7 @@ class Q_WEBENGINECORE_EXPORT QWebEngineLoadingInfo
     Q_PROPERTY(ErrorDomain errorDomain READ errorDomain CONSTANT FINAL)
     Q_PROPERTY(int errorCode READ errorCode CONSTANT FINAL)
     Q_PROPERTY(QMultiMap<QByteArray,QByteArray> responseHeaders READ responseHeaders CONSTANT REVISION(6,6) FINAL)
-    Q_PROPERTY(bool isDownload READ isDownload CONSTANT REVISION(6,9) FINAL)
+    Q_PROPERTY(bool isDownload READ isDownload CONSTANT REVISION(6,9))
 
 public:
     enum LoadStatus {
@@ -51,6 +51,7 @@ class Q_WEBENGINECORE_EXPORT QWebEngineLoadingInfo
     };
     Q_ENUM(ErrorDomain)
 
+    QWebEngineLoadingInfo() : QWebEngineLoadingInfo(QUrl(), LoadStartedStatus) {}
     QWebEngineLoadingInfo(const QWebEngineLoadingInfo &other);
     QWebEngineLoadingInfo &operator=(const QWebEngineLoadingInfo &other);
     QWebEngineLoadingInfo(QWebEngineLoadingInfo &&other);
diff --git a/src/core/api/qwebenginemessagepumpscheduler.cpp b/src/core/api/qwebenginemessagepumpscheduler.cpp
index a435e2c0c5a..860696c3740 100644
--- a/src/core/api/qwebenginemessagepumpscheduler.cpp
+++ b/src/core/api/qwebenginemessagepumpscheduler.cpp
@@ -16,11 +16,6 @@ void QWebEngineMessagePumpScheduler::scheduleImmediateWork()
     QCoreApplication::postEvent(this, new QTimerEvent(0), Qt::NormalEventPriority);
 }
 
-void QWebEngineMessagePumpScheduler::scheduleIdleWork()
-{
-    QCoreApplication::postEvent(this, new QTimerEvent(0), Qt::LowEventPriority);
-}
-
 void QWebEngineMessagePumpScheduler::scheduleDelayedWork(int delay)
 {
     if (delay < 0) {
diff --git a/src/core/api/qwebenginemessagepumpscheduler_p.h b/src/core/api/qwebenginemessagepumpscheduler_p.h
index 37f7dd9a6fc..b2c51415a93 100644
--- a/src/core/api/qwebenginemessagepumpscheduler_p.h
+++ b/src/core/api/qwebenginemessagepumpscheduler_p.h
@@ -29,7 +29,6 @@ class Q_WEBENGINECORE_EXPORT QWebEngineMessagePumpScheduler : public QObject
 public:
     QWebEngineMessagePumpScheduler(std::function<void()> callback);
     void scheduleImmediateWork();
-    void scheduleIdleWork();
     void scheduleDelayedWork(int delay);
 
 protected:
diff --git a/src/core/api/qwebenginenewwindowrequest.cpp b/src/core/api/qwebenginenewwindowrequest.cpp
index 1f0be9aa03c..500f3ac2bf2 100644
--- a/src/core/api/qwebenginenewwindowrequest.cpp
+++ b/src/core/api/qwebenginenewwindowrequest.cpp
@@ -98,7 +98,7 @@ QWebEngineNewWindowRequest::DestinationType QWebEngineNewWindowRequest::destinat
     \brief The URL that is requested for the new page.
 */
 /*!
-    \qmlproperty QUrl WebEngineNewWindowRequest::requestedUrl
+    \qmlproperty url WebEngineNewWindowRequest::requestedUrl
     \brief The URL that is requested for the new page.
     \since QtWebEngine 1.5
  */
@@ -112,7 +112,7 @@ QUrl QWebEngineNewWindowRequest::requestedUrl() const
     \brief The size that is requested for the new page.
 */
 /*!
-    \qmlproperty QRect WebEngineNewWindowRequest::requestedGeometry
+    \qmlproperty rect WebEngineNewWindowRequest::requestedGeometry
     \brief The size that is requested for the new page.
     \since QtWebEngine 2.0
  */
diff --git a/src/core/api/qwebenginepage.cpp b/src/core/api/qwebenginepage.cpp
index 311fb100a2c..6ff454a0720 100644
--- a/src/core/api/qwebenginepage.cpp
+++ b/src/core/api/qwebenginepage.cpp
@@ -57,6 +57,7 @@
 
 QT_BEGIN_NAMESPACE
 
+using namespace Qt::StringLiterals;
 using namespace QtWebEngineCore;
 
 static QWebEnginePage::WebWindowType toWindowType(WebContentsAdapterClient::WindowOpenDisposition disposition)
@@ -661,8 +662,7 @@ static QWebEnginePage::Feature toDeprecatedFeature(QWebEnginePermission::Permiss
         break;
     }
 
-    Q_UNREACHABLE();
-    return QWebEnginePage::Feature(-1);
+    Q_UNREACHABLE_RETURN(QWebEnginePage::Feature(-1));
 }
 QT_WARNING_POP
 #endif // QT_DEPRECATED_SINCE(6, 8)
@@ -1336,16 +1336,16 @@ void QWebEnginePage::triggerAction(WebAction action, bool)
         break;
     case CopyLinkToClipboard:
         if (d->view && d->view->lastContextMenuRequest() && !d->view->lastContextMenuRequest()->linkUrl().isEmpty()) {
-            QString urlString = d->view->lastContextMenuRequest()->linkUrl().toString(
-                    QUrl::FullyEncoded);
-            QString linkText = d->view->lastContextMenuRequest()->linkText().toHtmlEscaped();
+            const QString urlString =
+                    d->view->lastContextMenuRequest()->linkUrl().toString(QUrl::FullyEncoded);
+            const QString linkText = d->view->lastContextMenuRequest()->linkText().toHtmlEscaped();
             QString title = d->view->lastContextMenuRequest()->titleText();
             if (!title.isEmpty())
-                title = QStringLiteral(" title=\"%1\"").arg(title.toHtmlEscaped());
+                title = " title=\""_L1 + title.toHtmlEscaped() + u'"';
             QMimeData *data = new QMimeData();
             data->setText(urlString);
-            QString html = QStringLiteral("<a href=\"") + urlString + QStringLiteral("\"") + title + QStringLiteral(">")
-                         + linkText + QStringLiteral("</a>");
+            const QString html =
+                    "<a href=\""_L1 + urlString + u'"' + title + u'>' + linkText + "</a>"_L1;
             data->setHtml(html);
             data->setUrls(QList<QUrl>() << d->view->lastContextMenuRequest()->linkUrl());
             QGuiApplication::clipboard()->setMimeData(data);
@@ -1372,17 +1372,17 @@ void QWebEnginePage::triggerAction(WebAction action, bool)
         if (d->view && d->view->lastContextMenuRequest() && d->view->lastContextMenuRequest()->mediaUrl().isValid()
             && d->view->lastContextMenuRequest()->mediaType()
                     == QWebEngineContextMenuRequest::MediaTypeImage) {
-            QString urlString =
+            const QString urlString =
                     d->view->lastContextMenuRequest()->mediaUrl().toString(QUrl::FullyEncoded);
             QString alt = d->view->lastContextMenuRequest()->altText();
             if (!alt.isEmpty())
-                alt = QStringLiteral(" alt=\"%1\"").arg(alt.toHtmlEscaped());
+                alt = " alt=\""_L1 + alt.toHtmlEscaped() + u'"';
             QString title = d->view->lastContextMenuRequest()->titleText();
             if (!title.isEmpty())
-                title = QStringLiteral(" title=\"%1\"").arg(title.toHtmlEscaped());
+                title = " title=\""_L1 + title.toHtmlEscaped() + u'"';
             QMimeData *data = new QMimeData();
             data->setText(urlString);
-            QString html = QStringLiteral("<img src=\"") + urlString + QStringLiteral("\"") + title + alt + QStringLiteral("></img>");
+            const QString html = "<img src=\""_L1 + urlString + u'"' + title + alt + "></img>"_L1;
             data->setHtml(html);
             data->setUrls(QList<QUrl>() << d->view->lastContextMenuRequest()->mediaUrl());
             QGuiApplication::clipboard()->setMimeData(data);
@@ -1402,20 +1402,19 @@ void QWebEnginePage::triggerAction(WebAction action, bool)
                         == QWebEngineContextMenuRequest::MediaTypeAudio
                 || d->view->lastContextMenuRequest()->mediaType()
                         == QWebEngineContextMenuRequest::MediaTypeVideo)) {
-            QString urlString =
+            const QString urlString =
                     d->view->lastContextMenuRequest()->mediaUrl().toString(QUrl::FullyEncoded);
             QString title = d->view->lastContextMenuRequest()->titleText();
             if (!title.isEmpty())
-                title = QStringLiteral(" title=\"%1\"").arg(title.toHtmlEscaped());
+                title = " title=\""_L1 + title.toHtmlEscaped() + u'"';
             QMimeData *data = new QMimeData();
             data->setText(urlString);
-            if (d->view->lastContextMenuRequest()->mediaType()
-                == QWebEngineContextMenuRequest::MediaTypeAudio)
-                data->setHtml(QStringLiteral("<audio src=\"") + urlString + QStringLiteral("\"") + title +
-                              QStringLiteral("></audio>"));
-            else
-                data->setHtml(QStringLiteral("<video src=\"") + urlString + QStringLiteral("\"") + title +
-                              QStringLiteral("></video>"));
+            const bool isAudio = d->view->lastContextMenuRequest()->mediaType()
+                    == QWebEngineContextMenuRequest::MediaTypeAudio;
+            const auto avTagName = isAudio ? "audio"_L1 : "video"_L1;
+            const QString html = u'<' + avTagName + "src=\""_L1 + urlString + u'"' + title
+                    + "></"_L1 + avTagName + u'>';
+            data->setHtml(html);
             data->setUrls(QList<QUrl>() << d->view->lastContextMenuRequest()->mediaUrl());
             QGuiApplication::clipboard()->setMimeData(data);
         }
@@ -1491,40 +1490,47 @@ void QWebEnginePage::triggerAction(WebAction action, bool)
         QTimer::singleShot(0, this, [d](){ d->adapter->viewSource(); });
         break;
     case ToggleBold:
-        runJavaScript(QStringLiteral("document.execCommand('bold');"), QWebEngineScript::ApplicationWorld);
+        runJavaScript(u"document.execCommand('bold');"_s, QWebEngineScript::ApplicationWorld);
         break;
     case ToggleItalic:
-        runJavaScript(QStringLiteral("document.execCommand('italic');"), QWebEngineScript::ApplicationWorld);
+        runJavaScript(u"document.execCommand('italic');"_s, QWebEngineScript::ApplicationWorld);
         break;
     case ToggleUnderline:
-        runJavaScript(QStringLiteral("document.execCommand('underline');"), QWebEngineScript::ApplicationWorld);
+        runJavaScript(u"document.execCommand('underline');"_s, QWebEngineScript::ApplicationWorld);
         break;
     case ToggleStrikethrough:
-        runJavaScript(QStringLiteral("document.execCommand('strikethrough');"), QWebEngineScript::ApplicationWorld);
+        runJavaScript(u"document.execCommand('strikethrough');"_s,
+                      QWebEngineScript::ApplicationWorld);
         break;
     case AlignLeft:
-        runJavaScript(QStringLiteral("document.execCommand('justifyLeft');"), QWebEngineScript::ApplicationWorld);
+        runJavaScript(u"document.execCommand('justifyLeft');"_s,
+                      QWebEngineScript::ApplicationWorld);
         break;
     case AlignCenter:
-        runJavaScript(QStringLiteral("document.execCommand('justifyCenter');"), QWebEngineScript::ApplicationWorld);
+        runJavaScript(u"document.execCommand('justifyCenter');"_s,
+                      QWebEngineScript::ApplicationWorld);
         break;
     case AlignRight:
-        runJavaScript(QStringLiteral("document.execCommand('justifyRight');"), QWebEngineScript::ApplicationWorld);
+        runJavaScript(u"document.execCommand('justifyRight');"_s,
+                      QWebEngineScript::ApplicationWorld);
         break;
     case AlignJustified:
-        runJavaScript(QStringLiteral("document.execCommand('justifyFull');"), QWebEngineScript::ApplicationWorld);
+        runJavaScript(u"document.execCommand('justifyFull');"_s,
+                      QWebEngineScript::ApplicationWorld);
         break;
     case Indent:
-        runJavaScript(QStringLiteral("document.execCommand('indent');"), QWebEngineScript::ApplicationWorld);
+        runJavaScript(u"document.execCommand('indent');"_s, QWebEngineScript::ApplicationWorld);
         break;
     case Outdent:
-        runJavaScript(QStringLiteral("document.execCommand('outdent');"), QWebEngineScript::ApplicationWorld);
+        runJavaScript(u"document.execCommand('outdent');"_s, QWebEngineScript::ApplicationWorld);
         break;
     case InsertOrderedList:
-        runJavaScript(QStringLiteral("document.execCommand('insertOrderedList');"), QWebEngineScript::ApplicationWorld);
+        runJavaScript(u"document.execCommand('insertOrderedList');"_s,
+                      QWebEngineScript::ApplicationWorld);
         break;
     case InsertUnorderedList:
-        runJavaScript(QStringLiteral("document.execCommand('insertUnorderedList');"), QWebEngineScript::ApplicationWorld);
+        runJavaScript(u"document.execCommand('insertUnorderedList');"_s,
+                      QWebEngineScript::ApplicationWorld);
         break;
     case ChangeTextDirectionLTR:
         d->adapter->changeTextDirection(true /*left to right*/);
@@ -1748,7 +1754,7 @@ void QWebEnginePagePrivate::setToolTip(const QString &toolTipText)
     \since 5.12
 
     This signal is emitted when the JavaScript \c{window.print()} method is called on the main
-    frame, or the user pressed the print button of PDF viewer plugin.
+    frame, or the user pressed the print button of the PDF viewer plugin.
     Typically, the signal handler can simply call printToPdf().
 
     Since 6.8, this signal is only emitted for the main frame, instead of being emitted for any
@@ -2015,7 +2021,7 @@ void QWebEnginePage::toPlainText(const std::function<void(const QString &)> &res
 
 void QWebEnginePage::setHtml(const QString &html, const QUrl &baseUrl)
 {
-    setContent(html.toUtf8(), QStringLiteral("text/html;charset=UTF-8"), baseUrl);
+    setContent(html.toUtf8(), u"text/html;charset=UTF-8"_s, baseUrl);
 }
 
 void QWebEnginePage::setContent(const QByteArray &data, const QString &mimeType, const QUrl &baseUrl)
@@ -2073,7 +2079,7 @@ QUrl QWebEnginePage::iconUrl() const
 
     By default, this property contains a null icon. If touch icons are disabled
     (see \c QWebEngineSettings::TouchIconsEnabled), the favicon is provided in two sizes
-    (16x16 and 32x32 pixels) encapsulated in \c{QIcon}. Otherwise, single icon is provided
+    (16x16 and 32x32 pixels) encapsulated in \c{QIcon}. Otherwise, a single icon is provided
     with the largest available size.
 
     \sa iconChanged(), iconUrl(), iconUrlChanged(), QWebEngineSettings::TouchIconsEnabled
@@ -2235,7 +2241,7 @@ void QWebEnginePage::setDevToolsPage(QWebEnginePage *devToolsPage)
 
     If remote debugging is enabled (see \l{Qt WebEngine Developer Tools}), the id can be used to
    build the URL to connect to the developer tool websocket:
-   \c{ws://localhost:<debugggin-port>/devtools/page/<id>)}. The websocket can be used to to interact
+   \c{ws://localhost:<debugging-port>/devtools/page/<id>)}. The websocket can be used to to interact
    with the page using the \l{https://chromedevtools.github.io/devtools-protocol/}{DevTools
    Protocol}.
 */
@@ -2284,7 +2290,7 @@ bool QWebEnginePage::javaScriptPrompt(const QUrl &securityOrigin, const QString
 void QWebEnginePage::javaScriptConsoleMessage(JavaScriptConsoleMessageLevel level, const QString &message, int lineNumber, const QString &sourceID)
 {
     static QLoggingCategory loggingCategory("js", QtWarningMsg);
-    static QByteArray file = sourceID.toUtf8();
+    const QByteArray file = sourceID.toUtf8();
     QMessageLogger logger(file.constData(), lineNumber, nullptr, loggingCategory.categoryName());
 
     switch (level) {
@@ -2526,7 +2532,7 @@ QWebEnginePage::LifecycleState QWebEnginePage::recommendedState() const
   user.
 
   If the page is connected to a \e {view} then this property will be managed
-  automatically by the view according to it's own visibility.
+  automatically by the view according to its own visibility.
 
   \sa lifecycleState
 */
diff --git a/src/core/api/qwebengineprofile.cpp b/src/core/api/qwebengineprofile.cpp
index 1c5807a9386..a7955549ac1 100644
--- a/src/core/api/qwebengineprofile.cpp
+++ b/src/core/api/qwebengineprofile.cpp
@@ -216,11 +216,11 @@ void QWebEngineProfilePrivate::cleanDownloads()
     m_ongoingDownloads.clear();
 }
 
-void QWebEngineProfilePrivate::downloadRequested(DownloadItemInfo &info)
+void QWebEngineProfilePrivate::downloadRequested(const DownloadItemInfo &info)
 {
     Q_Q(QWebEngineProfile);
 
-    if (!q->receivers(SIGNAL(downloadRequested(QWebEngineDownloadRequest *)))) {
+    if (!q->receivers(SIGNAL(downloadRequested(QWebEngineDownloadRequest*)))) {
         m_profileAdapter->acceptDownload(info.id, info.accepted, info.useDownloadTargetCallback, info.path,
                                          info.savePageFormat);
         return;
diff --git a/src/core/api/qwebengineprofile_p.h b/src/core/api/qwebengineprofile_p.h
index 0ccc2703756..d4b3513cd5d 100644
--- a/src/core/api/qwebengineprofile_p.h
+++ b/src/core/api/qwebengineprofile_p.h
@@ -51,7 +51,7 @@ class Q_WEBENGINECORE_EXPORT QWebEngineProfilePrivate : public QtWebEngineCore::
 
     void cleanDownloads();
 
-    void downloadRequested(DownloadItemInfo &info) override;
+    void downloadRequested(const DownloadItemInfo &info) override;
     void downloadUpdated(const DownloadItemInfo &info) override;
 
     void showNotification(QSharedPointer<QtWebEngineCore::UserNotificationController> &) override;
diff --git a/src/core/api/qwebengineprofilebuilder.cpp b/src/core/api/qwebengineprofilebuilder.cpp
index a30a390c368..91a604ba194 100644
--- a/src/core/api/qwebengineprofilebuilder.cpp
+++ b/src/core/api/qwebengineprofilebuilder.cpp
@@ -10,6 +10,8 @@
 #include <QDir>
 #include <QStandardPaths>
 
+using namespace Qt::StringLiterals;
+
 /*!
     \class QWebEngineProfileBuilder
     \brief The QWebEngineProfileBuilder class provides a way to construct \l{QWebEngineProfile}.
@@ -53,15 +55,15 @@ QWebEngineProfile *QWebEngineProfileBuilder::createOffTheRecordProfile(QObject *
     \sa QWebEngineProfile::storageName()
 */
 QWebEngineProfile *QWebEngineProfileBuilder::createProfile(const QString &storageName,
-                                                           QObject *parent)
+                                                           QObject *parent) const
 {
-    d_ptr->m_storageName = storageName;
     auto buildLocationFromStandardPath = [](const QString &standardPath, const QString &name) {
-        QString location = standardPath;
+        QString location;
+        location += standardPath;
         if (location.isEmpty())
-            location = QDir::homePath() % QLatin1String("/.") % QCoreApplication::applicationName();
+            location += QDir::homePath() % "/."_L1 % QCoreApplication::applicationName();
 
-        location.append(QLatin1String("/QtWebEngine/") % name);
+        location += "/QtWebEngine/"_L1 % name;
         return location;
     };
 
@@ -80,7 +82,7 @@ QWebEngineProfile *QWebEngineProfileBuilder::createProfile(const QString &storag
 
     return new QWebEngineProfile(
             new QWebEngineProfilePrivate(new QtWebEngineCore::ProfileAdapter(
-                    d_ptr->m_storageName, d_ptr->m_dataPath, d_ptr->m_cachePath,
+                    storageName, d_ptr->m_dataPath, d_ptr->m_cachePath,
                     QtWebEngineCore::ProfileAdapter::HttpCacheType(d_ptr->m_httpCacheType),
                     QtWebEngineCore::ProfileAdapter::PersistentCookiesPolicy(
                             d_ptr->m_persistentCookiesPolicy),
diff --git a/src/core/api/qwebengineprofilebuilder.h b/src/core/api/qwebengineprofilebuilder.h
index fe8c713a82f..d81a6bd471f 100644
--- a/src/core/api/qwebengineprofilebuilder.h
+++ b/src/core/api/qwebengineprofilebuilder.h
@@ -4,31 +4,32 @@
 #ifndef QWEBENGINEPROFILEBUILDER_H
 #define QWEBENGINEPROFILEBUILDER_H
 
-#include <QtCore/QScopedPointer>
 #include <QtWebEngineCore/qtwebenginecoreglobal.h>
 #include <QtWebEngineCore/qwebengineprofile.h>
 
+#include <memory>
+
 QT_BEGIN_NAMESPACE
 
 struct QWebEngineProfileBuilderPrivate;
-class Q_WEBENGINECORE_EXPORT QWebEngineProfileBuilder
+class QWebEngineProfileBuilder
 {
 public:
-    QWebEngineProfileBuilder();
-    ~QWebEngineProfileBuilder();
-    QWebEngineProfile *createProfile(const QString &storageName, QObject *parent = nullptr);
-    static QWebEngineProfile *createOffTheRecordProfile(QObject *parent = nullptr);
-    QWebEngineProfileBuilder &setPersistentStoragePath(const QString &path);
-    QWebEngineProfileBuilder &setCachePath(const QString &path);
-    QWebEngineProfileBuilder &setHttpCacheType(QWebEngineProfile::HttpCacheType httpCacheType);
-    QWebEngineProfileBuilder &setPersistentCookiesPolicy(
-            QWebEngineProfile::PersistentCookiesPolicy persistentCookiesPolicy);
-    QWebEngineProfileBuilder &setHttpCacheMaximumSize(int maxSizeInBytes);
-    QWebEngineProfileBuilder &setPersistentPermissionsPolicy(
+    Q_WEBENGINECORE_EXPORT QWebEngineProfileBuilder();
+    Q_WEBENGINECORE_EXPORT ~QWebEngineProfileBuilder();
+    Q_WEBENGINECORE_EXPORT QWebEngineProfile *createProfile(const QString &storageName, QObject *parent = nullptr) const;
+    Q_WEBENGINECORE_EXPORT static QWebEngineProfile *createOffTheRecordProfile(QObject *parent = nullptr);
+    Q_WEBENGINECORE_EXPORT QWebEngineProfileBuilder &setPersistentStoragePath(const QString &path);
+    Q_WEBENGINECORE_EXPORT QWebEngineProfileBuilder &setCachePath(const QString &path);
+    Q_WEBENGINECORE_EXPORT QWebEngineProfileBuilder &setHttpCacheType(QWebEngineProfile::HttpCacheType httpCacheType);
+    Q_WEBENGINECORE_EXPORT QWebEngineProfileBuilder &setPersistentCookiesPolicy(
+                                    QWebEngineProfile::PersistentCookiesPolicy persistentCookiesPolicy);
+    Q_WEBENGINECORE_EXPORT QWebEngineProfileBuilder &setHttpCacheMaximumSize(int maxSizeInBytes);
+    Q_WEBENGINECORE_EXPORT QWebEngineProfileBuilder &setPersistentPermissionsPolicy(
             QWebEngineProfile::PersistentPermissionsPolicy persistentPermissionPolicy);
 
 private:
-    Q_DISABLE_COPY(QWebEngineProfileBuilder)
+    Q_DISABLE_COPY_MOVE(QWebEngineProfileBuilder)
     std::unique_ptr<QWebEngineProfileBuilderPrivate> d_ptr;
 };
 
diff --git a/src/core/api/qwebengineprofilebuilder_p.h b/src/core/api/qwebengineprofilebuilder_p.h
index 32fcc730ea7..4146b55085d 100644
--- a/src/core/api/qwebengineprofilebuilder_p.h
+++ b/src/core/api/qwebengineprofilebuilder_p.h
@@ -20,9 +20,8 @@
 #include "qwebengineprofile.h"
 
 QT_BEGIN_NAMESPACE
-struct Q_WEBENGINECORE_EXPORT QWebEngineProfileBuilderPrivate
+struct QWebEngineProfileBuilderPrivate
 {
-    QString m_storageName;
     QString m_dataPath;
     QString m_cachePath;
     QWebEngineProfile::HttpCacheType m_httpCacheType = QWebEngineProfile::DiskHttpCache;
diff --git a/src/core/api/qwebenginescript.cpp b/src/core/api/qwebenginescript.cpp
index 846b011967c..ab91576bd89 100644
--- a/src/core/api/qwebenginescript.cpp
+++ b/src/core/api/qwebenginescript.cpp
@@ -7,6 +7,7 @@
 #include <QtCore/QDebug>
 #include <QtCore/QFile>
 
+using namespace Qt::StringLiterals;
 using QtWebEngineCore::UserScript;
 
 QT_BEGIN_NAMESPACE
@@ -161,17 +162,17 @@ void QWebEngineScript::setSourceUrl(const QUrl &url)
     QFile file;
     if (url.isLocalFile()) {
         file.setFileName(url.toLocalFile());
-    } else if (url.scheme().compare(QLatin1String("qrc"), Qt::CaseInsensitive) == 0) {
+    } else if (url.scheme().compare("qrc"_L1, Qt::CaseInsensitive) == 0) {
         if (url.authority().isEmpty())
             file.setFileName(QLatin1Char(':') + url.path());
     }
 
     if (!file.open(QIODevice::ReadOnly)) {
-        qWarning() << "Can't open user script " << url;
+        qWarning("Can't open user script %ls", qUtf16Printable(url.toString()));
         return;
     }
 
-    QString source = QString::fromUtf8(file.readAll());
+    const QString source = QString::fromUtf8(file.readAll());
     setSourceCode(source);
 }
 
diff --git a/src/core/api/qwebenginesettings.h b/src/core/api/qwebenginesettings.h
index e5dc2d678d1..3813dfecb04 100644
--- a/src/core/api/qwebenginesettings.h
+++ b/src/core/api/qwebenginesettings.h
@@ -64,7 +64,7 @@ class Q_WEBENGINECORE_EXPORT QWebEngineSettings
         ForceDarkMode,
         PrintHeaderAndFooter,
         PreferCSSMarginsForPrinting,
-        JSTouchEventsEnabled,
+        TouchEventsApiEnabled,
     };
 
     enum FontSize {
diff --git a/src/core/api/qwebengineurlscheme.cpp b/src/core/api/qwebengineurlscheme.cpp
index be56a304801..d2ca56f62d8 100644
--- a/src/core/api/qwebengineurlscheme.cpp
+++ b/src/core/api/qwebengineurlscheme.cpp
@@ -335,29 +335,33 @@ void QWebEngineUrlScheme::setFlags(Flags newValue)
 void QWebEngineUrlScheme::registerScheme(const QWebEngineUrlScheme &scheme)
 {
     if (scheme.d->name.empty()) {
-        qWarning() << "QWebEngineUrlScheme::registerScheme: Scheme name cannot be empty";
+        qWarning("QWebEngineUrlScheme::registerScheme: Scheme name cannot be empty");
         return;
     }
 
     bool needsPort = scheme.d->has_port_component();
     bool hasPort = scheme.d->default_port != url::PORT_UNSPECIFIED;
     if (needsPort && !hasPort) {
-        qWarning() << "QWebEngineUrlScheme::registerScheme: Scheme" << scheme.name() << "needs a default port";
+        qWarning("QWebEngineUrlScheme::registerScheme: Scheme %s needs a default port",
+                 scheme.d->name.data());
         return;
     }
 
     if (url::CustomScheme::FindScheme(scheme.d->name)) {
-        qWarning() << "QWebEngineUrlScheme::registerScheme: Scheme" << scheme.name() << "already registered";
+        qWarning("QWebEngineUrlScheme::registerScheme: Scheme %s already registered",
+                 scheme.d->name.data());
         return;
     }
 
     if (url::IsStandard(scheme.d->name.data(), url::Component(0, static_cast<int>(scheme.d->name.size())))) {
-        qWarning() << "QWebEngineUrlScheme::registerScheme: Scheme" << scheme.name() << "is a standard scheme";
+        qWarning("QWebEngineUrlScheme::registerScheme: Scheme %s is a standard scheme",
+                 scheme.d->name.data());
         return;
     }
 
     if (g_schemesLocked) {
-        qWarning() << "QWebEngineUrlScheme::registerScheme: Too late to register scheme" << scheme.name();
+        qWarning("QWebEngineUrlScheme::registerScheme: Too late to register scheme %s",
+                 scheme.d->name.data());
         return;
     }
 
diff --git a/src/core/api/qwebenginewebauthuxrequest.cpp b/src/core/api/qwebenginewebauthuxrequest.cpp
index 18ebbb70ea9..8e64948214e 100644
--- a/src/core/api/qwebenginewebauthuxrequest.cpp
+++ b/src/core/api/qwebenginewebauthuxrequest.cpp
@@ -12,7 +12,7 @@
     \since QtWebEngine 6.7
     \brief Encapsulates the data of a WebAuth UX request.
 
-    Web engine's WebAuth UX requests are passed to the user in the
+    WebEngine's WebAuth UX requests are passed to the user in the
     \l WebEngineView::webAuthUxRequested() signal.
 
     For more information about how to handle web engine authenticator requests, see the
@@ -109,8 +109,9 @@
         \c{WebEngineWebAuthUxRequest.PinEntryReason.Challenge}.
     \li The minimum PIN length that the authenticator will accept for the PIN.
     \endlist
-    Use this structure to update the WebAuth UX dialog when the WebAuth UX state is \l
-    WebEngineWebAuthUxRequest.WebAuthUxState.CollectPin.
+    Use this structure to update the WebAuth UX dialog when the WebAuth UX
+    \l {WebEngineWebAuthUxRequest::}{state} is
+    \c {WebEngineWebAuthUxRequest.WebAuthUxState.CollectPin}.
 */
 
 /*!
@@ -137,7 +138,7 @@
 /*!
     \qmlproperty int QtWebEngine::webEngineWebAuthPinRequest::remainingAttempts
     \brief The number of attempts remaining before a hard lock. Should be ignored unless
-           \l{WebEngineWebAuthPinRequest::reason} is
+           \l{webEngineWebAuthPinRequest::reason} is
            \c{WebEngineWebAuthUxRequest.PinEntryReason.Challenge}.
 */
 
@@ -208,7 +209,7 @@
     \value StorageFull The resident credential could not be created because the
            authenticator has insufficient storage.
     \value UserConsentDenied User consent denied.
-    \value WinUserCancelled The user clicked \uicontrol Cancel in the native windows UI.
+    \value WinUserCancelled The user clicked \uicontrol Cancel in the native Windows UI.
 */
 
 /*!
diff --git a/src/core/authenticator_request_client_delegate_qt.cpp b/src/core/authenticator_request_client_delegate_qt.cpp
index 5f9fd9ca37d..5d01df536e1 100644
--- a/src/core/authenticator_request_client_delegate_qt.cpp
+++ b/src/core/authenticator_request_client_delegate_qt.cpp
@@ -103,11 +103,16 @@ bool AuthenticatorRequestClientDelegateQt::DoesBlockRequestOnFailure(
     }
     return true;
 }
+
 void AuthenticatorRequestClientDelegateQt::RegisterActionCallbacks(
-        base::OnceClosure cancel_callback, base::RepeatingClosure start_over_callback,
+        base::OnceClosure cancel_callback,
+        base::RepeatingClosure start_over_callback,
         AccountPreselectedCallback account_preselected_callback,
         device::FidoRequestHandlerBase::RequestCallback request_callback,
-        base::RepeatingClosure bluetooth_adapter_power_on_callback)
+        base::RepeatingClosure bluetooth_adapter_power_on_callback,
+        base::RepeatingCallback<
+                void(device::FidoRequestHandlerBase::BlePermissionCallback)>
+                        request_ble_permission_callback)
 {
     m_cancelCallback = std::move(cancel_callback);
     m_startOverCallback = std::move(start_over_callback);
@@ -116,13 +121,6 @@ void AuthenticatorRequestClientDelegateQt::RegisterActionCallbacks(
     m_bluetoothAdapterPowerOnCallback = std::move(bluetooth_adapter_power_on_callback);
 }
 
-void AuthenticatorRequestClientDelegateQt::ShouldReturnAttestation(
-        const std::string &relying_party_id, const device::FidoAuthenticator *authenticator,
-        bool is_enterprise_attestation, base::OnceCallback<void(bool)> callback)
-{
-    std::move(callback).Run(!is_enterprise_attestation);
-}
-
 void AuthenticatorRequestClientDelegateQt::SelectAccount(
         std::vector<device::AuthenticatorGetAssertionResponse> responses,
         base::OnceCallback<void(device::AuthenticatorGetAssertionResponse)> callback)
@@ -150,7 +148,7 @@ void AuthenticatorRequestClientDelegateQt::SelectAccount(
         if (has_user_identifying_info) {
             QString userName = toQt(*response.user_entity->name);
             m_userMap[userName] = nIndex;
-            userList.append(userName);
+            userList.append(std::move(userName));
         }
     }
     m_dialogController->selectAccount(userList);
diff --git a/src/core/authenticator_request_client_delegate_qt.h b/src/core/authenticator_request_client_delegate_qt.h
index 05c6136bd16..8c8089f04d3 100644
--- a/src/core/authenticator_request_client_delegate_qt.h
+++ b/src/core/authenticator_request_client_delegate_qt.h
@@ -34,15 +34,15 @@ class AuthenticatorRequestClientDelegateQt : public content::AuthenticatorReques
     // content::AuthenticatorRequestClientDelegate ovverrides
     void SetRelyingPartyId(const std::string &rp_id) override;
     bool DoesBlockRequestOnFailure(InterestingFailureReason reason) override;
-    void RegisterActionCallbacks(base::OnceClosure cancel_callback,
-                            base::RepeatingClosure start_over_callback,
-                            AccountPreselectedCallback account_preselected_callback,
-                            device::FidoRequestHandlerBase::RequestCallback request_callback,
-                            base::RepeatingClosure bluetooth_adapter_power_on_callback) override;
-    void ShouldReturnAttestation(const std::string &relying_party_id,
-                                 const device::FidoAuthenticator *authenticator,
-                                 bool is_enterprise_attestation,
-                                 base::OnceCallback<void(bool)> callback) override;
+    void RegisterActionCallbacks(
+        base::OnceClosure cancel_callback,
+        base::RepeatingClosure start_over_callback,
+        AccountPreselectedCallback account_preselected_callback,
+        device::FidoRequestHandlerBase::RequestCallback request_callback,
+        base::RepeatingClosure bluetooth_adapter_power_on_callback,
+        base::RepeatingCallback<
+            void(device::FidoRequestHandlerBase::BlePermissionCallback)>
+            request_ble_permission_callback) override;
     void SelectAccount(
             std::vector<device::AuthenticatorGetAssertionResponse> responses,
             base::OnceCallback<void(device::AuthenticatorGetAssertionResponse)> callback) override;
diff --git a/src/core/autofill_client_qt.cpp b/src/core/autofill_client_qt.cpp
index b9a84943e04..b0e846844ef 100644
--- a/src/core/autofill_client_qt.cpp
+++ b/src/core/autofill_client_qt.cpp
@@ -61,8 +61,9 @@ const PrefService *AutofillClientQt::GetPrefs() const
     return profile->GetPrefs();
 }
 
-void AutofillClientQt::ShowAutofillSuggestions(const autofill::AutofillClient::PopupOpenArgs &open_args,
-                                               base::WeakPtr<autofill::AutofillSuggestionDelegate> delegate)
+autofill::AutofillClient::SuggestionUiSessionId AutofillClientQt::ShowAutofillSuggestions(
+        const autofill::AutofillClient::PopupOpenArgs &open_args,
+        base::WeakPtr<autofill::AutofillSuggestionDelegate> delegate)
 {
     m_popupController->d->delegate = delegate;
     m_popupController->d->suggestions = open_args.suggestions;
@@ -74,6 +75,7 @@ void AutofillClientQt::ShowAutofillSuggestions(const autofill::AutofillClient::P
     adapterClient()->showAutofillPopup(m_popupController.data(),
                                        QRect(toQt(gfx::ToEnclosingRect(open_args.element_bounds))),
                                        autoSelectFirstSuggestion);
+    return {};
 }
 
 void AutofillClientQt::UpdateAutofillDataListValues(
diff --git a/src/core/autofill_client_qt.h b/src/core/autofill_client_qt.h
index 9e7bbd300a1..2f97e005ba5 100644
--- a/src/core/autofill_client_qt.h
+++ b/src/core/autofill_client_qt.h
@@ -45,16 +45,13 @@ class AutofillClientQt : public autofill::ContentAutofillClient,
     PrefService *GetPrefs() override;
     const PrefService *GetPrefs() const override;
 
-    void ShowAutofillSuggestions(
-            const PopupOpenArgs &open_args,
-            base::WeakPtr<autofill::AutofillSuggestionDelegate> delegate) override;
+    SuggestionUiSessionId
+    ShowAutofillSuggestions(const PopupOpenArgs &open_args,
+                            base::WeakPtr<autofill::AutofillSuggestionDelegate> delegate) override;
     void UpdateAutofillDataListValues(
             base::span<const autofill::SelectOption> datalist) override;
     void PinAutofillSuggestions() override;
     base::span<const autofill::Suggestion> GetAutofillSuggestions() const override;
-    void UpdatePopup(const std::vector<autofill::Suggestion> &suggestions,
-                     autofill::FillingProduct main_filling_product,
-                     autofill::AutofillSuggestionTriggerSource trigger_source) override{};
     void HideAutofillSuggestions(autofill::SuggestionHidingReason reason) override;
     bool IsAutocompleteEnabled() const override;
     bool IsPasswordManagerEnabled() override;
diff --git a/src/core/autofill_popup_controller.cpp b/src/core/autofill_popup_controller.cpp
index a60392051ab..99eb09f379c 100644
--- a/src/core/autofill_popup_controller.cpp
+++ b/src/core/autofill_popup_controller.cpp
@@ -9,7 +9,7 @@
 
 namespace QtWebEngineCore {
 
-using SuggestionPosition = autofill::AutofillSuggestionDelegate::SuggestionPosition;
+using SuggestionPosition = autofill::AutofillSuggestionDelegate::SuggestionMetadata;
 
 AutofillPopupController::AutofillPopupController(AutofillPopupControllerPrivate *dd)
 {
@@ -86,7 +86,7 @@ void AutofillPopupController::acceptSuggestion()
 
 void AutofillPopupController::notifyPopupShown()
 {
-    d->delegate->OnSuggestionsShown();
+    d->delegate->OnSuggestionsShown({});
 }
 
 void AutofillPopupController::notifyPopupHidden()
diff --git a/src/core/browser_accessibility_manager_qt.cpp b/src/core/browser_accessibility_manager_qt.cpp
index bc78b815aee..a36076ffef1 100644
--- a/src/core/browser_accessibility_manager_qt.cpp
+++ b/src/core/browser_accessibility_manager_qt.cpp
@@ -3,7 +3,7 @@
 
 #include "qtwebenginecoreglobal.h"
 
-#include "content/browser/accessibility/browser_accessibility_manager.h"
+#include "ui/accessibility/platform/browser_accessibility_manager.h"
 
 #include <QtGui/qtguiglobal.h>
 
@@ -12,18 +12,19 @@
 #include "browser_accessibility_manager_qt.h"
 #include "render_widget_host_view_qt.h" // WebContentsAccessibilityQt
 
-#include "content/browser/accessibility/browser_accessibility.h"
 #include "ui/accessibility/ax_enums.mojom.h"
+#include "ui/accessibility/platform/browser_accessibility.h"
 
 #include <QtGui/qaccessible.h>
 #endif // QT_CONFIG(accessibility)
 
-namespace content {
+namespace ui {
 
 // static
-BrowserAccessibilityManager *BrowserAccessibilityManager::Create(
-        const ui::AXTreeUpdate &initialTree,
-        ui::AXPlatformTreeManagerDelegate *delegate)
+BrowserAccessibilityManager *
+BrowserAccessibilityManager::Create(const ui::AXTreeUpdate &initialTree,
+                                    ui::AXNodeIdDelegate &nodeDelegate,
+                                    ui::AXPlatformTreeManagerDelegate *delegate)
 {
 #if QT_CONFIG(accessibility)
     Q_ASSERT(delegate);
@@ -35,7 +36,7 @@ BrowserAccessibilityManager *BrowserAccessibilityManager::Create(
         return nullptr;
     }
 
-    return new BrowserAccessibilityManagerQt(access, initialTree, delegate);
+    return new BrowserAccessibilityManagerQt(access, initialTree, nodeDelegate, delegate);
 #else
     Q_UNUSED(initialTree);
     Q_UNUSED(delegate);
@@ -44,12 +45,15 @@ BrowserAccessibilityManager *BrowserAccessibilityManager::Create(
 }
 
 // static
-BrowserAccessibilityManager *BrowserAccessibilityManager::Create(
-        ui::AXPlatformTreeManagerDelegate *delegate)
+BrowserAccessibilityManager *
+BrowserAccessibilityManager::Create(ui::AXNodeIdDelegate &nodeDelegate,
+                                    ui::AXPlatformTreeManagerDelegate *delegate)
 {
 #if QT_CONFIG(accessibility)
-    return BrowserAccessibilityManager::Create(BrowserAccessibilityManagerQt::GetEmptyDocument(), delegate);
+    return BrowserAccessibilityManager::Create(BrowserAccessibilityManagerQt::GetEmptyDocument(),
+                                               nodeDelegate, delegate);
 #else
+    Q_UNUSED(nodeDelegate);
     Q_UNUSED(delegate);
     return nullptr;
 #endif
@@ -57,11 +61,11 @@ BrowserAccessibilityManager *BrowserAccessibilityManager::Create(
 
 #if QT_CONFIG(accessibility)
 BrowserAccessibilityManagerQt::BrowserAccessibilityManagerQt(
-    QtWebEngineCore::WebContentsAccessibilityQt *webContentsAccessibility,
-    const ui::AXTreeUpdate &initialTree,
-    ui::AXPlatformTreeManagerDelegate *delegate)
-      : BrowserAccessibilityManager(delegate)
-      , m_webContentsAccessibility(webContentsAccessibility)
+        QtWebEngineCore::WebContentsAccessibilityQt *webContentsAccessibility,
+        const ui::AXTreeUpdate &initialTree, ui::AXNodeIdDelegate &nodeDelegate,
+        ui::AXPlatformTreeManagerDelegate *delegate)
+    : BrowserAccessibilityManager(nodeDelegate, delegate)
+    , m_webContentsAccessibility(webContentsAccessibility)
 {
     Initialize(initialTree);
     m_valid = true; // BrowserAccessibilityQt can start using the AXTree
@@ -74,7 +78,7 @@ BrowserAccessibilityManagerQt::~BrowserAccessibilityManagerQt()
 
 QAccessibleInterface *BrowserAccessibilityManagerQt::rootParentAccessible()
 {
-    content::BrowserAccessibility *parent_node = GetParentNodeFromParentTreeAsBrowserAccessibility();
+    ui::BrowserAccessibility *parent_node = GetParentNodeFromParentTreeAsBrowserAccessibility();
     if (!parent_node) {
         Q_ASSERT(m_webContentsAccessibility);
         return QAccessible::queryAccessibleInterface(m_webContentsAccessibility->accessibilityParentObject());
diff --git a/src/core/browser_accessibility_manager_qt.h b/src/core/browser_accessibility_manager_qt.h
index 5006f22111d..3b8f1833794 100644
--- a/src/core/browser_accessibility_manager_qt.h
+++ b/src/core/browser_accessibility_manager_qt.h
@@ -4,7 +4,7 @@
 #ifndef BROWSER_ACCESSIBILITY_MANAGER_QT_H
 #define BROWSER_ACCESSIBILITY_MANAGER_QT_H
 
-#include "content/browser/accessibility/browser_accessibility_manager.h"
+#include "ui/accessibility/platform/browser_accessibility_manager.h"
 
 #include <QtCore/qtclasshelpermacros.h>
 #include <QtCore/qtconfigmacros.h>
@@ -15,14 +15,15 @@ namespace QtWebEngineCore {
 class WebContentsAccessibilityQt;
 }
 
-namespace content {
+namespace ui {
 
 class BrowserAccessibilityManagerQt : public BrowserAccessibilityManager
 {
 public:
-    BrowserAccessibilityManagerQt(QtWebEngineCore::WebContentsAccessibilityQt *webContentsAccessibility,
-                                  const ui::AXTreeUpdate &initialTree,
-                                  ui::AXPlatformTreeManagerDelegate *delegate);
+    BrowserAccessibilityManagerQt(
+            QtWebEngineCore::WebContentsAccessibilityQt *webContentsAccessibility,
+            const ui::AXTreeUpdate &initialTree, ui::AXNodeIdDelegate &nodeDelegate,
+            ui::AXPlatformTreeManagerDelegate *delegate);
     ~BrowserAccessibilityManagerQt() override;
     void FireBlinkEvent(ax::mojom::Event event_type,
                         BrowserAccessibility *node,
diff --git a/src/core/browser_accessibility_qt.cpp b/src/core/browser_accessibility_qt.cpp
index 1d2f39c2f9e..ce6080716ba 100644
--- a/src/core/browser_accessibility_qt.cpp
+++ b/src/core/browser_accessibility_qt.cpp
@@ -11,21 +11,30 @@
 #include "type_conversion.h"
 
 #if QT_CONFIG(accessibility)
-#include "content/browser/accessibility/browser_accessibility.h"
 #include "ui/accessibility/ax_enums.mojom.h"
+#include "ui/accessibility/platform/browser_accessibility.h"
 
 #include <QtGui/qaccessible.h>
 
 namespace QtWebEngineCore {
 class BrowserAccessibilityInterface;
 
-class BrowserAccessibilityQt
-    : public content::BrowserAccessibility
+class BrowserAccessibilityQt : public ui::BrowserAccessibility
 {
 public:
-    BrowserAccessibilityQt(content::BrowserAccessibilityManager *manager, ui::AXNode *node);
+    BrowserAccessibilityQt(ui::BrowserAccessibilityManager *manager, ui::AXNode *node);
     ~BrowserAccessibilityQt();
 
+#if defined(Q_OS_MACOS)
+    // Mac-specific overrides to account for extra nodes
+    size_t PlatformChildCount() const override;
+    ui::BrowserAccessibility *PlatformGetChild(size_t child_index) const override;
+    ui::BrowserAccessibility *PlatformGetFirstChild() const override;
+    ui::BrowserAccessibility *PlatformGetLastChild() const override;
+    ui::BrowserAccessibility *PlatformGetNextSibling() const override;
+    ui::BrowserAccessibility *PlatformGetPreviousSibling() const override;
+#endif
+
     bool isReady() const;
 
     QtWebEngineCore::BrowserAccessibilityInterface *interface = nullptr;
@@ -127,17 +136,16 @@ class BrowserAccessibilityInterface
     void modelChange(QAccessibleTableModelChangeEvent *event) override;
 
 private:
-    content::BrowserAccessibility *findTable() const;
+    ui::BrowserAccessibility *findTable() const;
 
     QObject *m_object = nullptr;
     QAccessible::Id m_id = 0;
     BrowserAccessibilityQt *q;
 };
 
-BrowserAccessibilityQt::BrowserAccessibilityQt(content::BrowserAccessibilityManager *manager,
+BrowserAccessibilityQt::BrowserAccessibilityQt(ui::BrowserAccessibilityManager *manager,
                                                ui::AXNode *node)
-    : content::BrowserAccessibility(manager, node)
-    , interface(new BrowserAccessibilityInterface(this))
+    : ui::BrowserAccessibility(manager, node), interface(new BrowserAccessibilityInterface(this))
 {
 }
 
@@ -154,13 +162,103 @@ bool BrowserAccessibilityQt::isReady() const
     return manager()->GetFromID(node()->id()) != nullptr;
 }
 
+#if defined(Q_OS_MACOS)
+
+// Mac-only logic based on ui/accessibility/platform/browser_accessibility_mac.mm:
+
+size_t BrowserAccessibilityQt::PlatformChildCount() const
+{
+    size_t child_count = BrowserAccessibility::PlatformChildCount();
+
+    // If this is a table, include the extra fake nodes generated by
+    // AXTableInfo, for the column nodes and the table header container, all of
+    // which are only important on macOS.
+    const std::vector<raw_ptr<ui::AXNode, VectorExperimental>>* extra_mac_nodes =
+        node()->GetExtraMacNodes();
+    if (!extra_mac_nodes)
+        return child_count;
+
+    return child_count + extra_mac_nodes->size();
+}
+
+ui::BrowserAccessibility* BrowserAccessibilityQt::PlatformGetChild(size_t child_index) const
+{
+    if (child_index < BrowserAccessibility::PlatformChildCount())
+        return BrowserAccessibility::PlatformGetChild(child_index);
+
+    if (child_index >= PlatformChildCount())
+        return nullptr;
+
+    // If this is a table, include the extra fake nodes generated by
+    // AXTableInfo, for the column nodes and the table header container, all of
+    // which are only important on macOS.
+    const std::vector<raw_ptr<ui::AXNode, VectorExperimental>>* extra_mac_nodes =
+        node()->GetExtraMacNodes();
+    if (!extra_mac_nodes || extra_mac_nodes->empty())
+        return nullptr;
+
+    child_index -= BrowserAccessibility::PlatformChildCount();
+    if (child_index < extra_mac_nodes->size())
+        return manager_->GetFromAXNode((*extra_mac_nodes)[child_index]);
+
+    return nullptr;
+}
+
+ui::BrowserAccessibility* BrowserAccessibilityQt::PlatformGetFirstChild() const
+{
+    return PlatformGetChild(0);
+}
+
+ui::BrowserAccessibility* BrowserAccessibilityQt::PlatformGetLastChild() const
+{
+    const std::vector<raw_ptr<ui::AXNode, VectorExperimental>>* extra_mac_nodes =
+      node()->GetExtraMacNodes();
+    if (extra_mac_nodes && !extra_mac_nodes->empty())
+        return manager_->GetFromAXNode(extra_mac_nodes->back());
+    return BrowserAccessibility::PlatformGetLastChild();
+}
+
+ui::BrowserAccessibility* BrowserAccessibilityQt::PlatformGetNextSibling() const
+{
+    BrowserAccessibility* parent = PlatformGetParent();
+    if (parent) {
+        size_t next_child_index = node()->GetUnignoredIndexInParent() + 1;
+        if (next_child_index >= parent->InternalChildCount()
+                && next_child_index < parent->PlatformChildCount()) {
+            // Get the extra_mac_node.
+            return parent->PlatformGetChild(next_child_index);
+        } else if (next_child_index >= parent->PlatformChildCount()) {
+            return nullptr;
+        }
+    }
+    return BrowserAccessibility::PlatformGetNextSibling();
+}
+
+ui::BrowserAccessibility* BrowserAccessibilityQt::PlatformGetPreviousSibling() const
+{
+    BrowserAccessibility* parent = PlatformGetParent();
+    if (parent) {
+        size_t child_index = node()->GetUnignoredIndexInParent();
+        if (child_index > parent->InternalChildCount()
+                && child_index <= parent->PlatformChildCount()) {
+            // Get the extra_mac_node.
+            return parent->PlatformGetChild(child_index - 1);
+        } else if (child_index == 0) {
+            return nullptr;
+        }
+    }
+    return BrowserAccessibility::PlatformGetPreviousSibling();
+}
+
+#endif // defined(Q_OS_MACOS)
+
 BrowserAccessibilityInterface::BrowserAccessibilityInterface(BrowserAccessibilityQt *chromiumInterface)
     : q(chromiumInterface)
 {
     if (parent() && parent()->object()) {
         m_object = new QObject(parent()->object());
-        QString name = toQt(q->GetAuthorUniqueId());
-        if (!name.isEmpty())
+        const std::u16string name = q->GetAuthorUniqueId();
+        if (!name.empty())
             m_object->setObjectName(name);
     }
 
@@ -182,7 +280,7 @@ bool BrowserAccessibilityInterface::isValid() const
     if (!q->isReady())
         return false;
 
-    auto managerQt = static_cast<content::BrowserAccessibilityManagerQt *>(q->manager());
+    auto managerQt = static_cast<ui::BrowserAccessibilityManagerQt *>(q->manager());
     return managerQt && managerQt->isValid();
 }
 
@@ -195,8 +293,7 @@ QAccessibleInterface *BrowserAccessibilityInterface::childAt(int x, int y) const
 {
     for (int i = 0; i < childCount(); ++i) {
         QAccessibleInterface *childIface = child(i);
-        Q_ASSERT(childIface);
-        if (childIface->rect().contains(x,y))
+        if (childIface && childIface->rect().contains(x,y))
             return childIface;
     }
     return nullptr;
@@ -246,15 +343,15 @@ void *BrowserAccessibilityInterface::interface_cast(QAccessible::InterfaceType t
 
 QAccessibleInterface *BrowserAccessibilityInterface::parent() const
 {
-    content::BrowserAccessibility *chromiumParent = q->PlatformGetParent();
+    ui::BrowserAccessibility *chromiumParent = q->PlatformGetParent();
     if (chromiumParent)
         return toQAccessibleInterface(chromiumParent);
-    return static_cast<content::BrowserAccessibilityManagerQt*>(q->manager())->rootParentAccessible();
+    return static_cast<ui::BrowserAccessibilityManagerQt *>(q->manager())->rootParentAccessible();
 }
 
 QAccessibleInterface *BrowserAccessibilityInterface::child(int index) const
 {
-    content::BrowserAccessibility *chromiumChild = q->PlatformGetChild(index);
+    ui::BrowserAccessibility *chromiumChild = q->PlatformGetChild(index);
     return chromiumChild ? toQAccessibleInterface(chromiumChild) : nullptr;
 }
 
@@ -264,8 +361,9 @@ QAccessibleInterface *BrowserAccessibilityInterface::focusChild() const
         return const_cast<BrowserAccessibilityInterface *>(this);
 
     for (int i = 0; i < childCount(); ++i) {
-        if (QAccessibleInterface *iface = child(i)->focusChild())
-            return iface;
+        if (QAccessibleInterface *c = child(i))
+            if (QAccessibleInterface *iface = c->focusChild())
+                return iface;
     }
 
     return nullptr;
@@ -358,7 +456,7 @@ QAccessible::Role BrowserAccessibilityInterface::role() const
     case ax::mojom::Role::kCaption:
         return QAccessible::Heading;
     case ax::mojom::Role::kCaret:
-        return QAccessible::NoRole; // FIXME: https://codereview.chromium.org/2781613003
+        return QAccessible::Caret;
     case ax::mojom::Role::kCell:
         return QAccessible::Cell;
     case ax::mojom::Role::kCheckBox:
@@ -372,10 +470,9 @@ QAccessible::Role BrowserAccessibilityInterface::role() const
     case ax::mojom::Role::kColumn:
         return QAccessible::Column;
     case ax::mojom::Role::kColumnHeader:
-        return QAccessible::ColumnHeader;
+        return QAccessible::Cell;  // QAccessible::ColumnHeader causes wrong navigations on macOS
     case ax::mojom::Role::kComboBoxGrouping:
     case ax::mojom::Role::kComboBoxMenuButton:
-    case ax::mojom::Role::kTextFieldWithComboBox:
         return QAccessible::ComboBox;
     case ax::mojom::Role::kComboBoxSelect:
         return QAccessible::PopupMenu;
@@ -478,8 +575,6 @@ QAccessible::Role BrowserAccessibilityInterface::role() const
     case ax::mojom::Role::kFooter:
         // CORE-AAM recommends LANDMARK instead of FOOTER.
         return QAccessible::Section;
-    case ax::mojom::Role::kFooterAsNonLandmark:
-        return QAccessible::Section;
     case ax::mojom::Role::kForm:
         return QAccessible::Form;
     case ax::mojom::Role::kGraphicsDocument:
@@ -490,10 +585,11 @@ QAccessible::Role BrowserAccessibilityInterface::role() const
         return QAccessible::Graphic;
     case ax::mojom::Role::kGrid:
         return QAccessible::Table;
+    case ax::mojom::Role::kGridCell:
+        return QAccessible::Cell;
     case ax::mojom::Role::kGroup:
         return QAccessible::Grouping;
     case ax::mojom::Role::kHeader:
-    case ax::mojom::Role::kHeaderAsNonLandmark:
         return QAccessible::Section;
     case ax::mojom::Role::kHeading:
         return QAccessible::Heading;
@@ -607,7 +703,7 @@ QAccessible::Role BrowserAccessibilityInterface::role() const
     case ax::mojom::Role::kPane:
         return QAccessible::Pane;
     case ax::mojom::Role::kParagraph:
-        return QAccessible::Paragraph;
+        return QAccessible::Grouping; // QAccessible::Paragraph causes child nodes to be ignored by Windows Narrator
     case ax::mojom::Role::kPdfActionableHighlight:
         return QAccessible::Button;
     case ax::mojom::Role::kPdfRoot:
@@ -616,7 +712,7 @@ QAccessible::Role BrowserAccessibilityInterface::role() const
         return QAccessible::Grouping;
     case ax::mojom::Role::kPopUpButton:
         return QAccessible::ComboBox;
-    case ax::mojom::Role::kPortal:
+    case ax::mojom::Role::kPortalDeprecated:
         return QAccessible::Button;
     case ax::mojom::Role::kPreDeprecated:
         return QAccessible::Section;
@@ -633,7 +729,7 @@ QAccessible::Role BrowserAccessibilityInterface::role() const
     case ax::mojom::Role::kRowGroup:
         return QAccessible::Section;
     case ax::mojom::Role::kRowHeader:
-        return QAccessible::RowHeader;
+        return QAccessible::Cell; // QAccessible::RowHeader causes wrong navigations on macOS
     case ax::mojom::Role::kRuby:
         return QAccessible::Grouping;
     case ax::mojom::Role::kRubyAnnotation:
@@ -647,6 +743,8 @@ QAccessible::Role BrowserAccessibilityInterface::role() const
     case ax::mojom::Role::kSearchBox:
         return QAccessible::EditableText;
     case ax::mojom::Role::kSection:
+    case ax::mojom::Role::kSectionFooter:
+    case ax::mojom::Role::kSectionHeader:
     case ax::mojom::Role::kSectionWithoutName:
         return QAccessible::Section;
     case ax::mojom::Role::kSlider:
@@ -685,6 +783,8 @@ QAccessible::Role BrowserAccessibilityInterface::role() const
         return QAccessible::StaticText;
     case ax::mojom::Role::kTextField:
         return QAccessible::EditableText;
+    case ax::mojom::Role::kTextFieldWithComboBox:
+        return QAccessible::ComboBox;
     case ax::mojom::Role::kTime:
     case ax::mojom::Role::kTimer:
         return QAccessible::Clock;
@@ -838,7 +938,8 @@ BrowserAccessibilityInterface::keyBindingsForAction(const QString & /*actionName
 
 void BrowserAccessibilityInterface::addSelection(int startOffset, int endOffset)
 {
-    q->manager()->SetSelection(content::BrowserAccessibility::AXRange(q->CreatePositionAt(startOffset), q->CreatePositionAt(endOffset)));
+    q->manager()->SetSelection(ui::BrowserAccessibility::AXRange(q->CreatePositionAt(startOffset),
+                                                                 q->CreatePositionAt(endOffset)));
 }
 
 QString BrowserAccessibilityInterface::attributes(int offset, int *startOffset, int *endOffset) const
@@ -896,19 +997,22 @@ QString BrowserAccessibilityInterface::text(int startOffset, int endOffset) cons
 
 void BrowserAccessibilityInterface::removeSelection(int selectionIndex)
 {
-    q->manager()->SetSelection(content::BrowserAccessibility::AXRange(q->CreatePositionAt(0), q->CreatePositionAt(0)));
+    q->manager()->SetSelection(
+            ui::BrowserAccessibility::AXRange(q->CreatePositionAt(0), q->CreatePositionAt(0)));
 }
 
 void BrowserAccessibilityInterface::setCursorPosition(int position)
 {
-    q->manager()->SetSelection(content::BrowserAccessibility::AXRange(q->CreatePositionAt(position), q->CreatePositionAt(position)));
+    q->manager()->SetSelection(ui::BrowserAccessibility::AXRange(q->CreatePositionAt(position),
+                                                                 q->CreatePositionAt(position)));
 }
 
 void BrowserAccessibilityInterface::setSelection(int selectionIndex, int startOffset, int endOffset)
 {
     if (selectionIndex != 0)
         return;
-    q->manager()->SetSelection(content::BrowserAccessibility::AXRange(q->CreatePositionAt(startOffset), q->CreatePositionAt(endOffset)));
+    q->manager()->SetSelection(ui::BrowserAccessibility::AXRange(q->CreatePositionAt(startOffset),
+                                                                 q->CreatePositionAt(endOffset)));
 }
 
 int BrowserAccessibilityInterface::characterCount() const
@@ -975,29 +1079,42 @@ QVariant BrowserAccessibilityInterface::minimumStepSize() const
 
 QAccessibleInterface *BrowserAccessibilityInterface::cellAt(int row, int column) const
 {
-    int columns = 0;
-    int rows = 0;
-    if (!q->GetIntAttribute(ax::mojom::IntAttribute::kTableColumnCount, &columns)
-        || !q->GetIntAttribute(ax::mojom::IntAttribute::kTableRowCount, &rows)
-        || columns <= 0
-        || rows <= 0) {
+    if (!isValid() || !q->node()->IsTable())
         return nullptr;
-    }
 
-    if (row < 0 || row >= rows || column < 0 || column >= columns)
-        return nullptr;
+    auto *node = q->node()->GetTableCellFromCoords(row, column);
+    ui::BrowserAccessibility *cell = q->manager()->GetFromAXNode(node);
+    if (cell) {
+        int extent = 1;
+
+        if (cell->GetIntAttribute(ax::mojom::IntAttribute::kTableCellColumnSpan, &extent), extent != 1) {
+            if (cell->GetTableCellColIndex() != column) {
+                // Cell has a column extent greater than 1. Calling code may get confused by
+                // the same cell object being returned by calls to cellAt() with different
+                // parameters, so we return nothing instead
+                return nullptr;
+            }
+        }
 
-    std::optional<int> cell_id = q->GetCellId(row, column);
-    content::BrowserAccessibility *cell = cell_id ? q->manager()->GetFromID(*cell_id) : nullptr;
-    if (cell)
-        return content::toQAccessibleInterface(cell);
+        if (cell->GetIntAttribute(ax::mojom::IntAttribute::kTableCellRowSpan, &extent), extent != 1) {
+            if (cell->GetTableCellRowIndex() != row) {
+                // Cell has a row extent greater than 1. Calling code may get confused by
+                // the same cell object being returned by calls to cellAt() with different
+                // parameters, so we return nothing instead
+                return nullptr;
+            }
+        }
+
+        return ui::toQAccessibleInterface(cell);
+    }
 
     return nullptr;
 }
 
 QAccessibleInterface *BrowserAccessibilityInterface::caption() const
 {
-    return nullptr;
+    auto *caption = q->manager()->GetFromAXNode(q->node()->GetTableCaption());
+    return caption ? ui::toQAccessibleInterface(caption) : nullptr;
 }
 
 QAccessibleInterface *BrowserAccessibilityInterface::summary() const
@@ -1017,18 +1134,20 @@ QString BrowserAccessibilityInterface::rowDescription(int row) const
 
 int BrowserAccessibilityInterface::columnCount() const
 {
-    int columns = 0;
-    if (q->GetIntAttribute(ax::mojom::IntAttribute::kTableColumnCount, &columns))
-        return columns;
-    return 0;
+    if (!isValid())
+        return 0;
+
+    auto count = q->node()->GetTableColCount();
+    return count ? count.value() : 0;
 }
 
 int BrowserAccessibilityInterface::rowCount() const
 {
-    int rows = 0;
-    if (q->GetIntAttribute(ax::mojom::IntAttribute::kTableRowCount, &rows))
-        return rows;
-    return 0;
+    if (!isValid())
+        return 0;
+
+    auto count = q->node()->GetTableRowCount();
+    return count ? count.value() : 0;
 }
 
 int BrowserAccessibilityInterface::selectedCellCount() const
@@ -1093,6 +1212,9 @@ bool BrowserAccessibilityInterface::unselectColumn(int /*column*/)
 
 int BrowserAccessibilityInterface::columnExtent() const
 {
+    int column = 0;
+    if (q->GetIntAttribute(ax::mojom::IntAttribute::kTableCellColumnSpan, &column))
+        return column;
     return 1;
 }
 
@@ -1103,14 +1225,15 @@ QList<QAccessibleInterface *> BrowserAccessibilityInterface::columnHeaderCells()
 
 int BrowserAccessibilityInterface::columnIndex() const
 {
-    int column = 0;
-    if (q->GetIntAttribute(ax::mojom::IntAttribute::kTableCellColumnIndex, &column))
-        return column;
-    return 0;
+    auto index = q->node()->GetTableCellColIndex();
+    return index ? index.value() : 0;
 }
 
 int BrowserAccessibilityInterface::rowExtent() const
 {
+    int row = 0;
+    if (q->GetIntAttribute(ax::mojom::IntAttribute::kTableCellRowSpan, &row))
+        return row;
     return 1;
 }
 
@@ -1121,10 +1244,8 @@ QList<QAccessibleInterface *> BrowserAccessibilityInterface::rowHeaderCells() co
 
 int BrowserAccessibilityInterface::rowIndex() const
 {
-    int row = 0;
-    if (q->GetIntAttribute(ax::mojom::IntAttribute::kTableCellRowIndex, &row))
-        return row;
-    return 0;
+    auto index = q->node()->GetTableCellRowIndex();
+    return index ? index.value() : 0;
 }
 
 bool BrowserAccessibilityInterface::isSelected() const
@@ -1132,20 +1253,16 @@ bool BrowserAccessibilityInterface::isSelected() const
     return false;
 }
 
-content::BrowserAccessibility *BrowserAccessibilityInterface::findTable() const
+ui::BrowserAccessibility *BrowserAccessibilityInterface::findTable() const
 {
-    content::BrowserAccessibility *parent = q->PlatformGetParent();
-    while (parent && parent->GetRole() != ax::mojom::Role::kTable)
-        parent = parent->PlatformGetParent();
-
-    return parent;
+    return q->manager()->GetFromAXNode(q->node()->GetTableAncestor());
 }
 
 QAccessibleInterface *BrowserAccessibilityInterface::table() const
 {
-    content::BrowserAccessibility *table = findTable();
+    ui::BrowserAccessibility *table = findTable();
     Q_ASSERT(table);
-    return content::toQAccessibleInterface(table);
+    return ui::toQAccessibleInterface(table);
 }
 
 void BrowserAccessibilityInterface::modelChange(QAccessibleTableModelChangeEvent *)
@@ -1155,7 +1272,7 @@ void BrowserAccessibilityInterface::modelChange(QAccessibleTableModelChangeEvent
 } // namespace QtWebEngineCore
 
 #endif // QT_CONFIG(accessibility)
-namespace content {
+namespace ui {
 
 // static
 std::unique_ptr<BrowserAccessibility> BrowserAccessibility::Create(BrowserAccessibilityManager *man, ui::AXNode *node)
@@ -1181,4 +1298,4 @@ const QAccessibleInterface *toQAccessibleInterface(const BrowserAccessibility *o
 }
 #endif // #if QT_CONFIG(accessibility)
 
-} // namespace content
+} // namespace ui
diff --git a/src/core/browser_accessibility_qt.h b/src/core/browser_accessibility_qt.h
index 598aa3ef52d..85196e19c0a 100644
--- a/src/core/browser_accessibility_qt.h
+++ b/src/core/browser_accessibility_qt.h
@@ -9,13 +9,13 @@
 #if QT_CONFIG(accessibility)
 QT_FORWARD_DECLARE_CLASS(QAccessibleInterface)
 
-namespace content {
+namespace ui {
 class BrowserAccessibility;
 
 QAccessibleInterface *toQAccessibleInterface(BrowserAccessibility *obj);
 const QAccessibleInterface *toQAccessibleInterface(const BrowserAccessibility *obj);
 
-} // namespace content
+} // namespace ui
 #endif // QT_CONFIG(accessibility)
 
 #endif // BROWSER_ACCESSIBILITY_QT_H
diff --git a/src/core/browser_main_parts_qt.cpp b/src/core/browser_main_parts_qt.cpp
index 2104a91ccb9..35407a62b0d 100644
--- a/src/core/browser_main_parts_qt.cpp
+++ b/src/core/browser_main_parts_qt.cpp
@@ -153,8 +153,7 @@ class MessagePumpForUIQt : public base::MessagePump
         if (more_work_info.is_immediate())
             return m_scheduler.scheduleImmediateWork();
 
-        if (m_delegate->DoIdleWork())
-            return m_scheduler.scheduleIdleWork();
+        m_delegate->DoIdleWork();
 
         ScheduleDelayedWork(more_work_info.delayed_run_time);
     }
diff --git a/src/core/client_cert_select_controller.cpp b/src/core/client_cert_select_controller.cpp
index d6af984c187..e898da618ae 100644
--- a/src/core/client_cert_select_controller.cpp
+++ b/src/core/client_cert_select_controller.cpp
@@ -75,7 +75,7 @@ void ClientCertSelectController::select(const QSslCertificate &certificate)
         LOG(WARNING) << "ClientCertSelectController::select() certificate already selected";
         return;
     }
-    QByteArray derCertificate = certificate.toDer();
+    const QByteArray derCertificate = certificate.toDer();
     scoped_refptr<net::X509Certificate> selectedCert =
             net::X509Certificate::CreateFromBytes(base::make_span((const unsigned char *)derCertificate.constData(),
                                                                   (long unsigned)derCertificate.length()));
diff --git a/src/core/clipboard_qt.cpp b/src/core/clipboard_qt.cpp
index 463d858503f..1560d581594 100644
--- a/src/core/clipboard_qt.cpp
+++ b/src/core/clipboard_qt.cpp
@@ -32,6 +32,8 @@
 
 #include <memory>
 
+using namespace Qt::StringLiterals;
+
 namespace QtWebEngineCore {
 
 static void registerMetaTypes()
@@ -125,21 +127,22 @@ void ClipboardQt::WritePortableAndPlatformRepresentations(ui::ClipboardBuffer ty
     m_dataSrc[type] = std::move(data_src);
 }
 
-void ClipboardQt::WriteText(base::StringPiece text)
+void ClipboardQt::WriteText(std::string_view text)
 {
     getUncommittedData()->setText(toQString(text));
 }
 
-void ClipboardQt::WriteHTML(base::StringPiece markup, std::optional<base::StringPiece> source_url)
+void ClipboardQt::WriteHTML(std::string_view markup, std::optional<std::string_view> source_url)
 {
 
-    QString markup_string = toQString(markup);
+    QString markup_string;
 #if defined (Q_OS_MACOS)
     // We need to prepend the charset on macOS to prevent garbled Unicode characters
     // when pasting to certain applications (e.g. Notes, TextEdit)
     // Mirrors the behavior in ui/base/clipboard/clipboard_mac.mm in Chromium.
-    markup_string.prepend(QLatin1String("<meta charset='utf-8'>"));
+    markup_string += "<meta charset='utf-8'>"_L1;
 #endif
+    markup_string += toQString(markup);
 
 #if !defined(Q_OS_WIN)
     getUncommittedData()->setHtml(markup_string);
@@ -162,7 +165,7 @@ void ClipboardQt::WriteHTML(base::StringPiece markup, std::optional<base::String
 #endif // !defined(Q_OS_WIN)
 }
 
-void ClipboardQt::WriteRTF(base::StringPiece rtf)
+void ClipboardQt::WriteRTF(std::string_view rtf)
 {
     getUncommittedData()->setData(QString::fromLatin1(ui::kMimeTypeRTF), toQByteArray(rtf));
 }
@@ -177,12 +180,12 @@ void ClipboardQt::WriteBitmap(const SkBitmap &bitmap)
     getUncommittedData()->setImageData(toQImage(bitmap).copy());
 }
 
-void ClipboardQt::WriteBookmark(base::StringPiece title_in, base::StringPiece url_in)
+void ClipboardQt::WriteBookmark(std::string_view title_in, std::string_view url_in)
 {
     // FIXME: Untested, seems to be used only for drag-n-drop.
     // Write as a mozilla url (UTF16: URL, newline, title).
-    QString url = toQString(url_in);
-    QString title = toQString(title_in);
+    const QString url = toQString(url_in);
+    const QString title = toQString(title_in);
 
     QByteArray data;
     data.append(reinterpret_cast<const char *>(url.utf16()), url.size() * 2);
@@ -235,8 +238,10 @@ void ClipboardQt::ReadAvailableTypes(ui::ClipboardBuffer type,
     for (const auto& mime_type : GetStandardFormats(type, data_dst))
         types->push_back(mime_type);
 
-    if (mimeData->hasFormat(QString::fromLatin1(ui::kMimeTypeWebCustomData))) {
-        const QByteArray customData = mimeData->data(QString::fromLatin1(ui::kMimeTypeWebCustomData));
+    const QString serializedDataTransferCustomType =
+            QString::fromStdString(ui::ClipboardFormatType::DataTransferCustomType().Serialize());
+    if (mimeData->hasFormat(serializedDataTransferCustomType)) {
+        const QByteArray customData = mimeData->data(serializedDataTransferCustomType);
         const base::span custom_data(customData.constData(), (unsigned long)customData.size());
         ui::ReadCustomDataTypes(base::as_bytes(custom_data), types);
     }
@@ -337,15 +342,17 @@ void ClipboardQt::ReadPng(ui::ClipboardBuffer type, const ui::DataTransferEndpoi
     return std::move(callback).Run(std::move(pngData));
 }
 
-void ClipboardQt::ReadCustomData(ui::ClipboardBuffer clipboard_type, const std::u16string &type,
-                                 const ui::DataTransferEndpoint *data_dst,
-                                 std::u16string *result) const
+void ClipboardQt::ReadDataTransferCustomData(ui::ClipboardBuffer clipboard_type, const std::u16string &type,
+                                             const ui::DataTransferEndpoint *data_dst,
+                                             std::u16string *result) const
 {
     const QMimeData *mimeData = QGuiApplication::clipboard()->mimeData(
             clipboard_type == ui::ClipboardBuffer::kCopyPaste ? QClipboard::Clipboard : QClipboard::Selection);
     if (!mimeData)
         return;
-    const QByteArray customData = mimeData->data(QString::fromLatin1(ui::kMimeTypeWebCustomData));
+    const QString serializedDataTransferCustomType =
+            QString::fromStdString(ui::ClipboardFormatType::DataTransferCustomType().Serialize());
+    const QByteArray customData = mimeData->data(serializedDataTransferCustomType);
     const base::span custom_data(customData.constData(), (unsigned long)customData.size());
     if (auto maybe_result = ui::ReadCustomDataForType(base::as_bytes(custom_data), type))
         *result = *std::move(maybe_result);
@@ -369,7 +376,7 @@ void ClipboardQt::ReadSvg(ui::ClipboardBuffer clipboard_type,
         *result = toString16(QString::fromUtf8(svgData));
 }
 
-void ClipboardQt::WriteSvg(base::StringPiece markup)
+void ClipboardQt::WriteSvg(std::string_view markup)
 {
     getUncommittedData()->setData(QString::fromLatin1(ui::kMimeTypeSvg),
                                   toQByteArray(markup));
diff --git a/src/core/clipboard_qt.h b/src/core/clipboard_qt.h
index af75ff0e68e..077251fc7d1 100644
--- a/src/core/clipboard_qt.h
+++ b/src/core/clipboard_qt.h
@@ -24,7 +24,8 @@ class ClipboardQt : public ui::Clipboard
     void ReadHTML(ui::ClipboardBuffer type, const ui::DataTransferEndpoint *data_dst, std::u16string *markup, std::string *src_url, uint32_t *fragment_start,
                   uint32_t *fragment_end) const override;
     void ReadRTF(ui::ClipboardBuffer type, const ui::DataTransferEndpoint *data_dst, std::string *result) const override;
-    void ReadCustomData(ui::ClipboardBuffer clipboard_type, const std::u16string &type, const ui::DataTransferEndpoint *data_dst, std::u16string *result) const override;
+    void ReadDataTransferCustomData(ui::ClipboardBuffer clipboard_type, const std::u16string &type, const ui::DataTransferEndpoint *data_dst, std::u16string *result) const override;
+
     void ReadBookmark(const ui::DataTransferEndpoint *data_dst, std::u16string *title, std::string *url) const override;
     void ReadData(const ui::ClipboardFormatType &format, const ui::DataTransferEndpoint *data_dst, std::string *result) const override;
 #if BUILDFLAG(IS_OZONE)
@@ -48,14 +49,14 @@ class ClipboardQt : public ui::Clipboard
                                                  std::vector<PlatformRepresentation> platform_representations,
                                                  std::unique_ptr<ui::DataTransferEndpoint> data_src,
                                                  uint32_t) override;
-    void WriteText(base::StringPiece text) override;
-    void WriteHTML(base::StringPiece markup, std::optional<base::StringPiece> source_url) override;
-    void WriteRTF(base::StringPiece rtf) override;
-    void WriteBookmark(base::StringPiece title, base::StringPiece url) override;
+    void WriteText(std::string_view text) override;
+    void WriteHTML(std::string_view markup, std::optional<std::string_view> source_url) override;
+    void WriteRTF(std::string_view rtf) override;
+    void WriteBookmark(std::string_view title, std::string_view url) override;
     void WriteWebSmartPaste() override;
     void WriteBitmap(const SkBitmap &bitmap) override;
     void WriteData(const ui::ClipboardFormatType &format, base::span<const uint8_t> data) override;
-    void WriteSvg(base::StringPiece markup) override;
+    void WriteSvg(std::string_view markup) override;
     void WriteFilenames(std::vector<ui::FileInfo> filenames) override;
 
     void WriteClipboardHistory() override;
diff --git a/src/core/clipboard_util_win.cpp b/src/core/clipboard_util_win.cpp
index 2dbd173d3c8..f3ae7e730b8 100644
--- a/src/core/clipboard_util_win.cpp
+++ b/src/core/clipboard_util_win.cpp
@@ -45,7 +45,7 @@ std::string HtmlToCFHtml(const std::string &html, const std::string &base_url)
     size_t end_fragment_offset = start_fragment_offset + html.length();
     size_t end_html_offset = end_fragment_offset + strlen(end_markup);
 
-    std::string result = base::StringPrintf(header, start_html_offset, end_html_offset,
+    std::string result = base::StringPrintfNonConstexpr(header, start_html_offset, end_html_offset,
                                             start_fragment_offset, end_fragment_offset);
     if (!base_url.empty()) {
         result += source_url_prefix;
diff --git a/src/core/compositor/compositor.cpp b/src/core/compositor/compositor.cpp
index 35b30234f14..2cbe0846ab2 100644
--- a/src/core/compositor/compositor.cpp
+++ b/src/core/compositor/compositor.cpp
@@ -6,12 +6,15 @@
 #include "base/memory/ref_counted.h"
 #include "components/viz/common/surfaces/frame_sink_id.h"
 
+#include <QGuiApplication>
 #include <QHash>
-#include <QMutex>
+#include <QReadWriteLock>
 #include <QQuickWindow>
 
 namespace QtWebEngineCore {
 
+Q_LOGGING_CATEGORY(lcWebEngineCompositor, "qt.webengine.compositor");
+
 // Compositor::Id
 
 Compositor::Id::Id(viz::FrameSinkId fid) : client_id(fid.client_id()), sink_id(fid.sink_id()) { }
@@ -44,7 +47,8 @@ struct Compositor::Binding
 class Compositor::BindingMap
 {
 public:
-    void lock() { m_mutex.lock(); }
+    void lock() { m_mutex.lockForRead(); }
+    void lockForWrite() { m_mutex.lockForWrite(); }
 
     void unlock() { m_mutex.unlock(); }
 
@@ -59,7 +63,7 @@ class Compositor::BindingMap
     void remove(Id id) { m_map.remove(id); }
 
 private:
-    QMutex m_mutex;
+    QReadWriteLock m_mutex;
     QHash<Id, Binding *> m_map;
 } static g_bindings;
 
@@ -73,7 +77,7 @@ Compositor::Binding::~Binding()
 void Compositor::Observer::bind(Id id)
 {
     DCHECK(!m_binding);
-    g_bindings.lock();
+    g_bindings.lockForWrite();
     m_binding = g_bindings.findOrCreate(id);
     DCHECK(!m_binding->observer);
     m_binding->observer = this;
@@ -82,7 +86,7 @@ void Compositor::Observer::bind(Id id)
 
 void Compositor::Observer::unbind()
 {
-    g_bindings.lock();
+    g_bindings.lockForWrite();
     if (m_binding) {
         m_binding->observer = nullptr;
         if (m_binding->compositor == nullptr)
@@ -111,7 +115,7 @@ Compositor::Observer::~Observer()
 void Compositor::bind(Id id)
 {
     DCHECK(!m_binding);
-    g_bindings.lock();
+    g_bindings.lockForWrite();
     m_binding = g_bindings.findOrCreate(id);
     DCHECK(!m_binding->compositor);
     m_binding->compositor = this;
@@ -120,7 +124,7 @@ void Compositor::bind(Id id)
 
 void Compositor::unbind()
 {
-    g_bindings.lock();
+    g_bindings.lockForWrite();
     if (m_binding) {
         m_binding->compositor = nullptr;
         if (m_binding->observer == nullptr)
@@ -130,13 +134,12 @@ void Compositor::unbind()
     g_bindings.unlock();
 }
 
-Compositor::Handle<Compositor::Observer> Compositor::observer()
+void Compositor::readyToSwap()
 {
     g_bindings.lock();
     if (m_binding && m_binding->observer)
-        return m_binding->observer; // delay unlock
+        m_binding->observer->readyToSwap();
     g_bindings.unlock();
-    return nullptr;
 }
 
 void Compositor::waitForTexture()
@@ -149,18 +152,24 @@ void Compositor::releaseTexture()
 
 QSGTexture *Compositor::texture(QQuickWindow *, uint32_t textureOptions)
 {
-    Q_UNREACHABLE();
-    return nullptr;
+    Q_UNREACHABLE_RETURN(nullptr);
 }
 
 bool Compositor::textureIsFlipped()
 {
-    Q_UNREACHABLE();
-    return false;
+    Q_UNREACHABLE_RETURN(false);
 }
 
 void Compositor::releaseResources() { }
 
+Compositor::Compositor(Type type) : m_type(type)
+{
+    qCDebug(lcWebEngineCompositor, "Compositor Type: %s",
+            m_type == Type::Software ? "Software" : "Native");
+    qCDebug(lcWebEngineCompositor, "QPA Platform Plugin: %ls",
+            qUtf16Printable(QGuiApplication::platformName()));
+}
+
 Compositor::~Compositor()
 {
     DCHECK(!m_binding); // check that unbind() was called by derived final class
diff --git a/src/core/compositor/compositor.h b/src/core/compositor/compositor.h
index ee45b400be7..aaa1a74c8c0 100644
--- a/src/core/compositor/compositor.h
+++ b/src/core/compositor/compositor.h
@@ -18,6 +18,8 @@ class FrameSinkId;
 
 namespace QtWebEngineCore {
 
+Q_DECLARE_LOGGING_CATEGORY(lcWebEngineCompositor);
+
 // Produces composited frames for display.
 //
 // Used by quick/widgets libraries for accessing the frames and
@@ -99,8 +101,8 @@ class Q_WEBENGINECORE_EXPORT Compositor
     void bind(Id id);
     void unbind();
 
-    // Observer if bound.
-    Handle<Observer> observer();
+    // Tell observer ready to swap
+    void readyToSwap();
 
     // Update to next frame if possible.
     virtual void swapFrame() = 0;
@@ -132,7 +134,7 @@ class Q_WEBENGINECORE_EXPORT Compositor
     virtual void releaseResources();
 
 protected:
-    Compositor(Type type) : m_type(type) { }
+    Compositor(Type type);
     virtual ~Compositor();
 
 private:
diff --git a/src/core/compositor/display_software_output_surface.cpp b/src/core/compositor/display_software_output_surface.cpp
index 62f23edb50a..2ad608f26fb 100644
--- a/src/core/compositor/display_software_output_surface.cpp
+++ b/src/core/compositor/display_software_output_surface.cpp
@@ -73,8 +73,7 @@ void DisplaySoftwareOutputSurface::Device::OnSwapBuffers(SwapBuffersCallback swa
         m_swapCompletionCallback = std::move(swap_ack_callback);
     }
 
-    if (auto obs = observer())
-        obs->readyToSwap();
+    readyToSwap();
 }
 
 inline QImage::Format imageFormat(SkColorType colorType)
@@ -85,8 +84,7 @@ inline QImage::Format imageFormat(SkColorType colorType)
     case kRGBA_8888_SkColorType:
         return QImage::Format_RGBA8888_Premultiplied;
     default:
-        Q_UNREACHABLE();
-        return QImage::Format_ARGB32_Premultiplied;
+        Q_UNREACHABLE_RETURN(QImage::Format_ARGB32_Premultiplied);
     }
 }
 
diff --git a/src/core/compositor/native_skia_output_device.cpp b/src/core/compositor/native_skia_output_device.cpp
index 756803a3e4d..f42b2b93341 100644
--- a/src/core/compositor/native_skia_output_device.cpp
+++ b/src/core/compositor/native_skia_output_device.cpp
@@ -50,16 +50,19 @@ NativeSkiaOutputDevice::NativeSkiaOutputDevice(
     , m_representationFactory(shared_image_representation_factory)
     , m_deps(dependency)
 {
+    qCDebug(lcWebEngineCompositor, "Skia Graphics Context Type: %s",
+            gpu::GrContextTypeToString(contextState->gr_context_type()).c_str());
+
     capabilities_.uses_default_gl_framebuffer = false;
     capabilities_.supports_surfaceless = true;
     capabilities_.output_surface_origin = gfx::SurfaceOrigin::kTopLeft;
-    capabilities_.preserve_buffer_content = true;
-    capabilities_.only_invalidates_damage_rect = false;
 
 #if BUILDFLAG(IS_OZONE)
     m_isNativeBufferSupported = ui::OzonePlatform::GetInstance()
                                         ->GetPlatformRuntimeProperties()
                                         .supports_native_pixmaps;
+    qCDebug(lcWebEngineCompositor, "Native Buffer Supported: %s",
+            m_isNativeBufferSupported ? "yes" : "no");
 #endif
 }
 
@@ -73,14 +76,10 @@ void NativeSkiaOutputDevice::SetFrameSinkId(const viz::FrameSinkId &id)
     bind(id);
 }
 
-bool NativeSkiaOutputDevice::Reshape(const SkImageInfo &image_info,
-                                     const gfx::ColorSpace &colorSpace,
-                                     int sample_count,
-                                     float device_scale_factor,
-                                     gfx::OverlayTransform transform)
+bool NativeSkiaOutputDevice::Reshape(const ReshapeParams &params)
 {
-    m_shape = Shape{image_info, device_scale_factor, colorSpace, sample_count};
-    DCHECK_EQ(transform, gfx::OVERLAY_TRANSFORM_NONE);
+    m_shape = Shape{ params.image_info, params.device_scale_factor, params.color_space, params.sample_count };
+    DCHECK_EQ(params.transform, gfx::OVERLAY_TRANSFORM_NONE);
     return true;
 }
 
@@ -99,9 +98,7 @@ void NativeSkiaOutputDevice::Present(const std::optional<gfx::Rect> &update_rect
         std::swap(m_middleBuffer, m_backBuffer);
         m_readyToUpdate = true;
     }
-
-    if (auto obs = observer())
-        obs->readyToSwap();
+    readyToSwap();
 }
 
 void NativeSkiaOutputDevice::EnsureBackbuffer()
@@ -213,6 +210,8 @@ NativeSkiaOutputDevice::Buffer::Buffer(NativeSkiaOutputDevice *parent)
 
 NativeSkiaOutputDevice::Buffer::~Buffer()
 {
+    DCHECK(!textureCleanupCallback);
+
     if (m_scopedSkiaWriteAccess)
         endWriteSkia(false);
 
@@ -226,21 +225,33 @@ NativeSkiaOutputDevice::Buffer::~Buffer()
 // found in the LICENSE file.
 bool NativeSkiaOutputDevice::Buffer::initialize()
 {
-    uint32_t kDefaultSharedImageUsage = gpu::SHARED_IMAGE_USAGE_DISPLAY_READ
-                                      | gpu::SHARED_IMAGE_USAGE_DISPLAY_WRITE;
+    qCDebug(lcWebEngineCompositor, "Initializing buffer %p with SharedImage:", this);
+
+    gpu::SharedImageUsageSet sharedImageUsage =
+            gpu::SHARED_IMAGE_USAGE_DISPLAY_READ
+          | gpu::SHARED_IMAGE_USAGE_DISPLAY_WRITE;
     if (m_parent->m_contextState->gr_context_type() == gpu::GrContextType::kGL)
-        kDefaultSharedImageUsage |= gpu::SHARED_IMAGE_USAGE_GLES2_READ;
+        sharedImageUsage |= gpu::SHARED_IMAGE_USAGE_GLES2_READ;
     if (m_parent->m_isNativeBufferSupported)
-        kDefaultSharedImageUsage |= gpu::SHARED_IMAGE_USAGE_SCANOUT;
+        sharedImageUsage |= gpu::SHARED_IMAGE_USAGE_SCANOUT;
+
+    qCDebug(lcWebEngineCompositor, "  Usage: %s",
+            gpu::CreateLabelForSharedImageUsage(sharedImageUsage).c_str());
+    qCDebug(lcWebEngineCompositor, "  Pixels size: %dx%d", m_shape.imageInfo.width(),
+            m_shape.imageInfo.height());
+
+    auto mailbox = gpu::Mailbox::Generate();
 
-    auto mailbox = gpu::Mailbox::GenerateForSharedImage();
+    const SkColorType skColorType = m_shape.imageInfo.colorType();
+    const viz::SharedImageFormat sharedImageFormat =
+            viz::SkColorTypeToSinglePlaneSharedImageFormat(skColorType);
+    qCDebug(lcWebEngineCompositor, "  Format: %s", sharedImageFormat.ToString().c_str());
 
-    SkColorType skColorType = m_shape.imageInfo.colorType();
     if (!m_parent->m_factory->CreateSharedImage(
-                mailbox, viz::SkColorTypeToSinglePlaneSharedImageFormat(skColorType),
+                mailbox, sharedImageFormat,
                 { m_shape.imageInfo.width(), m_shape.imageInfo.height() }, m_shape.colorSpace,
                 kTopLeft_GrSurfaceOrigin, kPremul_SkAlphaType, m_parent->m_deps->GetSurfaceHandle(),
-                kDefaultSharedImageUsage, "QWE_SharedImageBuffer")) {
+                sharedImageUsage, "QWE_SharedImageBuffer")) {
         LOG(ERROR) << "CreateSharedImage failed.";
         return false;
     }
@@ -252,6 +263,7 @@ bool NativeSkiaOutputDevice::Buffer::initialize()
         LOG(ERROR) << "ProduceSkia() failed.";
         return false;
     }
+    qCDebug(lcWebEngineCompositor, "  Backing: %s", m_skiaRepresentation->backing_name());
 
     if (m_parent->m_isNativeBufferSupported) {
         m_overlayRepresentation = m_parent->m_representationFactory->ProduceOverlay(m_mailbox);
diff --git a/src/core/compositor/native_skia_output_device.h b/src/core/compositor/native_skia_output_device.h
index 294d678e434..7dabca07dfc 100644
--- a/src/core/compositor/native_skia_output_device.h
+++ b/src/core/compositor/native_skia_output_device.h
@@ -60,11 +60,7 @@ class NativeSkiaOutputDevice : public viz::SkiaOutputDevice, public Compositor
 
     // Overridden from SkiaOutputDevice.
     void SetFrameSinkId(const viz::FrameSinkId &frame_sink_id) override;
-    bool Reshape(const SkImageInfo &image_info,
-                 const gfx::ColorSpace &color_space,
-                 int sample_count,
-                 float device_scale_factor,
-                 gfx::OverlayTransform transform) override;
+    bool Reshape(const ReshapeParams &params) override;
     void Present(const std::optional<gfx::Rect>& update_rect,
                  BufferPresentedCallback feedback,
                  viz::OutputSurfaceFrame frame) override;
diff --git a/src/core/compositor/native_skia_output_device_direct3d11.cpp b/src/core/compositor/native_skia_output_device_direct3d11.cpp
index 495af7a408f..12ddecdbe7e 100644
--- a/src/core/compositor/native_skia_output_device_direct3d11.cpp
+++ b/src/core/compositor/native_skia_output_device_direct3d11.cpp
@@ -21,11 +21,13 @@ NativeSkiaOutputDeviceDirect3D11::NativeSkiaOutputDeviceDirect3D11(
                              shared_image_factory, shared_image_representation_factory,
                              didSwapBufferCompleteCallback)
 {
+    qCDebug(lcWebEngineCompositor, "Native Skia Output Device: Direct3D11");
+
     SkColorType skColorType = kRGBA_8888_SkColorType;
-    capabilities_.sk_color_types[static_cast<int>(gfx::BufferFormat::RGBA_8888)] = skColorType;
-    capabilities_.sk_color_types[static_cast<int>(gfx::BufferFormat::RGBX_8888)] = skColorType;
-    capabilities_.sk_color_types[static_cast<int>(gfx::BufferFormat::BGRA_8888)] = skColorType;
-    capabilities_.sk_color_types[static_cast<int>(gfx::BufferFormat::BGRX_8888)] = skColorType;
+    capabilities_.sk_color_type_map[viz::SinglePlaneFormat::kRGBA_8888] = skColorType;
+    capabilities_.sk_color_type_map[viz::SinglePlaneFormat::kRGBX_8888] = skColorType;
+    capabilities_.sk_color_type_map[viz::SinglePlaneFormat::kBGRA_8888] = skColorType;
+    capabilities_.sk_color_type_map[viz::SinglePlaneFormat::kBGRX_8888] = skColorType;
 }
 
 NativeSkiaOutputDeviceDirect3D11::~NativeSkiaOutputDeviceDirect3D11() { }
@@ -41,6 +43,8 @@ QSGTexture *NativeSkiaOutputDeviceDirect3D11::texture(QQuickWindow *win, uint32_
         return nullptr;
     }
 
+    qCDebug(lcWebEngineCompositor, "D3D: Importing DXGI Resource into D3D11 Texture.");
+
     Q_ASSERT(overlayImage->type() == gl::DCLayerOverlayType::kNV12Texture);
     Microsoft::WRL::ComPtr<ID3D11Texture2D> chromeTexture = overlayImage->nv12_texture();
     if (!chromeTexture) {
@@ -77,9 +81,9 @@ QSGTexture *NativeSkiaOutputDeviceDirect3D11::texture(QQuickWindow *win, uint32_
     ID3D11Texture2D *qtTexture = nullptr;
     hr = device1->OpenSharedResource1(sharedHandle, IID_PPV_ARGS(&qtTexture));
     if (FAILED(hr)) {
-        qWarning("D3D: Failed to share D3D11 texture (%s). This will result in failed rendering. "
+        qWarning("D3D: Failed to share D3D11 texture (%ls). This will result in failed rendering. "
                  "Report the bug, and try restarting with QTWEBENGINE_CHROMIUM_FLAGS=--disble-gpu",
-                 qPrintable(QSystemError::windowsComString(hr)));
+                 qUtf16Printable(QSystemError::windowsComString(hr)));
         ::CloseHandle(sharedHandle);
         return nullptr;
     }
diff --git a/src/core/compositor/native_skia_output_device_metal.cpp b/src/core/compositor/native_skia_output_device_metal.cpp
index a9d6e4fd53b..77f869de75e 100644
--- a/src/core/compositor/native_skia_output_device_metal.cpp
+++ b/src/core/compositor/native_skia_output_device_metal.cpp
@@ -18,11 +18,13 @@ NativeSkiaOutputDeviceMetal::NativeSkiaOutputDeviceMetal(
                              shared_image_factory, shared_image_representation_factory,
                              didSwapBufferCompleteCallback)
 {
+    qCDebug(lcWebEngineCompositor, "Native Skia Output Device: Metal");
+
     SkColorType skColorType = kRGBA_8888_SkColorType;
-    capabilities_.sk_color_types[static_cast<int>(gfx::BufferFormat::RGBA_8888)] = skColorType;
-    capabilities_.sk_color_types[static_cast<int>(gfx::BufferFormat::RGBX_8888)] = skColorType;
-    capabilities_.sk_color_types[static_cast<int>(gfx::BufferFormat::BGRA_8888)] = skColorType;
-    capabilities_.sk_color_types[static_cast<int>(gfx::BufferFormat::BGRX_8888)] = skColorType;
+    capabilities_.sk_color_type_map[viz::SinglePlaneFormat::kRGBA_8888] = skColorType;
+    capabilities_.sk_color_type_map[viz::SinglePlaneFormat::kRGBX_8888] = skColorType;
+    capabilities_.sk_color_type_map[viz::SinglePlaneFormat::kBGRA_8888] = skColorType;
+    capabilities_.sk_color_type_map[viz::SinglePlaneFormat::kBGRX_8888] = skColorType;
 }
 
 NativeSkiaOutputDeviceMetal::~NativeSkiaOutputDeviceMetal() { }
@@ -42,6 +44,8 @@ QSGTexture *NativeSkiaOutputDeviceMetal::texture(QQuickWindow *win, uint32_t tex
         return nullptr;
     }
 
+    qCDebug(lcWebEngineCompositor, "METAL: Importing IOSurface into Metal Texture.");
+
     // This is a workaround to not to release metal texture too early.
     // In RHI, QMetalTexture wraps MTLTexture. QMetalTexture seems to be only destructed after the
     // next MTLTexture is imported. The "old" MTLTexture can be still pontentially used by RHI
diff --git a/src/core/compositor/native_skia_output_device_opengl.cpp b/src/core/compositor/native_skia_output_device_opengl.cpp
index 558821bb54a..7cfc390d8a2 100644
--- a/src/core/compositor/native_skia_output_device_opengl.cpp
+++ b/src/core/compositor/native_skia_output_device_opengl.cpp
@@ -19,13 +19,9 @@
 #include "ui/gfx/linux/drm_util_linux.h"
 #include "ui/gfx/linux/native_pixmap_dmabuf.h"
 
-#if BUILDFLAG(IS_OZONE_X11)
+#if BUILDFLAG(IS_OZONE_X11) && QT_CONFIG(xcb_glx_plugin)
 #include "ozone/glx_helper.h"
-
-#if !defined(GL_RGBA8_OES)
-#define GL_RGBA8_OES 0x8058
 #endif
-#endif // BUILDFLAG(IS_OZONE_X11)
 
 #if QT_CONFIG(egl)
 #include "ozone/egl_helper.h"
@@ -63,16 +59,18 @@ NativeSkiaOutputDeviceOpenGL::NativeSkiaOutputDeviceOpenGL(
                              shared_image_factory, shared_image_representation_factory,
                              didSwapBufferCompleteCallback)
 {
+    qCDebug(lcWebEngineCompositor, "Native Skia Output Device: OpenGL");
+
     SkColorType skColorType = kRGBA_8888_SkColorType;
-#if BUILDFLAG(IS_OZONE_X11)
+#if BUILDFLAG(IS_OZONE_X11) && QT_CONFIG(xcb_glx_plugin)
     if (OzoneUtilQt::usingGLX() && m_contextState->gr_context_type() == gpu::GrContextType::kGL)
         skColorType = kBGRA_8888_SkColorType;
 #endif
 
-    capabilities_.sk_color_types[static_cast<int>(gfx::BufferFormat::RGBA_8888)] = skColorType;
-    capabilities_.sk_color_types[static_cast<int>(gfx::BufferFormat::RGBX_8888)] = skColorType;
-    capabilities_.sk_color_types[static_cast<int>(gfx::BufferFormat::BGRA_8888)] = skColorType;
-    capabilities_.sk_color_types[static_cast<int>(gfx::BufferFormat::BGRX_8888)] = skColorType;
+    capabilities_.sk_color_type_map[viz::SinglePlaneFormat::kRGBA_8888] = skColorType;
+    capabilities_.sk_color_type_map[viz::SinglePlaneFormat::kRGBX_8888] = skColorType;
+    capabilities_.sk_color_type_map[viz::SinglePlaneFormat::kBGRA_8888] = skColorType;
+    capabilities_.sk_color_type_map[viz::SinglePlaneFormat::kBGRX_8888] = skColorType;
 }
 
 NativeSkiaOutputDeviceOpenGL::~NativeSkiaOutputDeviceOpenGL() { }
@@ -150,14 +148,27 @@ QSGTexture *NativeSkiaOutputDeviceOpenGL::texture(QQuickWindow *win, uint32_t te
 
 #if BUILDFLAG(IS_OZONE)
     QOpenGLContext *glContext = QOpenGLContext::currentContext();
+    Q_ASSERT(glContext);
     auto glFun = glContext->functions();
     GLuint glTexture = 0;
 
+#if !defined(QT_NO_DEBUG) || defined(QT_FORCE_ASSERTS)
+    // Log and clear error flags for assert at end of function
+    while (true) {
+        auto glError = glFun->glGetError();
+        if (glError == GL_NO_ERROR || glError == GL_CONTEXT_LOST)
+            break;
+        qWarning("GL error flag set on entry: %s", getGLErrorString(glError));
+    }
+#endif // !defined(QT_NO_DEBUG) || defined(QT_FORCE_ASSERTS)
+
     if (nativePixmap) {
         Q_ASSERT(m_contextState->gr_context_type() == gpu::GrContextType::kGL);
 
-#if BUILDFLAG(IS_OZONE_X11)
+#if BUILDFLAG(IS_OZONE_X11) && QT_CONFIG(xcb_glx_plugin)
         if (OzoneUtilQt::usingGLX()) {
+            qCDebug(lcWebEngineCompositor, "GLX: Importing NativePixmap into GL Texture.");
+
             GLXHelper *glxHelper = GLXHelper::instance();
             auto *glxFun = glxHelper->functions();
 
@@ -202,17 +213,20 @@ QSGTexture *NativeSkiaOutputDeviceOpenGL::texture(QQuickWindow *win, uint32_t te
             glxFun->glXBindTexImageEXT(display, glxPixmap, GLX_FRONT_LEFT_EXT, nullptr);
             glFun->glBindTexture(GL_TEXTURE_2D, 0);
 
-            m_frontBuffer->textureCleanupCallback = [glFun, glxFun, display, glxPixmap,
-                                                     glTexture]() {
+            m_frontBuffer->textureCleanupCallback = [glFun, glxFun, display, glxPixmap, glTexture,
+                                                     glxHelper, pixmapId]() {
                 glxFun->glXReleaseTexImageEXT(display, glxPixmap, GLX_FRONT_LEFT_EXT);
                 glFun->glDeleteTextures(1, &glTexture);
                 glXDestroyGLXPixmap(display, glxPixmap);
+                glxHelper->freePixmap(pixmapId);
             };
         }
-#endif // BUILDFLAG(IS_OZONE_X11)
+#endif // BUILDFLAG(IS_OZONE_X11) && QT_CONFIG(xcb_glx_plugin)
 
 #if QT_CONFIG(egl)
         if (OzoneUtilQt::usingEGL()) {
+            qCDebug(lcWebEngineCompositor, "EGL: Importing NativePixmap into GL Texture.");
+
             EGLHelper *eglHelper = EGLHelper::instance();
             auto *eglFun = eglHelper->functions();
             auto *glExtFun = GLHelper::instance()->functions();
@@ -260,6 +274,7 @@ QSGTexture *NativeSkiaOutputDeviceOpenGL::texture(QQuickWindow *win, uint32_t te
 #endif // QT_CONFIG(egl)
     } else {
 #if BUILDFLAG(ENABLE_VULKAN)
+        qCDebug(lcWebEngineCompositor, "VULKAN: Importing VkImage into GL Texture.");
         Q_ASSERT(m_contextState->gr_context_type() == gpu::GrContextType::kVulkan);
 
         gpu::VulkanFunctionPointers *vfp = gpu::GetVulkanFunctionPointers();
@@ -283,14 +298,26 @@ QSGTexture *NativeSkiaOutputDeviceOpenGL::texture(QQuickWindow *win, uint32_t te
 
         auto *glExtFun = GLHelper::instance()->functions();
 
+        // Import memory object
         GLuint glMemoryObject;
-        glFun->glGenTextures(1, &glTexture);
-        glFun->glBindTexture(GL_TEXTURE_2D, glTexture);
         glExtFun->glCreateMemoryObjectsEXT(1, &glMemoryObject);
+        GLint dedicated = GL_TRUE;
+        glExtFun->glMemoryObjectParameterivEXT(glMemoryObject, GL_DEDICATED_MEMORY_OBJECT_EXT,
+                                               &dedicated);
         glExtFun->glImportMemoryFdEXT(glMemoryObject, importedImageSize,
                                       GL_HANDLE_TYPE_OPAQUE_FD_EXT, fd);
-        glExtFun->glTextureStorageMem2DEXT(glTexture, 1, GL_RGBA8_OES, size().width(),
-                                           size().height(), glMemoryObject, 0);
+        if (!glExtFun->glIsMemoryObjectEXT(glMemoryObject))
+            qFatal("VULKAN: Failed to import memory object.");
+
+        // Bind memory object to texture
+        glFun->glGenTextures(1, &glTexture);
+        glFun->glBindTexture(GL_TEXTURE_2D, glTexture);
+        glFun->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_TILING_EXT,
+                               vkImageInfo.fImageTiling == VK_IMAGE_TILING_OPTIMAL
+                                       ? GL_OPTIMAL_TILING_EXT
+                                       : GL_LINEAR_TILING_EXT);
+        glExtFun->glTexStorageMem2DEXT(GL_TEXTURE_2D, 1, GL_RGBA8, size().width(), size().height(),
+                                       glMemoryObject, 0);
         glFun->glBindTexture(GL_TEXTURE_2D, 0);
 
         m_frontBuffer->textureCleanupCallback = [glFun, glExtFun, glTexture, glMemoryObject]() {
@@ -307,6 +334,7 @@ QSGTexture *NativeSkiaOutputDeviceOpenGL::texture(QQuickWindow *win, uint32_t te
     texture = QNativeInterface::QSGOpenGLTexture::fromNative(glTexture, win, size(), texOpts);
     Q_ASSERT(glFun->glGetError() == GL_NO_ERROR);
 #elif defined(Q_OS_WIN)
+    qCDebug(lcWebEngineCompositor, "WGL: Importing DXGI Resource into GL Texture.");
     Q_ASSERT(m_contextState->gr_context_type() == gpu::GrContextType::kGL);
 
     Q_ASSERT(overlayImage->type() == gl::DCLayerOverlayType::kNV12Texture);
@@ -344,6 +372,7 @@ QSGTexture *NativeSkiaOutputDeviceOpenGL::texture(QQuickWindow *win, uint32_t te
         delete d3dSharedTexture;
     };
 #elif defined(Q_OS_MACOS)
+    qCDebug(lcWebEngineCompositor, "CGL: Importing IOSurface into GL Texture.");
     uint32_t glTexture = makeCGLTexture(win, ioSurface.get(), size());
     texture = QNativeInterface::QSGOpenGLTexture::fromNative(glTexture, win, size(), texOpts);
 
diff --git a/src/core/compositor/native_skia_output_device_vulkan.cpp b/src/core/compositor/native_skia_output_device_vulkan.cpp
index c292a3269e4..5f410621bf5 100644
--- a/src/core/compositor/native_skia_output_device_vulkan.cpp
+++ b/src/core/compositor/native_skia_output_device_vulkan.cpp
@@ -37,11 +37,13 @@ NativeSkiaOutputDeviceVulkan::NativeSkiaOutputDeviceVulkan(
                              shared_image_factory, shared_image_representation_factory,
                              didSwapBufferCompleteCallback)
 {
+    qCDebug(lcWebEngineCompositor, "Native Skia Output Device: Vulkan");
+
     SkColorType skColorType = kRGBA_8888_SkColorType;
-    capabilities_.sk_color_types[static_cast<int>(gfx::BufferFormat::RGBA_8888)] = skColorType;
-    capabilities_.sk_color_types[static_cast<int>(gfx::BufferFormat::RGBX_8888)] = skColorType;
-    capabilities_.sk_color_types[static_cast<int>(gfx::BufferFormat::BGRA_8888)] = skColorType;
-    capabilities_.sk_color_types[static_cast<int>(gfx::BufferFormat::BGRX_8888)] = skColorType;
+    capabilities_.sk_color_type_map[viz::SinglePlaneFormat::kRGBA_8888] = skColorType;
+    capabilities_.sk_color_type_map[viz::SinglePlaneFormat::kRGBX_8888] = skColorType;
+    capabilities_.sk_color_type_map[viz::SinglePlaneFormat::kBGRA_8888] = skColorType;
+    capabilities_.sk_color_type_map[viz::SinglePlaneFormat::kBGRX_8888] = skColorType;
 }
 
 NativeSkiaOutputDeviceVulkan::~NativeSkiaOutputDeviceVulkan() { }
@@ -110,16 +112,6 @@ QSGTexture *NativeSkiaOutputDeviceVulkan::texture(QQuickWindow *win, uint32_t te
     QVulkanFunctions *f = win->vulkanInstance()->functions();
     QVulkanDeviceFunctions *df = win->vulkanInstance()->deviceFunctions(qtVulkanDevice);
 
-    VkImageLayout imageLayout = VK_IMAGE_LAYOUT_UNDEFINED;
-    VkPhysicalDeviceProperties deviceProperties;
-    f->vkGetPhysicalDeviceProperties(qtPhysicalDevice, &deviceProperties);
-    if (deviceProperties.vendorID == 0x10DE) {
-        // FIXME: This is a workaround for Nvidia driver.
-        // The imported image is empty if the initialLayout is not
-        // VK_IMAGE_LAYOUT_PREINITIALIZED.
-        imageLayout = VK_IMAGE_LAYOUT_PREINITIALIZED;
-    }
-
     VkExternalMemoryImageCreateInfoKHR externalMemoryImageCreateInfo = {
         .sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_KHR,
         .pNext = nullptr,
@@ -144,20 +136,28 @@ QSGTexture *NativeSkiaOutputDeviceVulkan::texture(QQuickWindow *win, uint32_t te
         .pPlaneLayouts = &planeLayout,
     };
 
+    bool usingDrmModifier = false;
     if (nativePixmap) {
+        qCDebug(lcWebEngineCompositor, "VULKAN: Importing NativePixmap into VkImage.");
         gfx::NativePixmapHandle nativePixmapHandle = nativePixmap->ExportHandle();
-        if (nativePixmapHandle.planes.size() != 1)
-            qFatal("VULKAN: Multiple planes are not supported.");
+        qCDebug(lcWebEngineCompositor, "  DRM Format Modifier: 0x%lx", nativePixmapHandle.modifier);
+
+        if (nativePixmapHandle.modifier != gfx::NativePixmapHandle::kNoModifier) {
+            usingDrmModifier = true;
+            if (nativePixmapHandle.planes.size() != 1)
+                qFatal("VULKAN: Multiple planes are not supported.");
 
-        planeLayout.offset = nativePixmapHandle.planes[0].offset;
-        planeLayout.rowPitch = nativePixmapHandle.planes[0].stride;
-        modifierInfo.drmFormatModifier = nativePixmapHandle.modifier;
+            planeLayout.offset = nativePixmapHandle.planes[0].offset;
+            planeLayout.rowPitch = nativePixmapHandle.planes[0].stride;
+            modifierInfo.drmFormatModifier = nativePixmapHandle.modifier;
 
-        externalMemoryImageCreateInfo.pNext = &modifierInfo;
+            externalMemoryImageCreateInfo.pNext = &modifierInfo;
+        }
         externalMemoryImageCreateInfo.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;
 
         scopedFd = std::move(nativePixmapHandle.planes[0].fd);
     } else {
+        qCDebug(lcWebEngineCompositor, "VULKAN: Importing VkImage into VkImage.");
         externalMemoryImageCreateInfo.handleTypes =
                 VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR;
 
@@ -183,6 +183,7 @@ QSGTexture *NativeSkiaOutputDeviceVulkan::texture(QQuickWindow *win, uint32_t te
     if (!scopedFd.is_valid())
         qFatal("VULKAN: Unable to extract file descriptor.");
 #elif defined(Q_OS_WIN)
+    qCDebug(lcWebEngineCompositor, "VULKAN: Importing DXGI Resource into VkImage.");
     externalMemoryImageCreateInfo.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT;
 
     Q_ASSERT(overlayImage->type() == gl::DCLayerOverlayType::kNV12Texture);
@@ -205,10 +206,6 @@ QSGTexture *NativeSkiaOutputDeviceVulkan::texture(QQuickWindow *win, uint32_t te
     Q_ASSERT(sharedHandle != INVALID_HANDLE_VALUE);
 #endif
 
-    constexpr VkImageUsageFlags kUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT
-            | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT
-            | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
-
     VkImageCreateInfo importedImageCreateInfo = {
         .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
         .pNext = &externalMemoryImageCreateInfo,
@@ -224,17 +221,19 @@ QSGTexture *NativeSkiaOutputDeviceVulkan::texture(QQuickWindow *win, uint32_t te
         .arrayLayers = 1,
         .samples = VK_SAMPLE_COUNT_1_BIT,
         .tiling = VK_IMAGE_TILING_OPTIMAL,
-        .usage = kUsage,
+        // The image is fed into a combined image sampler
+        .usage = VK_IMAGE_USAGE_SAMPLED_BIT,
         .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
         .queueFamilyIndexCount = 0,
         .pQueueFamilyIndices = nullptr,
-        .initialLayout = imageLayout,
+        // VkExternalMemoryImageCreateInfo only allows UNDEFINED
+        .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
     };
 
 #if BUILDFLAG(IS_OZONE)
-    if (nativePixmap)
+    if (usingDrmModifier)
         importedImageCreateInfo.tiling = VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT;
-    else
+    else if (vkImageInfo.fAlloc.fMemory != VK_NULL_HANDLE)
         importedImageCreateInfo.tiling = vkImageInfo.fImageTiling;
 #endif
 
@@ -243,7 +242,7 @@ QSGTexture *NativeSkiaOutputDeviceVulkan::texture(QQuickWindow *win, uint32_t te
     result = df->vkCreateImage(qtVulkanDevice, &importedImageCreateInfo, nullptr /* pAllocator */,
                                &importedImage);
     if (result != VK_SUCCESS)
-        qFatal() << "VULKAN: vkCreateImage failed result:" << result;
+        qFatal("VULKAN: vkCreateImage failed result: %d", static_cast<int>(result));
 
 #if BUILDFLAG(IS_OZONE)
     VkImportMemoryFdInfoKHR importMemoryHandleInfo = {
@@ -304,13 +303,13 @@ QSGTexture *NativeSkiaOutputDeviceVulkan::texture(QQuickWindow *win, uint32_t te
     result = df->vkAllocateMemory(qtVulkanDevice, &memoryAllocateInfo, nullptr /* pAllocator */,
                                   &importedImageMemory);
     if (result != VK_SUCCESS)
-        qFatal() << "VULKAN: vkAllocateMemory failed result:" << result;
+        qFatal("VULKAN: vkAllocateMemory failed result: %d", static_cast<int>(result));
 
     df->vkBindImageMemory(qtVulkanDevice, importedImage, importedImageMemory, 0);
 
     QQuickWindow::CreateTextureOptions texOpts(textureOptions);
-    QSGTexture *texture = QNativeInterface::QSGVulkanTexture::fromNative(importedImage, imageLayout,
-                                                                         win, size(), texOpts);
+    QSGTexture *texture = QNativeInterface::QSGVulkanTexture::fromNative(
+            importedImage, importedImageCreateInfo.initialLayout, win, size(), texOpts);
 
     m_frontBuffer->textureCleanupCallback = [=]() {
         df->vkDestroyImage(qtVulkanDevice, importedImage, nullptr);
diff --git a/src/core/compositor/wgl_helper.cpp b/src/core/compositor/wgl_helper.cpp
index d6c8401373d..11526f4f95a 100644
--- a/src/core/compositor/wgl_helper.cpp
+++ b/src/core/compositor/wgl_helper.cpp
@@ -46,14 +46,14 @@ WGLHelper::WGLHelper() : m_functions(new WGLHelper::WGLFunctions())
 
     hr = CreateDXGIFactory(IID_PPV_ARGS(&m_factory));
     if (FAILED(hr)) {
-        qFatal() << "WGL: Failed to create DXGI Factory:"
-                 << qPrintable(QSystemError::windowsComString(hr));
+        qFatal("WGL: Failed to create DXGI Factory: %ls",
+               qUtf16Printable(QSystemError::windowsComString(hr)));
     }
 
     hr = m_factory->EnumAdapters(0, &m_adapter);
     if (FAILED(hr)) {
-        qFatal() << "WGL: Failed to enumerate adapters:"
-                 << qPrintable(QSystemError::windowsComString(hr));
+        qFatal("WGL: Failed to enumerate adapters: %ls",
+               qUtf16Printable(QSystemError::windowsComString(hr)));
     }
 
     uint devFlags = 0;
@@ -66,13 +66,15 @@ WGLHelper::WGLHelper() : m_functions(new WGLHelper::WGLFunctions())
                            featureLevels, std::size(featureLevels), D3D11_SDK_VERSION, &m_device,
                            /*pFeatureLevel=*/nullptr, &m_immediateContext);
     if (FAILED(hr)) {
-        qFatal() << "WGL: Failed to create D3D11 device:"
-                 << qPrintable(QSystemError::windowsComString(hr));
+        qFatal("WGL: Failed to create D3D11 device: %ls",
+               qUtf16Printable(QSystemError::windowsComString(hr)));
     }
 
     m_interopDevice = m_functions->wglDXOpenDeviceNV(m_device.Get());
-    if (m_interopDevice == INVALID_HANDLE_VALUE)
-        qWarning() << "WGL: Failed to open interop device:" << ::GetLastError();
+    if (m_interopDevice == INVALID_HANDLE_VALUE) {
+        qWarning("WGL: Failed to open interop device: %ls",
+                 qUtf16Printable(QSystemError::windowsString()));
+    }
 }
 
 WGLHelper::~WGLHelper()
@@ -95,9 +97,9 @@ D3DSharedTexture::D3DSharedTexture(WGLHelper::WGLFunctions *wglFun, ID3D11Device
     Microsoft::WRL::ComPtr<ID3D11Texture2D> srcTexture;
     hr = device1->OpenSharedResource1(dxgiSharedHandle, IID_PPV_ARGS(&srcTexture));
     if (FAILED(hr)) {
-        qWarning("WGL: Failed to share D3D11 texture (%s). This will result in failed rendering. "
+        qWarning("WGL: Failed to share D3D11 texture (%ls). This will result in failed rendering. "
                  "Report the bug, and try restarting with QTWEBENGINE_CHROMIUM_FLAGS=--disble-gpu",
-                 qPrintable(QSystemError::windowsComString(hr)));
+                 qUtf16Printable(QSystemError::windowsComString(hr)));
         return;
     }
     Q_ASSERT(srcTexture);
@@ -161,7 +163,8 @@ void D3DSharedTexture::lockObject()
 
     bool status = m_wglFun->wglDXLockObjectsNV(m_interopDevice, 1, &m_glTextureHandle);
     if (!status) {
-        qWarning() << "WGL: Failed to lock shared texture:" << ::GetLastError();
+        qWarning("WGL: Failed to lock shared texture: %ls",
+                 qUtf16Printable(QSystemError::windowsString()));
         return;
     }
 
@@ -177,7 +180,8 @@ void D3DSharedTexture::unlockObject()
 
     bool status = m_wglFun->wglDXUnlockObjectsNV(m_interopDevice, 1, &m_glTextureHandle);
     if (!status) {
-        qWarning() << "WGL: Failed to unlock shared texture:" << ::GetLastError();
+        qWarning("WGL: Failed to unlock shared texture: %ls",
+                 qUtf16Printable(QSystemError::windowsString()));
         return;
     }
 
diff --git a/src/core/configure/BUILD.root.gn.in b/src/core/configure/BUILD.root.gn.in
index 5a1fc1d63e8..efb49a59425 100644
--- a/src/core/configure/BUILD.root.gn.in
+++ b/src/core/configure/BUILD.root.gn.in
@@ -182,6 +182,7 @@ shared_library("QtWebEngineCore") {
   }
 
   if (is_win) {
+    configs -= [ "//build/config/compiler:no_rtti" ]
     configs += [ "//build/config/compiler:rtti" ]
     data_deps += [ ":QtWebEngineCoreSandbox" ]
   }
@@ -288,6 +289,7 @@ source_set("qtwebengine_sources") {
     "//chrome/browser/resources/net_internals:resources",
     "//chrome/browser/signin:identity_manager_provider",
     "//chrome/common:buildflags",
+    "//chrome/common:channel_info",
     "//chrome/common:version_header",
     "//components/custom_handlers",
     "//components/embedder_support:embedder_support",
@@ -403,11 +405,14 @@ source_set("qtwebengine_sources") {
       deps += [
         "//ui/base/x:gl",
         "//ui/gfx/linux:gpu_memory_buffer_support_x11",
+        "//ui/gfx/x",
       ]
 
       sources += [
         "//ui/ozone/platform/x11/gl_egl_utility_x11.cc",
         "//ui/ozone/platform/x11/gl_egl_utility_x11.h",
+        "//ui/ozone/platform/x11/native_pixmap_egl_x11_binding.cc",
+        "//ui/ozone/platform/x11/native_pixmap_egl_x11_binding.h",
       ]
     }
   }
@@ -612,7 +617,12 @@ repack("qtwebengine_repack_resources") {
     "$root_gen_dir/third_party/blink/public/resources/blink_resources.pak",
     "$root_gen_dir/ui/resources/webui_resources.pak",
   ]
-  output = "$root_out_dir/qtwebengine_resources.pak"
+  if (!is_debug) {
+    output = "$root_out_dir/qtwebengine_resources.pak"
+  } else {
+    output = "$root_out_dir/qtwebengine_resources.debug.pak"
+  }
+
   deps = [
      "//qtwebengine/browser:qt_webengine_resources",
      "//chrome/browser:dev_ui_browser_resources_grit",
@@ -692,7 +702,11 @@ repack("qtwebengine_repack_resources_100") {
     "$root_gen_dir/third_party/blink/public/resources/blink_scaled_resources_100_percent.pak",
     "$root_gen_dir/ui/resources/ui_resources_100_percent.pak",
   ]
-  output = "$root_out_dir/qtwebengine_resources_100p.pak"
+  if (!is_debug) {
+    output = "$root_out_dir/qtwebengine_resources_100p.pak"
+  } else {
+    output = "$root_out_dir/qtwebengine_resources_100p.debug.pak"
+  }
   deps = [
     "//chrome/renderer:resources_grit",
     "//components/resources:components_scaled_resources_grit",
@@ -716,7 +730,11 @@ repack("qtwebengine_repack_resources_200") {
     "$root_gen_dir/third_party/blink/public/resources/blink_scaled_resources_200_percent.pak",
     "$root_gen_dir/ui/resources/ui_resources_200_percent.pak",
   ]
-  output = "$root_out_dir/qtwebengine_resources_200p.pak"
+  if (!is_debug) {
+    output = "$root_out_dir/qtwebengine_resources_200p.pak"
+  } else {
+    output = "$root_out_dir/qtwebengine_resources_200p.debug.pak"
+  }
   deps = [
     "//chrome/renderer:resources_grit",
     "//components/resources:components_scaled_resources_grit",
@@ -738,7 +756,11 @@ repack("qtwebengine_repack_resources_devtools") {
     "$root_gen_dir/content/browser/devtools/devtools_resources.pak",
     "$root_gen_dir/third_party/blink/public/resources/inspector_overlay_resources.pak",
   ]
-  output = "$root_out_dir/qtwebengine_devtools_resources.pak"
+  if (!is_debug) {
+    output = "$root_out_dir/qtwebengine_devtools_resources.pak"
+  } else {
+    output = "$root_out_dir/qtwebengine_devtools_resources.debug.pak"
+  }
   deps = [
     "//content/browser/devtools:devtools_resources_grit",
     "//third_party/blink/public:devtools_inspector_resources_grit",
diff --git a/src/core/content_browser_client_qt.cpp b/src/core/content_browser_client_qt.cpp
index c3d613c9881..51396f6fb38 100644
--- a/src/core/content_browser_client_qt.cpp
+++ b/src/core/content_browser_client_qt.cpp
@@ -32,6 +32,7 @@
 #include "content/public/common/content_switches.h"
 #include "content/public/common/url_constants.h"
 #include "content/public/common/user_agent.h"
+#include "base/version_info/version_info.h"
 #include "ipc/ipc_channel_proxy.h"
 #include "extensions/buildflags/buildflags.h"
 #include "mojo/public/cpp/bindings/self_owned_associated_receiver.h"
@@ -162,7 +163,7 @@
 
 // Implement IsHandledProtocol as declared in //url/url_util_qt.h.
 namespace url {
-bool IsHandledProtocol(base::StringPiece scheme)
+bool IsHandledProtocol(std::string_view scheme)
 {
     static const char *const kProtocolList[] = {
         url::kHttpScheme,
@@ -288,6 +289,7 @@ void ContentBrowserClientQt::AllowCertificateError(content::WebContents *webCont
 
 
 base::OnceClosure ContentBrowserClientQt::SelectClientCertificate(content::BrowserContext *browser_context,
+                                                                  int process_id,
                                                                   content::WebContents *webContents,
                                                                   net::SSLCertRequestInfo *certRequestInfo,
                                                                   net::ClientCertIdentityList clientCerts,
@@ -703,17 +705,12 @@ static void LaunchURL(const GURL& url,
     contentsDelegate->launchExternalURL(toQt(url), page_transition, is_main_frame, has_user_gesture);
 }
 
-
-bool ContentBrowserClientQt::HandleExternalProtocol(const GURL &url,
-        base::RepeatingCallback<content::WebContents*()> web_contents_getter,
-        int frame_tree_node_id,
-        content::NavigationUIData *navigation_data,
-        bool is_primary_main_frame,
-        bool is_in_fenced_frame_tree,
-        network::mojom::WebSandboxFlags sandbox_flags,
-        ui::PageTransition page_transition,
-        bool has_user_gesture,
-        const std::optional<url::Origin> &initiating_origin,
+bool ContentBrowserClientQt::HandleExternalProtocol(
+        const GURL &url, base::RepeatingCallback<content::WebContents *()> web_contents_getter,
+        content::FrameTreeNodeId frame_tree_node_id, content::NavigationUIData *navigation_data,
+        bool is_primary_main_frame, bool is_in_fenced_frame_tree,
+        network::mojom::WebSandboxFlags sandbox_flags, ui::PageTransition page_transition,
+        bool has_user_gesture, const std::optional<url::Origin> &initiating_origin,
         content::RenderFrameHost *initiator_document,
         mojo::PendingRemote<network::mojom::URLLoaderFactory> *out_factory)
 {
@@ -779,8 +776,8 @@ std::vector<std::unique_ptr<blink::URLLoaderThrottle>>
 ContentBrowserClientQt::CreateURLLoaderThrottles(
         const network::ResourceRequest &request, content::BrowserContext *browser_context,
         const base::RepeatingCallback<content::WebContents *()> & /*wc_getter*/,
-        content::NavigationUIData * /*navigation_ui_data*/, int frame_tree_node_id,
-        std::optional<int64_t> navigation_id)
+        content::NavigationUIData * /*navigation_ui_data*/,
+        content::FrameTreeNodeId frame_tree_node_id, std::optional<int64_t> navigation_id)
 {
     std::vector<std::unique_ptr<blink::URLLoaderThrottle>> result;
     result.push_back(std::make_unique<ProtocolHandlerThrottle>(
@@ -936,17 +933,18 @@ bool ContentBrowserClientQt::DoesSiteRequireDedicatedProcess(content::BrowserCon
     return ContentBrowserClient::DoesSiteRequireDedicatedProcess(browser_context, effective_site_url);
 }
 
-bool ContentBrowserClientQt::ShouldUseSpareRenderProcessHost(content::BrowserContext *browser_context,
-                                                             const GURL &site_url)
+std::optional<content::ContentBrowserClient::SpareProcessRefusedByEmbedderReason>
+ContentBrowserClientQt::ShouldUseSpareRenderProcessHost(content::BrowserContext *browser_context,
+                                                        const GURL &site_url)
 {
 #if BUILDFLAG(ENABLE_EXTENSIONS)
     if (site_url.SchemeIs(extensions::kExtensionScheme))
-       return false;
+       return SpareProcessRefusedByEmbedderReason::ExtensionProcess;
 #endif
     return ContentBrowserClient::ShouldUseSpareRenderProcessHost(browser_context, site_url);
 }
 
-bool ContentBrowserClientQt::ShouldTreatURLSchemeAsFirstPartyWhenTopLevel(base::StringPiece scheme, bool is_embedded_origin_secure)
+bool ContentBrowserClientQt::ShouldTreatURLSchemeAsFirstPartyWhenTopLevel(std::string_view scheme, bool is_embedded_origin_secure)
 {
     if (is_embedded_origin_secure && scheme == content::kChromeUIScheme)
         return true;
@@ -982,8 +980,8 @@ std::string ContentBrowserClientQt::getUserAgent()
 {
     // Mention the Chromium version we're based on to get passed stupid UA-string-based feature detection (several WebRTC demos need this)
     return content::BuildUserAgentFromProduct("QtWebEngine/" + std::string(qWebEngineVersion())
-                                              + " Chrome/"
-                                              + std::string(qWebEngineChromiumVersion()));
+                                              + " Chrome/" + version_info::GetMajorVersionNumber()
+                                              + ".0.0.0");
 }
 
 blink::UserAgentMetadata ContentBrowserClientQt::GetUserAgentMetadata()
@@ -995,7 +993,7 @@ blink::UserAgentMetadata ContentBrowserClientQt::GetUserAgentMetadata()
 
 std::string ContentBrowserClientQt::GetProduct()
 {
-    QString productName(qApp->applicationName() % '/' % qApp->applicationVersion());
+    QString productName(qApp->applicationName() % u'/' % qApp->applicationVersion());
     return productName.toStdString();
 }
 
@@ -1044,8 +1042,9 @@ std::vector<base::FilePath> ContentBrowserClientQt::GetNetworkContextsParentDire
         toFilePath(QStandardPaths::writableLocation(QStandardPaths::CacheLocation)) };
 }
 
-mojo::PendingRemote<network::mojom::URLLoaderFactory> ContentBrowserClientQt::CreateNonNetworkNavigationURLLoaderFactory(
-        const std::string &scheme, int frame_tree_node_id)
+mojo::PendingRemote<network::mojom::URLLoaderFactory>
+ContentBrowserClientQt::CreateNonNetworkNavigationURLLoaderFactory(
+        const std::string &scheme, content::FrameTreeNodeId frame_tree_node_id)
 {
     content::WebContents *web_contents = content::WebContents::FromFrameTreeNodeId(frame_tree_node_id);
     Profile *profile = Profile::FromBrowserContext(web_contents->GetBrowserContext());
@@ -1245,15 +1244,15 @@ void ContentBrowserClientQt::WillCreateURLLoaderFactory(
     // Will manage its own lifetime
     // FIXME: use navigation_response_task_runner?
     new ProxyingURLLoaderFactoryQt(
-            adapter,
-            frame ? frame->GetFrameTreeNodeId() : content::RenderFrameHost::kNoFrameTreeNodeId,
+            adapter, frame ? frame->GetFrameTreeNodeId() : content::FrameTreeNodeId{},
             std::move(proxied_receiver), std::move(pending_url_loader_factory), type);
 }
 
 std::vector<std::unique_ptr<content::URLLoaderRequestInterceptor>>
-ContentBrowserClientQt::WillCreateURLLoaderRequestInterceptors(content::NavigationUIData *navigation_ui_data,
-                                       int frame_tree_node_id, int64_t navigation_id,
-                                       scoped_refptr<base::SequencedTaskRunner> navigation_response_task_runner)
+ContentBrowserClientQt::WillCreateURLLoaderRequestInterceptors(
+        content::NavigationUIData *navigation_ui_data, content::FrameTreeNodeId frame_tree_node_id,
+        int64_t navigation_id, bool force_no_https_upgrade,
+        scoped_refptr<base::SequencedTaskRunner> navigation_response_task_runner)
 {
     Q_UNUSED(navigation_ui_data);
     Q_UNUSED(navigation_id);
diff --git a/src/core/content_browser_client_qt.h b/src/core/content_browser_client_qt.h
index 285e13a4050..4e24012e46b 100644
--- a/src/core/content_browser_client_qt.h
+++ b/src/core/content_browser_client_qt.h
@@ -39,6 +39,7 @@ class ContentBrowserClientQt : public content::ContentBrowserClient
                                bool strict_enforcement,
                                base::OnceCallback<void(content::CertificateRequestResultType)> callback) override;
     base::OnceClosure SelectClientCertificate(content::BrowserContext* browser_context,
+                                              int process_id,
                                               content::WebContents* web_contents,
                                               net::SSLCertRequestInfo* cert_request_info,
                                               net::ClientCertIdentityList client_certs,
@@ -127,8 +128,9 @@ class ContentBrowserClientQt : public content::ContentBrowserClient
     bool ShouldUseProcessPerSite(content::BrowserContext *browser_context, const GURL &effective_url) override;
     bool DoesSiteRequireDedicatedProcess(content::BrowserContext *browser_context,
                                          const GURL &effective_site_url) override;
-    bool ShouldUseSpareRenderProcessHost(content::BrowserContext *browser_context, const GURL& site_url) override;
-    bool ShouldTreatURLSchemeAsFirstPartyWhenTopLevel(base::StringPiece scheme,
+    std::optional<SpareProcessRefusedByEmbedderReason>
+    ShouldUseSpareRenderProcessHost(content::BrowserContext *browser_context, const GURL& site_url) override;
+    bool ShouldTreatURLSchemeAsFirstPartyWhenTopLevel(std::string_view scheme,
                                                       bool is_embedded_origin_secure) override;
     bool DoesSchemeAllowCrossOriginSharedWorker(const std::string &scheme) override;
     void OverrideURLLoaderFactoryParams(content::BrowserContext *browser_context,
@@ -148,16 +150,11 @@ class ContentBrowserClientQt : public content::ContentBrowserClient
                         LoginAuthRequiredCallback auth_required_callback) override;
 
     bool HandleExternalProtocol(
-            const GURL &url,
-            base::RepeatingCallback<content::WebContents*()> web_contents_getter,
-            int frame_tree_node_id,
-            content::NavigationUIData *navigation_data,
-            bool is_primary_main_frame,
-            bool is_in_fenced_frame_tree,
-            network::mojom::WebSandboxFlags sandbox_flags,
-            ui::PageTransition page_transition,
-            bool has_user_gesture,
-            const std::optional<url::Origin> &initiating_origin,
+            const GURL &url, base::RepeatingCallback<content::WebContents *()> web_contents_getter,
+            content::FrameTreeNodeId frame_tree_node_id, content::NavigationUIData *navigation_data,
+            bool is_primary_main_frame, bool is_in_fenced_frame_tree,
+            network::mojom::WebSandboxFlags sandbox_flags, ui::PageTransition page_transition,
+            bool has_user_gesture, const std::optional<url::Origin> &initiating_origin,
             content::RenderFrameHost *initiator_document,
             mojo::PendingRemote<network::mojom::URLLoaderFactory> *out_factory) override;
 
@@ -165,7 +162,8 @@ class ContentBrowserClientQt : public content::ContentBrowserClient
     CreateURLLoaderThrottles(const network::ResourceRequest &request,
                              content::BrowserContext *browser_context,
                              const base::RepeatingCallback<content::WebContents *()> &wc_getter,
-                             content::NavigationUIData *navigation_ui_data, int frame_tree_node_id,
+                             content::NavigationUIData *navigation_ui_data,
+                             content::FrameTreeNodeId frame_tree_node_id,
                              std::optional<int64_t> navigation_id) override;
 
     std::vector<std::unique_ptr<content::NavigationThrottle>> CreateThrottlesForNavigation(
@@ -176,10 +174,11 @@ class ContentBrowserClientQt : public content::ContentBrowserClient
     bool HasCustomSchemeHandler(content::BrowserContext *browser_context,
                                 const std::string &scheme) override;
     std::vector<std::unique_ptr<content::URLLoaderRequestInterceptor>>
-    WillCreateURLLoaderRequestInterceptors(content::NavigationUIData *navigation_ui_data,
-                                           int frame_tree_node_id,
-                                           int64_t navigation_id,
-                                           scoped_refptr<base::SequencedTaskRunner> navigation_response_task_runner) override;
+    WillCreateURLLoaderRequestInterceptors(
+            content::NavigationUIData *navigation_ui_data,
+            content::FrameTreeNodeId frame_tree_node_id, int64_t navigation_id,
+            bool force_no_https_upgrade,
+            scoped_refptr<base::SequencedTaskRunner> navigation_response_task_runner) override;
     void WillCreateURLLoaderFactory(content::BrowserContext *browser_context,
                                     content::RenderFrameHost *frame,
                                     int render_process_id,
@@ -204,8 +203,9 @@ class ContentBrowserClientQt : public content::ContentBrowserClient
                                        cert_verifier::mojom::CertVerifierCreationParams *cert_verifier_creation_params) override;
 
     std::vector<base::FilePath> GetNetworkContextsParentDirectory() override;
-    mojo::PendingRemote<network::mojom::URLLoaderFactory> CreateNonNetworkNavigationURLLoaderFactory(const std::string &scheme,
-                                                                                                     int frame_tree_node_id) override;
+    mojo::PendingRemote<network::mojom::URLLoaderFactory>
+    CreateNonNetworkNavigationURLLoaderFactory(
+            const std::string &scheme, content::FrameTreeNodeId frame_tree_node_id) override;
     void RegisterNonNetworkSubresourceURLLoaderFactories(int render_process_id, int render_frame_id,
                                                          const std::optional<url::Origin>& request_initiator_origin,
                                                          NonNetworkURLLoaderFactoryMap *factories) override;
diff --git a/src/core/content_client_qt.cpp b/src/core/content_client_qt.cpp
index b8534cc9806..52e091f51bd 100644
--- a/src/core/content_client_qt.cpp
+++ b/src/core/content_client_qt.cpp
@@ -3,10 +3,11 @@
 
 #include "content_client_qt.h"
 
+#include "compositor/compositor.h"
+
 #include "base/command_line.h"
 #include "base/files/file_util.h"
 #include "base/json/json_string_value_serializer.h"
-#include "base/strings/string_piece.h"
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
 #include "base/values.h"
@@ -29,7 +30,12 @@
 #include <QFile>
 #include <QLibraryInfo>
 #include <QString>
+#include <QSysInfo>
+#include <QThread>
 
+#if BUILDFLAG(IS_WIN)
+#include "ui/gl/gl_utils.h"
+#endif
 
 #if BUILDFLAG(ENABLE_LIBRARY_CDMS)
 #include "media/cdm/cdm_paths.h"  // nogncheck
@@ -57,13 +63,15 @@ const char kWidevineCdmFileName[] =
 const char kPdfPluginPath[] = "internal-pdf-viewer";
 #endif // QT_CONFIG(webengine_printing_and_pdf)
 
+using namespace Qt::StringLiterals;
 using Robustness = content::CdmInfo::Robustness;
 
 static QString webenginePluginsPath()
 {
     // Look for plugins in /plugins/webengine or application dir.
     static bool initialized = false;
-    static QString potentialPluginsPath = QLibraryInfo::path(QLibraryInfo::PluginsPath) % QLatin1String("/webengine");
+    static QString potentialPluginsPath =
+            QLibraryInfo::path(QLibraryInfo::PluginsPath) % "/webengine"_L1;
     if (!initialized) {
         initialized = true;
         if (!QFileInfo::exists(potentialPluginsPath))
@@ -77,18 +85,33 @@ static QString webenginePluginsPath()
 static QString getLocalAppDataDir()
 {
     QString result;
-    wchar_t path[MAX_PATH];
-    if (SHGetSpecialFolderPath(0, path, CSIDL_LOCAL_APPDATA, FALSE))
+    PWSTR path;
+    HRESULT hr = SHGetKnownFolderPath(FOLDERID_LocalAppData, 0, NULL, &path);
+    if (SUCCEEDED(hr))
         result = QDir::fromNativeSeparators(QString::fromWCharArray(path));
+    CoTaskMemFree(path);
     return result;
 }
 
 static QString getProgramFilesDir(bool x86Dir = false)
 {
     QString result;
-    wchar_t path[MAX_PATH];
-    if (SHGetSpecialFolderPath(0, path, x86Dir ? CSIDL_PROGRAM_FILESX86 : CSIDL_PROGRAM_FILES, FALSE))
+    PWSTR path;
+    HRESULT hr = SHGetKnownFolderPath(x86Dir ? FOLDERID_ProgramFilesX86 : FOLDERID_ProgramFilesX64, 0, NULL, &path);
+    if (SUCCEEDED(hr))
         result = QDir::fromNativeSeparators(QString::fromWCharArray(path));
+    CoTaskMemFree(path);
+    return result;
+}
+
+static QString getSystem32Dir()
+{
+    QString result;
+    PWSTR path;
+    HRESULT hr = SHGetKnownFolderPath(FOLDERID_System, 0, NULL, &path);
+    if (SUCCEEDED(hr))
+        result = QDir::fromNativeSeparators(QString::fromWCharArray(path));
+    CoTaskMemFree(path);
     return result;
 }
 #endif
@@ -107,7 +130,8 @@ static QString ppapiPluginsPath()
 {
     // Look for plugins in /plugins/ppapi or application dir.
     static bool initialized = false;
-    static QString potentialPluginsPath = QLibraryInfo::path(QLibraryInfo::PluginsPath) % QLatin1String("/ppapi");
+    static QString potentialPluginsPath =
+            QLibraryInfo::path(QLibraryInfo::PluginsPath) % "/ppapi"_L1;
     if (!initialized) {
         initialized = true;
         if (!QFileInfo::exists(potentialPluginsPath))
@@ -151,7 +175,7 @@ namespace QtWebEngineCore {
 static const QDir widevineCdmDirHint(const QDir &widevineDir)
 {
     const QString hintFilePath = widevineDir.absolutePath() % QDir::separator()
-            % QLatin1String("latest-component-updated-widevine-cdm");
+            % "latest-component-updated-widevine-cdm"_L1;
     if (!QFileInfo::exists(hintFilePath)) {
         // CDM hint file does not exist.
         return widevineDir;
@@ -189,63 +213,93 @@ static bool IsWidevineAvailable(base::FilePath *cdm_path,
     if (!widevine_argument.empty())
         pluginPaths << QtWebEngineCore::toQt(widevine_argument);
     else {
-        pluginPaths << webenginePluginsPath() + QStringLiteral("/") + QString::fromLatin1(kWidevineCdmFileName);
+        pluginPaths << webenginePluginsPath() + u'/' + QLatin1StringView(kWidevineCdmFileName);
 #if QT_CONFIG(webengine_pepper_plugins)
-        pluginPaths << ppapiPluginsPath() + QStringLiteral("/") + QString::fromLatin1(kWidevineCdmFileName);
+        pluginPaths << ppapiPluginsPath() + u'/' + QLatin1StringView(kWidevineCdmFileName);
 #endif
 #if defined(Q_OS_OSX)
-    QDir potentialWidevineDir("/Applications/Google Chrome.app/Contents/Frameworks");
+    QDir potentialWidevineDir(u"/Applications/Google Chrome.app/Contents/Frameworks"_s);
+    const auto archDir = QSysInfo::currentCpuArchitecture() == "x86_64"_L1
+                       ? "mac_x64/"_L1
+                       : "mac_arm64/"_L1;
     if (potentialWidevineDir.exists()) {
         QFileInfoList widevineVersionDirs = potentialWidevineDir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot,
                                                                                QDir::Name | QDir::Reversed);
-        const QString library = QLatin1String("/Versions/Current/Libraries/"
-                                              "WidevineCdm/_platform_specific/mac_x64/libwidevinecdm.dylib");
+        const auto libraryBase = "/Versions/Current/Libraries/WidevineCdm/_platform_specific/"_L1;
+        const auto libraryFilename = "libwidevinecdm.dylib"_L1;
         for (const QFileInfo &info : widevineVersionDirs)
-            pluginPaths << info.absoluteFilePath() + library;
+            pluginPaths << info.absoluteFilePath() + libraryBase + archDir + libraryFilename;
     }
 
-    QDir oldPotentialWidevineDir(QDir::homePath() + "/Library/Application Support/Google/Chrome/WidevineCDM");
+    QDir oldPotentialWidevineDir(QDir::homePath() + "/Library/Application Support/Google/Chrome/WidevineCDM"_L1);
     if (oldPotentialWidevineDir.exists()) {
         QFileInfoList widevineVersionDirs = oldPotentialWidevineDir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name | QDir::Reversed);
         for (int i = 0; i < widevineVersionDirs.size(); ++i) {
-            QString versionDirPath(widevineVersionDirs.at(i).absoluteFilePath());
-            QString potentialWidevinePluginPath = versionDirPath + "/_platform_specific/mac_x64/" + QString::fromLatin1(kWidevineCdmFileName);
-            pluginPaths << potentialWidevinePluginPath;
+            const QString versionDirPath = widevineVersionDirs.at(i).absoluteFilePath();
+            QString potentialWidevinePluginPath = versionDirPath + "/_platform_specific/"_L1 + archDir
+                    + QLatin1StringView(kWidevineCdmFileName);
+            pluginPaths.append(std::move(potentialWidevinePluginPath));
         }
     }
 #elif defined(Q_OS_WIN)
-    const QString googleChromeDir = QLatin1String("/Google/Chrome/Application");
-    const QStringList programFileDirs{getProgramFilesDir() + googleChromeDir,
-                                      getProgramFilesDir(true) + googleChromeDir};
+    const auto arch = QSysInfo::currentCpuArchitecture();
+    auto appendArchitectureAndFilename = [&arch](QString &inString) {
+        if (arch == "x86_64"_L1) {
+            inString += "/win_x64/"_L1;
+        } else if (arch == "i386"_L1) {
+            inString += "/win_x86/"_L1;
+        } else if (arch == "arm64"_L1) {
+            inString += "/win_arm64/"_L1;
+        } else {
+            Q_UNREACHABLE();
+        }
+
+        inString += QLatin1StringView(kWidevineCdmFileName);
+    };
+
+    // Look inside Program Files; first for Microsoft Edge, then for Google Chrome
+    const auto microsoftEdgeDir = "/Microsoft/Edge/Application"_L1;
+    const auto googleChromeDir = "/Google/Chrome/Application"_L1;
+    const QStringList programFileDirs {
+        getProgramFilesDir() + microsoftEdgeDir,
+        getProgramFilesDir(true) + microsoftEdgeDir,
+        getProgramFilesDir() + googleChromeDir,
+        getProgramFilesDir(true) + googleChromeDir
+    };
+
     for (const QString &dir : programFileDirs) {
         QDir d(dir);
         if (d.exists()) {
             QFileInfoList widevineVersionDirs = d.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name | QDir::Reversed);
             for (int i = 0; i < widevineVersionDirs.size(); ++i) {
-                QString versionDirPath(widevineVersionDirs.at(i).absoluteFilePath());
-#ifdef WIN64
-                QString potentialWidevinePluginPath = versionDirPath +
-                                                        "/WidevineCdm/_platform_specific/win_x64/" +
-                                                        QString::fromLatin1(kWidevineCdmFileName);
-#else
-                QString potentialWidevinePluginPath = versionDirPath +
-                                                        "/WidevineCdm/_platform_specific/win_x86/" +
-                                                        QString::fromLatin1(kWidevineCdmFileName);
-#endif
+                QString potentialWidevinePluginPath
+                    = widevineVersionDirs.at(i).absoluteFilePath()
+                    + "/WidevineCdm/_platform_specific"_L1;
+
+                appendArchitectureAndFilename(potentialWidevinePluginPath);
                 pluginPaths << potentialWidevinePluginPath;
             }
         }
     }
-    QDir potentialWidevineDir(getLocalAppDataDir() + "/Google/Chrome/User Data/WidevineCDM");
-    if (potentialWidevineDir.exists()) {
-        QFileInfoList widevineVersionDirs = potentialWidevineDir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name | QDir::Reversed);
+
+    // Look inside WebView data that lives in system32
+    QDir potentialEdgeWebViewDir(getSystem32Dir() + "/Microsoft-Edge-WebView"_L1);
+    if (potentialEdgeWebViewDir.exists()) {
+        QString potentialWidevinePluginPath = potentialEdgeWebViewDir.absolutePath() + "/WidevineCdm/_platform_specific"_L1;
+        appendArchitectureAndFilename(potentialWidevinePluginPath);
+        pluginPaths << potentialWidevinePluginPath;
+    }
+
+    // As a last resort, look for Google Chrome data inside %APPDATA%. This may be obsolete
+    QDir potentialChromeUserDataDir(getLocalAppDataDir() + "/Google/Chrome/User Data/WidevineCDM"_L1);
+    if (potentialChromeUserDataDir.exists()) {
+        QFileInfoList widevineVersionDirs = potentialChromeUserDataDir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name | QDir::Reversed);
         for (int i = 0; i < widevineVersionDirs.size(); ++i) {
-            QString versionDirPath(widevineVersionDirs.at(i).absoluteFilePath());
-#ifdef WIN64
-            QString potentialWidevinePluginPath = versionDirPath + "/_platform_specific/win_x64/" + QString::fromLatin1(kWidevineCdmFileName);
-#else
-            QString potentialWidevinePluginPath = versionDirPath + "/_platform_specific/win_x86/" + QString::fromLatin1(kWidevineCdmFileName);
-#endif
+            QString potentialWidevinePluginPath
+                = widevineVersionDirs.at(i).absoluteFilePath()
+                + "/_platform_specific"_L1;
+
+            appendArchitectureAndFilename(potentialWidevinePluginPath);
             pluginPaths << potentialWidevinePluginPath;
         }
     }
@@ -253,23 +307,23 @@ static bool IsWidevineAvailable(base::FilePath *cdm_path,
         QList<QDir> potentialWidevineVersionDirs;
 
         // Google Chrome widevine modules
-        QDir chromeWidevineDir(QDir::homePath() + "/.config/google-chrome/WidevineCdm");
+        QDir chromeWidevineDir(QDir::homePath() + "/.config/google-chrome/WidevineCdm"_L1);
         if (chromeWidevineDir.exists())
             potentialWidevineVersionDirs << widevineCdmDirHint(chromeWidevineDir);
 
         // Firefox widevine modules
-        QDir firefoxPotentialProfilesDir(QDir::homePath() + "/.mozilla/firefox");
+        QDir firefoxPotentialProfilesDir(QDir::homePath() + "/.mozilla/firefox"_L1);
         if (firefoxPotentialProfilesDir.exists()) {
             QFileInfoList firefoxProfileDirs = firefoxPotentialProfilesDir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name | QDir::Reversed);
             for (const QFileInfo &info : firefoxProfileDirs) {
-                QDir widevinePluginsDir(info.absoluteFilePath() + "/gmp-widevinecdm");
+                QDir widevinePluginsDir(info.absoluteFilePath() + "/gmp-widevinecdm"_L1);
                 if (widevinePluginsDir.exists())
                     potentialWidevineVersionDirs << widevinePluginsDir;
             }
         }
 
         // Chromium widevine modules (might not work with proprietary codecs)
-        QDir chromiumWidevineDir(QDir::homePath() + "/.config/chromium/WidevineCdm");
+        QDir chromiumWidevineDir(QDir::homePath() + "/.config/chromium/WidevineCdm"_L1);
         if (chromiumWidevineDir.exists())
             potentialWidevineVersionDirs << widevineCdmDirHint(chromiumWidevineDir);
 
@@ -279,28 +333,29 @@ static bool IsWidevineAvailable(base::FilePath *cdm_path,
             widevineVersionDirs.prepend(QFileInfo(dir.absolutePath()));
             // ### alternatively look up in the manifest.json and take the path from there.
 #if Q_PROCESSOR_WORDSIZE == 8
-            const QString library = QLatin1String("/_platform_specific/linux_x64/libwidevinecdm.so");
+            const auto library = "/_platform_specific/linux_x64/libwidevinecdm.so"_L1;
 #else
-            const QString library = QLatin1String("/_platform_specific/linux_x86/libwidevinecdm.so");
+            const auto library = "/_platform_specific/linux_x86/libwidevinecdm.so"_L1;
 #endif
             for (const QFileInfo &info : widevineVersionDirs) {
-                pluginPaths << info.absoluteFilePath() + "/libwidevinecdm.so";
+                pluginPaths << info.absoluteFilePath() + "/libwidevinecdm.so"_L1;
                 pluginPaths << info.absoluteFilePath() + library;
             }
         }
 
         // Fixed paths:
-        pluginPaths << QStringLiteral("/usr/lib/chromium/libwidevinecdm.so") // Arch
-                    << QStringLiteral("/usr/lib/chromium-browser/libwidevinecdm.so") // Ubuntu/neon
-                    << QStringLiteral("/usr/lib64/chromium/libwidevinecdm.so") // OpenSUSE style
+        pluginPaths
+                << u"/usr/lib/chromium/libwidevinecdm.so"_s // Arch
+                << u"/usr/lib/chromium-browser/libwidevinecdm.so"_s // Ubuntu/neon
+                << u"/usr/lib64/chromium/libwidevinecdm.so"_s // OpenSUSE style
 #if Q_PROCESSOR_WORDSIZE == 8
-                    << QStringLiteral("/usr/lib64/chromium-browser/WidevineCdm/_platform_specific/linux_x64/libwidevinecdm.so") // Gentoo
-                    << QStringLiteral("/opt/google/chrome/WidevineCdm/_platform_specific/linux_x64/libwidevinecdm.so") // Old Google Chrome
+                << u"/usr/lib64/chromium-browser/WidevineCdm/_platform_specific/linux_x64/libwidevinecdm.so"_s // Gentoo
+                << u"/opt/google/chrome/WidevineCdm/_platform_specific/linux_x64/libwidevinecdm.so"_s // Old Google Chrome
 #else
-                    << QStringLiteral("/usr/lib/chromium-browser/WidevineCdm/_platform_specific/linux_x86/libwidevinecdm.so") // Gentoo
-                    << QStringLiteral("/opt/google/chrome/WidevineCdm/_platform_specific/linux_x86/libwidevinecdm.so") // Old Google Chrome
+                << u"/usr/lib/chromium-browser/WidevineCdm/_platform_specific/linux_x86/libwidevinecdm.so"_s // Gentoo
+                << u"/opt/google/chrome/WidevineCdm/_platform_specific/linux_x86/libwidevinecdm.so"_s // Old Google Chrome
 #endif
-                    << QStringLiteral("/opt/google/chrome/libwidevinecdm.so"); // Older Google Chrome
+                << u"/opt/google/chrome/libwidevinecdm.so"_s; // Older Google Chrome
 #endif
     }
 
@@ -400,7 +455,8 @@ void ContentClientQt::AddAdditionalSchemes(Schemes* schemes)
 #endif
 }
 
-base::StringPiece ContentClientQt::GetDataResource(int resource_id, ui::ResourceScaleFactor scale_factor)
+std::string_view ContentClientQt::GetDataResource(int resource_id,
+                                                  ui::ResourceScaleFactor scale_factor)
 {
     return ui::ResourceBundle::GetSharedInstance().GetRawDataResourceForScale(resource_id, scale_factor);
 }
@@ -435,4 +491,121 @@ blink::OriginTrialPolicy *ContentClientQt::GetOriginTrialPolicy()
     return origin_trial_policy_.get();
 }
 
+void ContentClientQt::SetGpuInfo(const gpu::GPUInfo &gpu_info)
+{
+    if (Q_LIKELY(!lcWebEngineCompositor().isDebugEnabled()))
+        return;
+
+    base::CommandLine *commandLine = base::CommandLine::ForCurrentProcess();
+    const bool isBrowserProcess = !commandLine->HasSwitch(switches::kProcessType);
+    const bool isMainThread = QThread::currentThread() == qApp->thread();
+
+    // Limit this to the main thread of the browser process for now.
+    if (!isBrowserProcess || !isMainThread)
+        return;
+
+    if (!gpu_info.IsInitialized()) {
+        // This is probably not an issue but suspicious.
+        qCDebug(lcWebEngineCompositor, "Failed to initialize GPUInfo.");
+        return;
+    }
+
+    const gpu::GPUInfo::GPUDevice &primary = gpu_info.gpu;
+
+    // Do not print the info again if the device hasn't been changed.
+    // Change of the device is unexpected: we don't support or implement fallback yet.
+    // It is suspicious if the info is logged twice.
+    if (m_gpuInfo && m_gpuInfo->gpu.device_string == primary.device_string)
+        return;
+    m_gpuInfo = gpu_info;
+
+    auto deviceToString = [](const gpu::GPUInfo::GPUDevice &device) -> QString {
+        if (device.vendor_id == 0x0)
+            return "Disabled"_L1;
+
+        QString log;
+
+        // TODO: Factor vendor translation out from QtWebEngineCore::GPUInfo.
+        // Only name the most commmon desktop GPU hardware vendors for now.
+        switch (device.vendor_id) {
+        case 0x1002:
+            log += "AMD"_L1;
+            break;
+        case 0x10DE:
+            log += "Nvidia"_L1;
+            break;
+        case 0x8086:
+            log += "Intel"_L1;
+            break;
+        default:
+            log += "vendor id: 0x"_L1 + QString::number(device.vendor_id, 16);
+        }
+
+        log += ", device id: 0x"_L1 + QString::number(device.device_id, 16);
+
+        if (!device.driver_vendor.empty()) {
+            log += ", driver: "_L1 + QLatin1StringView(device.driver_vendor) + u' '
+                    + QLatin1StringView(device.driver_version);
+        }
+        log += ", system device id: 0x"_L1 + QString::number(device.system_device_id, 16);
+
+        log += ", preference: "_L1;
+        switch (device.gpu_preference) {
+        case gl::GpuPreference::kNone:
+            log += "None"_L1;
+            break;
+        case gl::GpuPreference::kDefault:
+            log += "Default"_L1;
+            break;
+        case gl::GpuPreference::kLowPower:
+            log += "LowPower"_L1;
+            break;
+        case gl::GpuPreference::kHighPerformance:
+            log += "HighPerformance"_L1;
+            break;
+        }
+
+        log += ", active: "_L1 + (device.active ? "yes"_L1 : "no"_L1);
+        return log;
+    };
+
+    QString log;
+    if (gpu_info.gl_vendor.empty() || gpu_info.gl_vendor == "Disabled") {
+        log += "ANGLE is disabled:\n"_L1;
+        log += "  GL Renderer: "_L1 + QLatin1StringView(gpu_info.gl_renderer) + u'\n';
+        log += "  Software Renderer: "_L1 + (primary.IsSoftwareRenderer() ? "yes"_L1 : "no"_L1)
+                + u'\n';
+        log += "  Primary GPU: "_L1 + deviceToString(primary) + u'\n';
+    } else {
+        log += QLatin1StringView(gpu_info.display_type) + " display is initialized:\n"_L1;
+        log += "  GL Renderer: "_L1 + QLatin1StringView(gpu_info.gl_renderer) + u'\n';
+        log += "  "_L1 + QString::number(gpu_info.GpuCount()) + " GPU(s) detected:\n"_L1;
+        log += "    "_L1 + deviceToString(primary) + u'\n';
+        for (auto &secondary : gpu_info.secondary_gpus)
+            log += "    "_L1 + deviceToString(secondary) + u'\n';
+
+        log += "  NVIDIA Optimus: "_L1 + (gpu_info.optimus ? "enabled"_L1 : "disabled"_L1) + u'\n';
+        log += "  AMD Switchable: "_L1 + (gpu_info.amd_switchable ? "enabled"_L1 : "disabled"_L1);
+    }
+
+    qCDebug(lcWebEngineCompositor, "%ls", qUtf16Printable(log));
+
+#if BUILDFLAG(IS_WIN)
+    log = "Windows specific driver information:\n"_L1;
+
+    log += "  Direct Composition: "_L1;
+    if (gpu_info.overlay_info.direct_composition)
+        log += "enabled\n"_L1;
+    else if (gl::GetGlWorkarounds().disable_direct_composition)
+        log += "disabled by workaround\n"_L1;
+    else
+        log += "disabled\n"_L1;
+
+    log += "  Supports Overlays: "_L1
+            + (gpu_info.overlay_info.supports_overlays ? "yes"_L1 : "no"_L1) + u'\n';
+    log += "  Supports D3D Shared Images: "_L1 + (gpu_info.shared_image_d3d ? "yes"_L1 : "no"_L1);
+    qCDebug(lcWebEngineCompositor, "%ls", qUtf16Printable(log));
+#endif
+}
+
 } // namespace QtWebEngineCore
diff --git a/src/core/content_client_qt.h b/src/core/content_client_qt.h
index f58e17f9649..854233ae0b0 100644
--- a/src/core/content_client_qt.h
+++ b/src/core/content_client_qt.h
@@ -6,13 +6,14 @@
 
 #include "qtwebenginecoreglobal_p.h"
 
-#include "base/strings/string_piece.h"
 #include "base/synchronization/lock.h"
 #include "components/embedder_support/origin_trials/origin_trial_policy_impl.h"
 #include "content/public/common/content_client.h"
+#include "gpu/config/gpu_info.h"
 #include "ui/base/layout.h"
 
 #include <memory>
+#include <optional>
 
 namespace QtWebEngineCore {
 
@@ -25,16 +26,18 @@ class ContentClientQt : public content::ContentClient {
                                      std::vector<media::CdmHostFilePath> *cdm_host_file_paths) override;
     void AddAdditionalSchemes(Schemes* schemes) override;
 
-    base::StringPiece GetDataResource(int, ui::ResourceScaleFactor) override;
+    std::string_view GetDataResource(int, ui::ResourceScaleFactor) override;
     base::RefCountedMemory* GetDataResourceBytes(int resource_id) override;
     gfx::Image &GetNativeImageNamed(int resource_id) override;
     std::u16string GetLocalizedString(int message_id) override;
     blink::OriginTrialPolicy *GetOriginTrialPolicy() override;
+    void SetGpuInfo(const gpu::GPUInfo &gpu_info) override;
 
 private:
     // Used to lock when |origin_trial_policy_| is initialized.
     base::Lock origin_trial_policy_lock_;
     std::unique_ptr<embedder_support::OriginTrialPolicyImpl> origin_trial_policy_;
+    std::optional<gpu::GPUInfo> m_gpuInfo;
 };
 
 } // namespace QtWebEngineCore
diff --git a/src/core/content_main_delegate_qt.cpp b/src/core/content_main_delegate_qt.cpp
index 604657e3181..c96328b3efa 100644
--- a/src/core/content_main_delegate_qt.cpp
+++ b/src/core/content_main_delegate_qt.cpp
@@ -46,7 +46,6 @@
 #if BUILDFLAG(IS_MAC)
 #include "base/trace_event/trace_event.h"
 #include "content/public/common/content_features.h"
-#include "media/gpu/mac/vt_video_decode_accelerator_mac.h"
 #endif
 
 #include <QtCore/qcoreapplication.h>
@@ -171,13 +170,6 @@ void ContentMainDelegateQt::PreSandboxStartup()
 #if BUILDFLAG(IS_WIN)
         media::PreSandboxMediaFoundationInitialization();
 #endif
-
-#if BUILDFLAG(IS_MAC)
-        {
-            TRACE_EVENT0("gpu", "Initialize VideoToolbox");
-            media::InitializeVideoToolbox();
-        }
-#endif
     }
 
     if (parsedCommandLine->HasSwitch(switches::kApplicationName)) {
diff --git a/src/core/desktop_media_controller.cpp b/src/core/desktop_media_controller.cpp
index 09c1aea1914..abf62645089 100644
--- a/src/core/desktop_media_controller.cpp
+++ b/src/core/desktop_media_controller.cpp
@@ -42,7 +42,7 @@ std::unique_ptr<DesktopMediaList> createMediaList(DesktopMediaType type)
         std::unique_ptr<webrtc::DesktopCapturer> screenCapturer =
                 webrtc::DesktopCapturer::CreateScreenCapturer(options);
         if (!screenCapturer) {
-            qWarning() << "Screen capturing is not available. Media list will be empty.";
+            qWarning("Screen capturing is not available. Media list will be empty.");
             return nullptr;
         }
         auto capturer = std::make_unique<DesktopCapturerWrapper>(std::move(screenCapturer));
@@ -52,13 +52,13 @@ std::unique_ptr<DesktopMediaList> createMediaList(DesktopMediaType type)
         std::unique_ptr<webrtc::DesktopCapturer> windowCapturer =
                 webrtc::DesktopCapturer::CreateWindowCapturer(options);
         if (!windowCapturer) {
-            qWarning() << "Window capturing is not available. Media list will be empty.";
+            qWarning("Window capturing is not available. Media list will be empty.");
             return nullptr;
         }
         auto capturer = std::make_unique<DesktopCapturerWrapper>(std::move(windowCapturer));
         return std::make_unique<NativeDesktopMediaList>(
                 listType, std::move(capturer),
-                !content::desktop_capture::ShouldEnumerateCurrentProcessWindows());
+                !content::desktop_capture::ShouldEnumerateCurrentProcessWindows(), /*auto_show_delegated_source_list:*/ false);
     }
     default: {
         Q_UNREACHABLE();
diff --git a/src/core/devtools_frontend_qt.cpp b/src/core/devtools_frontend_qt.cpp
index 97a1ef68d60..e36b5a37819 100644
--- a/src/core/devtools_frontend_qt.cpp
+++ b/src/core/devtools_frontend_qt.cpp
@@ -26,7 +26,7 @@
 using namespace QtWebEngineCore;
 
 namespace {
-static const char kScreencastEnabled[] = "screencastEnabled";
+static const char kScreencastEnabled[] = "screencast-enabled";
 
 static std::string GetFrontendURL()
 {
diff --git a/src/core/devtools_manager_delegate_qt.cpp b/src/core/devtools_manager_delegate_qt.cpp
index 6654ead0ec6..b584ecb0de7 100644
--- a/src/core/devtools_manager_delegate_qt.cpp
+++ b/src/core/devtools_manager_delegate_qt.cpp
@@ -20,6 +20,7 @@
 #include "net/socket/tcp_server_socket.h"
 #include "ui/base/resource/resource_bundle.h"
 
+using namespace Qt::StringLiterals;
 using content::DevToolsAgentHost;
 
 namespace {
@@ -52,7 +53,7 @@ class TCPServerSocketFactory : public content::DevToolsSocketFactory {
 namespace QtWebEngineCore {
 
 DevToolsServerQt::DevToolsServerQt()
-    : m_bindAddress(QLatin1String("127.0.0.1"))
+    : m_bindAddress(u"127.0.0.1"_s)
     , m_port(0)
     , m_valid(false)
     , m_isStarted(false)
@@ -72,7 +73,7 @@ void DevToolsServerQt::parseAddressAndPort()
     if (commandLine.HasSwitch(switches::kRemoteDebuggingPort)) {
         portStr = QString::fromStdString(commandLine.GetSwitchValueASCII(switches::kRemoteDebuggingPort));
     } else if (!inspectorEnv.isEmpty()) {
-        int portColonPos = inspectorEnv.lastIndexOf(':');
+        int portColonPos = inspectorEnv.lastIndexOf(u':');
         if (portColonPos != -1) {
             portStr = inspectorEnv.mid(portColonPos + 1);
             m_bindAddress = inspectorEnv.mid(0, portColonPos);
@@ -83,8 +84,12 @@ void DevToolsServerQt::parseAddressAndPort()
 
     m_port = portStr.toInt(&m_valid);
     m_valid = m_valid && (m_port > 0 && m_port < 65535);
-    if (!m_valid)
-        qWarning("Invalid port given for the inspector server \"%s\". Examples of valid input: \"12345\" or \"192.168.2.14:12345\" (with the address of one of this host's network interface).", qPrintable(portStr));
+    if (!m_valid) {
+        qWarning("Invalid port given for the inspector server \"%ls\". "
+                 "Examples of valid input: \"12345\" or \"192.168.2.14:12345\" "
+                 "(with the address of one of this host's network interface).",
+                 qUtf16Printable(portStr));
+    }
 }
 
 std::unique_ptr<content::DevToolsSocketFactory> DevToolsServerQt::CreateSocketFactory()
@@ -123,8 +128,9 @@ void DevToolsServerQt::stop()
 void DevToolsManagerDelegateQt::Initialized(const net::IPEndPoint *ip_address)
 {
     if (ip_address && ip_address->address().size()) {
-        QString addressAndPort = QString::fromStdString(ip_address->ToString());
-        qWarning("Remote debugging server started successfully. Try pointing a Chromium-based browser to http://%s", qPrintable(addressAndPort));
+        qWarning("Remote debugging server started successfully. "
+                 "Try pointing a Chromium-based browser to http://%s",
+                 ip_address->ToString().c_str());
     }
     else
         qWarning("Couldn't start the inspector server on bind address. In case of invalid input, try something like: \"12345\" or \"192.168.2.14:12345\" (with the address of one of this host's interface).");
diff --git a/src/core/doc/qtwebengine.qdocconf b/src/core/doc/qtwebengine.qdocconf
index 3f836244dd8..eb1e8173e18 100644
--- a/src/core/doc/qtwebengine.qdocconf
+++ b/src/core/doc/qtwebengine.qdocconf
@@ -74,6 +74,7 @@ headerdirs  += ../../core/api \
 
 sourcedirs  += ../../core/api \
                ../../core/doc \
+               ../../core/tools/webenginedriver \
                ../../webenginequick/api \
                ../../webenginequick/doc \
                ../../webenginewidgets/api \
@@ -104,5 +105,9 @@ navigation.toctitles.inclusive = false
 # \QWE macro expands to 'Qt WebEngine' without auto-linking anywhere.
 macro.QWE    = "Qt \\WebEngine"
 
+# QTBUG-134416: Ignore overwrite warnings, attribution
+# documentation generates many of these
+spurious += "Output file already exists, overwriting .*"
+
 # Enforce zero documentation warnings
 warninglimit = 2
diff --git a/src/core/doc/src/qtwebengine-features.qdoc b/src/core/doc/src/qtwebengine-features.qdoc
index 246ca7b6ad9..b62eff3e5dc 100644
--- a/src/core/doc/src/qtwebengine-features.qdoc
+++ b/src/core/doc/src/qtwebengine-features.qdoc
@@ -457,7 +457,7 @@
     WebEngineView::javaScriptDialogRequested(),
     WebEngineView::colorDialogRequested(),
     WebEngineView::fileDialogRequested(), and
-    WebEngineView::formValidationMessageRequested() signals. For an example,
+    WebEngineView::formValidationMessageRequested() signals.
 
     \section1 PDF File Viewing
 
@@ -643,6 +643,11 @@
     When the \QWE spellchecker initializes, it will try to load the
     \c bdict dictionaries and to check them for consistency.
 
+    For CMake, you can use the \l qt_add_webengine_dictionary command to convert
+    Hunspell \c .dic files into the \c .bdic binary format. The command creates
+    a \c qtwebengine_dictionaries target, which your project can use a
+    dependency.
+
     If \c QTWEBENGINE_DICTIONARIES_PATH is set, the spellchecker uses the
     dictionaries in the specified directory without looking anywere else.
     Otherwise, it uses the \e qtwebengine_dictionaries directory relative to the
@@ -711,7 +716,7 @@
     Some websites use this API to decide whether they run on a mobile device or on desktop and base their design on it.
     This can cause unwanted results on touchscreen laptops or other setups that emulate a fake touch device.
 
-    Applications can set this feature explicitly with \l {QWebEngineSettings::JSTouchEventsEnabled}.
+    Applications can set this feature explicitly with \l {QWebEngineSettings::TouchEventsApiEnabled}.
 
     Note that touch events will still be delivered to web pages even if the API is disabled.
     Dispatching touch events to web pages can be prohibited by installing an event filter object
diff --git a/src/core/doc/src/qtwebengine-index.qdoc b/src/core/doc/src/qtwebengine-index.qdoc
index b20a96dc1fe..b34931d5ce0 100644
--- a/src/core/doc/src/qtwebengine-index.qdoc
+++ b/src/core/doc/src/qtwebengine-index.qdoc
@@ -9,6 +9,10 @@
 
     \QWE provides functionality for rendering regions of dynamic web content.
 
+    \note By default, Qt WebEngine depends on the \l {Qt Positioning} and
+    \l {Qt WebChannel} optional modules, but can be built without them. Be sure to
+    install these add-ons when using the online installer.
+
     The functionality in \QWE is divided into the following modules:
 
     \annotatedlist qtwebengine-modules
@@ -23,9 +27,9 @@
         \li \l{Qt WebEngine Debugging and Profiling}
         \li \l{Deploying Qt WebEngine Applications}
         \li \l{Porting from Qt WebKit to Qt WebEngine}
+        \li \l{Qt WebEngine Security Considerations}
     \endlist
 
-
     \section1 Module Evolution
 
     \l{Changes to Qt WebEngine} lists important changes in the module API
diff --git a/src/core/doc/src/qtwebengine-platform-notes.qdoc.in b/src/core/doc/src/qtwebengine-platform-notes.qdoc.in
index b9c191c299f..320a8a4c97e 100644
--- a/src/core/doc/src/qtwebengine-platform-notes.qdoc.in
+++ b/src/core/doc/src/qtwebengine-platform-notes.qdoc.in
@@ -31,6 +31,10 @@
 
     \section2 All Platforms
 
+    \note Qt WebEngine requires a C++20-compatible compiler on all platforms, due to its
+    dependency on the Chromium project.
+    While Qt as a whole only requires C++17, Qt WebEngine is an exception.
+
     On all platforms, the following tools are required at build time:
 
     \list
@@ -89,9 +93,17 @@
     \list 1
         \li Download the qtwebengine sources.
         \li From the earlier Qt version, run
-            \c {qmake && make (&& make install)}.
+            \code
+            ../qtbase/bin/qt-configure-module .
+            cmake --build . --parallel
+            cmake --install .
+            \endcode
     \endlist
 
+    \note You may also use \c qmake with \c make and \c make install,
+    but this method is considered legacy and not recommended for
+    Qt 6 and later.
+
     \section1 Mac App Store Compatibility
 
     Applications using \QWE are not compatible with the Mac App Store, because:
diff --git a/src/core/doc/src/qtwebengine-security.qdoc b/src/core/doc/src/qtwebengine-security.qdoc
new file mode 100644
index 00000000000..3ea57ad8326
--- /dev/null
+++ b/src/core/doc/src/qtwebengine-security.qdoc
@@ -0,0 +1,68 @@
+// Copyright (C) 2025 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/*!
+    \page qtwebengine-security.html
+    \title Qt WebEngine Security Considerations
+    \ingroup security-considerations
+    \brief Overview of security topics in Qt WebEngine
+
+    This page covers security issues for Qt WebEngine users. As part of Qt,
+    Qt WebEngine follows Qt's security policies. Refer to \l{Security in Qt}
+    for policy information.
+
+    \section1 Chromium Releases and Security Fixes
+
+    Qt WebEngine tracks the release schedule of Chromium. The latest Qt
+    WebEngine version includes the security fixes released in Chromium.
+    For the precise version numbers and released fixes, visit the wiki page
+    at \l{https://wiki.qt.io/QtWebEngine/ChromiumVersions}
+    {QtWebEngine/ChromiumVersions}.
+
+    For more information about how Qt WebEngine Core implements Chromium
+    features and specific versions, read the
+    \l{Qt WebEngine Core Module} section. It is also beneficial to be familiar
+    with Chromium's
+    \l{https://www.chromium.org/Home/chromium-security/}{Security Policy}.
+
+    \section1 Security Topics for Qt WebEngine Applications
+
+    Be aware of handling untrusted data and sensitive data within your
+    application. Data such as images, user information, and system
+    information can be loaded from remote resources, from within the
+    application, or locally on the system. Take care how you process untrusted
+    data in a secure way without degrading performance and exposing sensitive
+    information. Even revealing filenames and directory paths can expose
+    sensitive data such as system information and database structure.
+
+    Qt WebEngine and Chromium have mechanisms such as the
+    \e{same-origin policy} to minimize the risk of loading from unknown sources.
+    Many websites trick users with dialogues and by mimicking popular websites.
+    With \l{Qt WebEngine}, it is possible to simply load and show trusted data
+    to end-users and lock the interface to prevent unwanted input. Your user
+    interface should be robust to handle erroneous inputs and unexpected events.
+
+    A serious security issue for web applications is
+    \e{cross-site scripting} (XSS). The attack involves executing a piece of
+    code that can trick a web application to generate malicious HTML content to
+    gain the trust of your user. For example, your application unknowingly
+    takes malicious code to generate a dialog asking for user credentials.
+    Those credentials are then sent to an external service which can lead to
+    breached accounts. Because it is your application that generates the
+    dialog, users trust the malicious action. Be careful parsing URLs and make
+    sure that nobody can misuse your user interface.
+
+    Refer to \l{Handling Untrusted Data} for additional information about risks
+    and mitigation.
+
+    \section1 Configure Qt WebEngine Settings
+
+    It is good practice to enforce \e zero-trust policies that restrict access
+    by default. Configuring your Qt WebEngine deployment can help restrict user
+    and remote execution. \l QWebEngineSettings has attributes that can disable
+    JavaScript execution, disable auto-loading of images, or other mechanisms
+    to prevent unintended usage. For example, disabling
+    \l QWebEngineSettings::LocalContentCanAccessFileUrls can create a sandbox
+    environment similar to Chrome or Firefox.
+
+*/
diff --git a/src/core/doc/src/qwebenginesettings_lgpl.qdoc b/src/core/doc/src/qwebenginesettings_lgpl.qdoc
index 0b784508ca6..1cd797ab52d 100644
--- a/src/core/doc/src/qwebenginesettings_lgpl.qdoc
+++ b/src/core/doc/src/qwebenginesettings_lgpl.qdoc
@@ -193,7 +193,7 @@
     \value PreferCSSMarginsForPrinting Turns on preferring CSS margins over the margins
            of the specified QPageLayout.
            Disabled by default. (Added in Qt 6.9)
-    \value JSTouchEventsEnabled Enables support for JavaScript touch events API,
+    \value TouchEventsApiEnabled Enables support for JavaScript touch events API,
            meaning \c ontouchstart, \c ontouchend and \c ontouchmove handlers will be present in the \c document.window object.
            Enabled by default if a touch device detected by the system and disabled otherwise. (Added in Qt 6.9)
            Note that some websites use this API to decide whether they run on a mobile device or on desktop and base their design on it.
diff --git a/src/core/download_manager_delegate_qt.cpp b/src/core/download_manager_delegate_qt.cpp
index 88c8b0039ea..1278558539d 100644
--- a/src/core/download_manager_delegate_qt.cpp
+++ b/src/core/download_manager_delegate_qt.cpp
@@ -14,6 +14,7 @@
 #include <QFileInfo>
 #include <QMimeDatabase>
 #include <QStandardPaths>
+#include <QTimer>
 
 #include "profile_adapter_client.h"
 #include "profile_adapter.h"
@@ -22,8 +23,24 @@
 #include "type_conversion.h"
 #include "web_contents_delegate_qt.h"
 
+using namespace Qt::StringLiterals;
+
 namespace QtWebEngineCore {
 
+void provideDownloadTarget(download::DownloadItem *item, download::DownloadTargetCallback *callback,
+                           const base::FilePath &target)
+{
+    download::DownloadTargetInfo target_info;
+    target_info.target_disposition = download::DownloadItem::TARGET_DISPOSITION_OVERWRITE;
+    target_info.danger_type = download::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT;
+    target_info.insecure_download_status = download::DownloadItem::VALIDATED;
+    target_info.mime_type = item->GetMimeType();
+    target_info.display_name = item->GetFileNameToReportUser();
+    target_info.target_path = target;
+    target_info.intermediate_path = target.AddExtensionASCII("download");
+    std::move(*callback).Run(std::move(target_info));
+}
+
 DownloadManagerDelegateQt::DownloadManagerDelegateQt(ProfileAdapter *profileAdapter)
     : m_profileAdapter(profileAdapter)
     , m_currentId(0)
@@ -90,6 +107,14 @@ void DownloadManagerDelegateQt::removeDownload(quint32 downloadId)
 bool DownloadManagerDelegateQt::DetermineDownloadTarget(download::DownloadItem *item,
                                                         download::DownloadTargetCallback *callback)
 {
+    // The item came back for another round of target determination; this happens for example when
+    // network error occurs. We already gave it a target path, let it use that, then it can report
+    // the reason of its failure in OnDownloadUpdated().
+    if (m_currentId >= item->GetId() && !item->GetTargetFilePath().empty()) {
+        provideDownloadTarget(item, callback, item->GetTargetFilePath());
+        return true;
+    }
+
     m_currentId = item->GetId();
 
     // Keep the forced file path if set, also as the temporary file, so the check for existence
@@ -153,10 +178,10 @@ bool DownloadManagerDelegateQt::DetermineDownloadTarget(download::DownloadItem *
     }
 
     if (suggestedFilename.isEmpty()) {
-        suggestedFilename = QStringLiteral("qwe_download");
+        suggestedFilename += "qwe_download"_L1;
         QMimeType mimeType = QMimeDatabase().mimeTypeForName(mimeTypeString);
         if (mimeType.isValid() && !mimeType.preferredSuffix().isEmpty())
-            suggestedFilename += QStringLiteral(".") + mimeType.preferredSuffix();
+            suggestedFilename += u'.' + mimeType.preferredSuffix();
     }
 
     QDir defaultDownloadDirectory(m_profileAdapter->downloadPath());
@@ -167,16 +192,14 @@ bool DownloadManagerDelegateQt::DetermineDownloadTarget(download::DownloadItem *
     item->AddObserver(this);
     QList<ProfileAdapterClient*> clients = m_profileAdapter->clients();
     if (!clients.isEmpty()) {
-        Q_ASSERT(m_currentId == item->GetId());
-
         ProfileAdapterClient::DownloadItemInfo info = {};
         info.id = item->GetId();
         info.url = toQt(item->GetURL());
         info.state = item->GetState();
         info.totalBytes = item->GetTotalBytes();
         info.receivedBytes = item->GetReceivedBytes();
-        info.mimeType = mimeTypeString;
-        info.path = suggestedFilePath;
+        info.mimeType = std::move(mimeTypeString);
+        info.path = std::move(suggestedFilePath);
         info.savePageFormat = ProfileAdapterClient::UnknownSavePageFormat;
         info.accepted = acceptedByDefault;
         info.paused = false;
@@ -185,11 +208,12 @@ bool DownloadManagerDelegateQt::DetermineDownloadTarget(download::DownloadItem *
         info.useDownloadTargetCallback = true;
         info.downloadInterruptReason = item->GetLastReason();
         info.page = adapterClient;
-        info.suggestedFileName = suggestedFilename;
+        info.suggestedFileName = std::move(suggestedFilename);
         info.startTime = item->GetStartTime().ToTimeT();
 
         m_pendingDownloads.emplace(m_currentId, std::move(*callback));
-        clients[0]->downloadRequested(info);
+        QTimer::singleShot(0, m_profileAdapter,
+                           [client = clients[0], info]() { client->downloadRequested(info); });
     } else
         cancelDownload(std::move(*callback));
 
@@ -212,23 +236,13 @@ void DownloadManagerDelegateQt::downloadTargetDetermined(quint32 downloadId, boo
 
     QFileInfo suggestedFile(path);
     if (!suggestedFile.absoluteDir().mkpath(suggestedFile.absolutePath())) {
-        qWarning() << "Creating download path failed, download cancelled:" << suggestedFile.absolutePath();
+        qWarning("Creating download path failed, download cancelled: %ls",
+                 qUtf16Printable(suggestedFile.absolutePath()));
         cancelDownload(std::move(callback));
         return;
     }
     base::FilePath targetPath(toFilePathString(suggestedFile.absoluteFilePath()));
-
-    download::DownloadTargetInfo target_info;
-    target_info.target_disposition = download::DownloadItem::TARGET_DISPOSITION_OVERWRITE;
-    target_info.danger_type = download::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT;
-    target_info.insecure_download_status = download::DownloadItem::VALIDATED;
-    target_info.mime_type = item->GetMimeType();
-    target_info.intermediate_path =
-            targetPath.AddExtension(toFilePathString("download"));
-    target_info.display_name = base::FilePath();
-    target_info.target_path = targetPath;
-    target_info.interrupt_reason = download::DOWNLOAD_INTERRUPT_REASON_NONE;
-    std::move(callback).Run(std::move(target_info));
+    provideDownloadTarget(item, &callback, targetPath);
 }
 
 void DownloadManagerDelegateQt::GetSaveDir(content::BrowserContext* browser_context,
@@ -266,8 +280,8 @@ void DownloadManagerDelegateQt::ChooseSavePath(content::WebContents *web_content
     }
 
     if (suggestedFilePath.isEmpty()) {
-        suggestedFilePath = QFileInfo(toQt(suggested_path.AsUTF8Unsafe())).completeBaseName()
-                + QStringLiteral(".mhtml");
+        suggestedFilePath +=
+                QFileInfo(toQt(suggested_path.AsUTF8Unsafe())).completeBaseName() + ".mhtml"_L1;
     } else {
         acceptedByDefault = true;
     }
@@ -290,7 +304,7 @@ void DownloadManagerDelegateQt::ChooseSavePath(content::WebContents *web_content
     info.state = download::DownloadItem::IN_PROGRESS;
     info.totalBytes = -1;
     info.receivedBytes = 0;
-    info.mimeType = QStringLiteral("application/x-mimearchive");
+    info.mimeType = u"application/x-mimearchive"_s;
     info.path = suggestedFilePath;
     info.savePageFormat = suggestedSaveFormat;
     info.accepted = acceptedByDefault;
@@ -304,7 +318,8 @@ void DownloadManagerDelegateQt::ChooseSavePath(content::WebContents *web_content
     info.startTime = QDateTime::currentMSecsSinceEpoch();
 
     m_pendingSaves.emplace(m_currentId, std::move(callback));
-    clients[0]->downloadRequested(info);
+    QTimer::singleShot(0, m_profileAdapter,
+                       [client = clients[0], info]() { client->downloadRequested(info); });
 }
 
 void DownloadManagerDelegateQt::savePathDetermined(quint32 downloadId, bool accepted,
@@ -363,9 +378,8 @@ void DownloadManagerDelegateQt::OnDownloadUpdated(download::DownloadItem *downlo
         info.suggestedFileName = toQt(download->GetSuggestedFilename());
         info.startTime = download->GetStartTime().ToTimeT();
 
-        for (ProfileAdapterClient *client : std::as_const(clients)) {
-            client->downloadUpdated(info);
-        }
+        QTimer::singleShot(0, m_profileAdapter,
+                           [client = clients[0], info]() { client->downloadUpdated(info); });
     }
 }
 
diff --git a/src/core/extensions/extension_host_delegate_qt.cpp b/src/core/extensions/extension_host_delegate_qt.cpp
index 16133a598f8..b460cd6ce91 100644
--- a/src/core/extensions/extension_host_delegate_qt.cpp
+++ b/src/core/extensions/extension_host_delegate_qt.cpp
@@ -36,8 +36,7 @@ void ExtensionHostDelegateQt::OnMainFrameCreatedForBackgroundPage(ExtensionHost
 
 content::JavaScriptDialogManager *ExtensionHostDelegateQt::GetJavaScriptDialogManager()
 {
-    Q_UNREACHABLE();
-    return nullptr;
+    Q_UNREACHABLE_RETURN(nullptr);
 }
 
 void ExtensionHostDelegateQt::CreateTab(std::unique_ptr<content::WebContents> web_contents,
@@ -95,16 +94,14 @@ bool ExtensionHostDelegateQt::CheckMediaAccessPermission(
     Q_UNUSED(type);
     Q_UNUSED(extension);
 
-    Q_UNREACHABLE();
-    return false;
+    Q_UNREACHABLE_RETURN(false);
 }
 
 content::PictureInPictureResult ExtensionHostDelegateQt::EnterPictureInPicture(content::WebContents *web_contents)
 {
     Q_UNUSED(web_contents);
 
-    Q_UNREACHABLE();
-    return content::PictureInPictureResult::kNotSupported;
+    Q_UNREACHABLE_RETURN(content::PictureInPictureResult::kNotSupported);
 }
 
 void ExtensionHostDelegateQt::ExitPictureInPicture()
diff --git a/src/core/extensions/extension_system_qt.cpp b/src/core/extensions/extension_system_qt.cpp
index 78c6bb4855d..b14239e9dc4 100644
--- a/src/core/extensions/extension_system_qt.cpp
+++ b/src/core/extensions/extension_system_qt.cpp
@@ -31,7 +31,6 @@
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
-#include "content/public/browser/notification_service.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/url_data_source.h"
 #include "content/public/common/webplugininfo.h"
@@ -69,7 +68,7 @@ namespace extensions {
 namespace {
 
 // Implementation based on ComponentLoader::ParseManifest.
-std::optional<base::Value::Dict> ParseManifest(base::StringPiece manifest_contents)
+std::optional<base::Value::Dict> ParseManifest(std::string_view manifest_contents)
 {
     JSONStringValueDeserializer deserializer(manifest_contents);
     std::unique_ptr<base::Value> manifest = deserializer.Deserialize(nullptr, nullptr);
diff --git a/src/core/extensions/extensions_browser_client_qt.cpp b/src/core/extensions/extensions_browser_client_qt.cpp
index 155f9396376..bd95524f367 100644
--- a/src/core/extensions/extensions_browser_client_qt.cpp
+++ b/src/core/extensions/extensions_browser_client_qt.cpp
@@ -61,7 +61,7 @@ void DetermineCharset(const std::string &mime_type,
     if (base::StartsWith(mime_type, "text/", base::CompareCase::INSENSITIVE_ASCII)) {
         // All of our HTML files should be UTF-8 and for other resource types
         // (like images), charset doesn't matter.
-        DCHECK(base::IsStringUTF8(base::StringPiece(reinterpret_cast<const char *>(data->front()), data->size())));
+        DCHECK(base::IsStringUTF8(std::string_view(reinterpret_cast<const char *>(data->front()), data->size())));
         *out_charset = "utf-8";
     }
 }
@@ -76,7 +76,7 @@ scoped_refptr<base::RefCountedMemory> GetResource(int resource_id, const std::st
             : nullptr;
 
     if (replacements) {
-        base::StringPiece input(reinterpret_cast<const char *>(bytes->front()), bytes->size());
+        std::string_view input(reinterpret_cast<const char *>(bytes->front()), bytes->size());
         std::string temp_str = ui::ReplaceTemplateExpressions(input, *replacements);
         DCHECK(!temp_str.empty());
         return base::MakeRefCounted<base::RefCountedString>(std::move(temp_str));
@@ -169,7 +169,7 @@ class ResourceBundleFileLoader : public network::mojom::URLLoader
         client_->OnReceiveResponse(std::move(head), std::move(consumer_handle), std::nullopt);
 
         size_t write_size = data->size();
-        MojoResult result = producer_handle->WriteData(data->front(), &write_size, MOJO_WRITE_DATA_FLAG_NONE);
+        MojoResult result = producer_handle->WriteData((base::span<const uint8_t>)(*data), MOJO_WRITE_DATA_FLAG_NONE, write_size);
         OnFileWritten(result);
     }
 
@@ -383,7 +383,8 @@ bool ExtensionsBrowserClientQt::AllowCrossRendererResourceLoad(const network::Re
                                                                bool is_incognito,
                                                                const Extension *extension,
                                                                const ExtensionSet &extensions,
-                                                               const ProcessMap &process_map)
+                                                               const ProcessMap &process_map,
+                                                               const GURL& upstream_url)
 {
     if (extension && extension->id() == extension_misc::kPdfExtensionId)
         return true;
@@ -396,7 +397,7 @@ bool ExtensionsBrowserClientQt::AllowCrossRendererResourceLoad(const network::Re
     if (url_request_util::AllowCrossRendererResourceLoad(request, destination,
                                                          page_transition, child_id,
                                                          is_incognito, extension, extensions,
-                                                         process_map, &allowed)) {
+                                                         process_map, upstream_url, &allowed)) {
         return allowed;
     }
     // Couldn't determine if resource is allowed. Block the load.
@@ -517,11 +518,18 @@ bool ExtensionsBrowserClientQt::IsInDemoMode()
     return false;
 }
 
-ExtensionWebContentsObserver *ExtensionsBrowserClientQt::GetExtensionWebContentsObserver(content::WebContents *web_contents)
+extensions::ExtensionWebContentsObserver *
+ExtensionsBrowserClientQt::GetExtensionWebContentsObserver(content::WebContents *web_contents)
 {
     return ExtensionWebContentsObserverQt::FromWebContents(web_contents);
 }
 
+void ExtensionsBrowserClientQt::CreateExtensionWebContentsObserver(
+        content::WebContents *web_contents)
+{
+    ExtensionWebContentsObserverQt::CreateForWebContents(web_contents);
+}
+
 KioskDelegate *ExtensionsBrowserClientQt::GetKioskDelegate()
 {
     return nullptr;
@@ -543,8 +551,9 @@ media_device_salt::MediaDeviceSaltService *ExtensionsBrowserClientQt::GetMediaDe
     return nullptr;
 }
 mojo::PendingRemote<network::mojom::URLLoaderFactory>
-ExtensionsBrowserClientQt::GetControlledFrameEmbedderURLLoader(const url::Origin &,
-        int frame_tree_node_id, content::BrowserContext *browser_context)
+ExtensionsBrowserClientQt::GetControlledFrameEmbedderURLLoader(
+        const url::Origin &, content::FrameTreeNodeId frame_tree_node_id,
+        content::BrowserContext *browser_context)
 {
     return mojo::PendingRemote<network::mojom::URLLoaderFactory>();
 }
diff --git a/src/core/extensions/extensions_browser_client_qt.h b/src/core/extensions/extensions_browser_client_qt.h
index 8ce0b0dd5e9..d0ffb4b9760 100644
--- a/src/core/extensions/extensions_browser_client_qt.h
+++ b/src/core/extensions/extensions_browser_client_qt.h
@@ -48,7 +48,8 @@ class ExtensionsBrowserClientQt : public ExtensionsBrowserClient
                                         bool is_incognito,
                                         const Extension *extension,
                                         const ExtensionSet &extensions,
-                                        const ProcessMap &process_map) override;
+                                        const ProcessMap &process_map,
+                                        const GURL& upstream_url) override;
 
     PrefService *GetPrefServiceForContext(content::BrowserContext *context) override;
     void GetEarlyExtensionPrefsObservers(content::BrowserContext *context,
@@ -109,9 +110,12 @@ class ExtensionsBrowserClientQt : public ExtensionsBrowserClient
     media_device_salt::MediaDeviceSaltService *GetMediaDeviceSaltService(content::BrowserContext *context) override;
 
     mojo::PendingRemote<network::mojom::URLLoaderFactory>
-    GetControlledFrameEmbedderURLLoader(const url::Origin &, int frame_tree_node_id,
+    GetControlledFrameEmbedderURLLoader(const url::Origin &,
+                                        content::FrameTreeNodeId frame_tree_node_id,
                                         content::BrowserContext *browser_context) override;
 
+    void CreateExtensionWebContentsObserver(content::WebContents *) override;
+
 private:
     // Support for extension APIs.
     std::unique_ptr<ExtensionsAPIClient> api_client_;
diff --git a/src/core/extensions/file_system_delegate_qt.cpp b/src/core/extensions/file_system_delegate_qt.cpp
index 6c5b3391913..b19ebf92b23 100644
--- a/src/core/extensions/file_system_delegate_qt.cpp
+++ b/src/core/extensions/file_system_delegate_qt.cpp
@@ -36,20 +36,18 @@ FileEntryPickerQt::FileEntryPickerQt(
         this, std::make_unique<QtWebEngineCore::SelectFilePolicyQt>(web_contents));
     m_selectFileDialog->SelectFile(
         picker_type, std::u16string(), suggested_name, file_type_info, 0,
-        base::FilePath::StringType(), nullptr, nullptr, &caller);
+        base::FilePath::StringType(), nullptr, &caller);
 }
 
 FileEntryPickerQt::~FileEntryPickerQt() = default;
 
-void FileEntryPickerQt::FileSelected(const ui::SelectedFileInfo &file, int index, void *params)
+void FileEntryPickerQt::FileSelected(const ui::SelectedFileInfo &file, int index)
 {
-    MultiFilesSelected({ file }, params);
+    MultiFilesSelected({ file });
 }
 
-void FileEntryPickerQt::MultiFilesSelected(const std::vector<ui::SelectedFileInfo> &files,
-                                           void *params)
+void FileEntryPickerQt::MultiFilesSelected(const std::vector<ui::SelectedFileInfo> &files)
 {
-    Q_UNUSED(params);
     std::vector<base::FilePath> paths;
     for (const auto &file : files) {
         paths.push_back(file.file_path);
@@ -58,7 +56,7 @@ void FileEntryPickerQt::MultiFilesSelected(const std::vector<ui::SelectedFileInf
     delete this;
 }
 
-void FileEntryPickerQt::FileSelectionCanceled(void *params)
+void FileEntryPickerQt::FileSelectionCanceled()
 {
     std::move(m_fileSelectionCanceledCallback).Run();
     delete this;
diff --git a/src/core/extensions/file_system_delegate_qt.h b/src/core/extensions/file_system_delegate_qt.h
index 01b56fa569d..603c5436438 100644
--- a/src/core/extensions/file_system_delegate_qt.h
+++ b/src/core/extensions/file_system_delegate_qt.h
@@ -42,9 +42,9 @@ class FileEntryPickerQt : public ui::SelectFileDialog::Listener {
     ~FileEntryPickerQt() override;
 
     // ui::SelectFileDialog::Listener implementation.
-    void FileSelected(const ui::SelectedFileInfo &file, int index, void *params) override;
-    void MultiFilesSelected(const std::vector<ui::SelectedFileInfo> &files, void *params) override;
-    void FileSelectionCanceled(void *params) override;
+    void FileSelected(const ui::SelectedFileInfo &file, int index) override;
+    void MultiFilesSelected(const std::vector<ui::SelectedFileInfo> &files) override;
+    void FileSelectionCanceled() override;
 
     FileSystemDelegate::FilesSelectedCallback m_filesSelectedCallback;
     base::OnceClosure m_fileSelectionCanceledCallback;
diff --git a/src/core/favicon_driver_qt.cpp b/src/core/favicon_driver_qt.cpp
index b454ca90604..8b6c8bc3191 100644
--- a/src/core/favicon_driver_qt.cpp
+++ b/src/core/favicon_driver_qt.cpp
@@ -169,9 +169,11 @@ FaviconDriverQt::NavigationManifestData::NavigationManifestData(
 FaviconDriverQt::NavigationManifestData::~NavigationManifestData() = default;
 
 void FaviconDriverQt::OnDidDownloadManifest(ManifestDownloadCallback callback,
+                                            blink::mojom::ManifestRequestResult result,
                                             const GURL &manifest_url,
                                             blink::mojom::ManifestPtr manifest)
 {
+    Q_UNUSED(result);
     Q_UNUSED(manifest_url);
 
     // ~WebContentsImpl triggers running any pending callbacks for manifests.
diff --git a/src/core/favicon_driver_qt.h b/src/core/favicon_driver_qt.h
index a6307ea476d..1aaf0941fed 100644
--- a/src/core/favicon_driver_qt.h
+++ b/src/core/favicon_driver_qt.h
@@ -96,7 +96,9 @@ class FaviconDriverQt : public favicon::FaviconDriver,
     };
 
     // Callback when a manifest is downloaded.
-    void OnDidDownloadManifest(ManifestDownloadCallback callback, const GURL &manifest_url,
+    void OnDidDownloadManifest(ManifestDownloadCallback callback,
+                               blink::mojom::ManifestRequestResult result,
+                               const GURL &manifest_url,
                                blink::mojom::ManifestPtr manifest);
 
     // FaviconHandler::Delegate implementation.
diff --git a/src/core/file_picker_controller.cpp b/src/core/file_picker_controller.cpp
index fb124df7bb8..550ae0da026 100644
--- a/src/core/file_picker_controller.cpp
+++ b/src/core/file_picker_controller.cpp
@@ -18,6 +18,8 @@
 #include <QStringList>
 #include <QVariant>
 
+using namespace Qt::StringLiterals;
+
 namespace QtWebEngineCore {
 
 class FilePickerControllerPrivate {
@@ -75,7 +77,7 @@ void FilePickerController::accepted(const QStringList &files)
             continue;
         }
 
-        if (urlString.startsWith("file:")) {
+        if (urlString.startsWith("file:"_L1)) {
             base::FilePath filePath = toFilePath(urlString).NormalizePathSeparators();
             std::vector<base::FilePath::StringType> pathComponents;
             // Splits the file URL into scheme, host name, path and file name.
@@ -83,18 +85,20 @@ void FilePickerController::accepted(const QStringList &files)
 
             QString absolutePath;
 #if !defined(Q_OS_WIN)
-            absolutePath = "/";
+            absolutePath += u'/';
 #endif
 
             QString scheme = toQt(pathComponents[0]);
             if (scheme.size() > 5) {
 #if defined(Q_OS_WIN)
                 // There is no slash at the end of the file scheme and it is valid on Windows: file:C:/
-                if (scheme.size() == 7 && scheme.at(5).isLetter() && scheme.at(6) == ':') {
-                    absolutePath += scheme.at(5) + ":/";
+                if (scheme.size() == 7 && scheme.at(5).isLetter() && scheme.at(6) == u':') {
+                    absolutePath += scheme.at(5) + ":/"_L1;
                 } else {
 #endif
-                    qWarning("Ignoring invalid item in FilePickerController::accepted(QStringList): %s", qPrintable(urlString));
+                    qWarning("Ignoring invalid item in "
+                             "FilePickerController::accepted(QStringList): %ls",
+                             qUtf16Printable(urlString));
                     continue;
 #if defined(Q_OS_WIN)
                 }
@@ -106,28 +110,34 @@ void FilePickerController::accepted(const QStringList &files)
                 && base::FilePath::IsSeparator(urlString.at(6).toLatin1())
                 && !base::FilePath::IsSeparator(urlString.at(7).toLatin1())) {
 #if defined(Q_OS_WIN)
-                if (urlString.at(8) != ':' && pathComponents.size() > 2) {
-                    absolutePath += "//";
+                if (urlString.at(8) != u':' && pathComponents.size() > 2) {
+                    absolutePath += "//"_L1;
 #else
                 if (pathComponents.size() > 2) {
-                    absolutePath += "/";
+                    absolutePath += u'/';
 #endif
                 } else {
-                    qWarning("Ignoring invalid item in FilePickerController::accepted(QStringList): %s", qPrintable(urlString));
+                    qWarning("Ignoring invalid item in "
+                             "FilePickerController::accepted(QStringList): %ls",
+                             qUtf16Printable(urlString));
                     continue;
                 }
             }
 
-            // Build absolute path from file URI componenets.
-            for (size_t j = 1; j < pathComponents.size(); j++)
-                absolutePath += toQt(pathComponents[j]) + (j != pathComponents.size()-1 ? "/" : "");
+            // Build absolute path from file URI components.
+            for (size_t j = 1; j < pathComponents.size(); j++) {
+                absolutePath += toQt(pathComponents[j]);
+                if (j != pathComponents.size() - 1)
+                    absolutePath += u'/';
+            }
 
             if (toFilePath(absolutePath).IsAbsolute()) {
                 stringList.append(absolutePath);
                 continue;
             }
         }
-        qWarning("Ignoring invalid item in FilePickerController::accepted(QStringList): %s", qPrintable(urlString));
+        qWarning("Ignoring invalid item in FilePickerController::accepted(QStringList): %ls",
+                 qUtf16Printable(urlString));
     }
 
     FilePickerController::filesSelectedInChooser(stringList);
@@ -161,7 +171,7 @@ static QStringList listRecursively(const QDir &dir)
     const QFileInfoList infoList(dir.entryInfoList(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot | QDir::Hidden));
     for (const QFileInfo &fileInfo : infoList) {
         if (fileInfo.isDir()) {
-            ret.append(fileInfo.absolutePath() + QStringLiteral("/.")); // Match chromium's behavior. See chrome/browser/file_select_helper.cc
+            ret.append(fileInfo.absolutePath() + "/."_L1); // Match chromium's behavior. See chrome/browser/file_select_helper.cc
             ret.append(listRecursively(QDir(fileInfo.absoluteFilePath())));
         } else
             ret.append(fileInfo.absoluteFilePath());
@@ -213,13 +223,13 @@ void FilePickerController::filesSelectedInChooser(const QStringList &filesList)
         }
 
         if (files.empty())
-            d_ptr->fileSystemAccessDialogListener->FileSelectionCanceled(nullptr);
+            d_ptr->fileSystemAccessDialogListener->FileSelectionCanceled();
         else if (files.size() == 1)
             d_ptr->fileSystemAccessDialogListener->FileSelected(
-                    ui::SelectedFileInfo(files[0]), 0, nullptr);
+                    ui::SelectedFileInfo(files[0]), 0);
         else
             d_ptr->fileSystemAccessDialogListener->MultiFilesSelected(
-                    ui::FilePathListToSelectedFileInfoList(files), nullptr);
+                    ui::FilePathListToSelectedFileInfoList(files));
     }
 }
 
@@ -248,34 +258,34 @@ QStringList FilePickerController::nameFilters(const QStringList &acceptedMimeTyp
         return nameFilters;
 
     for (QString type : acceptedMimeTypes) {
-        if (type.startsWith(".")) {
+        if (type.startsWith(u'.')) {
             // A single suffix
             // Filename.type doesn't have to exist and mimeTypeForFile() supports
             // custom suffixes as valid (but unknown) MIME types.
-            const QMimeType &mimeType = mimeDatabase.mimeTypeForFile("filename" + type);
+            const QMimeType &mimeType = mimeDatabase.mimeTypeForFile("filename"_L1 + type);
             if (mimeType.isValid()) {
-                QString glob = "*" + type;
-                acceptedGlobs.append(glob);
-                nameFilters.append(mimeType.comment() + " (" + glob + ")");
+                QString glob = u'*' + type;
+                nameFilters.append(mimeType.comment() + " ("_L1 + glob + u')');
+                acceptedGlobs.append(std::move(glob));
             }
-        } else if (type.contains("/") && !type.endsWith("*")) {
+        } else if (type.contains(u'/') && !type.endsWith(u'*')) {
             // All suffixes for a given MIME type
             const QMimeType &mimeType = mimeDatabase.mimeTypeForName(type);
             if (mimeType.isValid() && !mimeType.globPatterns().isEmpty()) {
-                QString globs = mimeType.globPatterns().join(" ");
+                QString globs = mimeType.globPatterns().join(u' ');
+                nameFilters.append(mimeType.comment() + " ("_L1 + globs + u')');
                 acceptedGlobs.append(mimeType.globPatterns());
-                nameFilters.append(mimeType.comment() + " (" + globs + ")");
             }
-        } else if (type.endsWith("/*")) {
+        } else if (type.endsWith("/*"_L1)) {
             // All MIME types for audio/*, image/* or video/*
             // as separate filters as Chrome does
             static const QList<QMimeType> &allMimeTypes = mimeDatabase.allMimeTypes();
-            type = type.remove("/*");
+            type.chop(2);
             for (const QMimeType &m : allMimeTypes) {
                 if (m.name().startsWith(type) && !m.globPatterns().isEmpty()) {
-                    QString globs = m.globPatterns().join(" ");
+                    QString globs = m.globPatterns().join(u' ');
+                    nameFilters.append(m.comment() + " ("_L1 + globs + u')');
                     acceptedGlobs.append(m.globPatterns());
-                    nameFilters.append(m.comment() + " (" + globs + ")");
                 }
             }
         } else {
@@ -285,7 +295,7 @@ QStringList FilePickerController::nameFilters(const QStringList &acceptedMimeTyp
 
     const QString filter =
         QCoreApplication::translate("FilePickerController",
-                                    "Accepted types (%1)").arg(acceptedGlobs.join(' '));
+                                    "Accepted types (%1)").arg(acceptedGlobs.join(u' '));
     nameFilters.prepend(filter);
 
     return nameFilters;
diff --git a/src/core/file_system_access/file_system_access_permission_context_factory_qt.cpp b/src/core/file_system_access/file_system_access_permission_context_factory_qt.cpp
index 51c8a899191..6d1e8084afc 100644
--- a/src/core/file_system_access/file_system_access_permission_context_factory_qt.cpp
+++ b/src/core/file_system_access/file_system_access_permission_context_factory_qt.cpp
@@ -52,10 +52,4 @@ KeyedService *FileSystemAccessPermissionContextFactoryQt::BuildServiceInstanceFo
     return new FileSystemAccessPermissionContextQt(context);
 }
 
-void FileSystemAccessPermissionContextFactoryQt::BrowserContextShutdown(
-        content::BrowserContext *context)
-{
-    Q_UNUSED(context);
-}
-
 } // namespace QtWebEngineCore
diff --git a/src/core/file_system_access/file_system_access_permission_context_factory_qt.h b/src/core/file_system_access/file_system_access_permission_context_factory_qt.h
index 1d98243d6e3..8589a37132d 100644
--- a/src/core/file_system_access/file_system_access_permission_context_factory_qt.h
+++ b/src/core/file_system_access/file_system_access_permission_context_factory_qt.h
@@ -29,7 +29,6 @@ class FileSystemAccessPermissionContextFactoryQt : public BrowserContextKeyedSer
     content::BrowserContext *
     GetBrowserContextToUse(content::BrowserContext *context) const override;
     KeyedService *BuildServiceInstanceFor(content::BrowserContext *profile) const override;
-    void BrowserContextShutdown(content::BrowserContext *context) override;
 };
 
 } // namespace QtWebEngineCore
diff --git a/src/core/file_system_access/file_system_access_permission_grant_qt.cpp b/src/core/file_system_access/file_system_access_permission_grant_qt.cpp
index 67fa1c8cfbb..dc26a415ee8 100644
--- a/src/core/file_system_access/file_system_access_permission_grant_qt.cpp
+++ b/src/core/file_system_access/file_system_access_permission_grant_qt.cpp
@@ -3,6 +3,11 @@
 
 #include "file_system_access_permission_grant_qt.h"
 
+// based on chrome_file_system_access_permission_context.cc:
+// Copyright 2019 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
 #include "file_system_access_permission_request_manager_qt.h"
 
 #include "components/permissions/permission_util.h"
@@ -93,7 +98,8 @@ void FileSystemAccessPermissionGrantQt::RequestPermission(
     }
 
     // Drop fullscreen mode so that the user sees the URL bar.
-    base::ScopedClosureRunner fullscreen_block = web_contents->ForSecurityDropFullscreen();
+    base::ScopedClosureRunner fullscreen_block =
+            web_contents->ForSecurityDropFullscreen(display::kInvalidDisplayId);
 
     FileSystemAccessPermissionRequestManagerQt::Access access = m_type == GrantType::kRead
             ? FileSystemAccessPermissionRequestManagerQt::Access::kRead
diff --git a/src/core/media_capture_devices_dispatcher.cpp b/src/core/media_capture_devices_dispatcher.cpp
index 728d6d04a4c..56df02412bd 100644
--- a/src/core/media_capture_devices_dispatcher.cpp
+++ b/src/core/media_capture_devices_dispatcher.cpp
@@ -126,7 +126,7 @@ std::optional<int> GetZoomLevel(content::WebContents *capturer,
     }
 
     double zoom_level =
-            blink::PageZoomLevelToZoomFactor(content::HostZoomMap::GetZoomLevel(captured_wc));
+            blink::ZoomLevelToZoomFactor(content::HostZoomMap::GetZoomLevel(captured_wc));
     return std::round(100 * zoom_level);
 }
 
@@ -366,8 +366,12 @@ void MediaCaptureDevicesDispatcher::handleMediaAccessPermissionResponse(content:
     bool securityOriginsMatch = (requestSecurityOrigin.host() == securityOrigin.host()
                                  && requestSecurityOrigin.scheme() == securityOrigin.scheme()
                                  && requestSecurityOrigin.port() == securityOrigin.port());
-    if (!securityOriginsMatch)
-        qWarning("Security origin mismatch for media access permission: %s requested and %s provided\n", qPrintable(requestSecurityOrigin.toString()), qPrintable(securityOrigin.toString()));
+    if (!securityOriginsMatch) {
+        qWarning("Security origin mismatch for media access permission: %ls requested "
+                 "and %ls provided\n",
+                 qUtf16Printable(requestSecurityOrigin.toString()),
+                 qUtf16Printable(securityOrigin.toString()));
+    }
 
     WebContentsAdapterClient::MediaRequestFlags requestFlags = mediaRequestFlagsForRequest(request);
     WebContentsAdapterClient::MediaRequestFlags finalFlags = requestFlags & authorizationFlags;
diff --git a/src/core/native_web_keyboard_event_qt.cpp b/src/core/native_web_keyboard_event_qt.cpp
index 9a5576fbbd8..23ce3c91124 100644
--- a/src/core/native_web_keyboard_event_qt.cpp
+++ b/src/core/native_web_keyboard_event_qt.cpp
@@ -10,6 +10,8 @@
 #if !defined(Q_OS_MACOS)
 #include "native_web_keyboard_event_qt.h"
 
+#include "components/input/native_web_keyboard_event.h"
+
 #include <QtGui/QKeyEvent>
 
 namespace QtWebEngineCore {
@@ -45,7 +47,7 @@ void DestroyEvent(gfx::NativeEvent nativeEvent)
 } // namespace
 
 
-namespace content {
+namespace input {
 
 NativeWebKeyboardEvent::NativeWebKeyboardEvent(const blink::WebKeyboardEvent &web_event, gfx::NativeView)
     : blink::WebKeyboardEvent(web_event)
@@ -90,5 +92,5 @@ NativeWebKeyboardEvent::~NativeWebKeyboardEvent() {
     DestroyEvent(os_event);
 }
 
-}  // namespace content
+}  // namespace input
 #endif // !defined(Q_OS_MACOS)
diff --git a/src/core/native_web_keyboard_event_qt.h b/src/core/native_web_keyboard_event_qt.h
index 13179d07a82..7bcb65da92e 100644
--- a/src/core/native_web_keyboard_event_qt.h
+++ b/src/core/native_web_keyboard_event_qt.h
@@ -6,7 +6,8 @@
 
 #include <QtCore/qglobal.h>
 
-#include "content/public/common/input/native_web_keyboard_event.h"
+#include "ui/gfx/native_widget_types.h"
+#include "components/input/native_web_keyboard_event.h"
 
 QT_FORWARD_DECLARE_CLASS(QKeyEvent)
 
diff --git a/src/core/native_web_keyboard_event_qt_mac.mm b/src/core/native_web_keyboard_event_qt_mac.mm
index 0f5b12db43d..b16ab2e2240 100644
--- a/src/core/native_web_keyboard_event_qt_mac.mm
+++ b/src/core/native_web_keyboard_event_qt_mac.mm
@@ -33,8 +33,7 @@
         type = NSEventTypeKeyUp;
         break;
     default:
-        Q_UNREACHABLE();
-        return base::apple::OwnedNSEvent();
+        Q_UNREACHABLE_RETURN(base::apple::OwnedNSEvent());
     }
 
     NSString *text = keyEvent->text().toNSString();
@@ -72,8 +71,7 @@
         type = QEvent::KeyRelease;
         break;
     default:
-        Q_UNREACHABLE();
-        return nullptr;
+        Q_UNREACHABLE_RETURN(nullptr);
     }
 
     // Scan codes are hardware dependent codes for each key. There is no way to get these
@@ -103,7 +101,7 @@
         key = QAppleKeyMapper::fromCocoaKey(character);
     }
 
-    QString text = QString::fromNSString(characters);
+    const QString text = QString::fromNSString(characters);
     bool autorep = nsevent.ARepeat;
 
     return new QKeyEvent(type, key, modifiers, nativeScanCode, nativeVirtualKey, nativeModifiers,
@@ -112,7 +110,7 @@
 
 } // namespace QtWebEngineCore
 
-namespace content {
+namespace input {
 
 NativeWebKeyboardEvent::NativeWebKeyboardEvent(const blink::WebKeyboardEvent &web_event, gfx::NativeView)
     : blink::WebKeyboardEvent(web_event)
@@ -152,4 +150,4 @@
 
 NativeWebKeyboardEvent::~NativeWebKeyboardEvent() = default;
 
-}  // namespace content
+}  // namespace input
diff --git a/src/core/net/client_cert_store_data.cpp b/src/core/net/client_cert_store_data.cpp
index 0de6885df85..5f9c8243af9 100644
--- a/src/core/net/client_cert_store_data.cpp
+++ b/src/core/net/client_cert_store_data.cpp
@@ -92,8 +92,8 @@ namespace QtWebEngineCore {
 
 void ClientCertificateStoreData::add(const QSslCertificate &certificate, const QSslKey &privateKey)
 {
-    QByteArray sslKeyInBytes = privateKey.toPem();
-    QByteArray certInBytes = certificate.toDer();
+    const QByteArray sslKeyInBytes = privateKey.toPem();
+    const QByteArray certInBytes = certificate.toDer();
 
     Entry *data = new Entry;
     data->keyPtr = wrapOpenSSLPrivateKey(sslKeyInBytes);
diff --git a/src/core/net/cookie_monster_delegate_qt.cpp b/src/core/net/cookie_monster_delegate_qt.cpp
index cdbf2e8e873..687a02955d9 100644
--- a/src/core/net/cookie_monster_delegate_qt.cpp
+++ b/src/core/net/cookie_monster_delegate_qt.cpp
@@ -50,7 +50,7 @@ class CookieAccessFilter : public network::mojom::CookieRemoteAccessFilter
 
 static GURL sourceUrlForCookie(const QNetworkCookie &cookie)
 {
-    QString urlFragment = QStringLiteral("%1%2").arg(cookie.domain()).arg(cookie.path());
+    const QString urlFragment = cookie.domain() % cookie.path();
     return net::cookie_util::CookieOriginToURL(urlFragment.toStdString(), /* is_https */ cookie.isSecure());
 }
 
@@ -98,7 +98,7 @@ void CookieMonsterDelegateQt::setCookie(const QNetworkCookie &cookie, const QUrl
 
     net::CookieInclusionStatus inclusion;
     auto canonCookie = net::CanonicalCookie::Create(gurl, cookie_line, base::Time::Now(),
-                                                    std::nullopt, std::nullopt, true,
+                                                    std::nullopt, std::nullopt,
                                                     net::CookieSourceType::kOther, &inclusion);
     if (!canonCookie || !inclusion.IsInclude()) {
         LOG(WARNING) << "QWebEngineCookieStore::setCookie() - Tried to set invalid cookie";
diff --git a/src/core/net/custom_url_loader_factory.cpp b/src/core/net/custom_url_loader_factory.cpp
index edc103bceeb..eec3c5f7e1b 100644
--- a/src/core/net/custom_url_loader_factory.cpp
+++ b/src/core/net/custom_url_loader_factory.cpp
@@ -267,9 +267,8 @@ class CustomURLLoader : public network::mojom::URLLoader
             }
         }
         if (m_corsEnabled) {
-            std::string origin;
-            if (m_request.headers.GetHeader("Origin", &origin)) {
-                headers += base::StringPrintf("Access-Control-Allow-Origin: %s\n", origin.c_str());
+            if (std::optional<std::string> origin = m_request.headers.GetHeader("Origin")) {
+                headers += base::StringPrintf("Access-Control-Allow-Origin: %s\n", origin->c_str());
                 headers += "Access-Control-Allow-Credentials: true\n";
             }
         }
@@ -385,20 +384,21 @@ class CustomURLLoader : public network::mojom::URLLoader
             if (m_error || !m_device)
                 break;
 
-            void *buffer = nullptr;
-            size_t bufferSize = 0;
-            MojoResult beginResult = m_pipeProducerHandle->BeginWriteData(
-                    &buffer, &bufferSize, MOJO_BEGIN_WRITE_DATA_FLAG_NONE);
+            base::span<uint8_t> buffer;
+            MojoResult beginResult =
+                    m_pipeProducerHandle->BeginWriteData(
+                        0, MOJO_BEGIN_WRITE_DATA_FLAG_NONE, buffer);
             if (beginResult == MOJO_RESULT_SHOULD_WAIT) {
                 m_watcher->ArmOrNotify();
                 return false; // Wait for pipe watcher
             }
             if (beginResult != MOJO_RESULT_OK)
                 break;
+            size_t bufferSize = buffer.size();
             if (m_maxBytesToRead > 0 && m_maxBytesToRead <= int64_t{std::numeric_limits<uint32_t>::max()})
                 bufferSize = std::min(bufferSize, size_t(m_maxBytesToRead));
 
-            int readResult = m_device->read(static_cast<char *>(buffer), bufferSize);
+            int readResult = m_device->read(reinterpret_cast<char *>(buffer.data()), bufferSize);
             uint32_t bytesRead = std::max(readResult, 0);
             m_pipeProducerHandle->EndWriteData(bytesRead);
             m_totalBytesRead += bytesRead;
@@ -427,10 +427,9 @@ class CustomURLLoader : public network::mojom::URLLoader
     }
     bool ParseRange(const net::HttpRequestHeaders &headers)
     {
-        std::string range_header;
-        if (headers.GetHeader(net::HttpRequestHeaders::kRange, &range_header)) {
+        if (auto range_header = headers.GetHeader(net::HttpRequestHeaders::kRange)) {
             std::vector<net::HttpByteRange> ranges;
-            if (net::HttpUtil::ParseRangeHeader(range_header, &ranges)) {
+            if (net::HttpUtil::ParseRangeHeader(*range_header, &ranges)) {
                 // Chromium doesn't support multirange requests.
                 if (ranges.size() == 1) {
                     m_byteRange = ranges[0];
diff --git a/src/core/net/plugin_response_interceptor_url_loader_throttle.cpp b/src/core/net/plugin_response_interceptor_url_loader_throttle.cpp
index 3af8bf9e35f..bd2714dcb5b 100644
--- a/src/core/net/plugin_response_interceptor_url_loader_throttle.cpp
+++ b/src/core/net/plugin_response_interceptor_url_loader_throttle.cpp
@@ -80,7 +80,7 @@ namespace QtWebEngineCore {
 
 PluginResponseInterceptorURLLoaderThrottle::PluginResponseInterceptorURLLoaderThrottle(
         network::mojom::RequestDestination request_destination,
-        int frame_tree_node_id)
+        content::FrameTreeNodeId frame_tree_node_id)
     : m_request_destination(request_destination), m_frame_tree_node_id(frame_tree_node_id)
 {}
 
@@ -150,7 +150,8 @@ void PluginResponseInterceptorURLLoaderThrottle::WillProcessResponse(const GURL
     size_t len = payload.size();
     CHECK_EQ(MOJO_RESULT_OK,
                 producer_handle->WriteData(
-                    payload.c_str(), &len, MOJO_WRITE_DATA_FLAG_ALL_OR_NONE));
+                     base::make_span(reinterpret_cast<const uint8_t*>(payload.data()), len),
+                     MOJO_WRITE_DATA_FLAG_ALL_OR_NONE, len));
 
     network::URLLoaderCompletionStatus status(net::OK);
     status.decoded_body_length = len;
diff --git a/src/core/net/plugin_response_interceptor_url_loader_throttle.h b/src/core/net/plugin_response_interceptor_url_loader_throttle.h
index fb3918c45e3..dd47e2a4822 100644
--- a/src/core/net/plugin_response_interceptor_url_loader_throttle.h
+++ b/src/core/net/plugin_response_interceptor_url_loader_throttle.h
@@ -5,6 +5,7 @@
 #define PLUGIN_RESPONSE_INTERCEPTOR_URL_LOADER_THROTTLE_H_
 
 #include "base/memory/weak_ptr.h"
+#include "content/public/browser/frame_tree_node_id.h"
 #include "services/network/public/mojom/fetch_api.mojom-shared.h"
 #include "third_party/blink/public/common/loader/url_loader_throttle.h"
 
@@ -17,8 +18,9 @@ namespace QtWebEngineCore {
 class PluginResponseInterceptorURLLoaderThrottle : public blink::URLLoaderThrottle
 {
 public:
-    PluginResponseInterceptorURLLoaderThrottle(network::mojom::RequestDestination request_destination,
-                                               int frame_tree_node_id);
+    PluginResponseInterceptorURLLoaderThrottle(
+            network::mojom::RequestDestination request_destination,
+            content::FrameTreeNodeId frame_tree_node_id);
     ~PluginResponseInterceptorURLLoaderThrottle() override = default;
 
 private:
@@ -30,7 +32,7 @@ class PluginResponseInterceptorURLLoaderThrottle : public blink::URLLoaderThrott
     void ResumeLoad();
 
     const network::mojom::RequestDestination m_request_destination;
-    const int m_frame_tree_node_id;
+    const content::FrameTreeNodeId m_frame_tree_node_id;
 
     base::WeakPtrFactory<PluginResponseInterceptorURLLoaderThrottle>
         weak_factory_{this};
diff --git a/src/core/net/proxying_restricted_cookie_manager_qt.cpp b/src/core/net/proxying_restricted_cookie_manager_qt.cpp
index 207ab2b466e..b07e239f2f1 100644
--- a/src/core/net/proxying_restricted_cookie_manager_qt.cpp
+++ b/src/core/net/proxying_restricted_cookie_manager_qt.cpp
@@ -65,7 +65,8 @@ ProxyingRestrictedCookieManagerQt::~ProxyingRestrictedCookieManagerQt()
 
 void ProxyingRestrictedCookieManagerQt::GetAllForUrl(const GURL &url,
                                                      const net::SiteForCookies &site_for_cookies,
-                                                     const url::Origin &top_frame_origin, bool has_storage_access,
+                                                     const url::Origin &top_frame_origin,
+                                                     net::StorageAccessApiStatus storage_access_api_status,
                                                      network::mojom::CookieManagerGetOptionsPtr options,
                                                      bool is_ad_tagged,
                                                      bool force_disable_third_party_cookies,
@@ -74,7 +75,7 @@ void ProxyingRestrictedCookieManagerQt::GetAllForUrl(const GURL &url,
     DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
 
     if (allowCookies(url, site_for_cookies)) {
-        underlying_restricted_cookie_manager_->GetAllForUrl(url, site_for_cookies, top_frame_origin, has_storage_access,
+        underlying_restricted_cookie_manager_->GetAllForUrl(url, site_for_cookies, top_frame_origin, storage_access_api_status,
                                                             std::move(options), is_ad_tagged, force_disable_third_party_cookies, std::move(callback));
     } else {
         std::move(callback).Run(std::vector<net::CookieWithAccessResult>());
@@ -85,7 +86,7 @@ void ProxyingRestrictedCookieManagerQt::SetCanonicalCookie(const net::CanonicalC
                                                            const GURL &url,
                                                            const net::SiteForCookies &site_for_cookies,
                                                            const url::Origin &top_frame_origin,
-                                                           bool has_storage_access,
+                                                           net::StorageAccessApiStatus storage_access_api_status,
                                                            net::CookieInclusionStatus status,
                                                            SetCanonicalCookieCallback callback)
 {
@@ -93,7 +94,7 @@ void ProxyingRestrictedCookieManagerQt::SetCanonicalCookie(const net::CanonicalC
 
     if (allowCookies(url, site_for_cookies)) {
         underlying_restricted_cookie_manager_->SetCanonicalCookie(cookie, url, site_for_cookies, top_frame_origin,
-                                                                  has_storage_access, status, std::move(callback));
+                                                                  storage_access_api_status, status, std::move(callback));
     } else {
         std::move(callback).Run(false);
     }
@@ -102,25 +103,26 @@ void ProxyingRestrictedCookieManagerQt::SetCanonicalCookie(const net::CanonicalC
 void ProxyingRestrictedCookieManagerQt::AddChangeListener(const GURL &url,
                                                           const net::SiteForCookies &site_for_cookies,
                                                           const url::Origin &top_frame_origin,
-                                                          bool has_storage_access,
+                                                          net::StorageAccessApiStatus storage_access_api_status,
                                                           mojo::PendingRemote<network::mojom::CookieChangeListener> listener,
                                                           AddChangeListenerCallback callback)
 {
     DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
-    underlying_restricted_cookie_manager_->AddChangeListener(url, site_for_cookies, top_frame_origin, has_storage_access,
+    underlying_restricted_cookie_manager_->AddChangeListener(url, site_for_cookies, top_frame_origin, storage_access_api_status,
                                                              std::move(listener), std::move(callback));
 }
 
 void ProxyingRestrictedCookieManagerQt::SetCookieFromString(const GURL &url,
                                                             const net::SiteForCookies &site_for_cookies,
-                                                            const url::Origin &top_frame_origin, bool has_storage_access,
+                                                            const url::Origin &top_frame_origin,
+                                                            net::StorageAccessApiStatus storage_access_api_status,
                                                             const std::string &cookie,
                                                             SetCookieFromStringCallback callback)
 {
     DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
 
     if (allowCookies(url, site_for_cookies)) {
-        underlying_restricted_cookie_manager_->SetCookieFromString(url, site_for_cookies, top_frame_origin, has_storage_access,
+        underlying_restricted_cookie_manager_->SetCookieFromString(url, site_for_cookies, top_frame_origin, storage_access_api_status,
                                                                    cookie, std::move(callback));
     } else {
         std::move(callback).Run();
@@ -130,7 +132,8 @@ void ProxyingRestrictedCookieManagerQt::SetCookieFromString(const GURL &url,
 void ProxyingRestrictedCookieManagerQt::GetCookiesString(const GURL &url,
                                                          const net::SiteForCookies &site_for_cookies,
                                                          const url::Origin &top_frame_origin,
-                                                         bool has_storage_access, bool get_version_shared_memory,
+                                                         net::StorageAccessApiStatus storage_access_api_status,
+                                                         bool get_version_shared_memory,
                                                          bool is_ad_tagged,
                                                          bool force_disable_third_party_cookies,
                                                          GetCookiesStringCallback callback)
@@ -139,7 +142,7 @@ void ProxyingRestrictedCookieManagerQt::GetCookiesString(const GURL &url,
 
     if (allowCookies(url, site_for_cookies)) {
         underlying_restricted_cookie_manager_->GetCookiesString(url, site_for_cookies, top_frame_origin,
-                                                                has_storage_access, get_version_shared_memory,
+                                                                storage_access_api_status, get_version_shared_memory,
                                                                 is_ad_tagged, force_disable_third_party_cookies,
                                                                 std::move(callback));
     } else {
@@ -150,7 +153,7 @@ void ProxyingRestrictedCookieManagerQt::GetCookiesString(const GURL &url,
 void ProxyingRestrictedCookieManagerQt::CookiesEnabledFor(const GURL &url,
                                                           const net::SiteForCookies &site_for_cookies,
                                                           const url::Origin & /*top_frame_origin*/,
-                                                          bool /*has_storage_access*/,
+                                                          net::StorageAccessApiStatus /*storage_access_api_status*/,
                                                           CookiesEnabledForCallback callback)
 {
     DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
diff --git a/src/core/net/proxying_restricted_cookie_manager_qt.h b/src/core/net/proxying_restricted_cookie_manager_qt.h
index 403c235a787..658a09d5d6d 100644
--- a/src/core/net/proxying_restricted_cookie_manager_qt.h
+++ b/src/core/net/proxying_restricted_cookie_manager_qt.h
@@ -27,7 +27,7 @@ class ProxyingRestrictedCookieManagerQt : public network::mojom::RestrictedCooki
     void GetAllForUrl(const GURL &url,
                       const net::SiteForCookies &site_for_cookies,
                       const url::Origin &top_frame_origin,
-                      bool has_storage_access,
+                      net::StorageAccessApiStatus storage_access_api_status,
                       network::mojom::CookieManagerGetOptionsPtr options,
                       bool is_ad_tagged,
                       bool force_disable_third_party_cookies,
@@ -37,32 +37,33 @@ class ProxyingRestrictedCookieManagerQt : public network::mojom::RestrictedCooki
                             const GURL &url,
                             const net::SiteForCookies &site_for_cookies,
                             const url::Origin &top_frame_origin,
-                            bool has_storage_access,
+                            net::StorageAccessApiStatus storage_access_api_status,
                             net::CookieInclusionStatus status,
                             SetCanonicalCookieCallback callback) override;
     void AddChangeListener(const GURL &url,
                            const net::SiteForCookies &site_for_cookies,
                            const url::Origin &top_frame_origin,
-                           bool has_storage_access,
+                           net::StorageAccessApiStatus storage_access_api_status,
                            mojo::PendingRemote<network::mojom::CookieChangeListener> listener,
                            AddChangeListenerCallback callback) override;
     void SetCookieFromString(const GURL &url,
                              const net::SiteForCookies &site_for_cookies,
                              const url::Origin &top_frame_origin,
-                             bool has_storage_access,
+                             net::StorageAccessApiStatus storage_access_api_status,
                              const std::string &cookie,
                              SetCookieFromStringCallback callback) override;
     void GetCookiesString(const GURL &url,
                           const net::SiteForCookies &site_for_cookies,
                           const url::Origin &top_frame_origin,
-                          bool has_storage_access, bool get_version_shared_memory,
+                          net::StorageAccessApiStatus storage_access_api_status,
+                          bool get_version_shared_memory,
                           bool is_ad_tagged,
                           bool force_disable_third_party_cookies,
                           GetCookiesStringCallback callback) override;
     void CookiesEnabledFor(const GURL &url,
                            const net::SiteForCookies &site_for_cookies,
                            const url::Origin &top_frame_origin,
-                           bool has_storage_access,
+                           net::StorageAccessApiStatus storage_access_api_status,
                            CookiesEnabledForCallback callback) override;
 
     // Internal:
diff --git a/src/core/net/proxying_url_loader_factory_qt.cpp b/src/core/net/proxying_url_loader_factory_qt.cpp
index a726bbce7d5..67b40f7dbcc 100644
--- a/src/core/net/proxying_url_loader_factory_qt.cpp
+++ b/src/core/net/proxying_url_loader_factory_qt.cpp
@@ -100,8 +100,9 @@ class InterceptedRequest : public network::mojom::URLLoader
                          , public network::mojom::URLLoaderClient
 {
 public:
-    InterceptedRequest(ProfileAdapter *profile_adapter, int frame_tree_node_id, int32_t request_id,
-                       uint32_t options, const network::ResourceRequest &request,
+    InterceptedRequest(ProfileAdapter *profile_adapter, content::FrameTreeNodeId frame_tree_node_id,
+                       int32_t request_id, uint32_t options,
+                       const network::ResourceRequest &request,
                        const net::MutableNetworkTrafficAnnotationTag &traffic_annotation,
                        mojo::PendingReceiver<network::mojom::URLLoader> loader,
                        mojo::PendingRemote<network::mojom::URLLoaderClient> client,
@@ -150,7 +151,7 @@ class InterceptedRequest : public network::mojom::URLLoader
     QWebEngineUrlRequestInterceptor* getPageInterceptor();
 
     QPointer<ProfileAdapter> profile_adapter_;
-    const int frame_tree_node_id_;
+    const content::FrameTreeNodeId frame_tree_node_id_;
     const int32_t request_id_;
     const uint32_t options_;
     bool allow_local_ = false;
@@ -189,8 +190,8 @@ class InterceptedRequest : public network::mojom::URLLoader
 };
 
 InterceptedRequest::InterceptedRequest(
-        ProfileAdapter *profile_adapter, int frame_tree_node_id, int32_t request_id,
-        uint32_t options, const network::ResourceRequest &request,
+        ProfileAdapter *profile_adapter, content::FrameTreeNodeId frame_tree_node_id,
+        int32_t request_id, uint32_t options, const network::ResourceRequest &request,
         const net::MutableNetworkTrafficAnnotationTag &traffic_annotation,
         mojo::PendingReceiver<network::mojom::URLLoader> loader_receiver,
         mojo::PendingRemote<network::mojom::URLLoaderClient> client,
@@ -243,7 +244,7 @@ InterceptedRequest::~InterceptedRequest()
 
 content::WebContents* InterceptedRequest::webContents()
 {
-    if (frame_tree_node_id_ == content::RenderFrameHost::kNoFrameTreeNodeId)
+    if (frame_tree_node_id_.is_null())
         return nullptr;
     return content::WebContents::FromFrameTreeNodeId(frame_tree_node_id_);
 }
@@ -551,7 +552,7 @@ void InterceptedRequest::SendErrorAndCompleteImmediately(int error_code)
 }
 
 ProxyingURLLoaderFactoryQt::ProxyingURLLoaderFactoryQt(
-        ProfileAdapter *adapter, int frame_tree_node_id,
+        ProfileAdapter *adapter, content::FrameTreeNodeId frame_tree_node_id,
         mojo::PendingReceiver<network::mojom::URLLoaderFactory> loader_receiver,
         mojo::PendingRemote<network::mojom::URLLoaderFactory> target_factory_info,
         content::ContentBrowserClient::URLLoaderFactoryType type)
diff --git a/src/core/net/proxying_url_loader_factory_qt.h b/src/core/net/proxying_url_loader_factory_qt.h
index 209450c9ab1..d7ffd48ea09 100644
--- a/src/core/net/proxying_url_loader_factory_qt.h
+++ b/src/core/net/proxying_url_loader_factory_qt.h
@@ -6,6 +6,7 @@
 
 #include "base/memory/weak_ptr.h"
 #include "content/public/browser/content_browser_client.h"
+#include "content/public/browser/frame_tree_node_id.h"
 #include "mojo/public/cpp/bindings/receiver_set.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
 #include "services/network/public/mojom/url_loader.mojom.h"
@@ -29,7 +30,7 @@ class ProxyingURLLoaderFactoryQt : public network::mojom::URLLoaderFactory
 {
 public:
     ProxyingURLLoaderFactoryQt(
-            ProfileAdapter *adapter, int frameTreeNodeId,
+            ProfileAdapter *adapter, content::FrameTreeNodeId frameTreeNodeId,
             mojo::PendingReceiver<network::mojom::URLLoaderFactory> loader_receiver,
             mojo::PendingRemote<network::mojom::URLLoaderFactory> pending_target_factory_remote,
             content::ContentBrowserClient::URLLoaderFactoryType type);
@@ -49,7 +50,7 @@ class ProxyingURLLoaderFactoryQt : public network::mojom::URLLoaderFactory
     void OnProxyBindingError();
 
     QPointer<ProfileAdapter> m_profileAdapter;
-    int m_frameTreeNodeId;
+    content::FrameTreeNodeId m_frameTreeNodeId;
     mojo::ReceiverSet<network::mojom::URLLoaderFactory> m_proxyReceivers;
     mojo::Remote<network::mojom::URLLoaderFactory> m_targetFactory;
     base::WeakPtrFactory<ProxyingURLLoaderFactoryQt> m_weakFactory;
diff --git a/src/core/net/qrc_url_scheme_handler.cpp b/src/core/net/qrc_url_scheme_handler.cpp
index a8b4e4388a2..876c7d2031f 100644
--- a/src/core/net/qrc_url_scheme_handler.cpp
+++ b/src/core/net/qrc_url_scheme_handler.cpp
@@ -12,19 +12,21 @@
 
 #include <memory>
 
+using namespace Qt::StringLiterals;
+
 namespace QtWebEngineCore {
 
 void QrcUrlSchemeHandler::requestStarted(QWebEngineUrlRequestJob *job)
 {
-    QByteArray requestMethod = job->requestMethod();
+    const QByteArray requestMethod = job->requestMethod();
     if (requestMethod != "GET") {
         job->fail(QWebEngineUrlRequestJob::RequestDenied);
         return;
     }
 
-    QUrl requestUrl = job->requestUrl();
-    QString requestPath = requestUrl.path();
-    auto file = std::make_unique<QFile>(':' + requestPath, job);
+    const QUrl requestUrl = job->requestUrl();
+    const QString requestPath = requestUrl.path();
+    auto file = std::make_unique<QFile>(u':' + requestPath, job);
     if (!file->exists() || file->size() == 0) {
         qWarning("QResource '%s' not found or is empty", qUtf8Printable(requestPath));
         job->fail(QWebEngineUrlRequestJob::UrlNotFound);
@@ -33,7 +35,7 @@ void QrcUrlSchemeHandler::requestStarted(QWebEngineUrlRequestJob *job)
     QFileInfo fileInfo(*file);
     QMimeDatabase mimeDatabase;
     QMimeType mimeType = mimeDatabase.mimeTypeForFile(fileInfo);
-    if (mimeType.name() == QStringLiteral("application/x-extension-html"))
+    if (mimeType.name() == "application/x-extension-html"_L1)
         job->reply("text/html", file.release());
     else
         job->reply(mimeType.name().toUtf8(), file.release());
diff --git a/src/core/net/resource_request_body_qt.cpp b/src/core/net/resource_request_body_qt.cpp
index c0a00b0db0d..a82d01aae85 100644
--- a/src/core/net/resource_request_body_qt.cpp
+++ b/src/core/net/resource_request_body_qt.cpp
@@ -9,6 +9,8 @@
 #include "services/network/public/mojom/url_request.mojom-shared.h"
 #include "mojo/public/cpp/bindings/remote.h"
 
+using namespace Qt::StringLiterals;
+
 namespace QtWebEngineCore {
 
 ResourceRequestBody::ResourceRequestBody(network::ResourceRequestBody *requestBody, QObject *parent)
@@ -58,8 +60,8 @@ qint64 ResourceRequestBody::readData(char *data, qint64 maxSize)
                 break;
             }
             case network::mojom::DataElementDataView::Tag::kChunkedDataPipe: {
-                setErrorString(QStringLiteral("Chunked data pipe is used in request body upload, which "
-                                              "is currently not supported"));
+                setErrorString(u"Chunked data pipe is used in request body upload, which "
+                               "is currently not supported"_s);
                 // Nothing should come before or after DataElementChunkedDataPipe
                 return -1;
             }
@@ -110,7 +112,14 @@ void ResourceRequestBody::readDataElementFile(const base::FilePath &filePath, co
     const std::size_t fileSize = std::min(file.size(), length) - realOffset;
     const std::size_t bytesToRead = std::min(fileSize, static_cast<std::size_t>(maxSize));
 
-    file.open(QFile::ReadOnly);
+    if (!file.open(QFile::ReadOnly)) {
+        m_dataElementsIdx++;
+        m_dataElementFileIdx = 0;
+        setErrorString(u"Error while reading from file, skipping remaining content of "_s
+                       % file.fileName() % u": "_s % file.errorString());
+        return;
+    }
+
     file.seek(realOffset);
 
     std::memcpy(*data, file.read(bytesToRead).data(), bytesToRead);
@@ -143,23 +152,25 @@ ResourceRequestBody::getConsumerHandleFromPipeGetter(
 
 void ResourceRequestBody::readDataElementPipe(
         const mojo::ScopedHandleBase<mojo::DataPipeConsumerHandle> &consumerHandle,
-        qint64 &bytesRead, const qint64 &maxSize, char **data)
+        qint64 &bytesRead, qint64 maxSize, char **data)
 {
     MojoResult result;
     do {
         size_t bytesToRead = 1;
-        result = consumerHandle->ReadData(*data, &bytesToRead, MOJO_READ_DATA_FLAG_NONE);
+        base::span<uint8_t> buffer = base::make_span(reinterpret_cast<uint8_t*>(*data), reinterpret_cast<uint8_t*>(*data) + maxSize);
+        result = consumerHandle->ReadData(MOJO_READ_DATA_FLAG_NONE, buffer, bytesToRead);
 
         if (result == MOJO_RESULT_OK) {
             *data += bytesToRead;
             bytesRead += bytesToRead;
+            maxSize -= bytesToRead;
         } else if (result != MOJO_RESULT_SHOULD_WAIT && result != MOJO_RESULT_FAILED_PRECONDITION) {
-            setErrorString(QString::fromLatin1("Error while reading from data pipe, skipping"
-                                               "remaining content of data pipe. Mojo error code: ")
+            setErrorString("Error while reading from data pipe, skipping "
+                           "remaining content of data pipe. Mojo error code: "_L1
                            + QString::number(result));
         }
     } while ((result == MOJO_RESULT_SHOULD_WAIT || result == MOJO_RESULT_OK)
-             && bytesRead < maxSize);
+             && maxSize > 0);
 
     m_dataElementsIdx++;
 }
diff --git a/src/core/net/resource_request_body_qt.h b/src/core/net/resource_request_body_qt.h
index 43f95197e21..8c3be2bd806 100644
--- a/src/core/net/resource_request_body_qt.h
+++ b/src/core/net/resource_request_body_qt.h
@@ -59,7 +59,7 @@ class Q_WEBENGINECORE_EXPORT ResourceRequestBody : public QIODevice
     getConsumerHandleFromPipeGetter(mojo::Remote<network::mojom::DataPipeGetter> &pipeGetter);
     void
     readDataElementPipe(const mojo::ScopedHandleBase<mojo::DataPipeConsumerHandle> &consumerHandle,
-                        qint64 &bytesRead, const qint64 &maxSize, char **data);
+                        qint64 &bytesRead, qint64 maxSize, char **data);
     void pipeGetterOnReadComplete(int32_t status, uint64_t size);
 };
 
diff --git a/src/core/net/url_request_custom_job_proxy.cpp b/src/core/net/url_request_custom_job_proxy.cpp
index cac50162ff5..bf1a297ab94 100644
--- a/src/core/net/url_request_custom_job_proxy.cpp
+++ b/src/core/net/url_request_custom_job_proxy.cpp
@@ -6,6 +6,7 @@
 
 #include "content/public/browser/browser_thread.h"
 #include "net/base/net_errors.h"
+#include "net/http/http_util.h"
 #include "services/network/public/cpp/resource_request_body.h"
 
 #include "api/qwebengineurlrequestjob.h"
@@ -47,18 +48,8 @@ void URLRequestCustomJobProxy::reply(std::string contentType, QIODevice *device,
     if (!m_client)
         return;
     DCHECK (!m_ioTaskRunner || m_ioTaskRunner->RunsTasksInCurrentSequence());
-    QByteArray qcontentType = QByteArray::fromStdString(contentType).toLower();
-    const int sidx = qcontentType.indexOf(';');
-    if (sidx > 0) {
-        const int cidx = qcontentType.indexOf("charset=", sidx);
-        if (cidx > 0) {
-            m_client->m_charset = qcontentType.mid(cidx + 8).trimmed().toStdString();
-            qcontentType = qcontentType.first(sidx);
-        } else {
-            qWarning() << "QWebEngineUrlRequestJob::reply(): Unrecognized content-type format with ';'" << qcontentType;
-        }
-    }
-    m_client->m_mimeType = qcontentType.trimmed().toStdString();
+    bool hadCharset = false;
+    net::HttpUtil::ParseContentType(contentType, &m_client->m_mimeType, &m_client->m_charset, &hadCharset, nullptr);
     m_client->m_device = device;
     m_client->m_additionalResponseHeaders = std::move(additionalResponseHeaders);
     if (m_client->m_device && !m_client->m_device->isReadable())
diff --git a/src/core/ozone/egl_helper.cpp b/src/core/ozone/egl_helper.cpp
index 879e2fa4504..1ed679d2390 100644
--- a/src/core/ozone/egl_helper.cpp
+++ b/src/core/ozone/egl_helper.cpp
@@ -3,6 +3,7 @@
 
 #include "egl_helper.h"
 #include "ozone_util_qt.h"
+#include "web_engine_context.h"
 
 #include <QtCore/qthread.h>
 #include <QtGui/qguiapplication.h>
@@ -57,90 +58,14 @@ static const char *getEGLErrorString(uint32_t error)
 
 QT_BEGIN_NAMESPACE
 
-class ScopedGLContext
-{
-public:
-    ScopedGLContext(QOffscreenSurface *surface, EGLHelper::EGLFunctions *eglFun)
-        : m_context(new QOpenGLContext()), m_eglFun(eglFun)
-    {
-        if ((m_previousEGLContext = m_eglFun->eglGetCurrentContext())) {
-            m_previousEGLDrawSurface = m_eglFun->eglGetCurrentSurface(EGL_DRAW);
-            m_previousEGLReadSurface = m_eglFun->eglGetCurrentSurface(EGL_READ);
-            m_previousEGLDisplay = m_eglFun->eglGetCurrentDisplay();
-        }
-
-        if (!m_context->create()) {
-            qWarning("Failed to create OpenGL context.");
-            return;
-        }
-
-        Q_ASSERT(surface->isValid());
-        if (!m_context->makeCurrent(surface)) {
-            qWarning("Failed to make OpenGL context current.");
-            return;
-        }
-    }
-
-    ~ScopedGLContext()
-    {
-        if (!m_textures.empty()) {
-            auto *glFun = m_context->functions();
-            glFun->glDeleteTextures(m_textures.size(), m_textures.data());
-        }
-
-        if (m_previousEGLContext) {
-            // Make sure the scoped context is not current when restoring the previous
-            // EGL context otherwise the QOpenGLContext destructor resets the restored
-            // current context.
-            m_context->doneCurrent();
-
-            m_eglFun->eglMakeCurrent(m_previousEGLDisplay, m_previousEGLDrawSurface,
-                                     m_previousEGLReadSurface, m_previousEGLContext);
-            if (m_eglFun->eglGetError() != EGL_SUCCESS)
-                qWarning("Failed to restore EGL context.");
-        }
-    }
-
-    bool isValid() const { return m_context->isValid() && (m_context->surface() != nullptr); }
-
-    EGLContext eglContext() const
-    {
-        QNativeInterface::QEGLContext *nativeInterface =
-                m_context->nativeInterface<QNativeInterface::QEGLContext>();
-        return nativeInterface->nativeContext();
-    }
-
-    uint createTexture(int width, int height)
-    {
-        auto *glFun = m_context->functions();
-
-        uint glTexture;
-        glFun->glGenTextures(1, &glTexture);
-        glFun->glBindTexture(GL_TEXTURE_2D, glTexture);
-        glFun->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE,
-                            NULL);
-        glFun->glBindTexture(GL_TEXTURE_2D, 0);
-
-        m_textures.push_back(glTexture);
-        return glTexture;
-    }
-
-private:
-    QScopedPointer<QOpenGLContext> m_context;
-    EGLHelper::EGLFunctions *m_eglFun;
-    EGLContext m_previousEGLContext = nullptr;
-    EGLSurface m_previousEGLDrawSurface = nullptr;
-    EGLSurface m_previousEGLReadSurface = nullptr;
-    EGLDisplay m_previousEGLDisplay = nullptr;
-    std::vector<uint> m_textures;
-};
-
 EGLHelper::EGLFunctions::EGLFunctions()
 {
     QOpenGLContext *context = OzoneUtilQt::getQOpenGLContext();
 
     eglCreateImage =
             reinterpret_cast<PFNEGLCREATEIMAGEPROC>(context->getProcAddress("eglCreateImage"));
+    eglCreateDRMImageMESA = reinterpret_cast<PFNEGLCREATEDRMIMAGEMESAPROC>(
+            context->getProcAddress("eglCreateDRMImageMESA"));
     eglDestroyImage =
             reinterpret_cast<PFNEGLDESTROYIMAGEPROC>(context->getProcAddress("eglDestroyImage"));
     eglExportDMABUFImageMESA = reinterpret_cast<PFNEGLEXPORTDMABUFIMAGEMESAPROC>(
@@ -190,23 +115,15 @@ EGLHelper::EGLHelper()
     Q_ASSERT(QThread::currentThread() == qApp->thread());
     m_offscreenSurface->create();
 
-    const char *displayExtensions = m_functions->eglQueryString(m_eglDisplay, EGL_EXTENSIONS);
-    m_isDmaBufSupported = strstr(displayExtensions, "EGL_EXT_image_dma_buf_import")
-            && strstr(displayExtensions, "EGL_EXT_image_dma_buf_import_modifiers")
-            && strstr(displayExtensions, "EGL_MESA_image_dma_buf_export");
+    m_isDmaBufSupported = QtWebEngineCore::WebEngineContext::isGbmSupported();
 
+    // Check extensions.
     if (m_isDmaBufSupported) {
-        // FIXME: This disables GBM for nvidia. Remove this when nvidia fixes its GBM support.
-        //
-        // "Buffer allocation and submission to DRM KMS using gbm is not currently supported."
-        // See: https://download.nvidia.com/XFree86/Linux-x86_64/550.40.07/README/kms.html
-        //
-        // Chromium uses GBM to allocate scanout buffers. Scanout requires DRM KMS. If KMS is
-        // enabled, gbm_device and gbm_buffer are created without any issues but rendering to the
-        // buffer will malfunction. It is not known how to detect this problem before rendering
-        // so we just disable GBM for nvidia.
-        const char *displayVendor = m_functions->eglQueryString(m_eglDisplay, EGL_VENDOR);
-        m_isDmaBufSupported = !strstr(displayVendor, "NVIDIA");
+        const char *displayExtensions = m_functions->eglQueryString(m_eglDisplay, EGL_EXTENSIONS);
+        m_isDmaBufSupported = strstr(displayExtensions, "EGL_EXT_image_dma_buf_import")
+                && strstr(displayExtensions, "EGL_EXT_image_dma_buf_import_modifiers")
+                && strstr(displayExtensions, "EGL_MESA_drm_image")
+                && strstr(displayExtensions, "EGL_MESA_image_dma_buf_export");
     }
 
     // Try to create dma-buf.
@@ -226,34 +143,34 @@ void EGLHelper::queryDmaBuf(const int width, const int height, int *fd, int *str
     if (!m_isDmaBufSupported)
         return;
 
-    ScopedGLContext context(m_offscreenSurface.get(), m_functions.get());
-    if (!context.isValid())
-        return;
-
-    EGLContext eglContext = context.eglContext();
-    if (!eglContext) {
-        qWarning("EGL: No EGLContext.");
-        return;
-    }
-
-    uint64_t textureId = context.createTexture(width, height);
-    EGLImage eglImage = m_functions->eglCreateImage(m_eglDisplay, eglContext, EGL_GL_TEXTURE_2D,
-                                                    (EGLClientBuffer)textureId, NULL);
+    // clang-format off
+    EGLint attribs[] = {
+        EGL_WIDTH, width,
+        EGL_HEIGHT, height,
+        EGL_DRM_BUFFER_FORMAT_MESA, EGL_DRM_BUFFER_FORMAT_ARGB32_MESA,
+        EGL_DRM_BUFFER_USE_MESA, EGL_DRM_BUFFER_USE_SHARE_MESA,
+        EGL_NONE
+    };
+    // clang-format on
+
+    EGLImage eglImage = m_functions->eglCreateDRMImageMESA(m_eglDisplay, attribs);
     if (eglImage == EGL_NO_IMAGE) {
-        qWarning() << "EGL: Failed to create EGLImage:" << getLastEGLErrorString();
+        qWarning("EGL: Failed to create EGLImage: %s", getLastEGLErrorString());
         return;
     }
 
     int numPlanes = 0;
     if (!m_functions->eglExportDMABUFImageQueryMESA(m_eglDisplay, eglImage, nullptr, &numPlanes,
-                                                    modifiers))
-        qWarning() << "EGL: Failed to retrieve the pixel format of the buffer:"
-                   << getLastEGLErrorString();
+                                                    modifiers)) {
+        qWarning("EGL: Failed to retrieve the pixel format of the buffer: %s",
+                 getLastEGLErrorString());
+    }
     Q_ASSERT(numPlanes == 1);
 
-    if (!m_functions->eglExportDMABUFImageMESA(m_eglDisplay, eglImage, fd, stride, offset))
-        qWarning() << "EGL: Failed to retrieve the dma_buf file descriptor:"
-                   << getLastEGLErrorString();
+    if (!m_functions->eglExportDMABUFImageMESA(m_eglDisplay, eglImage, fd, stride, offset)) {
+        qWarning("EGL: Failed to retrieve the dma_buf file descriptor: %s",
+                 getLastEGLErrorString());
+    }
 
     m_functions->eglDestroyImage(m_eglDisplay, eglImage);
 }
diff --git a/src/core/ozone/egl_helper.h b/src/core/ozone/egl_helper.h
index a1a1aa0d667..7594e1f8469 100644
--- a/src/core/ozone/egl_helper.h
+++ b/src/core/ozone/egl_helper.h
@@ -11,6 +11,7 @@
 #include <EGL/eglext.h>
 
 #undef eglCreateImage
+#undef eglCreateDRMImageMESA
 #undef eglDestroyImage
 #undef eglExportDMABUFImageMESA
 #undef eglExportDMABUFImageQueryMESA
@@ -33,6 +34,7 @@ class EGLHelper
         EGLFunctions();
 
         PFNEGLCREATEIMAGEPROC eglCreateImage;
+        PFNEGLCREATEDRMIMAGEMESAPROC eglCreateDRMImageMESA;
         PFNEGLDESTROYIMAGEPROC eglDestroyImage;
         PFNEGLEXPORTDMABUFIMAGEMESAPROC eglExportDMABUFImageMESA;
         PFNEGLEXPORTDMABUFIMAGEQUERYMESAPROC eglExportDMABUFImageQueryMESA;
diff --git a/src/core/ozone/gl_helper.cpp b/src/core/ozone/gl_helper.cpp
index 32236e9fea1..f5135e23480 100644
--- a/src/core/ozone/gl_helper.cpp
+++ b/src/core/ozone/gl_helper.cpp
@@ -8,6 +8,32 @@
 
 QT_BEGIN_NAMESPACE
 
+const char *getGLErrorString(uint32_t error)
+{
+    switch (error) {
+    case GL_INVALID_ENUM:
+        return "GL_INVALID_ENUM";
+    case GL_INVALID_VALUE:
+        return "GL_INVALID_VALUE";
+    case GL_INVALID_OPERATION:
+        return "GL_INVALID_OPERATION";
+    case GL_STACK_OVERFLOW:
+        return "GL_STACK_OVERFLOW";
+    case GL_STACK_UNDERFLOW:
+        return "GL_STACK_UNDERFLOW";
+    case GL_OUT_OF_MEMORY:
+        return "GL_OUT_OF_MEMORY";
+    case GL_INVALID_FRAMEBUFFER_OPERATION:
+        return "GL_INVALID_FRAMEBUFFER_OPERATION";
+    case GL_CONTEXT_LOST:
+        return "GL_CONTEXT_LOST";
+    case GL_NO_ERROR:
+        return "GL_NO_ERROR";
+    default:
+        return "UNKNOWN";
+    }
+}
+
 GLHelper::GLExtFunctions::GLExtFunctions()
 {
     QOpenGLContext *context = OzoneUtilQt::getQOpenGLContext();
@@ -20,8 +46,12 @@ GLHelper::GLExtFunctions::GLExtFunctions()
             context->getProcAddress("glEGLImageTargetTexture2DOES"));
     glImportMemoryFdEXT = reinterpret_cast<PFNGLIMPORTMEMORYFDEXTPROC>(
             context->getProcAddress("glImportMemoryFdEXT"));
-    glTextureStorageMem2DEXT = reinterpret_cast<PFNGLTEXTURESTORAGEMEM2DEXTPROC>(
-            context->getProcAddress("glTextureStorageMem2DEXT"));
+    glIsMemoryObjectEXT = reinterpret_cast<PFNGLISMEMORYOBJECTEXTPROC>(
+            context->getProcAddress("glIsMemoryObjectEXT"));
+    glMemoryObjectParameterivEXT = reinterpret_cast<PFNGLMEMORYOBJECTPARAMETERIVEXTPROC>(
+            context->getProcAddress("glMemoryObjectParameterivEXT"));
+    glTexStorageMem2DEXT = reinterpret_cast<PFNGLTEXSTORAGEMEM2DEXTPROC>(
+            context->getProcAddress("glTexStorageMem2DEXT"));
 }
 
 GLHelper *GLHelper::instance()
diff --git a/src/core/ozone/gl_helper.h b/src/core/ozone/gl_helper.h
index 050bf70316c..ae8639c84ee 100644
--- a/src/core/ozone/gl_helper.h
+++ b/src/core/ozone/gl_helper.h
@@ -19,6 +19,8 @@
 
 QT_BEGIN_NAMESPACE
 
+const char *getGLErrorString(uint32_t error);
+
 class GLHelper
 {
 public:
@@ -30,7 +32,9 @@ class GLHelper
         PFNGLDELETEMEMORYOBJECTSEXTPROC glDeleteMemoryObjectsEXT;
         PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES;
         PFNGLIMPORTMEMORYFDEXTPROC glImportMemoryFdEXT;
-        PFNGLTEXTURESTORAGEMEM2DEXTPROC glTextureStorageMem2DEXT;
+        PFNGLISMEMORYOBJECTEXTPROC glIsMemoryObjectEXT;
+        PFNGLMEMORYOBJECTPARAMETERIVEXTPROC glMemoryObjectParameterivEXT;
+        PFNGLTEXSTORAGEMEM2DEXTPROC glTexStorageMem2DEXT;
     };
 
     static GLHelper *instance();
diff --git a/src/core/ozone/gl_ozone_angle_qt.cpp b/src/core/ozone/gl_ozone_angle_qt.cpp
index b23f3c60fca..359d04a4545 100644
--- a/src/core/ozone/gl_ozone_angle_qt.cpp
+++ b/src/core/ozone/gl_ozone_angle_qt.cpp
@@ -1,6 +1,10 @@
-// Copyright (C) 2024 The Qt Company Ltd.
+// Copyright (C) 2025 The Qt Company Ltd.
 // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
 
+// Copyright 2016 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
 #include "gl_ozone_angle_qt.h"
 
 #include "ui/base/ozone_buildflags.h"
@@ -12,6 +16,8 @@
 
 #if BUILDFLAG(IS_OZONE_X11)
 #include "ozone_util_qt.h"
+
+#include "ui/ozone/platform/x11/native_pixmap_egl_x11_binding.h"
 #endif
 
 extern "C" {
@@ -20,6 +26,34 @@ extern __eglMustCastToProperFunctionPointerType EGL_GetProcAddress(const char *p
 }
 
 namespace ui {
+namespace {
+// Based on //ui/ozone/platform/x11/x11_surface_factory.cc
+enum class NativePixmapSupportType {
+    // Importing native pixmaps not supported.
+    kNone,
+
+    // Native pixmaps are imported directly into EGL using the
+    // EGL_EXT_image_dma_buf_import extension.
+    kDMABuf,
+
+    // Native pixmaps are first imported as X11 pixmaps using DRI3 and then into
+    // EGL.
+    kX11Pixmap,
+};
+
+NativePixmapSupportType GetNativePixmapSupportType()
+{
+    if (gl::GLSurfaceEGL::GetGLDisplayEGL()->ext->b_EGL_EXT_image_dma_buf_import)
+        return NativePixmapSupportType::kDMABuf;
+
+#if BUILDFLAG(IS_OZONE_X11)
+    if (NativePixmapEGLX11Binding::CanImportNativeGLXPixmap())
+        return NativePixmapSupportType::kX11Pixmap;
+#endif
+
+    return NativePixmapSupportType::kNone;
+}
+} // namespace
 
 bool GLOzoneANGLEQt::LoadGLES2Bindings(const gl::GLImplementationParts & /*implementation*/)
 {
@@ -73,7 +107,16 @@ gl::EGLDisplayPlatform GLOzoneANGLEQt::GetNativeDisplay()
 
 bool GLOzoneANGLEQt::CanImportNativePixmap(gfx::BufferFormat format)
 {
-    return gl::GLSurfaceEGL::GetGLDisplayEGL()->ext->b_EGL_EXT_image_dma_buf_import;
+    switch (GetNativePixmapSupportType()) {
+    case NativePixmapSupportType::kDMABuf:
+        return NativePixmapEGLBinding::IsBufferFormatSupported(format);
+#if BUILDFLAG(IS_OZONE_X11)
+    case NativePixmapSupportType::kX11Pixmap:
+        return NativePixmapEGLX11Binding::IsBufferFormatSupported(format);
+#endif
+    default:
+        return false;
+    }
 }
 
 std::unique_ptr<NativePixmapGLBinding>
@@ -82,8 +125,19 @@ GLOzoneANGLEQt::ImportNativePixmap(scoped_refptr<gfx::NativePixmap> pixmap,
                                    gfx::Size plane_size, const gfx::ColorSpace &color_space,
                                    GLenum target, GLuint texture_id)
 {
-    return NativePixmapEGLBinding::Create(pixmap, plane_format, plane, plane_size, color_space,
-                                          target, texture_id);
+    switch (GetNativePixmapSupportType()) {
+    case NativePixmapSupportType::kDMABuf:
+        return NativePixmapEGLBinding::Create(pixmap, plane_format, plane, plane_size, color_space,
+                                              target, texture_id);
+#if BUILDFLAG(IS_OZONE_X11)
+    case NativePixmapSupportType::kX11Pixmap:
+        return NativePixmapEGLX11Binding::Create(pixmap, plane_format, plane_size, target,
+                                                 texture_id);
+#endif
+    default:
+        NOTREACHED();
+        return nullptr;
+    }
 }
 
 } // namespace ui
diff --git a/src/core/ozone/glx_helper.cpp b/src/core/ozone/glx_helper.cpp
index 2581681c04c..35929b6a343 100644
--- a/src/core/ozone/glx_helper.cpp
+++ b/src/core/ozone/glx_helper.cpp
@@ -7,6 +7,9 @@
 
 #include "glx_helper.h"
 #include "ozone_util_qt.h"
+#include "web_engine_context.h"
+
+#include "ui/gfx/linux/gpu_memory_buffer_support_x11.h"
 
 #include <unistd.h>
 #include <xcb/dri3.h>
@@ -40,8 +43,17 @@ GLXHelper::GLXHelper() : m_functions(new GLXHelper::GLXFunctions())
     m_display = x11Application->display();
     m_connection = x11Application->connection();
 
+    m_isDmaBufSupported = QtWebEngineCore::WebEngineContext::isGbmSupported()
+            && ui::GpuMemoryBufferSupportX11::GetInstance()->has_gbm_device();
+}
+
+GLXFBConfig GLXHelper::getFBConfig()
+{
+    if (m_configs)
+        return m_configs[0];
+
     // clang-format off
-    const int configAttribs[] = {
+    static const int configAttribs[] = {
         GLX_RED_SIZE, 8,
         GLX_GREEN_SIZE, 8,
         GLX_BLUE_SIZE, 8,
@@ -56,10 +68,17 @@ GLXHelper::GLXHelper() : m_functions(new GLXHelper::GLXFunctions())
     };
     // clang-format on
 
+    if (Q_UNLIKELY(!m_isDmaBufSupported)) {
+        qWarning("GLX: Frame buffer configuration is not expected to be used without dma-buf "
+                 "support.");
+    }
+
     int numConfigs = 0;
     m_configs = glXChooseFBConfig(m_display, /* screen */ 0, configAttribs, &numConfigs);
     if (!m_configs || numConfigs < 1)
         qFatal("GLX: Failed to find frame buffer configuration.");
+
+    return m_configs[0];
 }
 
 GLXPixmap GLXHelper::importBufferAsPixmap(int dmaBufFd, uint32_t size, uint16_t width,
@@ -85,8 +104,8 @@ GLXPixmap GLXHelper::importBufferAsPixmap(int dmaBufFd, uint32_t size, uint16_t
                                                 height, stride, depth, bpp, dmaBufFd);
     xcb_generic_error_t *error = xcb_request_check(m_connection, cookie);
     if (error) {
-        qWarning() << "GLX: XCB_DRI3_PIXMAP_FROM_BUFFER failed with error code:"
-                   << error->error_code;
+        qWarning("GLX: XCB_DRI3_PIXMAP_FROM_BUFFER failed with error code: 0x%x",
+                 error->error_code);
         free(error);
         return 0;
     }
@@ -94,4 +113,14 @@ GLXPixmap GLXHelper::importBufferAsPixmap(int dmaBufFd, uint32_t size, uint16_t
     return pixmapId;
 }
 
+void GLXHelper::freePixmap(uint32_t pixmapId) const
+{
+    xcb_void_cookie_t cookie = xcb_free_pixmap_checked(m_connection, pixmapId);
+    xcb_generic_error_t *error = xcb_request_check(m_connection, cookie);
+    if (error) {
+        qWarning("GLX: XCB_FREE_PIXMAP failed with error code: 0x%x", error->error_code);
+        free(error);
+    }
+}
+
 QT_END_NAMESPACE
diff --git a/src/core/ozone/glx_helper.h b/src/core/ozone/glx_helper.h
index bd61d253eb8..20bc7159cbe 100644
--- a/src/core/ozone/glx_helper.h
+++ b/src/core/ozone/glx_helper.h
@@ -7,6 +7,7 @@
 #include <QtCore/qscopedpointer.h>
 
 #include <GL/glx.h>
+#include <xcb/xcb.h>
 
 #undef glXBindTexImageEXT
 #undef glXReleaseTexImageEXT
@@ -29,9 +30,11 @@ class GLXHelper
     Display *getXDisplay() const { return m_display; }
     GLXFunctions *functions() const { return m_functions.get(); }
 
-    GLXFBConfig getFBConfig() const { return m_configs[0]; }
+    GLXFBConfig getFBConfig();
     GLXPixmap importBufferAsPixmap(int dmaBufFd, uint32_t size, uint16_t width, uint16_t height,
                                    uint16_t stride) const;
+    void freePixmap(uint32_t pixmapId) const;
+    bool isDmaBufSupported() const { return m_isDmaBufSupported; }
 
 private:
     GLXHelper();
@@ -40,6 +43,7 @@ class GLXHelper
     Display *m_display = nullptr;
     xcb_connection_t *m_connection = nullptr;
     GLXFBConfig *m_configs = nullptr;
+    bool m_isDmaBufSupported = false;
 };
 
 QT_END_NAMESPACE
diff --git a/src/core/ozone/surface_factory_qt.cpp b/src/core/ozone/surface_factory_qt.cpp
index a6bc21de263..95af160a723 100644
--- a/src/core/ozone/surface_factory_qt.cpp
+++ b/src/core/ozone/surface_factory_qt.cpp
@@ -18,7 +18,8 @@
 #include <QDebug>
 #include <QtGui/qtgui-config.h>
 
-#if QT_CONFIG(opengl) && BUILDFLAG(IS_OZONE_X11)
+#if QT_CONFIG(opengl) && BUILDFLAG(IS_OZONE_X11) && QT_CONFIG(xcb_glx_plugin)
+#include "ozone/glx_helper.h"
 #include "ui/gfx/linux/gpu_memory_buffer_support_x11.h"
 #endif
 
@@ -57,7 +58,7 @@ ui::GLOzone *SurfaceFactoryQt::GetGLOzone(const gl::GLImplementationParts &imple
             return impl.second.get();
     }
 
-    qFatal() << "GLOzone not found for" << gl::GetGLImplementationGLName(implementation);
+    qFatal("GLOzone not found for %s", gl::GetGLImplementationGLName(implementation));
     return nullptr;
 }
 
@@ -77,7 +78,7 @@ SurfaceFactoryQt::CreateVulkanImplementation(bool /*allow_protected_memory*/,
 bool SurfaceFactoryQt::CanCreateNativePixmapForFormat(gfx::BufferFormat format)
 {
 #if QT_CONFIG(opengl)
-#if BUILDFLAG(IS_OZONE_X11)
+#if BUILDFLAG(IS_OZONE_X11) && QT_CONFIG(xcb_glx_plugin)
     if (OzoneUtilQt::usingGLX())
         return ui::GpuMemoryBufferSupportX11::GetInstance()->CanCreateNativePixmapForFormat(format);
 #endif
@@ -116,7 +117,7 @@ scoped_refptr<gfx::NativePixmap> SurfaceFactoryQt::CreateNativePixmap(
 
     gfx::NativePixmapHandle handle;
 
-#if BUILDFLAG(IS_OZONE_X11)
+#if BUILDFLAG(IS_OZONE_X11) && QT_CONFIG(xcb_glx_plugin)
     if (OzoneUtilQt::usingGLX()) {
         auto gbmBuffer =
                 ui::GpuMemoryBufferSupportX11::GetInstance()->CreateBuffer(format, size, usage);
@@ -182,7 +183,7 @@ SurfaceFactoryQt::CreateNativePixmapFromHandle(
 #if QT_CONFIG(opengl)
     gfx::NativePixmapHandle bufferHandle;
 
-#if BUILDFLAG(IS_OZONE_X11)
+#if BUILDFLAG(IS_OZONE_X11) && QT_CONFIG(xcb_glx_plugin)
     if (OzoneUtilQt::usingGLX()) {
         auto gbmBuffer = ui::GpuMemoryBufferSupportX11::GetInstance()->CreateBufferFromHandle(
                 size, format, std::move(handle));
@@ -226,7 +227,7 @@ SurfaceFactoryQt::CreateNativePixmapFromHandle(
                 eglFun->eglCreateImage(eglDisplay, EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT,
                                        (EGLClientBuffer)NULL, attrs.data());
         if (eglImage == EGL_NO_IMAGE_KHR) {
-            qFatal() << "Failed to import EGLImage:" << eglHelper->getLastEGLErrorString();
+            qFatal("Failed to import EGLImage: %s", eglHelper->getLastEGLErrorString());
         }
 
         Q_ASSERT(numPlanes <= 3);
@@ -234,7 +235,7 @@ SurfaceFactoryQt::CreateNativePixmapFromHandle(
         int strides[3];
         int offsets[3];
         if (!eglFun->eglExportDMABUFImageMESA(eglDisplay, eglImage, fds, strides, offsets)) {
-            qFatal() << "Failed to export EGLImage:" << eglHelper->getLastEGLErrorString();
+            qFatal("Failed to export EGLImage: %s", eglHelper->getLastEGLErrorString());
         }
 
         bufferHandle.modifier = handle.modifier;
@@ -267,10 +268,10 @@ SurfaceFactoryQt::CreateNativePixmapFromHandle(
 bool SurfaceFactoryQt::SupportsNativePixmaps()
 {
 #if QT_CONFIG(opengl)
-#if BUILDFLAG(IS_OZONE_X11)
+#if BUILDFLAG(IS_OZONE_X11) && QT_CONFIG(xcb_glx_plugin)
     if (OzoneUtilQt::usingGLX())
-        return ui::GpuMemoryBufferSupportX11::GetInstance()->has_gbm_device();
-#endif // BUILDFLAG(IS_OZONE_X11)
+        return GLXHelper::instance()->isDmaBufSupported();
+#endif // BUILDFLAG(IS_OZONE_X11) && QT_CONFIG(xcb_glx_plugin)
 
 #if QT_CONFIG(egl)
     if (OzoneUtilQt::usingEGL())
diff --git a/src/core/permission_manager_qt.cpp b/src/core/permission_manager_qt.cpp
index 31953fb6900..e57e12e3d0e 100644
--- a/src/core/permission_manager_qt.cpp
+++ b/src/core/permission_manager_qt.cpp
@@ -26,6 +26,8 @@
 #include "web_contents_delegate_qt.h"
 #include "web_engine_settings.h"
 
+using namespace Qt::StringLiterals;
+
 namespace QtWebEngineCore {
 
 static QWebEnginePermission::PermissionType toQt(blink::PermissionType type)
@@ -77,6 +79,9 @@ static QWebEnginePermission::PermissionType toQt(blink::PermissionType type)
     case blink::PermissionType::WEB_PRINTING:
     case blink::PermissionType::SPEAKER_SELECTION:
     case blink::PermissionType::KEYBOARD_LOCK:
+    case blink::PermissionType::AUTOMATIC_FULLSCREEN:
+    case blink::PermissionType::HAND_TRACKING:
+    case blink::PermissionType::WEB_APP_INSTALLATION:
         LOG(INFO) << "Unexpected unsupported Blink permission type: " << static_cast<int>(type);
         break;
     }
@@ -110,8 +115,7 @@ static blink::PermissionType toBlink(QWebEnginePermission::PermissionType permis
         return blink::PermissionType::NUM;
     }
 
-    Q_UNREACHABLE();
-    return blink::PermissionType::NUM;
+    Q_UNREACHABLE_RETURN(blink::PermissionType::NUM);
 }
 
 static QWebEnginePermission::State toQt(blink::mojom::PermissionStatus state)
@@ -162,8 +166,7 @@ std::string permissionTypeString(QWebEnginePermission::PermissionType permission
     case QWebEnginePermission::PermissionType::LocalFontsAccess:
         return "LocalFontsAccess";
     default:
-        Q_UNREACHABLE();
-        return nullptr;
+        Q_UNREACHABLE_RETURN(nullptr);
     }
 }
 
@@ -195,14 +198,15 @@ PermissionManagerQt::PermissionManagerQt(ProfileAdapter *profileAdapter)
     factory.set_command_line_prefs(base::MakeRefCounted<ChromeCommandLinePrefStore>(
             base::CommandLine::ForCurrentProcess()));
 
-    QString userPrefStorePath = profileAdapter->dataPath();
+    QString userPrefStorePath;
+    userPrefStorePath += profileAdapter->dataPath();
     auto prefRegistry = base::MakeRefCounted<PrefRegistrySimple>();
 
     auto policy = profileAdapter->persistentPermissionsPolicy();
     if (!profileAdapter->isOffTheRecord() && policy == ProfileAdapter::PersistentPermissionsPolicy::StoreOnDisk &&
             !userPrefStorePath.isEmpty() && profileAdapter->ensureDataPathExists()) {
         userPrefStorePath += QDir::separator();
-        userPrefStorePath += QStringLiteral("permissions.json");
+        userPrefStorePath += "permissions.json"_L1;
         factory.set_user_prefs(base::MakeRefCounted<JsonPrefStore>(toFilePath(userPrefStorePath)));
     } else {
         factory.set_user_prefs(new InMemoryPrefStore);
@@ -275,9 +279,38 @@ void PermissionManagerQt::setPermission(
         }
     }
 
-    for (const auto &it : m_subscribers) {
-        if (it.second.origin == origin && it.second.type == permissionType)
-            it.second.callback.Run(blinkStatus);
+    // Notify subscribers
+    if (subscriptions()) {
+        std::vector<base::OnceClosure> callbacks;
+        callbacks.reserve(subscriptions()->size());
+        for (content::PermissionController::SubscriptionsMap::iterator iter(subscriptions());
+             !iter.IsAtEnd(); iter.Advance()) {
+            content::PermissionStatusSubscription *subscription = iter.GetCurrentValue();
+            if (!subscription)
+                continue;
+            content::RenderFrameHost *targetRfh = content::RenderFrameHost::FromID(
+                    subscription->render_process_id, subscription->render_frame_id);
+
+            if (subscription->embedding_origin != gorigin)
+                continue;
+            if (subscription->permission != toBlink(permissionType))
+                continue;
+            if ((!QWebEnginePermission::isPersistent(permissionType) || !m_persistence)
+                    && targetRfh && targetRfh != rfh)
+                continue;
+
+            // Behavior in callbacks may differ depending on the denial reason. Until we have
+            // a good reason to not do so, we just pass UNSPECIFIED to get the default behavior everywhere.
+            content::PermissionResult new_value(blinkStatus, content::PermissionStatusSource::UNSPECIFIED);
+            if (subscription->permission_result && subscription->permission_result->status == new_value.status)
+                continue;
+            subscription->permission_result = new_value;
+
+            callbacks.push_back(base::BindOnce(subscription->callback, blinkStatus,
+                                               /*ignore_status_override=*/false));
+        }
+        for (auto &callback : callbacks)
+            std::move(callback).Run();
     }
 
     if (state == QWebEnginePermission::State::Ask)
@@ -590,25 +623,6 @@ void PermissionManagerQt::ResetPermission(
     updater.Get().Remove(requesting_origin.spec());
 }
 
-content::PermissionControllerDelegate::SubscriptionId
-PermissionManagerQt::SubscribeToPermissionStatusChange(
-        blink::PermissionType permission, content::RenderProcessHost * /*render_process_host*/,
-        content::RenderFrameHost * /* render_frame_host */, const GURL &requesting_origin, bool,
-        base::RepeatingCallback<void(blink::mojom::PermissionStatus)> callback)
-{
-    auto subscriber_id = subscription_id_generator_.GenerateNextId();
-    m_subscribers.insert( { subscriber_id,
-                            Subscription { toQt(permission), toQt(requesting_origin), std::move(callback) } });
-    return subscriber_id;
-}
-
-void PermissionManagerQt::UnsubscribeFromPermissionStatusChange(
-        content::PermissionControllerDelegate::SubscriptionId subscription_id)
-{
-    if (!m_subscribers.erase(subscription_id))
-        LOG(WARNING) << "PermissionManagerQt::UnsubscribePermissionStatusChange called on unknown subscription id" << subscription_id;
-}
-
 blink::mojom::PermissionStatus PermissionManagerQt::getTransientPermissionStatus(blink::PermissionType permission,
         const GURL& requesting_origin,
         content::GlobalRenderFrameHostToken token)
diff --git a/src/core/permission_manager_qt.h b/src/core/permission_manager_qt.h
index 9c0e2d77815..7468e9861c4 100644
--- a/src/core/permission_manager_qt.h
+++ b/src/core/permission_manager_qt.h
@@ -66,14 +66,6 @@ class PermissionManagerQt : public content::PermissionControllerDelegate
             const content::PermissionRequestDescription &request_description,
             base::OnceCallback<void(const std::vector<blink::mojom::PermissionStatus> &)> callback) override;
 
-    content::PermissionControllerDelegate::SubscriptionId SubscribeToPermissionStatusChange(
-            blink::PermissionType permission, content::RenderProcessHost *render_process_host,
-            content::RenderFrameHost *render_frame_host, const GURL &requesting_origin, bool,
-            const base::RepeatingCallback<void(blink::mojom::PermissionStatus)> callback) override;
-
-    void UnsubscribeFromPermissionStatusChange(
-            content::PermissionControllerDelegate::SubscriptionId subscription_id) override;
-
 private:
     struct Request {
         int id;
@@ -115,8 +107,6 @@ class PermissionManagerQt : public content::PermissionControllerDelegate
     std::vector<QWebEnginePermission::PermissionType> m_permissionTypes;
     std::map<content::GlobalRenderFrameHostToken,
         QList<std::tuple<GURL, blink::PermissionType, bool>>> m_transientPermissions;
-    std::map<content::PermissionControllerDelegate::SubscriptionId, Subscription> m_subscribers;
-    content::PermissionControllerDelegate::SubscriptionId::Generator subscription_id_generator_;
     int m_requestIdCount;
     int m_transientWriteCount;
     std::unique_ptr<PrefService> m_prefService;
diff --git a/src/core/pref_service_adapter.cpp b/src/core/pref_service_adapter.cpp
index 011aeb05c4f..0e11058395d 100644
--- a/src/core/pref_service_adapter.cpp
+++ b/src/core/pref_service_adapter.cpp
@@ -55,6 +55,8 @@ namespace {
 static const char kPrefMediaDeviceIDSalt[] = "qtwebengine.media_device_salt_id";
 }
 
+using namespace Qt::StringLiterals;
+
 namespace QtWebEngineCore {
 
 void PrefServiceAdapter::setup(const ProfileAdapter &profileAdapter)
@@ -64,11 +66,12 @@ void PrefServiceAdapter::setup(const ProfileAdapter &profileAdapter)
     factory.set_command_line_prefs(base::MakeRefCounted<ChromeCommandLinePrefStore>(
             base::CommandLine::ForCurrentProcess()));
 
-    QString userPrefStorePath = profileAdapter.dataPath();
+    QString userPrefStorePath;
+    userPrefStorePath += profileAdapter.dataPath();
     if (!profileAdapter.isOffTheRecord() && !userPrefStorePath.isEmpty() &&
             const_cast<ProfileAdapter *>(&profileAdapter)->ensureDataPathExists()) {
         userPrefStorePath += QDir::separator();
-        userPrefStorePath += QStringLiteral("user_prefs.json");
+        userPrefStorePath += "user_prefs.json"_L1;
         factory.set_user_prefs(base::MakeRefCounted<JsonPrefStore>(toFilePath(userPrefStorePath)));
     } else {
         factory.set_user_prefs(new InMemoryPrefStore);
@@ -205,7 +208,10 @@ QStringList PrefServiceAdapter::spellCheckLanguages() const
 
 void PrefServiceAdapter::setSpellCheckEnabled(bool enabled)
 {
-    if (!WebEngineLibraryInfo::getPath(base::DIR_APP_DICTIONARIES, true).empty()) {
+    if (enabled == m_prefService->GetBoolean(spellcheck::prefs::kSpellCheckEnable))
+        return;
+
+    if (!WebEngineLibraryInfo::getPath(base::DIR_APP_DICTIONARIES, enabled).empty()) {
         m_prefService->SetBoolean(spellcheck::prefs::kSpellCheckEnable, enabled);
         m_prefService->SchedulePendingLossyWrites();
     }
diff --git a/src/core/printing/pdf_stream_delegate_qt.cpp b/src/core/printing/pdf_stream_delegate_qt.cpp
index afb21e17d07..bb82c3302d1 100644
--- a/src/core/printing/pdf_stream_delegate_qt.cpp
+++ b/src/core/printing/pdf_stream_delegate_qt.cpp
@@ -98,7 +98,7 @@ PdfStreamDelegateQt::GetStreamInfo(content::RenderFrameHost* embedder_frame)
     return helper->TakeStreamInfo();
 }
 
-void PdfStreamDelegateQt::OnPdfEmbedderSandboxed(int)
+void PdfStreamDelegateQt::OnPdfEmbedderSandboxed(content::FrameTreeNodeId)
 {
     NOTIMPLEMENTED();
 }
diff --git a/src/core/printing/pdf_stream_delegate_qt.h b/src/core/printing/pdf_stream_delegate_qt.h
index 4999775d323..61ceed777d2 100644
--- a/src/core/printing/pdf_stream_delegate_qt.h
+++ b/src/core/printing/pdf_stream_delegate_qt.h
@@ -18,7 +18,7 @@ class PdfStreamDelegateQt : public pdf::PdfStreamDelegate
     // pdf::PdfStreamDelegate:
     std::optional<GURL> MapToOriginalUrl(content::NavigationHandle &navigation_handle) override;
     std::optional<StreamInfo> GetStreamInfo(content::RenderFrameHost *embedder_frame) override;
-    void OnPdfEmbedderSandboxed(int) override;
+    void OnPdfEmbedderSandboxed(content::FrameTreeNodeId) override;
     bool ShouldAllowPdfFrameNavigation(content::NavigationHandle*) override;
 };
 
diff --git a/src/core/printing/print_view_manager_base_qt.cpp b/src/core/printing/print_view_manager_base_qt.cpp
index a691bc2b64b..742862a53ef 100644
--- a/src/core/printing/print_view_manager_base_qt.cpp
+++ b/src/core/printing/print_view_manager_base_qt.cpp
@@ -27,12 +27,14 @@
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/render_view_host.h"
-#include "content/public/browser/notification_service.h"
-#include "content/public/browser/notification_types.h"
 #include "printing/metafile_skia.h"
 #include "printing/print_job_constants.h"
 #include "printing/printed_document.h"
 
+#include <string>
+
+using namespace std::string_literals;
+
 namespace QtWebEngineCore {
 
 namespace {
@@ -160,7 +162,7 @@ void PrintViewManagerBaseQt::NavigationStopped()
 
 std::u16string PrintViewManagerBaseQt::RenderSourceName()
 {
-     return toString16(QLatin1String(""));
+    return u""s;
 }
 
 void PrintViewManagerBaseQt::PrintDocument(scoped_refptr<base::RefCountedMemory> print_data,
diff --git a/src/core/printing/print_view_manager_base_qt.h b/src/core/printing/print_view_manager_base_qt.h
index d4b5bfe826b..f2d4149abd4 100644
--- a/src/core/printing/print_view_manager_base_qt.h
+++ b/src/core/printing/print_view_manager_base_qt.h
@@ -13,8 +13,6 @@
 #include "components/prefs/pref_member.h"
 #include "components/printing/browser/print_manager.h"
 #include "components/printing/common/print.mojom-forward.h"
-#include "content/public/browser/notification_observer.h"
-#include "content/public/browser/notification_registrar.h"
 
 namespace base {
 class RefCountedBytes;
@@ -130,7 +128,6 @@ class PrintViewManagerBaseQt : public printing::PrintManager
     void ReleasePrinterQuery();
 
 private:
-    content::NotificationRegistrar m_registrar;
     scoped_refptr<printing::PrintJob> m_printJob;
     content::RenderFrameHost *m_printingRFH;
     bool m_didPrintingSucceed;
diff --git a/src/core/printing/print_view_manager_qt.cpp b/src/core/printing/print_view_manager_qt.cpp
index a2bafa741db..b0f1788fdd3 100644
--- a/src/core/printing/print_view_manager_qt.cpp
+++ b/src/core/printing/print_view_manager_qt.cpp
@@ -265,7 +265,8 @@ bool PrintViewManagerQt::PrintToPDFInternal(const QPageLayout &pageLayout,
                     FindPdfChildFrame(full_page_plugin ? full_page_plugin : rfh))
             rfh = pdf_rfh;
     } else {
-        auto *ftn = content::FrameTreeNode::GloballyFindByID(static_cast<int>(frameId));
+        auto *ftn = content::FrameTreeNode::GloballyFindByID(
+                static_cast<content::FrameTreeNodeId>(frameId));
         if (!ftn)
             return false;
         rfh = ftn->current_frame_host();
@@ -362,7 +363,8 @@ void PrintViewManagerQt::SetupScriptedPrintPreview(SetupScriptedPrintPreviewCall
     if (web_contents()->GetPrimaryMainFrame() == rfh)
         client->printRequested();
     else
-        client->printRequestedByFrame(static_cast<quint64>(rfh->GetFrameTreeNodeId()));
+        client->printRequestedByFrame(
+                static_cast<quint64>(rfh->GetFrameTreeNodeId().GetUnsafeValue()));
 }
 
 void PrintViewManagerQt::ShowScriptedPrintPreview(bool /*source_is_modifiable*/)
diff --git a/src/core/profile_adapter.cpp b/src/core/profile_adapter.cpp
index 8a7e491dca9..d3a00ad551e 100644
--- a/src/core/profile_adapter.cpp
+++ b/src/core/profile_adapter.cpp
@@ -41,13 +41,16 @@
 #include <QString>
 #include <QStandardPaths>
 
+using namespace Qt::StringLiterals;
+
 namespace {
 inline QString buildLocationFromStandardPath(const QString &standardPath, const QString &name) {
-    QString location = standardPath;
+    QString location;
+    location += standardPath;
     if (location.isEmpty())
-        location = QDir::homePath() % QLatin1String("/.") % QCoreApplication::applicationName();
+        location += QDir::homePath() % "/."_L1 % QCoreApplication::applicationName();
 
-    location.append(QLatin1String("/QtWebEngine/") % name);
+    location += "/QtWebEngine/"_L1 % name;
     return location;
 }
 }
@@ -270,9 +273,9 @@ QString ProfileAdapter::dataPath() const
     // a location to do so.
     QString name = m_name;
     if (m_offTheRecord)
-        name = QStringLiteral("OffTheRecord");
+        name = u"OffTheRecord"_s;
     else if (m_name.isEmpty())
-        name = QStringLiteral("UnknownProfile");
+        name = u"UnknownProfile"_s;
     return buildLocationFromStandardPath(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation), name);
 }
 
@@ -322,9 +325,9 @@ QString ProfileAdapter::httpCachePath() const
 {
     if (m_offTheRecord)
         return QString();
-    QString basePath = cachePath();
+    const QString basePath = cachePath();
     if (!basePath.isEmpty())
-        return basePath % QLatin1String("/Cache");
+        return basePath % "/Cache"_L1;
     return QString();
 }
 
@@ -537,7 +540,7 @@ void ProfileAdapter::removeUrlSchemeHandler(QWebEngineUrlSchemeHandler *handler)
 
 void ProfileAdapter::removeUrlScheme(const QByteArray &scheme)
 {
-    QByteArray canonicalScheme = scheme.toLower();
+    const QByteArray canonicalScheme = scheme.toLower();
     if (schemeType(canonicalScheme) == SchemeType::Protected) {
         qWarning("Cannot remove the URL scheme handler for an internal scheme: %s", scheme.constData());
         return;
@@ -549,7 +552,7 @@ void ProfileAdapter::removeUrlScheme(const QByteArray &scheme)
 void ProfileAdapter::installUrlSchemeHandler(const QByteArray &scheme, QWebEngineUrlSchemeHandler *handler)
 {
     Q_ASSERT(handler);
-    QByteArray canonicalScheme = scheme.toLower();
+    const QByteArray canonicalScheme = scheme.toLower();
     SchemeType type = schemeType(canonicalScheme);
 
     if (type == SchemeType::Protected) {
@@ -608,12 +611,12 @@ QList<QWebEnginePermission> ProfileAdapter::listPermissions(const QUrl &origin,
 
 QString ProfileAdapter::httpAcceptLanguageWithoutQualities() const
 {
-    const QStringList list = m_httpAcceptLanguage.split(QLatin1Char(','));
     QString out;
-    for (const QString &str : list) {
-        if (!out.isEmpty())
-            out.append(QLatin1Char(','));
-        out.append(str.split(QLatin1Char(';')).first());
+    auto sep = ""_L1;
+    for (auto lang : m_httpAcceptLanguage.tokenize(u',')) {
+        out += sep;
+        out += *lang.tokenize(u';').begin(); // tokenize() is never empty with KeepEmptyParts!
+        sep = ","_L1;
     }
     return out;
 }
diff --git a/src/core/profile_adapter_client.h b/src/core/profile_adapter_client.h
index aaeefb5440a..cb83e82799b 100644
--- a/src/core/profile_adapter_client.h
+++ b/src/core/profile_adapter_client.h
@@ -103,7 +103,7 @@ class Q_WEBENGINECORE_EXPORT ProfileAdapterClient
 
     virtual ~ProfileAdapterClient() { }
 
-    virtual void downloadRequested(DownloadItemInfo &info) = 0;
+    virtual void downloadRequested(const DownloadItemInfo &info) = 0;
     virtual void downloadUpdated(const DownloadItemInfo &info) = 0;
     virtual void showNotification(QSharedPointer<UserNotificationController> &) { }
 
diff --git a/src/core/profile_io_data_qt.cpp b/src/core/profile_io_data_qt.cpp
index dd448a66c90..d57af0b4023 100644
--- a/src/core/profile_io_data_qt.cpp
+++ b/src/core/profile_io_data_qt.cpp
@@ -62,7 +62,7 @@ void ProfileIODataQt::shutdownOnUIThread()
 
     bool posted = content::BrowserThread::DeleteSoon(content::BrowserThread::IO, FROM_HERE, this);
     if (!posted) {
-        qWarning() << "Could not delete ProfileIODataQt on io thread !";
+        qWarning("Could not delete ProfileIODataQt on io thread !");
         delete this;
     }
 }
diff --git a/src/core/profile_qt.cpp b/src/core/profile_qt.cpp
index a85685e81b6..04c58ac34e6 100644
--- a/src/core/profile_qt.cpp
+++ b/src/core/profile_qt.cpp
@@ -267,7 +267,8 @@ void ProfileQt::setupStoragePath()
     auto it = std::find(storagePaths.begin(), storagePaths.end(), thisStoragePath);
     if (it == storagePaths.end()) {
         if (storagePaths.size() >= (PATH_QT_END - PATH_QT_START)) {
-            qWarning() << "Number of profile paths exceeded " << PATH_QT_END - PATH_QT_START << ", storage may break";
+            qWarning("Number of profile paths exceeded %ull, storage may break",
+                     static_cast<qulonglong>(PATH_QT_END - PATH_QT_START));
             return;
         }
 
diff --git a/src/core/render_view_context_menu_qt.cpp b/src/core/render_view_context_menu_qt.cpp
index b7aabfd5b66..089b9202003 100644
--- a/src/core/render_view_context_menu_qt.cpp
+++ b/src/core/render_view_context_menu_qt.cpp
@@ -36,7 +36,7 @@ namespace QtWebEngineCore {
             QT_TRANSLATE_NOOP("RenderViewContextMenuQt", "Save page"),
             QT_TRANSLATE_NOOP("RenderViewContextMenuQt", "View page source")
         };
-        return QCoreApplication::translate("RenderViewContextMenuQt", qUtf8Printable(names[menuItem]));
+        return QCoreApplication::translate("RenderViewContextMenuQt", names[menuItem]);
     }
 
     RenderViewContextMenuQt::RenderViewContextMenuQt(QWebEngineContextMenuRequest *request)
diff --git a/src/core/render_widget_host_view_qt.cpp b/src/core/render_widget_host_view_qt.cpp
index e17e5075c13..0d3d9777514 100644
--- a/src/core/render_widget_host_view_qt.cpp
+++ b/src/core/render_widget_host_view_qt.cpp
@@ -12,6 +12,8 @@
 #include "web_contents_adapter_client.h"
 #include "web_event_factory.h"
 
+#include "components/input/cursor_manager.h"
+#include "components/input/render_widget_host_input_event_router.h"
 #include "components/viz/common/features.h"
 #include "components/viz/common/frame_sinks/begin_frame_source.h"
 #include "components/viz/common/surfaces/frame_sink_id_allocator.h"
@@ -20,14 +22,12 @@
 #include "content/browser/renderer_host/render_frame_host_impl.h"
 #include "content/browser/renderer_host/frame_tree.h"
 #include "content/browser/renderer_host/frame_tree_node.h"
-#include "content/browser/renderer_host/cursor_manager.h"
 #include "content/browser/renderer_host/render_frame_host_impl.h"
 #include "content/browser/renderer_host/render_view_host_delegate.h"
 #include "content/browser/renderer_host/render_view_host_impl.h"
-#include "content/browser/renderer_host/render_widget_host_input_event_router.h"
-#include "content/browser/renderer_host/ui_events_helper.h"
 #include "content/common/content_switches_internal.h"
 #include "content/common/cursors/webcursor.h"
+#include "content/common/input/events_helper.h"
 #include "content/common/input/synthetic_gesture_target.h"
 #include "content/public/browser/web_contents.h"
 #include "third_party/skia/include/core/SkColor.h"
@@ -96,7 +96,7 @@ static display::ScreenInfos screenInfosFromQtForUpdate(QScreen *currentScreen)
 {
     display::ScreenInfo screenInfo;
     const auto &screens = qApp->screens();
-    if (screens.isEmpty()) {
+    if (!currentScreen || screens.isEmpty()) {
         screenInfo.device_scale_factor = qGuiApp->devicePixelRatio();
         return display::ScreenInfos(screenInfo);
     }
@@ -136,7 +136,7 @@ class FlingingCompositor : public ui::Compositor
 
     void BeginMainFrame(const viz::BeginFrameArgs &args) override
     {
-        if (args.type != viz::BeginFrameArgs::MISSED && !m_rwhv->is_currently_scrolling_viewport())
+        if (args.type != viz::BeginFrameArgs::MISSED && !m_rwhv->GetViewRenderInputRouter()->is_currently_scrolling_viewport())
             m_rwhv->host()->ProgressFlingIfNeeded(args.frame_time);
         ui::Compositor::BeginMainFrame(args);
     }
@@ -176,7 +176,7 @@ RenderWidgetHostViewQt::RenderWidgetHostViewQt(content::RenderWidgetHost *widget
     if (host()->delegate() && host()->delegate()->GetInputEventRouter())
         host()->delegate()->GetInputEventRouter()->AddFrameSinkIdOwner(GetFrameSinkId(), this);
 
-    m_cursorManager.reset(new content::CursorManager(this));
+    m_cursorManager.reset(new input::CursorManager(this));
 
     m_touchSelectionControllerClient.reset(new TouchSelectionControllerClientQt(this));
     resetTouchSelectionController();
@@ -308,7 +308,9 @@ void RenderWidgetHostViewQt::OnRendererWidgetCreated()
 
 QObject *WebContentsAccessibilityQt::accessibilityParentObject() const
 {
-    return m_rwhv->m_adapterClient->accessibilityParentObject();
+    if (m_rwhv && m_rwhv->m_adapterClient)
+        return m_rwhv->m_adapterClient->accessibilityParentObject();
+    return nullptr;
 }
 
 // Set focus to the associated View component.
@@ -460,12 +462,10 @@ bool RenderWidgetHostViewQt::updateCursorFromResource(ui::mojom::CursorType type
         hotY = 7;
         break;
     default:
-        Q_UNREACHABLE();
-        return false;
+        Q_UNREACHABLE_RETURN(false);
     }
 #else
-    Q_UNREACHABLE();
-    return false;
+    Q_UNREACHABLE_RETURN(false);
 #endif
 
     const gfx::ImageSkia *imageSkia = ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(resourceId);
@@ -609,7 +609,7 @@ void RenderWidgetHostViewQt::DisplayCursor(const ui::Cursor &cursorInfo)
     m_delegate->updateCursor(QCursor(shape));
 }
 
-content::CursorManager *RenderWidgetHostViewQt::GetCursorManager()
+input::CursorManager *RenderWidgetHostViewQt::GetCursorManager()
 {
     return m_cursorManager.get();
 }
@@ -638,7 +638,7 @@ void RenderWidgetHostViewQt::RenderProcessGone()
 }
 
 bool RenderWidgetHostViewQt::TransformPointToCoordSpaceForView(const gfx::PointF &point,
-                                                               content::RenderWidgetHostViewInput *target_view,
+                                                               input::RenderWidgetHostViewInput *target_view,
                                                                gfx::PointF *transformed_point)
 {
     if (target_view == this) {
@@ -763,9 +763,9 @@ void RenderWidgetHostViewQt::OnTextSelectionChanged(content::TextInputManager *t
 
 void RenderWidgetHostViewQt::OnGestureEvent(const ui::GestureEventData& gesture)
 {
-    if ((gesture.type() == ui::ET_GESTURE_PINCH_BEGIN
-         || gesture.type() == ui::ET_GESTURE_PINCH_UPDATE
-         || gesture.type() == ui::ET_GESTURE_PINCH_END)
+    if ((gesture.type() == ui::EventType::kGesturePinchBegin
+         || gesture.type() == ui::EventType::kGesturePinchUpdate
+         || gesture.type() == ui::EventType::kGesturePinchEnd)
         && !content::IsPinchToZoomEnabled()) {
         return;
     }
@@ -845,7 +845,7 @@ void RenderWidgetHostViewQt::notifyHidden()
     m_delegatedFrameHost->DetachFromCompositor();
 }
 
-void RenderWidgetHostViewQt::ProcessAckedTouchEvent(const content::TouchEventWithLatencyInfo &touch, blink::mojom::InputEventResultState ack_result)
+void RenderWidgetHostViewQt::ProcessAckedTouchEvent(const input::TouchEventWithLatencyInfo &touch, blink::mojom::InputEventResultState ack_result)
 {
     const bool eventConsumed = (ack_result == blink::mojom::InputEventResultState::kConsumed);
     const bool isSetBlocking = content::InputEventResultStateIsSetBlocking(ack_result);
@@ -925,6 +925,7 @@ void RenderWidgetHostViewQt::WheelEventAck(const blink::WebMouseWheelEvent &even
 }
 
 void RenderWidgetHostViewQt::GestureEventAck(const blink::WebGestureEvent &event,
+                                             blink::mojom::InputEventResultSource ack_source,
                                              blink::mojom::InputEventResultState ack_result)
 {
     ForwardTouchpadZoomEventIfNecessary(event, ack_result);
diff --git a/src/core/render_widget_host_view_qt.h b/src/core/render_widget_host_view_qt.h
index 821e563d3ab..64c19acdbb2 100644
--- a/src/core/render_widget_host_view_qt.h
+++ b/src/core/render_widget_host_view_qt.h
@@ -8,7 +8,6 @@
 #include "delegated_frame_host_client_qt.h"
 #include "render_widget_host_view_qt_delegate.h"
 
-#include "base/memory/weak_ptr.h"
 #include "components/viz/common/resources/transferable_resource.h"
 #include "components/viz/common/surfaces/parent_local_surface_id_allocator.h"
 #include "components/viz/host/host_frame_sink_client.h"
@@ -39,7 +38,6 @@ class WebContentsAdapterClient;
 class RenderWidgetHostViewQt
     : public content::RenderWidgetHostViewBase
     , public ui::GestureProviderClient
-    , public base::SupportsWeakPtr<RenderWidgetHostViewQt>
     , public content::TextInputManager::Observer
     , public content::RenderFrameMetadataProvider::Observer
     , public content::RenderWidgetHost::InputEventObserver
@@ -79,7 +77,7 @@ class RenderWidgetHostViewQt
     void UnlockPointer() override;
     void UpdateCursor(const ui::Cursor&) override;
     void DisplayCursor(const ui::Cursor&) override;
-    content::CursorManager *GetCursorManager() override;
+    input::CursorManager *GetCursorManager() override;
     void SetIsLoading(bool) override;
     void ImeCancelComposition() override;
     void ImeCompositionRangeChanged(const gfx::Range &,
@@ -87,7 +85,7 @@ class RenderWidgetHostViewQt
                                     const std::optional<std::vector<gfx::Rect>> &) override;
     void RenderProcessGone() override;
     bool TransformPointToCoordSpaceForView(const gfx::PointF &point,
-                                           content::RenderWidgetHostViewInput *target_view,
+                                           input::RenderWidgetHostViewInput *target_view,
                                            gfx::PointF *transformed_point) override;
     void Destroy() override;
     void UpdateTooltipUnderCursor(const std::u16string &tooltip_text) override;
@@ -95,6 +93,7 @@ class RenderWidgetHostViewQt
     void WheelEventAck(const blink::WebMouseWheelEvent &event,
                        blink::mojom::InputEventResultState ack_result) override;
     void GestureEventAck(const blink::WebGestureEvent &event,
+                         blink::mojom::InputEventResultSource ack_source,
                          blink::mojom::InputEventResultState ack_result) override;
     content::MouseWheelPhaseHandler *GetMouseWheelPhaseHandler() override;
     viz::ScopedSurfaceIdAllocator DidUpdateVisualProperties(const cc::RenderFrameMetadata &metadata) override;
@@ -102,7 +101,7 @@ class RenderWidgetHostViewQt
 
     // Overridden from RenderWidgetHostViewBase:
     gfx::Rect GetBoundsInRootWindow() override;
-    void ProcessAckedTouchEvent(const content::TouchEventWithLatencyInfo &touch,
+    void ProcessAckedTouchEvent(const input::TouchEventWithLatencyInfo &touch,
                                 blink::mojom::InputEventResultState ack_result) override;
     viz::SurfaceId GetCurrentSurfaceId() const override;
     const viz::FrameSinkId &GetFrameSinkId() const override;
@@ -194,7 +193,7 @@ class RenderWidgetHostViewQt
 
     scoped_refptr<base::SingleThreadTaskRunner> m_taskRunner;
 
-    std::unique_ptr<content::CursorManager> m_cursorManager;
+    std::unique_ptr<input::CursorManager> m_cursorManager;
 
     ui::FilteredGestureProvider m_gestureProvider;
 
@@ -232,8 +231,6 @@ class RenderWidgetHostViewQt
     std::unique_ptr<ui::TouchSelectionController> m_touchSelectionController;
     gfx::SelectionBound m_selectionStart;
     gfx::SelectionBound m_selectionEnd;
-
-    base::WeakPtrFactory<RenderWidgetHostViewQt> m_weakPtrFactory { this };
 };
 
 class WebContentsAccessibilityQt : public content::WebContentsAccessibility
diff --git a/src/core/render_widget_host_view_qt_delegate_client.cpp b/src/core/render_widget_host_view_qt_delegate_client.cpp
index 9bc69e9bfcf..43420beabf5 100644
--- a/src/core/render_widget_host_view_qt_delegate_client.cpp
+++ b/src/core/render_widget_host_view_qt_delegate_client.cpp
@@ -10,10 +10,11 @@
 #include "web_contents_adapter_client.h"
 #include "web_event_factory.h"
 
+#include "components/input/render_widget_host_input_event_router.h"
 #include "content/browser/renderer_host/render_view_host_impl.h"
-#include "content/browser/renderer_host/render_widget_host_input_event_router.h"
 #include "ui/touch_selection/touch_selection_controller.h"
 
+#include <QDebug>
 #include <QEvent>
 #include <QInputMethodEvent>
 #include <QSet>
@@ -24,6 +25,8 @@
 #include <QtGui/private/qguiapplication_p.h>
 #include <QtGui/private/qinputcontrol_p.h>
 
+using namespace Qt::StringLiterals;
+
 namespace QtWebEngineCore {
 
 static inline int firstAvailableId(const QMap<int, int> &map)
@@ -76,12 +79,31 @@ class MotionEventQt : public ui::MotionEvent
         , flags(flagsFromModifiers(modifiers))
         , index(index)
     {
+#if !defined(QT_NO_DEBUG) || defined(QT_FORCE_ASSERTS)
         // index is only valid for POINTER_DOWN and POINTER_UP and should correspond to the point
         // causing it see blink_event_util.cc:ToWebTouchPointState for details
-        Q_ASSERT_X((action != Action::POINTER_DOWN && action != Action::POINTER_UP && index == -1)
-                || (action == Action::POINTER_DOWN && index >= 0 && touchPoint(index).state() == QEventPoint::Pressed)
-                || (action == Action::POINTER_UP && index >= 0 && touchPoint(index).state() == QEventPoint::Released),
-                "MotionEventQt", qPrintable(QString("action: %1, index: %2, state: %3").arg(int(action)).arg(index).arg(touchPoint(index).state())));
+        if (action == Action::POINTER_DOWN || action == Action::POINTER_UP) {
+            const auto actionString = (action == Action::POINTER_DOWN ? "Action::POINTER_DOWN"_L1
+                                                                      : "Action::POINTER_UP"_L1);
+            Q_ASSERT_X(index >= 0 && index < touchPoints.size(), "MotionEventQt",
+                       qPrintable("Invalid index for "_L1 + actionString + ": "_L1
+                                  + QString::number(index)));
+
+            const QEventPoint::State state = touchPoint(index).state();
+            QString stateString;
+            QDebug(&stateString) << state;
+            Q_ASSERT_X(
+                    (action == Action::POINTER_DOWN && state == QEventPoint::Pressed)
+                            || (action == Action::POINTER_UP && state == QEventPoint::Released),
+                    "MotionEventQt",
+                    qPrintable("Unexpected state for "_L1 + actionString + ": "_L1 + stateString));
+        } else {
+            Q_ASSERT_X(index == -1, "MotionEventQt",
+                       qPrintable("Unexpected index for action "_L1
+                                  + QString::number(static_cast<int>(action)) + ": "_L1
+                                  + QString::number(index)));
+        }
+#endif
     }
 
     uint32_t GetUniqueEventId() const override { return eventId; }
@@ -486,10 +508,9 @@ void RenderWidgetHostViewQtDelegateClient::handleKeyEvent(QKeyEvent *event)
     if (!m_rwhv->GetFocusedWidget())
         return;
 
-    content::NativeWebKeyboardEvent webEvent = WebEventFactory::toWebKeyboardEvent(event);
+    input::NativeWebKeyboardEvent webEvent = WebEventFactory::toWebKeyboardEvent(event);
     if (webEvent.GetType() == blink::WebInputEvent::Type::kRawKeyDown && !m_editCommand.empty()) {
         ui::LatencyInfo latency;
-        latency.set_source_event_type(ui::SourceEventType::KEY_PRESS);
         std::vector<blink::mojom::EditCommandPtr> commands;
         commands.emplace_back(blink::mojom::EditCommand::New(m_editCommand, ""));
         m_editCommand.clear();
@@ -744,8 +765,8 @@ void RenderWidgetHostViewQtDelegateClient::handleInputMethodEvent(QInputMethodEv
     if (!m_rwhv->host())
         return;
 
-    QString commitString = event->commitString();
-    QString preeditString = event->preeditString();
+    const QString commitString = event->commitString();
+    const QString preeditString = event->preeditString();
 
     int cursorPositionInPreeditString = -1;
     gfx::Range selectionRange = gfx::Range::InvalidRange();
diff --git a/src/core/render_widget_host_view_qt_delegate_item.cpp b/src/core/render_widget_host_view_qt_delegate_item.cpp
index 6ece45f9bb2..e82dabb5fff 100644
--- a/src/core/render_widget_host_view_qt_delegate_item.cpp
+++ b/src/core/render_widget_host_view_qt_delegate_item.cpp
@@ -14,6 +14,8 @@
 #include <QtGui/qaccessible.h>
 #endif
 
+using namespace Qt::StringLiterals;
+
 namespace QtWebEngineCore {
 
 RenderWidgetHostViewQtDelegateItem::RenderWidgetHostViewQtDelegateItem(RenderWidgetHostViewQtDelegateClient *client, bool isPopup)
@@ -35,8 +37,8 @@ RenderWidgetHostViewQtDelegateItem::RenderWidgetHostViewQtDelegateItem(RenderWid
 
 RenderWidgetHostViewQtDelegateItem::~RenderWidgetHostViewQtDelegateItem()
 {
-    unbind(); // Compositor::Observer
     releaseTextureResources();
+    unbind(); // Compositor::Observer
     if (m_widgetDelegate) {
         m_widgetDelegate->Unbind();
         m_widgetDelegate->Destroy();
@@ -54,8 +56,8 @@ void RenderWidgetHostViewQtDelegateItem::initAsPopup(const QRect &screenRect)
 QRectF RenderWidgetHostViewQtDelegateItem::viewGeometry() const
 {
     // Transform the entire rect to find the correct top left corner.
-    const QPointF p1 = mapToGlobal(mapFromScene(QPointF(0, 0)));
-    const QPointF p2 = mapToGlobal(mapFromScene(QPointF(width(), height())));
+    const QPointF p1 = mapToGlobal(mapFromItem(this, QPointF(0, 0)));
+    const QPointF p2 = mapToGlobal(mapFromItem(this, QPointF(width(), height())));
     QRectF geometry = QRectF(p1, p2).normalized();
     // But keep the size untransformed to behave like other QQuickItems.
     geometry.setSize(size());
@@ -346,7 +348,7 @@ void RenderWidgetHostViewQtDelegateItem::itemChange(ItemChange change, const Ite
                             &RenderWidgetHostViewQtDelegateItem::releaseTextureResources,
                             Qt::DirectConnection));
             if (!m_isPopup)
-                m_windowConnections.append(connect(value.window, SIGNAL(closing(QQuickCloseEvent *)), SLOT(onHide())));
+                m_windowConnections.append(connect(value.window, SIGNAL(closing(QQuickCloseEvent*)), SLOT(onHide())));
         }
         m_client->visualPropertiesChanged();
     } else if (change == QQuickItem::ItemVisibleHasChanged) {
@@ -368,6 +370,12 @@ QSGNode *RenderWidgetHostViewQtDelegateItem::updatePaintNode(QSGNode *oldNode, U
     if (!comp)
         return oldNode;
 
+    if (comp->type() == Compositor::Type::Native
+        && QGuiApplication::platformName() == "offscreen"_L1) {
+        comp->swapFrame();
+        return oldNode;
+    }
+
     QQuickWindow *win = QQuickItem::window();
 
     QSGImageNode *node = nullptr;
diff --git a/src/core/renderer/content_renderer_client_qt.cpp b/src/core/renderer/content_renderer_client_qt.cpp
index 5342cc63263..a88d407b4d7 100644
--- a/src/core/renderer/content_renderer_client_qt.cpp
+++ b/src/core/renderer/content_renderer_client_qt.cpp
@@ -311,7 +311,7 @@ void ContentRendererClientQt::GetNavigationErrorStringsInternal(content::RenderF
         resourceId = IDR_NET_ERROR_HTML;
 
         std::string extracted_string = ui::ResourceBundle::GetSharedInstance().LoadDataResourceString(resourceId);
-        const base::StringPiece template_html(extracted_string.data(), extracted_string.size());
+        const std::string_view template_html(extracted_string.data(), extracted_string.size());
         if (template_html.empty())
             NOTREACHED() << "unable to load template. ID: " << resourceId;
         else // "t" is the id of the templates root node.
@@ -494,13 +494,14 @@ void ContentRendererClientQt::InitSpellCheck()
 
 void ContentRendererClientQt::WillSendRequest(blink::WebLocalFrame *frame,
                                               ui::PageTransition transition_type,
-                                              const blink::WebURL &url,
+                                              const blink::WebURL &upstream_url,
+                                              const blink::WebURL &target_url,
                                               const net::SiteForCookies &site_for_cookies,
                                               const url::Origin *initiator_origin,
                                               GURL *new_url)
 {
 #if BUILDFLAG(ENABLE_EXTENSIONS)
-    ExtensionsRendererClientQt::GetInstance()->WillSendRequest(frame, transition_type, url, site_for_cookies,
+    ExtensionsRendererClientQt::GetInstance()->WillSendRequest(frame, transition_type, target_url, site_for_cookies,
                                                                initiator_origin, new_url);
     if (!new_url->is_empty())
         return;
diff --git a/src/core/renderer/content_renderer_client_qt.h b/src/core/renderer/content_renderer_client_qt.h
index c93914f0842..36a2ffe0a4b 100644
--- a/src/core/renderer/content_renderer_client_qt.h
+++ b/src/core/renderer/content_renderer_client_qt.h
@@ -84,7 +84,8 @@ class ContentRendererClientQt
 
     void WillSendRequest(blink::WebLocalFrame *frame,
                          ui::PageTransition transition_type,
-                         const blink::WebURL &url,
+                         const blink::WebURL &upstream_url,
+                         const blink::WebURL &target_url,
                          const net::SiteForCookies &site_for_cookies,
                          const url::Origin *initiator_origin,
                          GURL *new_url) override;
diff --git a/src/core/renderer/extensions/extensions_renderer_client_qt.cpp b/src/core/renderer/extensions/extensions_renderer_client_qt.cpp
index 8b0c695d04b..f5be05cc477 100644
--- a/src/core/renderer/extensions/extensions_renderer_client_qt.cpp
+++ b/src/core/renderer/extensions/extensions_renderer_client_qt.cpp
@@ -69,49 +69,9 @@ ExtensionsRendererClientQt *ExtensionsRendererClientQt::GetInstance()
     return client.Pointer();
 }
 
-extensions::Dispatcher *ExtensionsRendererClientQt::GetDispatcher()
+void ExtensionsRendererClientQt::FinishInitialization()
 {
-    return extension_dispatcher_.get();
-}
-
-void ExtensionsRendererClientQt::OnExtensionLoaded(const extensions::Extension &extension)
-{
-    resource_request_policy_->OnExtensionLoaded(extension);
-}
-
-void ExtensionsRendererClientQt::OnExtensionUnloaded(const extensions::ExtensionId &extension_id)
-{
-    resource_request_policy_->OnExtensionUnloaded(extension_id);
-}
-
-bool ExtensionsRendererClientQt::ExtensionAPIEnabledForServiceWorkerScript(const GURL &scope, const GURL &script_url) const
-{
-    if (!script_url.SchemeIs(extensions::kExtensionScheme))
-        return false;
-
-    const extensions::Extension* extension =
-            extensions::RendererExtensionRegistry::Get()->GetExtensionOrAppByURL(script_url);
-
-    if (!extension || !extensions::BackgroundInfo::IsServiceWorkerBased(extension))
-        return false;
-
-    if (scope != extension->url())
-        return false;
-
-    const std::string& sw_script = extensions::BackgroundInfo::GetBackgroundServiceWorkerScript(extension);
-
-    return extension->GetResourceURL(sw_script) == script_url;
-}
-
-void ExtensionsRendererClientQt::RenderThreadStarted()
-{
-    content::RenderThread *thread = content::RenderThread::Get();
-    if (!extension_dispatcher_)
-        extension_dispatcher_.reset(new extensions::Dispatcher(std::move(api_providers_)));
-    extension_dispatcher_->OnRenderThreadStarted(thread);
-    resource_request_policy_.reset(new extensions::ResourceRequestPolicyQt(extension_dispatcher_.get()));
-
-    thread->AddObserver(extension_dispatcher_.get());
+    resource_request_policy_.reset(new extensions::ResourceRequestPolicyQt(dispatcher()));
 }
 
 void ExtensionsRendererClientQt::WebViewCreated(blink::WebView *web_view, const url::Origin *outermost_origin)
@@ -119,15 +79,6 @@ void ExtensionsRendererClientQt::WebViewCreated(blink::WebView *web_view, const
     new extensions::ExtensionWebViewHelper(web_view, outermost_origin);
 }
 
-void ExtensionsRendererClientQt::RenderFrameCreated(content::RenderFrame *render_frame,
-                                                    service_manager::BinderRegistry *registry)
-{
-    new extensions::ExtensionsRenderFrameObserver(render_frame, registry);
-    new extensions::ExtensionFrameHelper(render_frame,
-                                         extension_dispatcher_.get());
-    extension_dispatcher_->OnRenderFrameCreated(render_frame);
-}
-
 bool ExtensionsRendererClientQt::OverrideCreatePlugin(content::RenderFrame *render_frame,
                                                       const blink::WebPluginParams &params)
 {
@@ -154,17 +105,17 @@ void ExtensionsRendererClientQt::WillSendRequest(blink::WebLocalFrame *frame,
 
 void ExtensionsRendererClientQt::RunScriptsAtDocumentStart(content::RenderFrame *render_frame)
 {
-    extension_dispatcher_->RunScriptsAtDocumentStart(render_frame);
+    dispatcher()->RunScriptsAtDocumentStart(render_frame);
 }
 
 void ExtensionsRendererClientQt::RunScriptsAtDocumentEnd(content::RenderFrame *render_frame)
 {
-    extension_dispatcher_->RunScriptsAtDocumentEnd(render_frame);
+    dispatcher()->RunScriptsAtDocumentEnd(render_frame);
 }
 
 void ExtensionsRendererClientQt::RunScriptsAtDocumentIdle(content::RenderFrame *render_frame)
 {
-    extension_dispatcher_->RunScriptsAtDocumentIdle(render_frame);
+    dispatcher()->RunScriptsAtDocumentIdle(render_frame);
 }
 
 
diff --git a/src/core/renderer/extensions/extensions_renderer_client_qt.h b/src/core/renderer/extensions/extensions_renderer_client_qt.h
index 4b8d23b8d12..cfe4d56a60a 100644
--- a/src/core/renderer/extensions/extensions_renderer_client_qt.h
+++ b/src/core/renderer/extensions/extensions_renderer_client_qt.h
@@ -32,7 +32,6 @@ class Origin;
 }
 
 namespace extensions {
-class Dispatcher;
 class ResourceRequestPolicyQt;
 }
 
@@ -47,15 +46,11 @@ class ExtensionsRendererClientQt : public extensions::ExtensionsRendererClient
     // extensions::ExtensionsRendererClient implementation.
     bool IsIncognitoProcess() const override;
     int GetLowestIsolatedWorldId() const override;
-    extensions::Dispatcher *GetDispatcher() override;
-    void OnExtensionLoaded(const extensions::Extension &extension) override;
-    void OnExtensionUnloaded(const extensions::ExtensionId &extension_id) override;
-    void RenderThreadStarted() override;
+    void FinishInitialization() override;
 
     // Match ContentRendererClientQt's method names...
     void WebViewCreated(blink::WebView *web_view,
                         const url::Origin *outermost_origin);
-    void RenderFrameCreated(content::RenderFrame *, service_manager::BinderRegistry *);
     bool OverrideCreatePlugin(content::RenderFrame *render_frame,
                               const blink::WebPluginParams &params);
     void WillSendRequest(blink::WebLocalFrame *frame,
@@ -65,19 +60,13 @@ class ExtensionsRendererClientQt : public extensions::ExtensionsRendererClient
                          const url::Origin *initiator_origin,
                          GURL *new_url);
 
-    bool ExtensionAPIEnabledForServiceWorkerScript(const GURL &scope, const GURL &script_url) const override;
-
     void RunScriptsAtDocumentStart(content::RenderFrame *render_frame);
     void RunScriptsAtDocumentEnd(content::RenderFrame *render_frame);
     void RunScriptsAtDocumentIdle(content::RenderFrame *render_frame);
 
-    extensions::Dispatcher *extension_dispatcher()
-    { return extension_dispatcher_.get(); }
-
     static ExtensionsRendererClientQt *GetInstance();
 
 private:
-    std::unique_ptr<extensions::Dispatcher> extension_dispatcher_;
     std::unique_ptr<extensions::ResourceRequestPolicyQt> resource_request_policy_;
 };
 
diff --git a/src/core/renderer/user_resource_controller.cpp b/src/core/renderer/user_resource_controller.cpp
index 82579ea7d79..9ced854ffd4 100644
--- a/src/core/renderer/user_resource_controller.cpp
+++ b/src/core/renderer/user_resource_controller.cpp
@@ -124,11 +124,11 @@ class UserResourceController::RenderFrameObserverHelper
 
 // Helper class to create WeakPtrs so the AfterLoad tasks can be canceled and to
 // avoid running scripts more than once per injection point.
-class UserResourceController::RenderFrameObserverHelper::Runner : public base::SupportsWeakPtr<Runner>
+class UserResourceController::RenderFrameObserverHelper::Runner
 {
 public:
     explicit Runner(blink::WebLocalFrame *frame, UserResourceController *controller)
-        : m_frame(frame), m_userResourceController(controller)
+        : m_frame(frame), m_userResourceController(controller), m_weakPtrFactory(this)
     {
     }
 
@@ -140,11 +140,13 @@ class UserResourceController::RenderFrameObserverHelper::Runner : public base::S
             m_ran[p] = true;
         }
     }
+    base::WeakPtr<Runner> AsWeakPtr() { return m_weakPtrFactory.GetWeakPtr(); }
 
 private:
     blink::WebLocalFrame *m_frame;
     std::bitset<3> m_ran;
     UserResourceController *m_userResourceController;
+    base::WeakPtrFactory<Runner> m_weakPtrFactory;
 };
 
 void UserResourceController::runScripts(QtWebEngineCore::UserScriptData::InjectionPoint p,
diff --git a/src/core/renderer_host/web_channel_ipc_transport_host.cpp b/src/core/renderer_host/web_channel_ipc_transport_host.cpp
index c1271702a73..0cc24014fa5 100644
--- a/src/core/renderer_host/web_channel_ipc_transport_host.cpp
+++ b/src/core/renderer_host/web_channel_ipc_transport_host.cpp
@@ -49,7 +49,7 @@ uint WebChannelIPCTransportHost::worldId() const
 void WebChannelIPCTransportHost::sendMessage(const QJsonObject &message)
 {
     QJsonDocument doc(message);
-    QByteArray json = doc.toJson(QJsonDocument::Compact);
+    const QByteArray json = doc.toJson(QJsonDocument::Compact);
     content::RenderFrameHost *frame = web_contents()->GetPrimaryMainFrame();
     qCDebug(log).nospace() << "sending webchannel message to " << frame << ": " << doc;
     GetWebChannelIPCTransportRemote(frame)->DispatchWebChannelMessage(
diff --git a/src/core/select_file_dialog_factory_qt.cpp b/src/core/select_file_dialog_factory_qt.cpp
index 7035de77e28..8d0690628ae 100644
--- a/src/core/select_file_dialog_factory_qt.cpp
+++ b/src/core/select_file_dialog_factory_qt.cpp
@@ -65,7 +65,7 @@ class SelectFileDialogQt : public ui::SelectFileDialog
     void SelectFileImpl(Type type, const std::u16string &title, const base::FilePath &default_path,
                         const FileTypeInfo *file_types, int file_type_index,
                         const base::FilePath::StringType &default_extension,
-                        gfx::NativeWindow owning_window, void *params, const GURL *) override;
+                        gfx::NativeWindow owning_window, const GURL *) override;
 
     bool HasMultipleFileTypeChoicesImpl() override;
 
@@ -106,20 +106,19 @@ void SelectFileDialogQt::SelectFileImpl(Type type, const std::u16string &title,
                                         const base::FilePath &default_path,
                                         const FileTypeInfo *file_types, int file_type_index,
                                         const base::FilePath::StringType &default_extension,
-                                        gfx::NativeWindow owning_window, void *params, const GURL *caller)
+                                        gfx::NativeWindow owning_window, const GURL *caller)
 {
     Q_UNUSED(title);
     Q_UNUSED(file_type_index);
     Q_UNUSED(default_extension);
     Q_UNUSED(owning_window);
-    Q_UNUSED(params);
     Q_UNUSED(caller);
 
     QStringList acceptedSuffixes;
     if (file_types) {
         for (const auto &typeExtensions : file_types->extensions) {
             for (const auto &extension : typeExtensions)
-                acceptedSuffixes.append("." + toQt(extension));
+                acceptedSuffixes.append(u'.' + toQt(extension));
         }
     }
 
diff --git a/src/core/tools/qwebengine_convert_dict/CMakeLists.txt b/src/core/tools/qwebengine_convert_dict/CMakeLists.txt
index fcc11bdcb8c..4d36ca004fb 100644
--- a/src/core/tools/qwebengine_convert_dict/CMakeLists.txt
+++ b/src/core/tools/qwebengine_convert_dict/CMakeLists.txt
@@ -7,6 +7,7 @@ if(QT_FEATURE_webengine_spellchecker AND NOT CMAKE_CROSSCOMPILING)
         TARGET_DESCRIPTION "QtWebEngine Dictionary Conversion Tool"
         INSTALL_DIR ${INSTALL_LIBEXECDIR}
         TOOLS_TARGET WebEngineCore
+        DEFINES TOOLKIT_QT
         SOURCES main.cpp
         INCLUDE_DIRECTORIES
             ../../../3rdparty/chromium/third_party/abseil-cpp
diff --git a/src/core/tools/qwebengine_convert_dict/main.cpp b/src/core/tools/qwebengine_convert_dict/main.cpp
index ac5daab0b3c..3264e4c1395 100644
--- a/src/core/tools/qwebengine_convert_dict/main.cpp
+++ b/src/core/tools/qwebengine_convert_dict/main.cpp
@@ -32,6 +32,8 @@
 #include <QDir>
 #include <QCoreApplication>
 
+using namespace Qt::StringLiterals;
+
 // see also src/core/type_conversion.h
 inline base::FilePath::StringType toFilePathString(const QString &str)
 {
@@ -68,11 +70,11 @@ template<class T>
 QTextStream &operator<<(QTextStream &out, base::span<T> span)
 {
     out << '[';
-    QString prefix;
+    QLatin1StringView prefix;
     for (const auto &element : span) {
         out << prefix;
         out << element;
-        prefix = QStringLiteral(",");
+        prefix = ","_L1;
     }
     out << ']';
     return out;
@@ -93,20 +95,20 @@ inline bool VerifyWords(const convert_dict::DicReader::WordList& org_words,
 
     int affix_ids[hunspell::BDict::MAX_AFFIXES_PER_WORD];
 
-    static const int buf_size = 128;
-    char buf[buf_size];
     for (size_t i = 0; i < org_words.size(); i++) {
-        int affix_matches = iter.Advance(buf, buf_size, affix_ids);
+        auto buf_size = org_words[i].first.size() + 1;
+        std::string buf(buf_size, '\0');
+        int affix_matches = iter.Advance(buf.data(), buf_size, affix_ids);
         if (affix_matches == 0) {
             out << "Found the end before we expected\n";
             return false;
         }
 
-        if (org_words[i].first != buf) {
+        if (buf.back() != '\0' || buf.compare(0, buf_size - 1, org_words[i].first) != 0) {
             out << "Word does not match!\n"
                 << "  Index:    " << i << "\n"
                 << "  Expected: " << QString::fromStdString(org_words[i].first) << "\n"
-                << "  Actual:   " << QString::fromUtf8(buf) << "\n";
+                << "  Actual:   " << QString::fromStdString(buf) << "\n";
             return false;
         }
 
@@ -118,7 +120,7 @@ inline bool VerifyWords(const convert_dict::DicReader::WordList& org_words,
                         [](int a, int b) { return a == b; })) {
             out << "Affixes do not match!\n"
                 << "  Index:    " << i << "\n"
-                << "  Word:     " << QString::fromUtf8(buf) << "\n"
+                << "  Word:     " << QString::fromStdString(buf) << "\n"
                 << "  Expected: " << expectedAffixes << "\n"
                 << "  Actual:   " << actualAffixes << "\n";
             return false;
@@ -131,8 +133,8 @@ inline bool VerifyWords(const convert_dict::DicReader::WordList& org_words,
 #if defined(Q_OS_DARWIN) && defined(QT_MAC_FRAMEWORK_BUILD)
 QString frameworkIcuDataPath()
 {
-    return QLibraryInfo::location(QLibraryInfo::LibrariesPath) +
-            QStringLiteral("/QtWebEngineCore.framework/Resources/");
+    return QLibraryInfo::location(QLibraryInfo::LibrariesPath)
+            + "/QtWebEngineCore.framework/Resources/"_L1;
 }
 #endif
 
@@ -155,15 +157,14 @@ int main(int argc, char *argv[])
     }
 #if defined(USE_ICU_FILE)
     bool icuDataDirFound = false;
-    QString icuDataDir = QLibraryInfo::path(QLibraryInfo::DataPath)
-            % QLatin1String("/resources");
+    QString icuDataDir = QLibraryInfo::path(QLibraryInfo::DataPath) % "/resources"_L1;
 
     // Try to look up the path to the ICU data directory via an environment variable
     // (e.g. for the case when the tool is ran during build phase, and regular installed
     // ICU data file is not available).
     const QString icuPossibleEnvDataDir = qEnvironmentVariable("QT_WEBENGINE_ICU_DATA_DIR");
     const QString appPath = QCoreApplication::applicationDirPath();
-    QLatin1String icuDataFilePath("/icudtl.dat");
+    const auto icuDataFilePath = "/icudtl.dat"_L1;
     if (!icuPossibleEnvDataDir.isEmpty() && QFileInfo::exists(icuPossibleEnvDataDir)) {
         icuDataDir = icuPossibleEnvDataDir;
         icuDataDirFound = true;
diff --git a/src/core/type_conversion.cpp b/src/core/type_conversion.cpp
index 27143093b77..ba6414fe68a 100644
--- a/src/core/type_conversion.cpp
+++ b/src/core/type_conversion.cpp
@@ -23,8 +23,6 @@ QImage toQImage(const SkBitmap &bitmap)
     QImage image;
     switch (bitmap.colorType()) {
     case kUnknown_SkColorType:
-    case kRGBA_F16_SkColorType:
-    case kRGBA_F32_SkColorType:
     case kRGBA_F16Norm_SkColorType:
     case kR8G8_unorm_SkColorType:
     case kA16_float_SkColorType:
@@ -138,6 +136,37 @@ QImage toQImage(const SkBitmap &bitmap)
             break;
         }
         break;
+    case kRGBA_F16_SkColorType:
+    case kRGB_F16F16F16x_SkColorType:
+        switch (bitmap.alphaType()) {
+        case kUnknown_SkAlphaType:
+            break;
+        case kUnpremul_SkAlphaType:
+            image = toQImage(bitmap, QImage::Format_RGBA16FPx4);
+            break;
+        case kOpaque_SkAlphaType:
+            image = toQImage(bitmap, QImage::Format_RGBX16FPx4);
+            break;
+        case kPremul_SkAlphaType:
+            image = toQImage(bitmap, QImage::Format_RGBA16FPx4_Premultiplied);
+            break;
+        }
+        break;
+    case kRGBA_F32_SkColorType:
+        switch (bitmap.alphaType()) {
+        case kUnknown_SkAlphaType:
+            break;
+        case kUnpremul_SkAlphaType:
+            image = toQImage(bitmap, QImage::Format_RGBA32FPx4);
+            break;
+        case kOpaque_SkAlphaType:
+            image = toQImage(bitmap, QImage::Format_RGBX32FPx4);
+            break;
+        case kPremul_SkAlphaType:
+            image = toQImage(bitmap, QImage::Format_RGBA32FPx4_Premultiplied);
+            break;
+        }
+        break;
     }
     return image;
 }
diff --git a/src/core/type_conversion.h b/src/core/type_conversion.h
index edaeb7a88b1..1a21351cee2 100644
--- a/src/core/type_conversion.h
+++ b/src/core/type_conversion.h
@@ -26,6 +26,8 @@
 #include "url/gurl.h"
 #include "url/origin.h"
 
+#include <string_view>
+
 QT_FORWARD_DECLARE_CLASS(QSslCertificate)
 
 namespace gfx {
@@ -58,7 +60,7 @@ inline QString toQt(const std::optional<std::u16string> &string)
     return QString::fromStdU16String(*string);
 }
 
-inline QString toQString(const base::StringPiece &string)
+inline QString toQString(const std::string_view &string)
 {
     return QString::fromUtf8(string.data(), string.size());
 }
@@ -68,7 +70,7 @@ inline QString toQString(const std::string &string)
     return QString::fromStdString(string);
 }
 
-inline QByteArray toQByteArray(const base::StringPiece &string)
+inline QByteArray toQByteArray(const std::string_view &string)
 {
     return QByteArray(string.data(), string.size());
 }
diff --git a/src/core/user_script.cpp b/src/core/user_script.cpp
index c33fb908178..92030ed1db2 100644
--- a/src/core/user_script.cpp
+++ b/src/core/user_script.cpp
@@ -10,11 +10,11 @@
 namespace {
 
 // Helper function to parse Greasemonkey headers
-bool GetDeclarationValue(const base::StringPiece& line,
-                         const base::StringPiece& prefix,
+bool GetDeclarationValue(std::string_view line,
+                         std::string_view prefix,
                          std::string* value) {
-    base::StringPiece::size_type index = line.find(prefix);
-    if (index == base::StringPiece::npos)
+    std::string_view::size_type index = line.find(prefix);
+    if (index == std::string_view::npos)
         return false;
 
     std::string temp(line.data() + index + prefix.length(),
@@ -62,7 +62,7 @@ QString UserScript::name() const
 void UserScript::setName(const QString &name)
 {
     m_name = name;
-    m_scriptData.url = GURL(QStringLiteral("userScript:%1").arg(name).toStdString());
+    m_scriptData.url = GURL("userScript:" + name.toStdString());
 }
 
 QString UserScript::sourceCode() const
@@ -138,24 +138,24 @@ void UserScript::parseMetadataHeader()
     // Logic taken from Chromium (extensions/browser/user_script_loader.cc)
     // http://wiki.greasespot.net/Metadata_block
     const std::string &script_text = m_scriptData.source;
-    base::StringPiece line;
+    std::string_view line;
     size_t line_start = 0;
     size_t line_end = line_start;
     bool in_metadata = false;
 
-    static const base::StringPiece kUserScriptBegin("// ==UserScript==");
-    static const base::StringPiece kUserScriptEnd("// ==/UserScript==");
-    static const base::StringPiece kNameDeclaration("// @name");
-    static const base::StringPiece kIncludeDeclaration("// @include");
-    static const base::StringPiece kExcludeDeclaration("// @exclude");
-    static const base::StringPiece kMatchDeclaration("// @match");
-    static const base::StringPiece kRunAtDeclaration("// @run-at");
-    static const base::StringPiece kRunAtDocumentStartValue("document-start");
-    static const base::StringPiece kRunAtDocumentEndValue("document-end");
-    static const base::StringPiece kRunAtDocumentIdleValue("document-idle");
+    static const std::string_view kUserScriptBegin("// ==UserScript==");
+    static const std::string_view kUserScriptEnd("// ==/UserScript==");
+    static const std::string_view kNameDeclaration("// @name");
+    static const std::string_view kIncludeDeclaration("// @include");
+    static const std::string_view kExcludeDeclaration("// @exclude");
+    static const std::string_view kMatchDeclaration("// @match");
+    static const std::string_view kRunAtDeclaration("// @run-at");
+    static const std::string_view kRunAtDocumentStartValue("document-start");
+    static const std::string_view kRunAtDocumentEndValue("document-end");
+    static const std::string_view kRunAtDocumentIdleValue("document-idle");
     // FIXME: Scripts don't run in subframes by default. If we would like to
     // support @noframes rule, we have to change the current default behavior.
-    // static const base::StringPiece kNoFramesDeclaration("// @noframes");
+    // static const std::string_view kNoFramesDeclaration("// @noframes");
 
     while (line_start < script_text.length()) {
         line_end = script_text.find('\n', line_start);
@@ -164,7 +164,7 @@ void UserScript::parseMetadataHeader()
         if (line_end == std::string::npos)
             line_end = script_text.length() - 1;
 
-        line = base::StringPiece(script_text.data() + line_start, line_end - line_start);
+        line = std::string_view(script_text.data() + line_start, line_end - line_start);
 
         if (!in_metadata) {
             if (base::StartsWith(line, kUserScriptBegin))
diff --git a/src/core/web_contents_adapter.cpp b/src/core/web_contents_adapter.cpp
index 42882fbe441..67f9362d1a9 100644
--- a/src/core/web_contents_adapter.cpp
+++ b/src/core/web_contents_adapter.cpp
@@ -76,7 +76,7 @@
 
 #if QT_CONFIG(accessibility)
 #include "browser_accessibility_qt.h"
-#include "content/browser/accessibility/browser_accessibility_manager.h"
+#include "ui/accessibility/platform/browser_accessibility_manager.h"
 #include <QtGui/qaccessible.h>
 #endif
 
@@ -93,6 +93,8 @@
 #include "extensions/extension_web_contents_observer_qt.h"
 #endif
 
+using namespace Qt::StringLiterals;
+
 namespace QtWebEngineCore {
 
 #define CHECK_INITIALIZED(return_value)         \
@@ -659,13 +661,13 @@ void WebContentsAdapter::load(const QWebEngineHttpRequest &request)
     Q_UNUSED(guard);
 
     // Add URL scheme if missing from view-source URL.
-    if (request.url().scheme() == content::kViewSourceScheme) {
+    if (request.url().scheme() == QLatin1StringView(content::kViewSourceScheme)) {
         QUrl pageUrl = QUrl(request.url().toString().remove(0,
                                                            strlen(content::kViewSourceScheme) + 1));
         if (pageUrl.scheme().isEmpty()) {
             QUrl extendedUrl = QUrl::fromUserInput(pageUrl.toString());
-            extendedUrl = QUrl(QString("%1:%2").arg(content::kViewSourceScheme,
-                                                    extendedUrl.toString()));
+            extendedUrl = QUrl(QLatin1StringView(content::kViewSourceScheme) + u':'
+                               + extendedUrl.toString());
             gurl = toGurl(extendedUrl);
         }
     }
@@ -733,7 +735,7 @@ void WebContentsAdapter::setContent(const QByteArray &data, const QString &mimeT
 
     WebEngineSettings::get(m_adapterClient->webEngineSettings())->doApply();
 
-    QByteArray encodedData = data.toPercentEncoding();
+    const QByteArray encodedData = data.toPercentEncoding();
     std::string urlString;
     if (!mimeType.isEmpty())
         urlString = std::string("data:") + mimeType.toStdString() + std::string(",");
@@ -750,7 +752,8 @@ void WebContentsAdapter::setContent(const QByteArray &data, const QString &mimeT
     content::NavigationController::LoadURLParams params((dataUrlToLoad));
     params.load_type = content::NavigationController::LOAD_TYPE_DATA;
     params.base_url_for_data_url = toGurl(baseUrl);
-    params.virtual_url_for_data_url = baseUrl.isEmpty() ? GURL(url::kAboutBlankURL) : toGurl(baseUrl);
+    params.virtual_url_for_special_cases =
+            baseUrl.isEmpty() ? GURL(url::kAboutBlankURL) : toGurl(baseUrl);
     params.can_load_local_resources = true;
     params.transition_type = ui::PageTransitionFromInt(ui::PAGE_TRANSITION_TYPED | ui::PAGE_TRANSITION_FROM_API);
     params.override_user_agent = content::NavigationController::UA_OVERRIDE_TRUE;
@@ -980,10 +983,10 @@ void WebContentsAdapter::serializeNavigationHistory(QDataStream &output)
 void WebContentsAdapter::setZoomFactor(qreal factor)
 {
     CHECK_INITIALIZED();
-    if (factor < blink::kMinimumPageZoomFactor || factor > blink::kMaximumPageZoomFactor)
+    if (factor < blink::kMinimumBrowserZoomFactor || factor > blink::kMaximumBrowserZoomFactor)
         return;
 
-    double zoomLevel = blink::PageZoomFactorToZoomLevel(static_cast<double>(factor));
+    double zoomLevel = blink::ZoomFactorToZoomLevel(static_cast<double>(factor));
     content::HostZoomMap *zoomMap = content::HostZoomMap::GetForWebContents(m_webContents.get());
 
     if (zoomMap) {
@@ -998,7 +1001,7 @@ void WebContentsAdapter::setZoomFactor(qreal factor)
 qreal WebContentsAdapter::currentZoomFactor() const
 {
     CHECK_INITIALIZED(1);
-    return blink::PageZoomLevelToZoomFactor(content::HostZoomMap::GetZoomLevel(m_webContents.get()));
+    return blink::ZoomLevelToZoomFactor(content::HostZoomMap::GetZoomLevel(m_webContents.get()));
 }
 
 ProfileQt* WebContentsAdapter::profile()
@@ -1030,12 +1033,12 @@ QAccessibleInterface *WebContentsAdapter::browserAccessible()
     content::RenderFrameHostImpl *rfh = static_cast<content::RenderFrameHostImpl *>(m_webContents->GetPrimaryMainFrame());
     if (!rfh)
         return nullptr;
-    content::BrowserAccessibilityManager *manager = rfh->GetOrCreateBrowserAccessibilityManager();
+    ui::BrowserAccessibilityManager *manager = rfh->GetOrCreateBrowserAccessibilityManager();
     if (!manager) // FIXME!
         return nullptr;
-    content::BrowserAccessibility *acc = manager->GetFromAXNode(manager->GetRoot());
+    ui::BrowserAccessibility *acc = manager->GetFromAXNode(manager->GetRoot());
 
-    return content::toQAccessibleInterface(acc);
+    return ui::toQAccessibleInterface(acc);
 }
 #endif // QT_CONFIG(accessibility)
 
@@ -1045,7 +1048,8 @@ content::RenderFrameHost *WebContentsAdapter::renderFrameHostFromFrameId(quint64
     if (frameId == kUseMainFrameId) {
         result = m_webContents->GetPrimaryMainFrame();
     } else {
-        auto *ftn = content::FrameTreeNode::GloballyFindByID(static_cast<int>(frameId));
+        auto *ftn = content::FrameTreeNode::GloballyFindByID(
+                static_cast<content::FrameTreeNodeId>(frameId));
         if (!ftn)
             return nullptr;
 
@@ -1069,7 +1073,7 @@ void WebContentsAdapter::runJavaScript(const QString &javaScript, quint32 worldI
     if (!rfh)
         return exit();
     if (!static_cast<content::RenderFrameHostImpl*>(rfh)->GetAssociatedLocalFrame()) {
-        qWarning() << "Local frame is gone, not running script";
+        qWarning("Local frame is gone, not running script");
         return exit();
     }
 
@@ -1620,7 +1624,9 @@ static QMimeData *mimeDataFromDropData(const content::DropData &dropData)
     if (!dropData.custom_data.empty()) {
         base::Pickle pickle;
         ui::WriteCustomDataToPickle(dropData.custom_data, &pickle);
-        mimeData->setData(QLatin1String(ui::kMimeTypeWebCustomData), QByteArray((const char*)pickle.data(), pickle.size()));
+        mimeData->setData(QString::fromStdString(
+                                  ui::ClipboardFormatType::DataTransferCustomType().Serialize()),
+                          QByteArray((const char*)pickle.data(), pickle.size()));
     }
     return mimeData;
 }
@@ -1750,8 +1756,10 @@ static void fillDropDataFromMimeData(content::DropData *dropData, const QMimeDat
         dropData->html = toOptionalString16(mimeData->html());
     if (mimeData->hasText())
         dropData->text = toOptionalString16(mimeData->text());
-    if (mimeData->hasFormat(QLatin1String(ui::kMimeTypeWebCustomData))) {
-        const QByteArray customData = mimeData->data(QLatin1String(ui::kMimeTypeWebCustomData));
+    const QString serializedDataTransferCustomType =
+            QString::fromStdString(ui::ClipboardFormatType::DataTransferCustomType().Serialize());
+    if (mimeData->hasFormat(serializedDataTransferCustomType)) {
+        const QByteArray customData = mimeData->data(serializedDataTransferCustomType);
         const base::span custom_data(customData.constData(), (long unsigned)customData.length());
         if (auto maybe_data = ui::ReadCustomDataIntoMap(base::as_bytes(custom_data)))
             dropData->custom_data = *std::move(maybe_data);
@@ -1942,17 +1950,18 @@ void WebContentsAdapter::changeTextDirection(bool leftToRight)
 
 quint64 WebContentsAdapter::mainFrameId() const
 {
-    CHECK_INITIALIZED(content::RenderFrameHost::kNoFrameTreeNodeId);
-    return static_cast<quint64>(m_webContents->GetPrimaryMainFrame()->GetFrameTreeNodeId());
+    CHECK_INITIALIZED(-1); // content::RenderFrameHost::kNoFrameTreeNodeId);
+    return static_cast<quint64>(
+            m_webContents->GetPrimaryMainFrame()->GetFrameTreeNodeId().GetUnsafeValue());
 }
 
 #define CHECK_INITIALIZED_AND_VALID_FRAME(webengine_frame_id_variable, frame_tree_node_variable,   \
                                           return_value)                                            \
     CHECK_INITIALIZED(return_value);                                                               \
-    if (webengine_frame_id_variable == kInvalidFrameId)                                            \
+    if (webengine_frame_id_variable == -1) /* kInvalidFrameId)*/                                   \
         return return_value;                                                                       \
     auto *frame_tree_node_variable = content::FrameTreeNode::GloballyFindByID(                     \
-            static_cast<int>(webengine_frame_id_variable));                                        \
+            static_cast<content::FrameTreeNodeId>(webengine_frame_id_variable));                   \
     if (!frame_tree_node_variable)                                                                 \
     return return_value
 
@@ -1966,7 +1975,7 @@ QString WebContentsAdapter::frameHtmlName(quint64 id) const
 {
     CHECK_INITIALIZED_AND_VALID_FRAME(id, ftn, QString());
     auto &maybeName = ftn->html_name();
-    return maybeName ? QString::fromStdString(*maybeName) : QString("");
+    return maybeName ? QString::fromStdString(*maybeName) : ""_L1;
 }
 
 QList<quint64> WebContentsAdapter::frameChildren(quint64 id) const
@@ -1976,7 +1985,7 @@ QList<quint64> WebContentsAdapter::frameChildren(quint64 id) const
     size_t numChildren = ftn->child_count();
     result.reserve(numChildren);
     for (size_t i = 0; i < numChildren; ++i) {
-        result.push_back(ftn->child_at(i)->frame_tree_node_id());
+        result.push_back(ftn->child_at(i)->frame_tree_node_id().GetUnsafeValue());
     }
     return result;
 }
@@ -2002,7 +2011,7 @@ std::optional<quint64> WebContentsAdapter::findFrameIdByName(const QString &name
     auto *ftn = content::FrameTreeNode::From(m_webContents->GetPrimaryMainFrame());
     Q_ASSERT(ftn);
     if (auto *foundFtn = ftn->frame_tree().FindByName(name.toStdString()))
-        return foundFtn->frame_tree_node_id();
+        return foundFtn->frame_tree_node_id().GetUnsafeValue();
     return {};
 }
 
@@ -2228,7 +2237,7 @@ void WebContentsAdapter::discard()
 
     if (m_webContents->IsLoading()) {
         m_webContentsDelegate->didFailLoad(m_webContentsDelegate->url(webContents()), net::Error::ERR_ABORTED,
-                                           QStringLiteral("Discarded"));
+                                           u"Discarded"_s);
         m_webContentsDelegate->DidStopLoading();
     }
 
diff --git a/src/core/web_contents_delegate_qt.cpp b/src/core/web_contents_delegate_qt.cpp
index 33a90fcea06..92b1eb415db 100644
--- a/src/core/web_contents_delegate_qt.cpp
+++ b/src/core/web_contents_delegate_qt.cpp
@@ -57,6 +57,8 @@
 #include <QTimer>
 #include <QWindow>
 
+using namespace Qt::StringLiterals;
+
 namespace QtWebEngineCore {
 
 static WebContentsAdapterClient::JavaScriptConsoleMessageLevel mapToJavascriptConsoleMessageLevel(blink::mojom::ConsoleMessageLevel log_level)
@@ -200,7 +202,8 @@ QUrl WebContentsDelegateQt::url(content::WebContents *source) const
         if (source->GetVisibleURL().SchemeIs(content::kViewSourceScheme) &&
             (url.has_password() || url.has_username() || url.has_ref())) {
             GURL strippedUrl = net::SimplifyUrlForRequest(url);
-            newUrl = QUrl(QString("%1:%2").arg(content::kViewSourceScheme, QString::fromStdString(strippedUrl.spec())));
+            newUrl = QUrl(QLatin1StringView(content::kViewSourceScheme) + u':'
+                          + QString::fromStdString(strippedUrl.spec()));
         }
         // If there is a visible entry there are special cases where we dont wan't to use the actual URL
         if (newUrl.isEmpty())
@@ -209,8 +212,10 @@ QUrl WebContentsDelegateQt::url(content::WebContents *source) const
     m_pendingUrlUpdate = false;
     return newUrl;
 }
-void WebContentsDelegateQt::AddNewContents(content::WebContents *source, std::unique_ptr<content::WebContents> new_contents, const GURL &target_url,
-                                           WindowOpenDisposition disposition, const blink::mojom::WindowFeatures &window_features, bool user_gesture, bool *was_blocked)
+content::WebContents *WebContentsDelegateQt::AddNewContents(
+        content::WebContents *source, std::unique_ptr<content::WebContents> new_contents,
+        const GURL &target_url, WindowOpenDisposition disposition,
+        const blink::mojom::WindowFeatures &window_features, bool user_gesture, bool *was_blocked)
 {
     Q_UNUSED(source)
     QSharedPointer<WebContentsAdapter> newAdapter = createWindow(std::move(new_contents), disposition, window_features.bounds, toQt(target_url), user_gesture);
@@ -225,6 +230,8 @@ void WebContentsDelegateQt::AddNewContents(content::WebContents *source, std::un
         newAdapter->loadDefault();
     if (was_blocked)
         *was_blocked = !newAdapter;
+
+    return nullptr;
 }
 
 void WebContentsDelegateQt::CloseContents(content::WebContents *source)
@@ -246,7 +253,7 @@ void WebContentsDelegateQt::LoadProgressChanged(double progress)
     }
 }
 
-bool WebContentsDelegateQt::HandleKeyboardEvent(content::WebContents *, const content::NativeWebKeyboardEvent &event)
+bool WebContentsDelegateQt::HandleKeyboardEvent(content::WebContents *, const input::NativeWebKeyboardEvent &event)
 {
     Q_ASSERT(!event.skip_if_unhandled);
     if (event.os_event)
@@ -781,10 +788,13 @@ void WebContentsDelegateQt::launchExternalURL(const QUrl &url, ui::PageTransitio
 
     if (!navigationAllowedByPolicy || !navigationRequestAccepted) {
         QString errorDescription;
-        if (!navigationAllowedByPolicy)
-            errorDescription = QStringLiteral("Launching external protocol forbidden by WebEngineSettings::UnknownUrlSchemePolicy");
-        else
-            errorDescription = QStringLiteral("Launching external protocol suppressed by 'navigationRequested' API");
+        if (!navigationAllowedByPolicy) {
+            errorDescription = u"Launching external protocol forbidden by "
+                               "WebEngineSettings::UnknownUrlSchemePolicy"_s;
+        } else {
+            errorDescription = u"Launching external protocol suppressed by "
+                               "'navigationRequested' API"_s;
+        }
         didFailLoad(url, net::Error::ERR_ABORTED, errorDescription);
     }
 }
@@ -880,8 +890,7 @@ void WebContentsDelegateQt::ResourceLoadComplete(content::RenderFrameHost* rende
 }
 
 void WebContentsDelegateQt::InnerWebContentsAttached(content::WebContents *inner_web_contents,
-                                        content::RenderFrameHost *render_frame_host,
-                                        bool is_full_page)
+                                                     content::RenderFrameHost *render_frame_host)
 {
     blink::web_pref::WebPreferences guestPrefs = inner_web_contents->GetOrCreateWebPreferences();
     webEngineSettings()->overrideWebPreferences(inner_web_contents, &guestPrefs);
diff --git a/src/core/web_contents_delegate_qt.h b/src/core/web_contents_delegate_qt.h
index 95f4ec4f0d1..114519a635f 100644
--- a/src/core/web_contents_delegate_qt.h
+++ b/src/core/web_contents_delegate_qt.h
@@ -82,11 +82,14 @@ class WebContentsDelegateQt : public content::WebContentsDelegate
     content::WebContents *OpenURLFromTab(content::WebContents *source, const content::OpenURLParams &params,
                                          base::OnceCallback<void(content::NavigationHandle&)> navigation_handle_callback) override;
     void NavigationStateChanged(content::WebContents* source, content::InvalidateTypes changed_flags) override;
-    void AddNewContents(content::WebContents *source, std::unique_ptr<content::WebContents> new_contents, const GURL &target_url,
-                        WindowOpenDisposition disposition, const blink::mojom::WindowFeatures &window_features, bool user_gesture, bool *was_blocked) override;
+    content::WebContents *AddNewContents(content::WebContents *source,
+                                         std::unique_ptr<content::WebContents> new_contents,
+                                         const GURL &target_url, WindowOpenDisposition disposition,
+                                         const blink::mojom::WindowFeatures &window_features,
+                                         bool user_gesture, bool *was_blocked) override;
     void CloseContents(content::WebContents *source) override;
     void LoadProgressChanged(double progress) override;
-    bool HandleKeyboardEvent(content::WebContents *source, const content::NativeWebKeyboardEvent &event) override;
+    bool HandleKeyboardEvent(content::WebContents *source, const input::NativeWebKeyboardEvent &event) override;
     std::unique_ptr<content::ColorChooser> OpenColorChooser(content::WebContents *source, SkColor color, const std::vector<blink::mojom::ColorSuggestionPtr> &suggestions) override;
     void WebContentsCreated(content::WebContents *source_contents, int opener_render_process_id, int opener_render_frame_id,
                             const std::string &frame_name, const GURL &target_url, content::WebContents *new_contents) override;
@@ -132,8 +135,7 @@ class WebContentsDelegateQt : public content::WebContentsDelegate
                               const content::GlobalRequestID& request_id,
                               const blink::mojom::ResourceLoadInfo& resource_load_info) override;
     void InnerWebContentsAttached(content::WebContents *inner_web_contents,
-                                  content::RenderFrameHost *render_frame_host,
-                                  bool is_full_page) override;
+                                  content::RenderFrameHost *render_frame_host) override;
     using content::WebContentsObserver::BeforeUnloadFired;
 
     void emitLoadSucceeded(const QUrl &url);
diff --git a/src/core/web_contents_view_qt.h b/src/core/web_contents_view_qt.h
index 862cda0c8c8..d04a4924f47 100644
--- a/src/core/web_contents_view_qt.h
+++ b/src/core/web_contents_view_qt.h
@@ -91,8 +91,6 @@ class WebContentsViewQt
 
     void UpdateDragOperation(ui::mojom::DragOperation dragOperation, bool document_is_handling_drag) override;
 
-    void TransferDragSecurityInfo(content::WebContentsView *) override {}
-
     void ShowContextMenu(content::RenderFrameHost &, const content::ContextMenuParams &params) override;
 
     void GotFocus(content::RenderWidgetHostImpl *render_widget_host) override;
diff --git a/src/core/web_engine_context.cpp b/src/core/web_engine_context.cpp
index e15005e578f..bf26e18f202 100644
--- a/src/core/web_engine_context.cpp
+++ b/src/core/web_engine_context.cpp
@@ -32,7 +32,10 @@
 #endif
 #include "components/discardable_memory/service/discardable_shared_memory_manager.h"
 #include "components/download/public/common/download_task_runner.h"
+#include "components/input/switches.h"
+#include "components/power_monitor/make_power_monitor_device_source.h"
 #include "components/viz/common/features.h"
+#include "components/variations/variations_ids_provider.h"
 #include "components/web_cache/browser/web_cache_manager.h"
 #include "content/app/mojo_ipc_support.h"
 #include "content/browser/devtools/devtools_http_handler.h"
@@ -77,6 +80,7 @@
 #include "ui/native_theme/native_theme_features.h"
 #include "ui/gl/gl_utils.h"
 #include "ui/gl/gl_switches.h"
+#include "url/url_features.h"
 #if defined(Q_OS_WIN)
 #include "sandbox/win/src/sandbox_types.h"
 #include "content/public/app/sandbox_helper_win.h"
@@ -123,6 +127,8 @@
 #define STRINGIFY_LITERAL(x) #x
 #define STRINGIFY_EXPANDED(x) STRINGIFY_LITERAL(x)
 
+using namespace Qt::StringLiterals;
+
 namespace QtWebEngineCore {
 
 Q_WEBENGINE_LOGGING_CATEGORY(webEngineContextLog, "qt.webenginecontext")
@@ -145,7 +151,7 @@ class GPUInfo
         Qualcomm,
         Samsung,
         Broadcom,
-        VMWare,
+        VMware,
         VirtIO,
 
         // Khronos-registered vendors
@@ -180,7 +186,7 @@ class GPUInfo
             {0x5143, Qualcomm},
             {0x144D, Samsung},
             {0x14E4, Broadcom},
-            {0x15AD, VMWare},
+            {0x15AD, VMware},
             {0x1AF4, VirtIO},
             {0x10001, Vivante},
             {0x10002, VeriSilicon},
@@ -195,27 +201,29 @@ class GPUInfo
         if (it != vendorIdMap.end())
             return it->second;
 
-        qWarning() << "Unknown Vendor ID:" << QStringLiteral("0x%1").arg(vendorId, 0, 16);
+        qWarning("Unknown Vendor ID: 0x%llx", vendorId);
         return Unknown;
     }
 
-    static Vendor deviceNameToVendor(const QString &deviceName)
+    static Vendor deviceNameToVendor(QLatin1StringView deviceName)
     {
         // TODO: Test and add more vendors to the list.
-        if (deviceName.contains(QLatin1StringView("AMD"), Qt::CaseInsensitive))
+        if (deviceName.contains("AMD"_L1, Qt::CaseInsensitive))
             return AMD;
-        if (deviceName.contains(QLatin1StringView("Intel"), Qt::CaseInsensitive))
+        if (deviceName.contains("Intel"_L1, Qt::CaseInsensitive))
             return Intel;
-        if (deviceName.contains(QLatin1StringView("Nvidia"), Qt::CaseInsensitive))
+        if (deviceName.contains("Nvidia"_L1, Qt::CaseInsensitive))
             return Nvidia;
+        if (deviceName.contains("VMware"_L1, Qt::CaseInsensitive))
+            return VMware;
 
 #if BUILDFLAG(IS_OZONE)
-        if (deviceName.contains(QLatin1StringView("Mesa llvmpipe")))
+        if (deviceName.contains("Mesa llvmpipe"_L1))
             return Mesa;
 #endif
 
 #if defined(Q_OS_MACOS)
-        if (deviceName.contains(QLatin1StringView("Apple")))
+        if (deviceName.contains("Apple"_L1))
             return Apple;
 #endif
 
@@ -238,7 +246,7 @@ class GPUInfo
             {Qualcomm, "Qualcomm"},
             {Samsung, "Samsung"},
             {Broadcom, "Broadcom"},
-            {VMWare, "VMWare"},
+            {VMware, "VMware"},
             {VirtIO, "VirtIO"},
             {Vivante, "Vivante"},
             {VeriSilicon, "VeriSilicon"},
@@ -253,11 +261,11 @@ class GPUInfo
         if (it != vendorNameMap.end())
             return it->second;
 
-        Q_UNREACHABLE();
-        return "Unknown";
+        Q_UNREACHABLE_RETURN("Unknown");
     }
 
     Vendor vendor() const { return m_vendor; }
+    QString deviceName() const { return m_deviceName; }
     QString getAdapterLuid() const { return m_adapterLuid; }
 
 private:
@@ -280,6 +288,7 @@ class GPUInfo
             }
             if (d3d11Rhi) {
                 m_vendor = vendorIdToVendor(d3d11Rhi->driverInfo().vendorId);
+                m_deviceName = QString::fromUtf8(d3d11Rhi->driverInfo().deviceName);
 
                 const QRhiD3D11NativeHandles *handles =
                         static_cast<const QRhiD3D11NativeHandles *>(d3d11Rhi->nativeHandles());
@@ -293,8 +302,10 @@ class GPUInfo
             QRhiMetalInitParams params;
             QScopedPointer<QRhi> metalRhi(
                     QRhi::create(QRhi::Metal, &params, QRhi::Flags(), nullptr));
-            if (metalRhi)
+            if (metalRhi) {
                 m_vendor = deviceNameToVendor(QLatin1StringView(metalRhi->driverInfo().deviceName));
+                m_deviceName = QString::fromUtf8(metalRhi->driverInfo().deviceName);
+            }
         }
 #endif
 
@@ -304,8 +315,10 @@ class GPUInfo
             params.fallbackSurface = QRhiGles2InitParams::newFallbackSurface();
             QScopedPointer<QRhi> glRhi(
                     QRhi::create(QRhi::OpenGLES2, &params, QRhi::Flags(), nullptr));
-            if (glRhi)
+            if (glRhi) {
                 m_vendor = deviceNameToVendor(QLatin1StringView(glRhi->driverInfo().deviceName));
+                m_deviceName = QString::fromUtf8(glRhi->driverInfo().deviceName);
+            }
         }
 #endif
 
@@ -325,6 +338,7 @@ class GPUInfo
                     // see https://www.phoronix.com/news/Mesa-20.1-Vulkan-Dev-Selection
                     // Try to detect this case and at least warn about it.
                     m_vendor = vendorIdToVendor(vulkanRhi->driverInfo().vendorId);
+                    m_deviceName = QString::fromUtf8(vulkanRhi->driverInfo().deviceName);
                 }
             }
         }
@@ -335,6 +349,7 @@ class GPUInfo
     }
 
     Vendor m_vendor = Unknown;
+    QString m_deviceName;
     QString m_adapterLuid;
 };
 
@@ -352,7 +367,7 @@ static bool usingSupportedSGBackend()
     QString device = QQuickWindow::sceneGraphBackend();
 
     for (int index = 0; index < args.count(); ++index) {
-        if (args.at(index).startsWith(QLatin1StringView("--device="))) {
+        if (args.at(index).startsWith("--device="_L1)) {
             device = args.at(index).mid(9);
             break;
         }
@@ -363,7 +378,7 @@ static bool usingSupportedSGBackend()
     if (device.isEmpty())
         device = qEnvironmentVariable("QMLSCENE_DEVICE");
 
-    return device.isEmpty() || device == QLatin1StringView("rhi");
+    return device.isEmpty() || device == "rhi"_L1;
 }
 
 static std::string getGLType(bool disableGpu)
@@ -411,44 +426,38 @@ void dummyGetPluginCallback(const std::vector<content::WebPluginInfo>&)
 static void logContext(const std::string &glType, base::CommandLine *cmd)
 {
     if (Q_UNLIKELY(webEngineContextLog().isDebugEnabled())) {
-        QStringList log;
-        log << QLatin1StringView("\n");
-
-        log << QLatin1StringView("Chromium GL Backend: " + glType) << QLatin1StringView("\n");
-        log << QLatin1StringView("Chromium ANGLE Backend: " + getAngleType(glType, cmd))
-            << QLatin1StringView("\n");
-        log << QLatin1StringView("Chromium Vulkan Backend: " + getVulkanType(cmd))
-            << QLatin1StringView("\n");
-        log << QLatin1StringView("\n");
-
-        log << QLatin1StringView("QSG RHI Backend:") << QSGRhiSupport::instance()->rhiBackendName()
-            << QLatin1StringView("\n");
-        log << QLatin1StringView("QSG RHI Backend Supported:")
-            << QLatin1StringView(usingSupportedSGBackend() ? "yes" : "no")
-            << QLatin1StringView("\n");
-        log << QLatin1StringView("GPU Vendor: "
-                                 + GPUInfo::vendorToString(GPUInfo::instance()->vendor()))
-            << QLatin1StringView("\n");
-        log << QLatin1StringView("\n");
+        QString log;
+        log += u'\n';
+
+        log += "Chromium GL Backend: "_L1 + QLatin1StringView(glType) + "\n"_L1;
+        log += "Chromium ANGLE Backend: "_L1 + QLatin1StringView(getAngleType(glType, cmd)) + u'\n';
+        log += "Chromium Vulkan Backend: "_L1 + QLatin1StringView(getVulkanType(cmd)) + u'\n';
+        log += u'\n';
+
+        log += "QSG RHI Backend: "_L1 + QSGRhiSupport::instance()->rhiBackendName() + u'\n';
+        log += "QSG RHI Backend Supported: "_L1 + (usingSupportedSGBackend() ? "yes"_L1 : "no"_L1)
+                + u'\n';
+        log += "QSG RHI Device: "_L1 + GPUInfo::instance()->deviceName() + u'\n';
+        log += "QSG RHI GPU Vendor: "_L1
+                + QLatin1StringView(GPUInfo::vendorToString(GPUInfo::instance()->vendor())) + u'\n';
+        log += u'\n';
 
 #if QT_CONFIG(opengl)
 #if BUILDFLAG(IS_OZONE)
-        log << QLatin1StringView("Using GLX:")
-            << QLatin1StringView(OzoneUtilQt::usingGLX() ? "yes" : "no") << QLatin1StringView("\n");
-        log << QLatin1StringView("Using EGL:")
-            << QLatin1StringView(OzoneUtilQt::usingEGL() ? "yes" : "no") << QLatin1StringView("\n");
+        log += "Using GLX: "_L1 + (OzoneUtilQt::usingGLX() ? "yes"_L1 : "no"_L1) + u'\n';
+        log += "Using EGL: "_L1 + (OzoneUtilQt::usingEGL() ? "yes"_L1 : "no"_L1) + u'\n';
 #endif // BUILDFLAG(IS_OZONE)
-        log << QLatin1StringView("Using Shared GL:")
-            << QLatin1StringView(QOpenGLContext::globalShareContext() ? "yes" : "no")
-            << QLatin1StringView("\n");
+        log += "Using Shared GL: "_L1 + (QOpenGLContext::globalShareContext() ? "yes"_L1 : "no"_L1)
+                + u'\n';
+        log += u'\n';
 #endif // QT_CONFIG(opengl)
 
-        log << QLatin1StringView("Init Parameters:\n");
+        log += "Init Parameters:\n"_L1;
         const base::CommandLine::SwitchMap switchMap = cmd->GetSwitches();
         for (const auto &pair : switchMap)
-            log << QStringLiteral(" *  %1 %2\n").arg(toQt(pair.first)).arg(toQt(pair.second));
+            log += " *  "_L1 + toQt(pair.first) + u' ' + toQt(pair.second) + u'\n';
 
-        qCDebug(webEngineContextLog) << qPrintable(log.join(QLatin1Char(' ')));
+        qCDebug(webEngineContextLog, "%ls", qUtf16Printable(log));
     }
 }
 
@@ -460,14 +469,14 @@ static void setupProxyPac(base::CommandLine *commandLine)
         QUrl pac_url(toQt(commandLine->GetSwitchValueASCII(switches::kProxyPacUrl)));
         if (pac_url.isValid()
             && (pac_url.isLocalFile()
-                || !pac_url.scheme().compare(QLatin1StringView("qrc"), Qt::CaseInsensitive))) {
+                || !pac_url.scheme().compare("qrc"_L1, Qt::CaseInsensitive))) {
             QFile file;
             if (pac_url.isLocalFile())
                 file.setFileName(pac_url.toLocalFile());
             else
                 file.setFileName(pac_url.path().prepend(QLatin1Char(':')));
             if (file.exists() && file.open(QIODevice::ReadOnly | QIODevice::Text)) {
-                QByteArray ba = file.readAll();
+                const QByteArray ba = file.readAll();
                 commandLine->RemoveSwitch(switches::kProxyPacUrl);
                 commandLine->AppendSwitchASCII(switches::kProxyPacUrl,
                         ba.toBase64().prepend("data:application/x-javascript-config;base64,").toStdString());
@@ -484,6 +493,13 @@ static void cleanupVizProcess()
     content::GetHostFrameSinkManager()->SetConnectionLostCallback(base::DoNothing());
     auto factory = static_cast<content::VizProcessTransportFactory*>(content::ImageTransportFactory::GetInstance());
     factory->PrepareForShutDown();
+
+    // Wait for viz destroy tasks to be completed on the GPU thread.
+    base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL,
+                              base::WaitableEvent::InitialState::NOT_SIGNALED);
+    gpuChildThread->main_thread_runner()->PostTask(
+            FROM_HERE, base::BindOnce([](base::WaitableEvent *event) { event->Signal(); }, &event));
+    event.Wait();
 }
 
 static QStringList parseEnvCommandLine(const QString &cmdLine)
@@ -777,10 +793,6 @@ WebEngineContext::WebEngineContext()
     base::apple::SetOverrideAmIBundled(false);
 #endif
 
-    base::ThreadPoolInstance::Create("Browser");
-    m_contentRunner = content::ContentMainRunner::Create();
-    m_browserRunner = content::BrowserMainRunner::Create();
-
 #ifdef Q_OS_LINUX
     // Call qputenv before BrowserMainRunnerImpl::Initialize is called.
     // http://crbug.com/245466
@@ -818,7 +830,7 @@ WebEngineContext::WebEngineContext()
 #endif
     } else {
         parsedCommandLine->AppendSwitch(sandbox::policy::switches::kNoSandbox);
-        qInfo() << "Sandboxing disabled by user.";
+        qInfo("Sandboxing disabled by user.");
     }
 
     // Do not advertise a feature we have removed at compile time
@@ -846,7 +858,6 @@ WebEngineContext::WebEngineContext()
     disableFeatures.push_back(features::kEyeDropper.name);
 
     // Explicitly tell Chromium about default-on features we do not support
-    disableFeatures.push_back(features::kAttributionReportingCrossAppWebOverride.name);
     disableFeatures.push_back(features::kBackgroundFetch.name);
     disableFeatures.push_back(features::kInstalledApp.name);
     parsedCommandLine->AppendSwitchASCII(switches::kDisableBlinkFeatures, "WebOTP");
@@ -854,16 +865,20 @@ WebEngineContext::WebEngineContext()
     disableFeatures.push_back(features::kWebPayments.name);
     disableFeatures.push_back(features::kWebUsb.name);
 
+    // Currently causing more issues than it fixes.
+    // Probably will be removed in 134, tst_origins should be updated in this case.
+    disableFeatures.push_back(url::kStandardCompliantNonSpecialSchemeURLParsing.name);
+
     if (useEmbeddedSwitches) {
         // embedded switches are based on the switches for Android, see content/browser/android/content_startup_flags.cc
         enableFeatures.push_back(features::kOverlayScrollbar.name);
         parsedCommandLine->AppendSwitch(switches::kEnableViewport);
-        parsedCommandLine->AppendSwitch(switches::kValidateInputEventStream);
+        parsedCommandLine->AppendSwitch(input::switches::kValidateInputEventStream);
         parsedCommandLine->AppendSwitch(cc::switches::kDisableCompositedAntialiasing);
     }
 
 #if BUILDFLAG(IS_OZONE)
-    if (GPUInfo::instance()->vendor() == GPUInfo::Nvidia) {
+    if (!isGbmSupported()) {
         disableFeatures.push_back(media::kVaapiVideoDecodeLinux.name);
         parsedCommandLine->AppendSwitch(switches::kDisableGpuMemoryBufferVideoFrames);
     }
@@ -875,20 +890,11 @@ WebEngineContext::WebEngineContext()
                       == gl::kGLImplementationANGLEName);
     }
 
-    if (usingANGLE && !parsedCommandLine->HasSwitch(switches::kUseANGLE)) {
-        parsedCommandLine->AppendSwitchASCII(switches::kUseANGLE,
-                                             gl::kANGLEImplementationOpenGLEGLName);
-    }
-
 #if QT_CONFIG(webengine_vulkan)
     if (QQuickWindow::graphicsApi() == QSGRendererInterface::OpenGL && usingSupportedSGBackend()) {
-        if (usingANGLE && GPUInfo::instance()->vendor() == GPUInfo::Nvidia) {
-            qWarning("Disable ANGLE because GBM is not supported with the current configuration. "
+        if (usingANGLE && !isGbmSupported()) {
+            qWarning("GBM is not supported with the current configuration. "
                      "Fallback to Vulkan rendering in Chromium.");
-            parsedCommandLine->RemoveSwitch(switches::kUseANGLE);
-            parsedCommandLine->RemoveSwitch(switches::kUseGL);
-            parsedCommandLine->AppendSwitchASCII(switches::kUseGL,
-                                                 gl::kGLImplementationDesktopName);
             parsedCommandLine->AppendSwitchASCII(switches::kUseVulkan,
                                                  switches::kVulkanImplementationNameNative);
             enableFeatures.push_back(features::kVulkan.name);
@@ -912,11 +918,10 @@ WebEngineContext::WebEngineContext()
                     found++;
             }
             if (found != requiredDeviceExtensions.size()) {
-                qWarning().nospace()
-                        << "Vulkan rendering may fail because " << deviceExtensionsVar
-                        << " environment variable is already set but it doesn't contain"
-                        << " some of the required Vulkan device extensions:\n"
-                        << qPrintable(requiredDeviceExtensions.join('\n'));
+                qWarning("Vulkan rendering may fail because %s environment variable is already "
+                         "set but it doesn't contain some of the required Vulkan device "
+                         "extensions:\n%s",
+                         deviceExtensionsVar, requiredDeviceExtensions.join('\n').constData());
             }
         } else {
             qputenv(deviceExtensionsVar, requiredDeviceExtensions.join(';'));
@@ -981,6 +986,7 @@ WebEngineContext::WebEngineContext()
         contentMainParams.sandbox_info = &sandbox_info;
     }
 #endif
+    m_contentRunner = content::ContentMainRunner::Create();
     m_contentRunner->Initialize(std::move(contentMainParams));
 
     mojo::core::Configuration mojoConfiguration;
@@ -991,11 +997,16 @@ WebEngineContext::WebEngineContext()
     m_mainDelegate->PreBrowserMain();
     base::MessagePump::OverrideMessagePumpForUIFactory(messagePumpFactory);
     content::BrowserTaskExecutor::Create();
+    auto* provider = m_mainDelegate->CreateVariationsIdsProvider();
+    if (!provider) {
+        variations::VariationsIdsProvider::Create(
+                variations::VariationsIdsProvider::Mode::kUseSignedInState);
+    }
     m_mainDelegate->PostEarlyInitialization({});
     content::StartBrowserThreadPool();
     content::BrowserTaskExecutor::PostFeatureListSetup();
     tracing::InitTracingPostThreadPoolStartAndFeatureList(false);
-    base::PowerMonitor::Initialize(std::make_unique<base::PowerMonitorDeviceSource>());
+    base::PowerMonitor::GetInstance()->Initialize(MakePowerMonitorDeviceSource());
     content::ProcessVisibilityTracker::GetInstance();
     m_discardableSharedMemoryManager = std::make_unique<discardable_memory::DiscardableSharedMemoryManager>();
 
@@ -1009,6 +1020,7 @@ WebEngineContext::WebEngineContext()
 
     content::MainFunctionParams mainParams(base::CommandLine::ForCurrentProcess());
     mainParams.startup_data = std::move(startupData);
+    m_browserRunner = content::BrowserMainRunner::Create();
     m_browserRunner->Initialize(std::move(mainParams));
 
     m_devtoolsServer.reset(new DevToolsServerQt());
@@ -1066,7 +1078,7 @@ base::CommandLine *WebEngineContext::initCommandLine(bool &useEmbeddedSwitches,
     }
 
     base::CommandLine *parsedCommandLine = base::CommandLine::ForCurrentProcess();
-    int index = appArgs.indexOf(QRegularExpression(QLatin1StringView("--webEngineArgs"),
+    int index = appArgs.indexOf(QRegularExpression(u"--webEngineArgs"_s,
                                                    QRegularExpression::CaseInsensitiveOption));
     if (qEnvironmentVariableIsSet(kChromiumFlagsEnv)) {
         appArgs = appArgs.mid(0, 1); // Take application name and drop the rest
@@ -1081,27 +1093,26 @@ base::CommandLine *WebEngineContext::initCommandLine(bool &useEmbeddedSwitches,
         }
     }
 #if defined(QTWEBENGINE_EMBEDDED_SWITCHES)
-    useEmbeddedSwitches = !appArgs.contains(QStringLiteral("--disable-embedded-switches"));
+    useEmbeddedSwitches = !appArgs.contains("--disable-embedded-switches"_L1);
 #else
-    useEmbeddedSwitches = appArgs.contains(QStringLiteral("--enable-embedded-switches"));
+    useEmbeddedSwitches = appArgs.contains("--enable-embedded-switches"_L1);
 #endif
-    enableGLSoftwareRendering =
-            appArgs.removeAll(QStringLiteral("--enable-webgl-software-rendering"));
-    appArgs.removeAll(QStringLiteral("--disable-embedded-switches"));
-    appArgs.removeAll(QStringLiteral("--enable-embedded-switches"));
+    enableGLSoftwareRendering = appArgs.removeAll("--enable-webgl-software-rendering"_L1);
+    appArgs.removeAll("--disable-embedded-switches"_L1);
+    appArgs.removeAll("--enable-embedded-switches"_L1);
 
     bool isRemoteDebugPort =
             (-1
-             != appArgs.indexOf(QRegularExpression(QStringLiteral("--remote-debugging-port=.*"),
+             != appArgs.indexOf(QRegularExpression(u"--remote-debugging-port=.*"_s,
                                                    QRegularExpression::CaseInsensitiveOption)))
             || !qEnvironmentVariable("QTWEBENGINE_REMOTE_DEBUGGING").isEmpty();
     bool isRemoteAllowOrigins =
             (-1
-             != appArgs.indexOf(QRegularExpression(QStringLiteral("--remote-allow-origins=.*"),
+             != appArgs.indexOf(QRegularExpression(u"--remote-allow-origins=.*"_s,
                                                    QRegularExpression::CaseInsensitiveOption)));
 
     if (isRemoteDebugPort && !isRemoteAllowOrigins) {
-        appArgs.append(QStringLiteral("--remote-allow-origins=*"));
+        appArgs.append(u"--remote-allow-origins=*"_s);
         qWarning("Added {--remote-allow-origins=*} to command-line arguments "
                  "to avoid web socket connection errors during remote debugging.");
     }
@@ -1125,6 +1136,46 @@ bool WebEngineContext::closingDown()
     return m_closingDown;
 }
 
+#if BUILDFLAG(IS_OZONE)
+bool WebEngineContext::isGbmSupported()
+{
+    static bool supported = []() {
+        const static char kForceGbmEnv[] = "QTWEBENGINE_FORCE_USE_GBM";
+        if (Q_UNLIKELY(qEnvironmentVariableIsSet(kForceGbmEnv))) {
+            qWarning("%s environment variable is set and it is for debugging purposes only.",
+                     kForceGbmEnv);
+            bool ok;
+            int forceGbm = qEnvironmentVariableIntValue(kForceGbmEnv, &ok);
+            if (ok) {
+                qWarning("GBM support is force %s.", forceGbm != 0 ? "enabled" : "disabled");
+                return (forceGbm != 0);
+            }
+
+            qWarning("Ignoring invalid value of %s and do not force GBM. "
+                     "Use 0 to force disable or 1 to force enable.",
+                     kForceGbmEnv);
+        }
+
+        if (GPUInfo::instance()->vendor() == GPUInfo::Nvidia) {
+            // FIXME: This disables GBM for Nvidia. Remove this when Nvidia fixes its GBM support.
+            //
+            // "Buffer allocation and submission to DRM KMS using gbm is not currently supported."
+            // See: https://download.nvidia.com/XFree86/Linux-x86_64/570.86.16/README/kms.html"
+            //
+            // Chromium uses GBM to allocate scanout buffers. Scanout requires DRM KMS. If KMS is
+            // enabled, gbm_device and gbm_buffer are created without any issues but rendering to
+            // the buffer will malfunction. It is not known how to detect this problem before
+            // rendering so we just disable GBM for Nvidia.
+            return false;
+        }
+
+        return true;
+    }();
+
+    return supported;
+}
+#endif
+
 void WebEngineContext::registerMainThreadFactories()
 {
     content::UtilityProcessHost::RegisterUtilityMainThreadFactory(content::CreateInProcessUtilityThread);
@@ -1152,7 +1203,7 @@ const char *qWebEngineChromiumVersion() noexcept
 
 const char *qWebEngineChromiumSecurityPatchVersion() noexcept
 {
-    return "129.0.6668.58"; // FIXME: Remember to update
+    return "139.0.7258.67"; // FIXME: Remember to update
 }
 
 QT_END_NAMESPACE
diff --git a/src/core/web_engine_context.h b/src/core/web_engine_context.h
index 1a3d0feada7..6f2bf04c4b1 100644
--- a/src/core/web_engine_context.h
+++ b/src/core/web_engine_context.h
@@ -65,6 +65,9 @@ class WebEngineContext : public base::RefCounted<WebEngineContext> {
     static ProxyAuthentication qProxyNetworkAuthentication(QString host, int port);
     static void flushMessages();
     static bool closingDown();
+#if BUILDFLAG(IS_OZONE)
+    static bool isGbmSupported();
+#endif
     ProfileAdapter *createDefaultProfileAdapter();
     ProfileAdapter *defaultProfileAdapter();
 
diff --git a/src/core/web_engine_library_info.cpp b/src/core/web_engine_library_info.cpp
index ac01cbc90e5..27ef606c5d1 100644
--- a/src/core/web_engine_library_info.cpp
+++ b/src/core/web_engine_library_info.cpp
@@ -34,6 +34,7 @@
 #error "No name defined for QtWebEngine's process"
 #endif
 
+using namespace Qt::StringLiterals;
 using namespace QtWebEngineCore;
 
 Q_WEBENGINE_LOGGING_CATEGORY(webEngineLibraryInfoLog, "qt.webengine.libraryinfo")
@@ -41,7 +42,8 @@ Q_WEBENGINE_LOGGING_CATEGORY(webEngineLibraryInfoLog, "qt.webengine.libraryinfo"
 namespace {
 
 QString fallbackDir() {
-    static QString directory = QDir::homePath() % QLatin1String("/.") % QCoreApplication::applicationName();
+    static const QString directory =
+            QDir::homePath() % "/."_L1 % QCoreApplication::applicationName();
     return directory;
 }
 
@@ -57,8 +59,8 @@ static QString getBundlePath(CFBundleRef frameworkBundle)
     // The following is a fix for QtWebEngineProcess crashes on OS X 10.7 and before.
     // We use it for the other OS X versions as well to make sure it works and because
     // the directory structure should be the same.
-    if (qApp->applicationName() == QLatin1String(qWebEngineProcessName())) {
-        path = QDir::cleanPath(qApp->applicationDirPath() % QLatin1String("/../../../.."));
+    if (qApp->applicationName() == QLatin1StringView(qWebEngineProcessName())) {
+        path = QDir::cleanPath(qApp->applicationDirPath() % "/../../../.."_L1);
     } else if (frameworkBundle) {
         CFURLRef bundleUrl = CFBundleCopyBundleURL(frameworkBundle);
         CFStringRef bundlePath = CFURLCopyFileSystemPath(bundleUrl, kCFURLPOSIXPathStyle);
@@ -75,8 +77,8 @@ static QString getResourcesPath(CFBundleRef frameworkBundle)
     // The following is a fix for QtWebEngineProcess crashes on OS X 10.7 and before.
     // We use it for the other OS X versions as well to make sure it works and because
     // the directory structure should be the same.
-    if (qApp->applicationName() == QLatin1String(qWebEngineProcessName())) {
-        path = getBundlePath(frameworkBundle) % QLatin1String("/Resources");
+    if (qApp->applicationName() == QLatin1StringView(qWebEngineProcessName())) {
+        path = getBundlePath(frameworkBundle) % "/Resources"_L1;
     } else if (frameworkBundle) {
         CFURLRef resourcesRelativeUrl = CFBundleCopyResourcesDirectoryURL(frameworkBundle);
         CFStringRef resourcesRelativePath = CFURLCopyFileSystemPath(resourcesRelativeUrl, kCFURLPOSIXPathStyle);
@@ -121,20 +123,18 @@ QString subProcessPath()
     static QString processPath;
     if (processPath.isEmpty()) {
 #if defined(Q_OS_WIN)
-        const QString processBinary = QLatin1String(qWebEngineProcessName()) % QLatin1String(".exe");
+        const QString processBinary = QLatin1StringView(qWebEngineProcessName()) % ".exe"_L1;
 #else
-        const QString processBinary = QLatin1String(qWebEngineProcessName());
+        const auto processBinary = QLatin1StringView(qWebEngineProcessName());
 #endif
 
         QStringList candidatePaths;
-        const QString fromEnv = qEnvironmentVariable("QTWEBENGINEPROCESS_PATH");
-        if (!fromEnv.isEmpty()) {
-            // Only search in QTWEBENGINEPROCESS_PATH if set
-            candidatePaths << fromEnv;
-        } else {
+        bool includeOverrideMessage = false;
+        if (QString fromEnv = qEnvironmentVariable("QTWEBENGINEPROCESS_PATH"); fromEnv.isEmpty()) {
+            includeOverrideMessage = true;
 #if defined(Q_OS_DARWIN) && defined(QT_MAC_FRAMEWORK_BUILD)
-            candidatePaths << getBundlePath(frameworkBundle()) % QStringLiteral("/Helpers/")
-                            % qWebEngineProcessName() % QStringLiteral(".app/Contents/MacOS/")
+            candidatePaths << getBundlePath(frameworkBundle()) % "/Helpers/"_L1
+                            % qWebEngineProcessName() % ".app/Contents/MacOS/"_L1
                             % qWebEngineProcessName();
 #else
             candidatePaths << QLibraryInfo::path(QLibraryInfo::LibraryExecutablesPath)
@@ -144,29 +144,30 @@ QString subProcessPath()
 #endif
             candidatePaths << QCoreApplication::applicationDirPath()
                               % QLatin1Char('/') % processBinary;
+        } else {
+            // Only search in QTWEBENGINEPROCESS_PATH if set
+            candidatePaths.append(std::move(fromEnv));
         }
 
         for (const QString &candidate : std::as_const(candidatePaths)) {
             if (QFileInfo::exists(candidate)) {
                 processPath = candidate;
-                qCDebug(webEngineLibraryInfoLog, "Qt WebEngine process path: %s",
-                        qPrintable(candidate));
+                qCDebug(webEngineLibraryInfoLog, "Qt WebEngine process path: %ls",
+                        qUtf16Printable(candidate));
                 break;
             }
         }
         if (processPath.isEmpty()) {
-            QStringList errorMessage;
-            errorMessage.append(
-                    QStringLiteral("The following paths were searched for Qt WebEngine Process:"));
+            QString errorMessage;
+            errorMessage += "The following paths were searched for Qt WebEngine Process:\n"_L1;
             for (const QString &candidate : std::as_const(candidatePaths))
-                errorMessage.append(QStringLiteral("  ") % candidate);
-            errorMessage.append(QStringLiteral("but could not find it."));
-            if (fromEnv.isEmpty()) {
-                errorMessage.append(
-                        QStringLiteral("You may override the default search path by using "
-                                       "QTWEBENGINEPROCESS_PATH environment variable."));
+                errorMessage += "  "_L1 + candidate + u'\n';
+            errorMessage += "but could not find it.\n"_L1;
+            if (includeOverrideMessage) {
+                errorMessage += "You may override the default search path by using "
+                                "QTWEBENGINEPROCESS_PATH environment variable.\n"_L1;
             }
-            qFatal("%s", qPrintable(errorMessage.join('\n')));
+            qFatal("%ls", qUtf16Printable(errorMessage));
         }
 
 #if defined(Q_OS_WIN)
@@ -189,51 +190,44 @@ QString localesPath()
     if (potentialLocalesPath.isEmpty()) {
         QStringList candidatePaths;
         const QString translationPakFilename =
-#if QT_VERSION >= QT_VERSION_CHECK(6, 3, 0)
-                QLatin1String(WebEngineLibraryInfo::getResolvedLocale() + ".pak");
-#else
-                QLatin1String((WebEngineLibraryInfo::getResolvedLocale() + ".pak").c_str());
-#endif
-        const QString fromEnv = qEnvironmentVariable("QTWEBENGINE_LOCALES_PATH");
-        if (!fromEnv.isEmpty()) {
-            // Only search in QTWEBENGINE_LOCALES_PATH if set
-            candidatePaths << fromEnv;
-        } else {
+                QLatin1StringView(WebEngineLibraryInfo::getResolvedLocale()) % ".pak"_L1;
+        bool includeOverrideMessage = false;
+        if (QString fromEnv = qEnvironmentVariable("QTWEBENGINE_LOCALES_PATH"); fromEnv.isEmpty()) {
+            includeOverrideMessage = true;
 #if defined(Q_OS_DARWIN) && defined(QT_MAC_FRAMEWORK_BUILD)
             candidatePaths << getResourcesPath(frameworkBundle()) % QDir::separator()
-                            % QLatin1String("qtwebengine_locales");
+                            % "qtwebengine_locales"_L1;
 #endif
             candidatePaths << QLibraryInfo::path(QLibraryInfo::TranslationsPath) % QDir::separator()
-                            % QLatin1String("qtwebengine_locales");
+                            % "qtwebengine_locales"_L1;
             candidatePaths << fallbackDir();
+        } else {
+            // Only search in QTWEBENGINE_LOCALES_PATH if set
+            candidatePaths.append(std::move(fromEnv));
         }
 
         for (const QString &candidate : std::as_const(candidatePaths)) {
             if (QFileInfo::exists(candidate % QDir::separator() % translationPakFilename)) {
                 potentialLocalesPath = candidate;
-                qCDebug(webEngineLibraryInfoLog, "Qt WebEngine locales path: %s",
-                        qPrintable(candidate));
+                qCDebug(webEngineLibraryInfoLog, "Qt WebEngine locales path: %ls",
+                        qUtf16Printable(candidate));
                 break;
             }
         }
 
         if (potentialLocalesPath.isEmpty()) {
-            QStringList warningMessage;
-            warningMessage.append(
-                    QStringLiteral("The following paths were searched for Qt WebEngine locales:"));
+            QString warningMessage;
+            warningMessage += "The following paths were searched for Qt WebEngine locales:\n"_L1;
             for (const QString &candidate : std::as_const(candidatePaths))
-                warningMessage.append(QStringLiteral("  ") % candidate);
-            warningMessage.append(
-                    QStringLiteral(
-                            "but could not find the translation file for the current locale: ")
-                    % translationPakFilename);
-            if (fromEnv.isEmpty()) {
-                warningMessage.append(
-                        QStringLiteral("You may override the default search paths by using "
-                                       "QTWEBENGINE_LOCALES_PATH environment variable."));
+                warningMessage += "  "_L1 % candidate + u'\n';
+            warningMessage += "but could not find the translation file for the current locale: "_L1
+                    + translationPakFilename + u'\n';
+            if (includeOverrideMessage) {
+                warningMessage += "You may override the default search paths by using "
+                                  "QTWEBENGINE_LOCALES_PATH environment variable.\n"_L1;
             }
-            warningMessage.append(QStringLiteral("Translations WILL NOT be correct."));
-            qWarning("%s", qPrintable(warningMessage.join('\n')));
+            warningMessage += "Translations WILL NOT be correct.\n"_L1;
+            qWarning("%ls", qUtf16Printable(warningMessage));
         }
     }
 
@@ -244,64 +238,65 @@ QString localesPath()
 QString dictionariesPath(bool showWarnings)
 {
     static QString potentialDictionariesPath;
-    static QStringList warningMessage;
+    static QString warningMessage;
     static bool initialized = false;
     QStringList candidatePaths;
     if (!initialized) {
         initialized = true;
 
-        const QString fromEnv = qEnvironmentVariable("QTWEBENGINE_DICTIONARIES_PATH");
-        if (!fromEnv.isEmpty()) {
-            // Only search in QTWEBENGINE_DICTIONARIES_PATH if set
-            candidatePaths << fromEnv;
-        } else {
+        bool includeOverrideMessage = false;
+        if (QString fromEnv = qEnvironmentVariable("QTWEBENGINE_DICTIONARIES_PATH");
+            fromEnv.isEmpty()) {
+            includeOverrideMessage = true;
             // First try to find dictionaries near the application.
 #ifdef Q_OS_DARWIN
             QString resourcesDictionariesPath = getMainApplicationResourcesPath()
-                    % QDir::separator() % QLatin1String("qtwebengine_dictionaries");
-            candidatePaths << resourcesDictionariesPath;
+                    % QDir::separator() % "qtwebengine_dictionaries"_L1;
+            candidatePaths.append(std::move(resourcesDictionariesPath));
 #endif
             QString applicationDictionariesPath = QCoreApplication::applicationDirPath()
-                    % QDir::separator() % QLatin1String("qtwebengine_dictionaries");
-            candidatePaths << applicationDictionariesPath;
+                    % QDir::separator() % "qtwebengine_dictionaries"_L1;
+            candidatePaths.append(std::move(applicationDictionariesPath));
 
             // Then try to find dictionaries near the installed library.
 #if defined(Q_OS_DARWIN) && defined(QT_MAC_FRAMEWORK_BUILD)
-            QString frameworkDictionariesPath = getResourcesPath(frameworkBundle())
-                    % QLatin1String("/qtwebengine_dictionaries");
-            candidatePaths << frameworkDictionariesPath;
+            QString frameworkDictionariesPath =
+                    getResourcesPath(frameworkBundle()) % "/qtwebengine_dictionaries"_L1;
+            candidatePaths.append(std::move(frameworkDictionariesPath));
 #endif
 
             QString libraryDictionariesPath = QLibraryInfo::path(QLibraryInfo::DataPath)
-                    % QDir::separator() % QLatin1String("qtwebengine_dictionaries");
-            candidatePaths << libraryDictionariesPath;
+                    % QDir::separator() % "qtwebengine_dictionaries"_L1;
+            candidatePaths.append(std::move(libraryDictionariesPath));
+        } else {
+            // Only search in QTWEBENGINE_DICTIONARIES_PATH if set
+            candidatePaths.append(std::move(fromEnv));
         }
 
         for (const QString &candidate : std::as_const(candidatePaths)) {
             if (QFileInfo::exists(candidate)) {
                 potentialDictionariesPath = candidate;
-                qCDebug(webEngineLibraryInfoLog, "Qt WebEngine dictionaries path: %s",
-                        qPrintable(candidate));
+                qCDebug(webEngineLibraryInfoLog, "Qt WebEngine dictionaries path: %ls",
+                        qUtf16Printable(candidate));
                 break;
             }
         }
         if (potentialDictionariesPath.isEmpty()) {
-            warningMessage.append(QStringLiteral(
-                    "The following paths were searched for Qt WebEngine dictionaries:"));
+            warningMessage +=
+                    "The following paths were searched for Qt WebEngine dictionaries:\n"_L1;
             for (const QString &candidate : std::as_const(candidatePaths))
-                warningMessage.append(QStringLiteral("  ") % candidate);
-            warningMessage.append(QStringLiteral("but could not find it."));
-            if (fromEnv.isEmpty()) {
-                warningMessage.append(
-                        QStringLiteral("You may override the default search path by using "
-                                       "QTWEBENGINE_DICTIONARIES_PATH environment variable."));
+                warningMessage += "  "_L1 + candidate + u'\n';
+            warningMessage += "but could not find it.\n"_L1;
+            if (includeOverrideMessage) {
+                warningMessage += "You may override the default search path by using "
+                                  "QTWEBENGINE_DICTIONARIES_PATH environment variable.\n"_L1;
             }
-            warningMessage.append(QStringLiteral("Spellchecking can not be enabled."));
+            warningMessage += "Spellchecking can not be enabled.\n"_L1;
         }
     }
 
     if (showWarnings && !warningMessage.isEmpty()) {
-        qWarning("%s", qPrintable(warningMessage.join('\n')));
+        qWarning("%ls", qUtf16Printable(warningMessage));
     }
 
     return potentialDictionariesPath;
@@ -313,44 +308,48 @@ QString resourcesPath()
     static QString potentialResourcesPath;
     if (potentialResourcesPath.isEmpty()) {
         QStringList candidatePaths;
-        const QString resourcesPakFilename = QLatin1String("qtwebengine_resources.pak");
-        const QString fromEnv = qEnvironmentVariable("QTWEBENGINE_RESOURCES_PATH");
-        if (!fromEnv.isEmpty()) {
-            // Only search in QTWEBENGINE_RESOURCES_PATH if set
-            candidatePaths << fromEnv;
-        } else {
+#if !defined(QT_USE_DEBUG_RESOURCES)
+        const auto resourcesPakFilename = "qtwebengine_resources.pak"_L1;
+#else
+        const auto resourcesPakFilename = "qtwebengine_resources.debug.pak"_L1;
+#endif
+        bool includeOverrideMessage = false;
+        if (QString fromEnv = qEnvironmentVariable("QTWEBENGINE_RESOURCES_PATH");
+            fromEnv.isEmpty()) {
+            includeOverrideMessage = true;
 #if defined(Q_OS_DARWIN) && defined(QT_MAC_FRAMEWORK_BUILD)
             candidatePaths << getResourcesPath(frameworkBundle());
 #endif
             candidatePaths << QLibraryInfo::path(QLibraryInfo::DataPath) % QDir::separator()
-                            % QLatin1String("resources");
+                            % "resources"_L1;
             candidatePaths << QLibraryInfo::path(QLibraryInfo::DataPath);
             candidatePaths << QCoreApplication::applicationDirPath();
             candidatePaths << fallbackDir();
+        } else {
+            // Only search in QTWEBENGINE_RESOURCES_PATH if set
+            candidatePaths.append(std::move(fromEnv));
         }
 
         for (const QString &candidate : std::as_const(candidatePaths)) {
             if (QFileInfo::exists(candidate % QDir::separator() % resourcesPakFilename)) {
                 potentialResourcesPath = candidate;
-                qCDebug(webEngineLibraryInfoLog, "Qt WebEngine resources path: %s",
-                        qPrintable(candidate));
+                qCDebug(webEngineLibraryInfoLog, "Qt WebEngine resources path: %ls",
+                        qUtf16Printable(candidate));
                 break;
             }
         }
 
         if (potentialResourcesPath.isEmpty()) {
-            QStringList errorMessage;
-            errorMessage.append(QStringLiteral(
-                    "The following paths were searched for Qt WebEngine resources:"));
+            QString errorMessage;
+            errorMessage += "The following paths were searched for Qt WebEngine resources:\n"_L1;
             for (const QString &candidate : std::as_const(candidatePaths))
-                errorMessage.append(QStringLiteral("  ") % candidate);
-            errorMessage.append(QStringLiteral("but could not find any."));
-            if (fromEnv.isEmpty()) {
-                errorMessage.append(
-                        QStringLiteral("You may override the default search paths by using "
-                                       "QTWEBENGINE_RESOURCES_PATH environment variable."));
+                errorMessage += "  "_L1 + candidate + u'\n';
+            errorMessage += "but could not find any.\n"_L1;
+            if (includeOverrideMessage) {
+                errorMessage += "You may override the default search paths by using "
+                                "QTWEBENGINE_RESOURCES_PATH environment variable.\n"_L1;
             }
-            qFatal("%s", qPrintable(errorMessage.join('\n')));
+            qFatal("%ls", qUtf16Printable(errorMessage));
         }
     }
 
@@ -362,14 +361,25 @@ base::FilePath WebEngineLibraryInfo::getPath(int key, bool showWarnings)
 {
     QString directory;
     switch (key) {
+#if !defined(QT_USE_DEBUG_RESOURCES)
     case QT_RESOURCES_PAK:
-        return toFilePath(resourcesPath() % QLatin1String("/qtwebengine_resources.pak"));
+        return toFilePath(resourcesPath() % "/qtwebengine_resources.pak"_L1);
     case QT_RESOURCES_100P_PAK:
-        return toFilePath(resourcesPath() % QLatin1String("/qtwebengine_resources_100p.pak"));
+        return toFilePath(resourcesPath() % "/qtwebengine_resources_100p.pak"_L1);
     case QT_RESOURCES_200P_PAK:
-        return toFilePath(resourcesPath() % QLatin1String("/qtwebengine_resources_200p.pak"));
+        return toFilePath(resourcesPath() % "/qtwebengine_resources_200p.pak"_L1);
     case QT_RESOURCES_DEVTOOLS_PAK:
-        return toFilePath(resourcesPath() % QLatin1String("/qtwebengine_devtools_resources.pak"));
+        return toFilePath(resourcesPath() % "/qtwebengine_devtools_resources.pak"_L1);
+#else
+    case QT_RESOURCES_PAK:
+        return toFilePath(resourcesPath() % "/qtwebengine_resources.debug.pak"_L1);
+    case QT_RESOURCES_100P_PAK:
+        return toFilePath(resourcesPath() % "/qtwebengine_resources_100p.debug.pak"_L1);
+    case QT_RESOURCES_200P_PAK:
+        return toFilePath(resourcesPath() % "/qtwebengine_resources_200p.debug.pak"_L1);
+    case QT_RESOURCES_DEVTOOLS_PAK:
+        return toFilePath(resourcesPath() % "/qtwebengine_devtools_resources.debug.pak"_L1);
+#endif
 #if defined(Q_OS_DARWIN) && defined(QT_MAC_FRAMEWORK_BUILD)
     case QT_FRAMEWORK_BUNDLE:
         return toFilePath(getBundlePath(frameworkBundle()));
diff --git a/src/core/web_engine_settings.cpp b/src/core/web_engine_settings.cpp
index ec4d600e8ab..4138cce692a 100644
--- a/src/core/web_engine_settings.cpp
+++ b/src/core/web_engine_settings.cpp
@@ -24,6 +24,8 @@
 #include <QFont>
 #include <QTimer>
 
+using namespace Qt::StringLiterals;
+
 namespace QtWebEngineCore {
 
 QHash<QWebEngineSettings::WebAttribute, bool> WebEngineSettings::s_defaultAttributes;
@@ -284,7 +286,7 @@ void WebEngineSettings::initDefaults()
         s_defaultAttributes.insert(QWebEngineSettings::ForceDarkMode, forceDarkMode);
         s_defaultAttributes.insert(QWebEngineSettings::PrintHeaderAndFooter, false);
         s_defaultAttributes.insert(QWebEngineSettings::PreferCSSMarginsForPrinting, false);
-        s_defaultAttributes.insert(QWebEngineSettings::JSTouchEventsEnabled,
+        s_defaultAttributes.insert(QWebEngineSettings::TouchEventsApiEnabled,
                                    isTouchScreenDetected());
     }
 
@@ -318,7 +320,7 @@ void WebEngineSettings::initDefaults()
         s_defaultFontSizes.insert(QWebEngineSettings::DefaultFontSize, 16);
     }
 
-    m_defaultEncoding = QStringLiteral("ISO-8859-1");
+    m_defaultEncoding = u"ISO-8859-1"_s;
     m_unknownUrlSchemePolicy = QWebEngineSettings::InheritedUnknownUrlSchemePolicy;
     m_imageAnimationPolicy = QWebEngineSettings::ImageAnimationPolicy::Inherited;
 }
@@ -399,8 +401,8 @@ void WebEngineSettings::applySettingsToWebPreferences(blink::web_pref::WebPrefer
     prefs->dns_prefetching_enabled = testAttribute(QWebEngineSettings::DnsPrefetchEnabled);
     prefs->disable_reading_from_canvas = !testAttribute(QWebEngineSettings::ReadingFromCanvasEnabled);
     prefs->animation_policy = toBlinkImageAnimationPolicy(imageAnimationPolicy());
-    bool touchEventsEnabled = isAttributeExplicitlySet(QWebEngineSettings::JSTouchEventsEnabled)
-            ? testAttribute(QWebEngineSettings::JSTouchEventsEnabled)
+    bool touchEventsEnabled = isAttributeExplicitlySet(QWebEngineSettings::TouchEventsApiEnabled)
+            ? testAttribute(QWebEngineSettings::TouchEventsApiEnabled)
             : isTouchScreenDetected();
     prefs->touch_event_feature_detection_enabled = touchEventsEnabled;
 
diff --git a/src/core/web_event_factory.cpp b/src/core/web_event_factory.cpp
index 86f10315b2b..946c6874623 100644
--- a/src/core/web_event_factory.cpp
+++ b/src/core/web_event_factory.cpp
@@ -38,6 +38,7 @@
 #include "native_web_keyboard_event_qt.h"
 #include "render_widget_host_view_qt_delegate.h"
 
+#include <QtCore/private/qstringiterator_p.h>
 #include <QtGui/private/qtgui-config_p.h>
 
 #include <QCoreApplication>
@@ -51,6 +52,8 @@
 #endif
 #include <QWheelEvent>
 
+using namespace Qt::StringLiterals;
+
 namespace QtWebEngineCore {
 
 using namespace blink;
@@ -59,26 +62,26 @@ enum class KeyboardDriver { Unknown, Windows, Cocoa, Xkb, Evdev };
 
 static KeyboardDriver keyboardDriverImpl()
 {
-    QString platformName = QGuiApplication::platformName();
+    const QString platformName = QGuiApplication::platformName();
 
-    if (platformName == QLatin1String("windows"))
+    if (platformName == "windows"_L1)
         return KeyboardDriver::Windows;
 
-    if (platformName == QLatin1String("cocoa"))
+    if (platformName == "cocoa"_L1)
         return KeyboardDriver::Cocoa;
 
-    if (platformName == QLatin1String("xcb") || platformName == QLatin1String("wayland"))
+    if (platformName == "xcb"_L1 || platformName == "wayland"_L1)
         return KeyboardDriver::Xkb;
 
 #if QT_CONFIG(libinput)
     // Based on QEglFSIntegration::createInputHandlers and QLibInputKeyboard::processKey.
-    if (platformName == QLatin1String("eglfs") && !qEnvironmentVariableIntValue("QT_QPA_EGLFS_NO_LIBINPUT"))
+    if (platformName == "eglfs"_L1 && !qEnvironmentVariableIntValue("QT_QPA_EGLFS_NO_LIBINPUT"))
         return KeyboardDriver::Xkb;
 #endif
 
 #if QT_CONFIG(evdev)
     // Based on QEglFSIntegration::createInputHandlers.
-    if (platformName == QLatin1String("eglfs"))
+    if (platformName == "eglfs"_L1)
         return KeyboardDriver::Evdev;
 #endif
 
@@ -1249,9 +1252,9 @@ static WebInputEvent::Modifiers lockKeyModifiers(const quint32 nativeModifiers)
 {
     unsigned result = 0;
     if (keyboardDriver() == KeyboardDriver::Xkb) {
-        if (nativeModifiers & 0x42) /* Caps_Lock */
+        if (nativeModifiers & 0x2) /* XCB_MOD_MASK_LOCK */
             result |= WebInputEvent::kCapsLockOn;
-        if (nativeModifiers & 0x4d) /* Num_Lock */
+        if (nativeModifiers & 0x10) /* XCB_MOD_MASK_2 */
             result |= WebInputEvent::kNumLockOn;
     } else if (keyboardDriver() == KeyboardDriver::Windows) {
         if (nativeModifiers & 0x100) /* CapsLock */
@@ -1564,8 +1567,7 @@ blink::WebMouseWheelEvent::Phase toBlinkPhase(QWheelEvent *ev)
     case Qt::ScrollEnd:
         return blink::WebMouseWheelEvent::kPhaseEnded;
     }
-    Q_UNREACHABLE();
-    return blink::WebMouseWheelEvent::kPhaseNone;
+    Q_UNREACHABLE_RETURN(blink::WebMouseWheelEvent::kPhaseNone);
 }
 
 blink::WebMouseWheelEvent::Phase getMomentumPhase(QWheelEvent *ev)
@@ -1580,8 +1582,7 @@ blink::WebMouseWheelEvent::Phase getMomentumPhase(QWheelEvent *ev)
     case Qt::ScrollUpdate:
         return blink::WebMouseWheelEvent::kPhaseNone;
     }
-    Q_UNREACHABLE();
-    return blink::WebMouseWheelEvent::kPhaseNone;
+    Q_UNREACHABLE_RETURN(blink::WebMouseWheelEvent::kPhaseNone);
 }
 
 blink::WebMouseWheelEvent WebEventFactory::toWebWheelEvent(QWheelEvent *ev)
@@ -1660,9 +1661,9 @@ void WebEventFactory::sendUnhandledWheelEvent(const blink::WebGestureEvent &even
     delegate->unhandledWheelEvent(&ev);
 }
 
-content::NativeWebKeyboardEvent WebEventFactory::toWebKeyboardEvent(QKeyEvent *ev)
+input::NativeWebKeyboardEvent WebEventFactory::toWebKeyboardEvent(QKeyEvent *ev)
 {
-    content::NativeWebKeyboardEvent webKitEvent(ToNativeEvent(ev));
+    input::NativeWebKeyboardEvent webKitEvent(ToNativeEvent(ev));
     webKitEvent.SetTimeStamp(base::TimeTicks::Now());
     bool isBackTabWithoutModifier =
             ev->key() == Qt::Key_Backtab && ev->modifiers() == Qt::NoModifier;
@@ -1673,16 +1674,17 @@ content::NativeWebKeyboardEvent WebEventFactory::toWebKeyboardEvent(QKeyEvent *e
     int qtKey = qtKeyForKeyEvent(ev);
     Qt::KeyboardModifiers qtModifiers =
             isBackTabWithoutModifier ? Qt::ShiftModifier : qtModifiersForEvent(ev);
-    QString qtText = qtTextForKeyEvent(ev, qtKey, qtModifiers);
+    const QString qtText = qtTextForKeyEvent(ev, qtKey, qtModifiers);
 
     webKitEvent.native_key_code = nativeKeyCodeForKeyEvent(ev);
     webKitEvent.windows_key_code = windowsKeyCodeForQtKey(qtKey, qtModifiers & Qt::KeypadModifier);
 
     if (qtKey >= Qt::Key_Escape)
         webKitEvent.dom_key = domKeyForQtKey(qtKey);
-    else if (!qtText.isEmpty())
-        webKitEvent.dom_key = ui::DomKey::FromCharacter(qtText.toUcs4().first());
-    else {
+    else if (!qtText.isEmpty()) {
+        QStringIterator it(qtText);
+        webKitEvent.dom_key = ui::DomKey::FromCharacter(it.next());
+    } else {
         QChar ch(qtKey);
         if (!(qtModifiers & Qt::ShiftModifier)) // No way to check for caps lock
             ch = ch.toLower();
diff --git a/src/core/web_event_factory.h b/src/core/web_event_factory.h
index 53ebfb5096c..873a08a6350 100644
--- a/src/core/web_event_factory.h
+++ b/src/core/web_event_factory.h
@@ -6,7 +6,7 @@
 
 #include "QtGui/qtguiglobal.h"
 
-#include "content/public/common/input/native_web_keyboard_event.h"
+#include "components/input/native_web_keyboard_event.h"
 #if QT_CONFIG(gestures)
 #include "third_party/blink/public/common/input/web_gesture_event.h"
 #endif
@@ -46,7 +46,7 @@ class WebEventFactory {
     static blink::WebMouseWheelEvent toWebWheelEvent(QWheelEvent *);
     static bool coalesceWebWheelEvent(blink::WebMouseWheelEvent &, QWheelEvent *);
     static void sendUnhandledWheelEvent(const blink::WebGestureEvent &, RenderWidgetHostViewQtDelegate *);
-    static content::NativeWebKeyboardEvent toWebKeyboardEvent(QKeyEvent*);
+    static input::NativeWebKeyboardEvent toWebKeyboardEvent(QKeyEvent*);
     static bool getEditCommand(QKeyEvent *event, std::string *editCommand);
 };
 
diff --git a/src/gn/CMakeLists.txt b/src/gn/CMakeLists.txt
index 9782f17abc8..ec5b36d4a02 100644
--- a/src/gn/CMakeLists.txt
+++ b/src/gn/CMakeLists.txt
@@ -26,7 +26,7 @@ set(GN_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})
 set(GN_LINKER ${CMAKE_CXX_COMPILER})
 set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${WEBENGINE_ROOT_SOURCE_DIR}/cmake")
 
-find_package(Python3 REQUIRED)
+find_package(Python3 3.8 REQUIRED)
 find_package(Ninja 1.7.2 REQUIRED)
 
 if(WIN32)
@@ -55,6 +55,15 @@ else()
     message(FATAL_ERROR "Unsupported gn platform !")
 endif()
 
+if(GCC_LEGACY_SUPPORT)
+    set(GN_GCC_LEGACY_SUPPORT --gcc-legacy-support)
+endif()
+
+string(REPLACE " " ";" ninja_flags "$ENV{NINJAFLAGS}")
+if(CMAKE_VERBOSE_MAKEFILE)
+    list(APPEND ninja_flags -v)
+endif()
+
 list(JOIN CMAKE_OSX_ARCHITECTURES "$<COMMA>" OSX_ARCH)
 add_custom_command(
     OUTPUT ${GN_EXECUTABLE}
@@ -70,11 +79,12 @@ add_custom_command(
         --platform ${platform}
         --ar ${CMAKE_AR}
         --qt-version "${QT_REPO_MODULE_VERSION}.qtwebengine.qt.io"
-        $<$<PLATFORM_ID:Darwin>:--isysroot>
-        $<$<PLATFORM_ID:Darwin>:${CMAKE_OSX_SYSROOT}>
+        $<$<AND:$<PLATFORM_ID:Darwin>,$<BOOL:${CMAKE_OSX_SYSROOT}>>:--isysroot>
+        $<$<AND:$<PLATFORM_ID:Darwin>,$<BOOL:${CMAKE_OSX_SYSROOT}>>:${CMAKE_OSX_SYSROOT}>
         $<$<AND:$<PLATFORM_ID:Darwin>,$<BOOL:${OSX_ARCH}>>:--osx-architectures>
         $<$<AND:$<PLATFORM_ID:Darwin>,$<BOOL:${OSX_ARCH}>>:${OSX_ARCH}>
-    COMMAND Ninja::ninja -C ${GN_BINARY_DIR}/$<CONFIG> ${GN_EXECUTABLE}
+        ${GN_GCC_LEGACY_SUPPORT}
+    COMMAND Ninja::ninja ${ninja_flags} -C ${GN_BINARY_DIR}/$<CONFIG> ${GN_EXECUTABLE}
     VERBATIM
     USES_TERMINAL
     COMMAND_EXPAND_LISTS
diff --git a/src/host/BUILD.clang-cl.toolchain.gn.in b/src/host/BUILD.clang-cl.toolchain.gn.in
new file mode 100644
index 00000000000..b9b1fedc4cc
--- /dev/null
+++ b/src/host/BUILD.clang-cl.toolchain.gn.in
@@ -0,0 +1,80 @@
+import("//build/config/sysroot.gni")
+import("//build/toolchain/win/toolchain.gni")
+
+msvc_toolchain("x64") {
+  cl = "clang-cl.exe"
+  environment = "environment.x64"
+  toolchain_args = {
+    current_os = "win"
+    current_cpu = "x64"
+    is_clang = true
+    use_clang_coverage = false
+  }
+}
+
+msvc_toolchain("x86") {
+  cl = "clang-cl.exe"
+  environment = "environment.x86"
+  toolchain_args = {
+    current_os = "win"
+    current_cpu = "x86"
+    is_clang = true
+    use_clang_coverage = false
+  }
+}
+
+msvc_toolchain("arm64") {
+  cl = "clang-cl.exe"
+  environment = "environment.arm64"
+  toolchain_args = {
+    current_os = "win"
+    current_cpu = "arm64"
+    is_clang = true
+    use_clang_coverage = false
+  }
+}
+
+#TODO: drop it after clean up breakpad, remove upload symbols exacutable
+msvc_system_allocator_toolchain("x64_host_with_system_allocator") {
+  cl = "clang-cl.exe"
+  environment = "environment.x64"
+  toolchain_args = {
+    current_cpu = "x64"
+    current_os = "win"
+    is_clang = true
+    use_clang_coverage = false
+  }
+}
+
+msvc_system_allocator_toolchain("arm64_host_with_system_allocator") {
+  cl = "clang-cl.exe"
+  environment = "environment.arm64"
+  toolchain_args = {
+    current_cpu = "arm64"
+    current_os = "win"
+    is_clang = true
+    use_clang_coverage = false
+  }
+}
+
+msvc_system_allocator_toolchain("x64_with_system_allocator") {
+  cl = "clang-cl.exe"
+  environment = "environment.x64"
+  toolchain_args = {
+    current_cpu = "x64"
+    current_os = "win"
+    is_clang = true
+    use_clang_coverage = false
+  }
+}
+
+msvc_system_allocator_toolchain("arm64_with_system_allocator") {
+  cl = "clang-cl.exe"
+  environment = "environment.arm64"
+  toolchain_args = {
+    current_cpu = "arm64"
+    current_os = "win"
+    is_clang = true
+    use_clang_coverage = false
+  }
+}
diff --git a/src/host/BUILD.msvc.toolchain.gn.in b/src/host/BUILD.msvc.toolchain.gn.in
new file mode 100644
index 00000000000..827002affa9
--- /dev/null
+++ b/src/host/BUILD.msvc.toolchain.gn.in
@@ -0,0 +1,80 @@
+import("//build/config/sysroot.gni")
+import("//build/toolchain/win/toolchain.gni")
+
+msvc_toolchain("x64") {
+  cl = "cl.exe"
+  environment = "environment.x64"
+  toolchain_args = {
+    current_os = "win"
+    current_cpu = "x64"
+    is_clang = false
+    use_clang_coverage = false
+  }
+}
+
+msvc_toolchain("x86") {
+  cl = "cl.exe"
+  environment = "environment.x86"
+  toolchain_args = {
+    current_os = "win"
+    current_cpu = "x86"
+    is_clang = false
+    use_clang_coverage = false
+  }
+}
+
+msvc_toolchain("arm64") {
+  cl = "cl.exe"
+  environment = "environment.arm64"
+  toolchain_args = {
+    current_os = "win"
+    current_cpu = "arm64"
+    is_clang = false
+    use_clang_coverage = false
+  }
+}
+
+#TODO: drop it after clean up breakpad, remove upload symbols exacutable
+msvc_system_allocator_toolchain("x64_host_with_system_allocator") {
+  cl = "cl.exe"
+  environment = "environment.x64"
+  toolchain_args = {
+    current_cpu = "x64"
+    current_os = "win"
+    is_clang = false
+    use_clang_coverage = false
+  }
+}
+
+msvc_system_allocator_toolchain("arm64_host_with_system_allocator") {
+  cl = "cl.exe"
+  environment = "environment.arm64"
+  toolchain_args = {
+    current_cpu = "arm64"
+    current_os = "win"
+    is_clang = false
+    use_clang_coverage = false
+  }
+}
+
+msvc_system_allocator_toolchain("x64_with_system_allocator") {
+  cl = "cl.exe"
+  environment = "environment.x64"
+  toolchain_args = {
+    current_cpu = "x64"
+    current_os = "win"
+    is_clang = false
+    use_clang_coverage = false
+  }
+}
+
+msvc_system_allocator_toolchain("arm64_with_system_allocator") {
+  cl = "cl.exe"
+  environment = "environment.arm64"
+  toolchain_args = {
+    current_cpu = "arm64"
+    current_os = "win"
+    is_clang = false
+    use_clang_coverage = false
+  }
+}
diff --git a/src/host/CMakeLists.txt b/src/host/CMakeLists.txt
index d40275217bb..7e9eab365c3 100644
--- a/src/host/CMakeLists.txt
+++ b/src/host/CMakeLists.txt
@@ -12,6 +12,7 @@ endif()
 
 include(${WEBENGINE_ROOT_SOURCE_DIR}/.cmake.conf)
 include(${WEBENGINE_ROOT_SOURCE_DIR}/cmake/Functions.cmake)
+include(${WEBENGINE_ROOT_SOURCE_DIR}/cmake/QtToolchainHelpers.cmake)
 
 set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${WEBENGINE_ROOT_SOURCE_DIR}/cmake")
 
diff --git a/src/pdf/CMakeLists.txt b/src/pdf/CMakeLists.txt
index 33d918f8c39..9f7ef7d0e99 100644
--- a/src/pdf/CMakeLists.txt
+++ b/src/pdf/CMakeLists.txt
@@ -3,7 +3,6 @@
 
 cmake_minimum_required(VERSION 3.19)
 find_package(Ninja 1.7.2 REQUIRED)
-find_package(Nodejs 14.19 REQUIRED)
 find_package(PkgConfig)
 if(PkgConfig_FOUND)
     create_pkg_config_host_wrapper(${CMAKE_CURRENT_BINARY_DIR})
@@ -70,7 +69,7 @@ add_dependencies(prepare_docs_Pdf generate_pdf_attributions)
 #   TOOLCHAIN SETUP
 ##
 
-if(LINUX OR MINGW OR ANDROID)
+if(LINUX OR MINGW OR ANDROID OR WIN32)
     setup_toolchains()
 endif()
 
@@ -120,13 +119,18 @@ foreach(arch ${archs})
           qt_libjpeg_config="${buildDir}/${config}/${arch}:qt_libjpeg_config"
           qt_harfbuzz_config="${buildDir}/${config}/${arch}:qt_harfbuzz_config"
           qt_freetype_config="${buildDir}/${config}/${arch}:qt_freetype_config"
+          is_qtwebengine=true
+          is_qtpdf=true
+          enable_bluetooth_emulation=false
           enable_swiftshader=false
           enable_swiftshader_vulkan=false
           angle_enable_swiftshader=false
           dawn_use_swiftshader=false
+          pdf_enable_fontations=false
           use_cups=false
           use_dawn=false
           build_dawn_tests=false
+          enable_nocompile_tests=false
           enable_ipc_fuzzer=false
           enable_remoting=false
           enable_resource_allowlist_generation=false
@@ -135,14 +139,23 @@ foreach(arch ${archs})
           chrome_pgo_phase=0
           strip_absolute_paths_from_debug_symbols=false
           v8_enable_webassembly=false
-        )
+          use_v8_context_snapshot=false
+          v8_use_external_startup_data=false
+  )
 
         if(LINUX OR ANDROID)
             list(APPEND gnArgArg
+                enable_vr=false
                 is_cfi=false
                 ozone_auto_platforms=false
                 enable_arcore=false
                 use_ml_inliner=false
+                use_udev=false
+                use_gio=false
+                use_glib=false
+                use_nss_certs=false
+                use_xkbcommon=false
+                v8_use_external_startup_data=false
             )
             extend_gn_list(gnArgArg
                 ARGS use_system_icu
@@ -152,7 +165,11 @@ foreach(arch ${archs})
                 ARGS use_system_libopenjpeg2
                 CONDITION QT_FEATURE_webengine_system_libopenjpeg2
             )
-        endif()
+            extend_gn_list(gnArgArg
+                ARGS is_gcc_legacy
+                CONDITION QT_FEATURE_webengine_gcc_legacy_support
+            )
+         endif()
         if(MACOS)
             list(APPEND gnArgArg angle_enable_vulkan=false)
         endif()
@@ -165,7 +182,6 @@ foreach(arch ${archs})
         endif()
         if(WIN32 OR ANDROID)
           list(APPEND gnArgArg
-              ninja_use_custom_environment_files=false
               safe_browsing_mode=0
           )
           extend_gn_list(gnArgArg
@@ -252,6 +268,7 @@ add_gn_build_artifacts_to_target(
     CMAKE_TARGET Pdf
     NINJA_TARGET QtPdf
     MODULE pdf
+    DEPENDS Pdf_sync_headers
     BUILDDIR ${buildDir}
     COMPLETE_STATIC TRUE
     NINJA_STAMP QtPdf.stamp
diff --git a/src/pdf/doc/qtpdf.qdocconf b/src/pdf/doc/qtpdf.qdocconf
index 7f69c539ac9..15151ae0936 100644
--- a/src/pdf/doc/qtpdf.qdocconf
+++ b/src/pdf/doc/qtpdf.qdocconf
@@ -42,6 +42,7 @@ depends += qtcore \
            qtdoc \
            qmake \
            qtdesigner \
+           qtqml \
            qtquick \
            qtquickcontrols \
            qtcmake \
diff --git a/src/pdf/qpdfbookmarkmodel.cpp b/src/pdf/qpdfbookmarkmodel.cpp
index 41979e27db1..44fb07c621f 100644
--- a/src/pdf/qpdfbookmarkmodel.cpp
+++ b/src/pdf/qpdfbookmarkmodel.cpp
@@ -219,7 +219,7 @@ struct QPdfBookmarkModelPrivate
     \inmodule QtPdf
     \inherits QAbstractItemModel
 
-    \brief The QPdfBookmarkModel class holds a tree of of links (anchors)
+    \brief The QPdfBookmarkModel class holds a tree of links (anchors)
     within a PDF document, such as the table of contents.
 
     This is used in the \l {Model/View Programming} paradigm to display a
diff --git a/src/pdfquick/CMakeLists.txt b/src/pdfquick/CMakeLists.txt
index e52d26f4413..5da3d53f93e 100644
--- a/src/pdfquick/CMakeLists.txt
+++ b/src/pdfquick/CMakeLists.txt
@@ -34,11 +34,17 @@ qt_internal_add_qml_module(PdfQuick
         qtpdfquickglobal_p.h
     INCLUDE_DIRECTORIES
         ../3rdparty/chromium
-    PUBLIC_LIBRARIES
+    LIBRARIES
+        Qt::PdfPrivate
         Qt::QuickPrivate
+    PRIVATE_MODULE_INTERFACE
         Qt::PdfPrivate
+        Qt::QuickPrivate
+    PUBLIC_LIBRARIES
         Qt::Core
         Qt::Gui
+        Qt::Pdf
         Qt::Qml
+        Qt::Quick
     NO_GENERATE_CPP_EXPORTS
 )
diff --git a/src/pdfquick/qquickpdfdocument.cpp b/src/pdfquick/qquickpdfdocument.cpp
index 7ffb0527e32..217e8db1cf7 100644
--- a/src/pdfquick/qquickpdfdocument.cpp
+++ b/src/pdfquick/qquickpdfdocument.cpp
@@ -7,6 +7,7 @@
 #include <QtCore/qstandardpaths.h>
 #include <QtQml/qqmlcontext.h>
 #include <QtQml/qqmlengine.h>
+#include <QtQml/qqmlinfo.h>
 #include <QtQuick/qquickitem.h>
 #include <QtQml/qqmlfile.h>
 #include <QThread>
@@ -64,7 +65,13 @@ void QQuickPdfDocument::classBegin()
 
     This property holds a URL pointing to the PDF file to be loaded.
 
-    \note At this time, only local filesystem URLs are supported.
+    \note At this time, only local filesystem and
+    \l {The Qt Resource System} {resource} URLs are supported. Nevertheless,
+    the \c source property is a \l {QUrl}{URL}, not merely a filesystem path.
+    PdfDocument resolves it via QQmlContext::resolvedUrl(). You should
+    typically ensure that the URL starts with a \c {file://} scheme, unless you
+    mean to load the PDF file from resources, or it comes from some component
+    (such as \l {QtQuick.Controls::}{FileDialog}) that resolves it in advance.
 */
 void QQuickPdfDocument::setSource(QUrl source)
 {
@@ -85,6 +92,8 @@ void QQuickPdfDocument::setSource(QUrl source)
     m_resolvedSource = context ? context->resolvedUrl(source) : source;
     if (m_resolvedSource.isValid())
         m_doc->load(QQmlFile::urlToLocalFileOrQrc(m_resolvedSource));
+    else
+        qmlWarning(this) << QQuickPdfDocument::tr("Cannot open: %1").arg(m_resolvedSource.toString());
 }
 
 /*!
diff --git a/src/pdfwidgets/CMakeLists.txt b/src/pdfwidgets/CMakeLists.txt
index 99287435450..c7a7780ea64 100644
--- a/src/pdfwidgets/CMakeLists.txt
+++ b/src/pdfwidgets/CMakeLists.txt
@@ -9,11 +9,12 @@ qt_internal_add_module(PdfWidgets
         qpdfview.cpp qpdfview.h qpdfview_p.h
         qtpdfwidgetsglobal.h
     LIBRARIES
+        Qt::PdfPrivate
         Qt::WidgetsPrivate
     PUBLIC_LIBRARIES
         Qt::Core
         Qt::Gui
+        Qt::Pdf
         Qt::Widgets
-        Qt::PdfPrivate
     NO_GENERATE_CPP_EXPORTS
 )
diff --git a/src/process/CMakeLists.txt b/src/process/CMakeLists.txt
index 630ba42a8b0..37bca3b4c54 100644
--- a/src/process/CMakeLists.txt
+++ b/src/process/CMakeLists.txt
@@ -13,8 +13,16 @@ find_package(Qt6 COMPONENTS Gui)
 get_target_property(qtWebEngineProcessName WebEngineCore QTWEBENGINEPROCESS_NAME)
 get_target_property(isFramework WebEngineCore FRAMEWORK)
 
-qt_internal_add_executable(${qtWebEngineProcessName}
+if(isFramework)
+  set(install_dir "${INSTALL_LIBDIR}/QtWebEngineCore.framework/Versions/A/Helpers")
+else()
+  set(install_dir "${INSTALL_LIBEXECDIR}")
+endif()
+
+qt_internal_add_app(${qtWebEngineProcessName}
+    TARGET_DESCRIPTION "QtWebEngine internal process"
     NO_INSTALL
+    INCLUDE_DIRECTORIES ../core
     SOURCES main.cpp
 )
 
@@ -43,21 +51,12 @@ qt_internal_extend_target(${qtWebEngineProcessName}
         Qt::WebEngineCorePrivate
 )
 
-target_include_directories(${qtWebEngineProcessName} PRIVATE ../core)
-
 qt_get_cmake_configurations(configs)
 
 foreach(config ${configs})
     string(TOUPPER "${config}" config_upper)
-    if(isFramework)
-       set(outputPath
-           "${QT_BUILD_DIR}/${INSTALL_LIBDIR}/QtWebEngineCore.framework/Versions/A/Helpers"
-       )
-    else()
-       set(outputPath "${QT_BUILD_DIR}/${INSTALL_LIBEXECDIR}")
-    endif()
     set_target_properties(${qtWebEngineProcessName} PROPERTIES
-        RUNTIME_OUTPUT_DIRECTORY_${config_upper} "${outputPath}"
+        RUNTIME_OUTPUT_DIRECTORY_${config_upper} "${QT_BUILD_DIR}/${install_dir}"
     )
 
     if("${config}" STREQUAL "Debug")
@@ -67,6 +66,8 @@ foreach(config ${configs})
     endif()
 endforeach()
 
+set_property(TARGET ${qtWebEngineProcessName} PROPERTY EXCLUDE_FROM_ALL OFF)
+
 if(isFramework)
     set_target_properties(${qtWebEngineProcessName} PROPERTIES
         MACOSX_BUNDLE TRUE
@@ -86,7 +87,7 @@ if(isFramework)
         USES_TERMINAL
     )
     install(TARGETS ${qtWebEngineProcessName}
-        BUNDLE DESTINATION "${INSTALL_LIBDIR}/QtWebEngineCore.framework/Versions/A/Helpers"
+        BUNDLE DESTINATION "${install_dir}"
         COMPONENT Runtime
     )
     qt_enable_separate_debug_info(${qtWebEngineProcessName}
@@ -94,12 +95,12 @@ if(isFramework)
         DSYM_OUTPUT_DIR "${CMAKE_BINARY_DIR}/${INSTALL_LIBDIR}"
     )
 else()
-    qt_apply_rpaths(TARGET ${qtWebEngineProcessName} INSTALL_PATH "${INSTALL_LIBEXECDIR}" RELATIVE_RPATH)
+    qt_apply_rpaths(TARGET ${qtWebEngineProcessName} INSTALL_PATH "${install_dir}" RELATIVE_RPATH)
     install(TARGETS ${qtWebEngineProcessName}
         CONFIGURATIONS ${configs}
-        RUNTIME DESTINATION "${INSTALL_LIBEXECDIR}"
+        RUNTIME DESTINATION "${install_dir}"
     )
-    qt_enable_separate_debug_info(${qtWebEngineProcessName} "${INSTALL_LIBEXECDIR}" QT_EXECUTABLE)
-    qt_internal_install_pdb_files(${qtWebEngineProcessName} "${INSTALL_LIBEXECDIR}")
+    qt_enable_separate_debug_info(${qtWebEngineProcessName} "${install_dir}" QT_EXECUTABLE)
+    qt_internal_install_pdb_files(${qtWebEngineProcessName} "${install_dir}")
 endif()
 
diff --git a/src/webenginequick/api/qquickwebengineprofile.cpp b/src/webenginequick/api/qquickwebengineprofile.cpp
index 70343e5ce1c..f6d6cd4760d 100644
--- a/src/webenginequick/api/qquickwebengineprofile.cpp
+++ b/src/webenginequick/api/qquickwebengineprofile.cpp
@@ -243,11 +243,11 @@ void QQuickWebEngineProfilePrivate::cleanDownloads()
     m_ongoingDownloads.clear();
 }
 
-void QQuickWebEngineProfilePrivate::downloadRequested(DownloadItemInfo &info)
+void QQuickWebEngineProfilePrivate::downloadRequested(const DownloadItemInfo &info)
 {
     Q_Q(QQuickWebEngineProfile);
 
-    if (!q->receivers(SIGNAL(downloadRequested(QQuickWebEngineDownloadRequest *)))) {
+    if (!q->receivers(SIGNAL(downloadRequested(QQuickWebEngineDownloadRequest*)))) {
         m_profileAdapter->acceptDownload(info.id, info.accepted, info.useDownloadTargetCallback, info.path,
                                          info.savePageFormat);
         return;
diff --git a/src/webenginequick/api/qquickwebengineprofile.h b/src/webenginequick/api/qquickwebengineprofile.h
index df41404da36..17a0548688e 100644
--- a/src/webenginequick/api/qquickwebengineprofile.h
+++ b/src/webenginequick/api/qquickwebengineprofile.h
@@ -48,7 +48,7 @@ class Q_WEBENGINEQUICK_EXPORT QQuickWebEngineProfile : public QObject {
 
 public:
     QQuickWebEngineProfile(QObject *parent = nullptr);
-    QQuickWebEngineProfile(const QString &storageName, QObject *parent = nullptr);
+    explicit QQuickWebEngineProfile(const QString &storageName, QObject *parent = nullptr);
     ~QQuickWebEngineProfile();
 
     enum HttpCacheType {
diff --git a/src/webenginequick/api/qquickwebengineprofile_p.h b/src/webenginequick/api/qquickwebengineprofile_p.h
index 477936f98c4..fde24763665 100644
--- a/src/webenginequick/api/qquickwebengineprofile_p.h
+++ b/src/webenginequick/api/qquickwebengineprofile_p.h
@@ -50,7 +50,7 @@ class QQuickWebEngineProfilePrivate : public QtWebEngineCore::ProfileAdapterClie
 
     void cleanDownloads();
 
-    void downloadRequested(DownloadItemInfo &info) override;
+    void downloadRequested(const DownloadItemInfo &info) override;
     void downloadUpdated(const DownloadItemInfo &info) override;
 
     void showNotification(QSharedPointer<QtWebEngineCore::UserNotificationController> &controller) override;
diff --git a/src/webenginequick/api/qquickwebengineprofileprototype_p.h b/src/webenginequick/api/qquickwebengineprofileprototype_p.h
index 5573d2f5d0b..a29956e5b80 100644
--- a/src/webenginequick/api/qquickwebengineprofileprototype_p.h
+++ b/src/webenginequick/api/qquickwebengineprofileprototype_p.h
@@ -48,7 +48,7 @@ class Q_WEBENGINEQUICK_EXPORT QQuickWebEngineProfilePrototype : public QObject,
     ~QQuickWebEngineProfilePrototype();
 
     QString storageName() const;
-    void setStorageName(const QString &path);
+    void setStorageName(const QString &storageName);
 
     QString persistentStoragePath() const;
     void setPersistentStoragePath(const QString &path);
diff --git a/src/webenginequick/api/qquickwebenginesettings.cpp b/src/webenginequick/api/qquickwebenginesettings.cpp
index 29bf0f93e93..fadc1bfef0d 100644
--- a/src/webenginequick/api/qquickwebenginesettings.cpp
+++ b/src/webenginequick/api/qquickwebenginesettings.cpp
@@ -519,7 +519,7 @@ bool QQuickWebEngineSettings::scrollAnimatorEnabled() const
 }
 
 /*!
-    \qmlproperty bool WebEngineSettings::jsTouchEventsEnabled
+    \qmlproperty bool WebEngineSettings::touchEventsApiEnabled
     \since QtWebEngine 6.9
 
     Enables support for JavaScript touch events API, meaning \c ontouchstart,
@@ -532,9 +532,9 @@ bool QQuickWebEngineSettings::scrollAnimatorEnabled() const
     Enabled by default if a touch device detected by the system
     and disabled otherwise.
  */
-bool QQuickWebEngineSettings::jsTouchEventsEnabled() const
+bool QQuickWebEngineSettings::touchEventsApiEnabled() const
 {
-    return d_ptr->testAttribute(QWebEngineSettings::JSTouchEventsEnabled);
+    return d_ptr->testAttribute(QWebEngineSettings::TouchEventsApiEnabled);
 }
 
 /*!
@@ -921,12 +921,12 @@ void QQuickWebEngineSettings::setImageAnimationPolicy(
         Q_EMIT imageAnimationPolicyChanged();
 }
 
-void QQuickWebEngineSettings::setJSTouchEventsEnabled(bool on)
+void QQuickWebEngineSettings::setTouchEventsApiEnabled(bool on)
 {
-    bool wasOn = d_ptr->testAttribute(QWebEngineSettings::JSTouchEventsEnabled);
-    d_ptr->setAttribute(QWebEngineSettings::JSTouchEventsEnabled, on);
+    bool wasOn = d_ptr->testAttribute(QWebEngineSettings::TouchEventsApiEnabled);
+    d_ptr->setAttribute(QWebEngineSettings::TouchEventsApiEnabled, on);
     if (wasOn != on)
-        Q_EMIT jsTouchEventsEnabledChanged();
+        Q_EMIT touchEventsApiEnabledChanged();
 }
 
 QT_END_NAMESPACE
diff --git a/src/webenginequick/api/qquickwebenginesettings_p.h b/src/webenginequick/api/qquickwebenginesettings_p.h
index 85b1a538e2d..843e21a4df9 100644
--- a/src/webenginequick/api/qquickwebenginesettings_p.h
+++ b/src/webenginequick/api/qquickwebenginesettings_p.h
@@ -63,7 +63,7 @@ class Q_WEBENGINEQUICK_EXPORT QQuickWebEngineSettings : public QObject {
     Q_PROPERTY(ImageAnimationPolicy imageAnimationPolicy READ imageAnimationPolicy WRITE setImageAnimationPolicy NOTIFY imageAnimationPolicyChanged REVISION(6,8) FINAL)
     Q_PROPERTY(bool printHeaderAndFooter READ printHeaderAndFooter WRITE setPrintHeaderAndFooter NOTIFY printHeaderAndFooterChanged REVISION(6,9) FINAL)
     Q_PROPERTY(bool preferCSSMarginsForPrinting READ preferCSSMarginsForPrinting WRITE setPreferCSSMarginsForPrinting NOTIFY preferCSSMarginsForPrintingChanged REVISION(6,9) FINAL)
-    Q_PROPERTY(bool jsTouchEventsEnabled READ jsTouchEventsEnabled WRITE setJSTouchEventsEnabled NOTIFY jsTouchEventsEnabledChanged REVISION(6,9) FINAL)
+    Q_PROPERTY(bool touchEventsApiEnabled READ touchEventsApiEnabled WRITE setTouchEventsApiEnabled NOTIFY touchEventsApiEnabledChanged REVISION(6,9) FINAL)
 
     QML_NAMED_ELEMENT(WebEngineSettings)
     QML_ADDED_IN_VERSION(1, 1)
@@ -126,7 +126,7 @@ class Q_WEBENGINEQUICK_EXPORT QQuickWebEngineSettings : public QObject {
     ImageAnimationPolicy imageAnimationPolicy() const;
     bool printHeaderAndFooter() const;
     bool preferCSSMarginsForPrinting() const;
-    bool jsTouchEventsEnabled() const;
+    bool touchEventsApiEnabled() const;
 
     void setAutoLoadImages(bool on);
     void setJavascriptEnabled(bool on);
@@ -166,7 +166,7 @@ class Q_WEBENGINEQUICK_EXPORT QQuickWebEngineSettings : public QObject {
     void setImageAnimationPolicy(ImageAnimationPolicy policy);
     void setPrintHeaderAndFooter(bool on);
     void setPreferCSSMarginsForPrinting(bool on);
-    void setJSTouchEventsEnabled(bool on);
+    void setTouchEventsApiEnabled(bool on);
 
 signals:
     void autoLoadImagesChanged();
@@ -207,7 +207,7 @@ class Q_WEBENGINEQUICK_EXPORT QQuickWebEngineSettings : public QObject {
     Q_REVISION(6,8) void imageAnimationPolicyChanged();
     Q_REVISION(6,9) void printHeaderAndFooterChanged();
     Q_REVISION(6,9) void preferCSSMarginsForPrintingChanged();
-    Q_REVISION(6,9) void jsTouchEventsEnabledChanged();
+    Q_REVISION(6,9) void touchEventsApiEnabledChanged();
 
 private:
     explicit QQuickWebEngineSettings(QQuickWebEngineSettings *parentSettings = nullptr);
diff --git a/src/webenginequick/api/qquickwebengineview.cpp b/src/webenginequick/api/qquickwebengineview.cpp
index f1b7c204657..ade8b451c4a 100644
--- a/src/webenginequick/api/qquickwebengineview.cpp
+++ b/src/webenginequick/api/qquickwebengineview.cpp
@@ -516,8 +516,7 @@ static QQuickWebEngineView::Feature toDeprecatedFeature(QWebEnginePermission::Pe
         break;
     }
 
-    Q_UNREACHABLE();
-    return QQuickWebEngineView::Feature(-1);
+    Q_UNREACHABLE_RETURN(QQuickWebEngineView::Feature(-1));
 }
 QT_WARNING_POP
 #endif // QT_DEPRECATED_SINCE(6, 8)
@@ -879,6 +878,7 @@ QObject *QQuickWebEngineViewPrivate::accessibilityParentObject()
 
 ProfileAdapter *QQuickWebEngineViewPrivate::profileAdapter()
 {
+    initializeProfile();
     return m_profile->d_ptr->profileAdapter();
 }
 
@@ -1450,8 +1450,9 @@ QQuickWebEngineViewPrivate::createTouchHandleDelegate(const QMap<int, QImage> &i
 {
     Q_Q(QQuickWebEngineView);
     // lifecycle managed by Chromium's TouchHandleDrawable
-    QQuickWebEngineTouchHandle *handle = new QQuickWebEngineTouchHandle();
+    QQuickWebEngineTouchHandle *handle(nullptr);
     if (m_touchHandleDelegate) {
+        handle = new QQuickWebEngineTouchHandle();
         QQmlContext *qmlContext = QQmlEngine::contextForObject(q);
         QQmlContext *context = new QQmlContext(qmlContext, handle);
         context->setContextObject(handle);
@@ -1462,7 +1463,9 @@ QQuickWebEngineViewPrivate::createTouchHandleDelegate(const QMap<int, QImage> &i
         handle->setItem(item, false);
     } else {
         QQuickItem *item = ui()->createTouchHandle();
-        Q_ASSERT(item);
+        if (!item) {
+            return nullptr;
+        }
         QQmlEngine *engine = qmlEngine(item);
         Q_ASSERT(engine);
         QQuickWebEngineTouchHandleProvider *touchHandleProvider =
@@ -1470,6 +1473,7 @@ QQuickWebEngineViewPrivate::createTouchHandleDelegate(const QMap<int, QImage> &i
                         engine->imageProvider(QQuickWebEngineTouchHandleProvider::identifier()));
         Q_ASSERT(touchHandleProvider);
         touchHandleProvider->init(images);
+        handle = new QQuickWebEngineTouchHandle();
         handle->setItem(item, true);
     }
     return handle;
diff --git a/src/webenginequick/doc/src/webengineview_lgpl.qdoc b/src/webenginequick/doc/src/webengineview_lgpl.qdoc
index 8c6b99dd7ea..3f042a8c3ef 100644
--- a/src/webenginequick/doc/src/webengineview_lgpl.qdoc
+++ b/src/webenginequick/doc/src/webengineview_lgpl.qdoc
@@ -1334,7 +1334,7 @@
 
     If remote debugging is enabled (see \l{Qt WebEngine Developer Tools}), the id can be used to
     build the URL to connect to the developer tool websocket:
-    \c{ws://localhost:<debugggin-port>/devtools/page/<id>)}. The websocket can be used to to interact
+    \c{ws://localhost:<debugging-port>/devtools/page/<id>)}. The websocket can be used to to interact
     with the page using the \l{https://chromedevtools.github.io/devtools-protocol/}{DevTools
     Protocol}.
 */
diff --git a/src/webenginequick/render_widget_host_view_qt_delegate_quickwindow.cpp b/src/webenginequick/render_widget_host_view_qt_delegate_quickwindow.cpp
index 090b0928109..52538b652c1 100644
--- a/src/webenginequick/render_widget_host_view_qt_delegate_quickwindow.cpp
+++ b/src/webenginequick/render_widget_host_view_qt_delegate_quickwindow.cpp
@@ -7,13 +7,32 @@
 
 namespace QtWebEngineCore {
 
+struct ItemTransform {
+    qreal rotation = 0.;
+    qreal scale = 1.;
+};
+
+// Helper function to calculate the cumulative rotation and scale.
+static inline struct ItemTransform getTransformValuesFromItemTree(QQuickItem *item)
+{
+    struct ItemTransform returnValue;
+
+    while (item) {
+        returnValue.rotation += item->rotation();
+        returnValue.scale *= item->scale();
+        item = item->parentItem();
+    }
+
+    return returnValue;
+}
+
 static inline QPoint getOffset(QQuickItem *item)
 {
     // get parent window (scene) offset
     QPointF offset = item->mapFromScene(QPoint(0, 0));
     offset = item->mapToGlobal(offset);
     // get local offset
-    offset -= item->mapToScene(QPoint(0, 0));
+    offset -= item->mapToGlobal(QPoint(0, 0));
     return offset.toPoint();
 }
 
@@ -32,10 +51,11 @@ static inline QPointF transformPoint(const QPointF &point, const QTransform &tra
 
 RenderWidgetHostViewQtDelegateQuickWindow::RenderWidgetHostViewQtDelegateQuickWindow(
         RenderWidgetHostViewQtDelegateItem *realDelegate, QWindow *parent)
-    : QQuickWindow(parent), m_realDelegate(realDelegate), m_virtualParent(nullptr), m_rotated(false)
+    : QQuickWindow(), m_realDelegate(realDelegate), m_virtualParent(nullptr), m_transformed(false)
 {
     setFlags(Qt::Tool | Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint | Qt::WindowDoesNotAcceptFocus);
     realDelegate->setParentItem(contentItem());
+    setTransientParent(parent);
 }
 
 RenderWidgetHostViewQtDelegateQuickWindow::~RenderWidgetHostViewQtDelegateQuickWindow()
@@ -56,9 +76,13 @@ void RenderWidgetHostViewQtDelegateQuickWindow::setVirtualParent(QQuickItem *vir
 // chromium knows nothing about local transformation
 void RenderWidgetHostViewQtDelegateQuickWindow::InitAsPopup(const QRect &rect)
 {
-    m_rotated = m_virtualParent->rotation() > 0 || m_virtualParent->parentItem()->rotation() > 0;
-    if (m_rotated) {
-        // code below tries to cover the case where webengine view is rotated,
+    // To decide if there is a scale or rotation, we check it from the transfrom
+    // to also cover the case where the scale is higher up in the item tree.
+    QTransform transform = m_virtualParent->itemTransform(nullptr, nullptr);
+    m_transformed = transform.isRotating() || transform.isScaling();
+
+    if (m_transformed) {
+        // code below tries to cover the case where webengine view is rotated or scaled,
         // the code assumes the rotation is in the form of  90, 180, 270 degrees
         // to archive that we keep chromium unaware of transformation and we transform
         // just the window content.
@@ -67,7 +91,6 @@ void RenderWidgetHostViewQtDelegateQuickWindow::InitAsPopup(const QRect &rect)
         QPointF offset = m_virtualParent->mapFromScene(QPoint(0, 0));
         offset = m_virtualParent->mapToGlobal(offset);
         // get local transform
-        QTransform transform = m_virtualParent->itemTransform(nullptr, nullptr);
         QPointF tl = transformPoint(rect.topLeft(), transform, offset, m_virtualParent);
         QPointF br = transformPoint(rect.bottomRight(), transform, offset, m_virtualParent);
         QRectF popupRect(tl, br);
@@ -80,7 +103,13 @@ void RenderWidgetHostViewQtDelegateQuickWindow::InitAsPopup(const QRect &rect)
         m_realDelegate->setX(-rect.width() / 2.0 + geometry().width() / 2.0);
         m_realDelegate->setY(-rect.height() / 2.0 + geometry().height() / 2.0);
         m_realDelegate->setTransformOrigin(QQuickItem::Center);
-        m_realDelegate->setRotation(m_virtualParent->parentItem()->rotation());
+
+        // We need to read the values for scale and rotation from the item tree as it is not
+        // sufficient to only use the virtual parent item and its parent for the case that the
+        // scale or rotation is applied higher up the item tree.
+        struct ItemTransform transformValues = getTransformValuesFromItemTree(m_virtualParent);
+        m_realDelegate->setRotation(transformValues.rotation);
+        m_realDelegate->setScale(transformValues.scale);
     } else {
         QRect geometry(rect);
         geometry.moveTo(rect.topLeft() - getOffset(m_virtualParent));
@@ -93,13 +122,13 @@ void RenderWidgetHostViewQtDelegateQuickWindow::InitAsPopup(const QRect &rect)
 
 void RenderWidgetHostViewQtDelegateQuickWindow::Resize(int width, int height)
 {
-    if (!m_rotated)
+    if (!m_transformed)
         QQuickWindow::resize(width, height);
 }
 
 void RenderWidgetHostViewQtDelegateQuickWindow::MoveWindow(const QPoint &screenPos)
 {
-    if (!m_rotated)
+    if (!m_transformed)
         QQuickWindow::setPosition(screenPos - getOffset(m_virtualParent));
 }
 
diff --git a/src/webenginequick/render_widget_host_view_qt_delegate_quickwindow_p.h b/src/webenginequick/render_widget_host_view_qt_delegate_quickwindow_p.h
index 3559bd2f080..691fceb5257 100644
--- a/src/webenginequick/render_widget_host_view_qt_delegate_quickwindow_p.h
+++ b/src/webenginequick/render_widget_host_view_qt_delegate_quickwindow_p.h
@@ -49,7 +49,7 @@ class RenderWidgetHostViewQtDelegateQuickWindow : public QQuickWindow , public W
     QPointer<RenderWidgetHostViewQtDelegateItem> m_realDelegate;
     QQuickItem *m_virtualParent;
     QRect m_rect;
-    bool m_rotated;
+    bool m_transformed;
 };
 
 } // namespace QtWebEngineCore
diff --git a/src/webenginequick/ui_delegates_manager.cpp b/src/webenginequick/ui_delegates_manager.cpp
index f4036059d6a..93ac634227e 100644
--- a/src/webenginequick/ui_delegates_manager.cpp
+++ b/src/webenginequick/ui_delegates_manager.cpp
@@ -122,8 +122,7 @@ bool UIDelegatesManager::ensureComponentLoaded(ComponentType type)
     switch (type) {
     FOR_EACH_COMPONENT_TYPE(COMPONENT_MEMBER_CASE_STATEMENT, NO_SEPARATOR)
     default:
-        Q_UNREACHABLE();
-        return false;
+        Q_UNREACHABLE_RETURN(false);
     }
     QString fileName(fileNameForComponent(type));
 #ifndef UI_DELEGATES_DEBUG
@@ -155,6 +154,7 @@ bool UIDelegatesManager::ensureComponentLoaded(ComponentType type)
         }
         return true;
     }
+    qWarning("Default ui delegate %s can not be found.", qPrintable(fileName));
     return false;
 }
 
diff --git a/src/webenginewidgets/api/qwebengineview.cpp b/src/webenginewidgets/api/qwebengineview.cpp
index 0e2a1be3a34..8557ebb8f51 100644
--- a/src/webenginewidgets/api/qwebengineview.cpp
+++ b/src/webenginewidgets/api/qwebengineview.cpp
@@ -439,6 +439,7 @@ void QWebEngineViewPrivate::widgetChanged(QtWebEngineCore::WebEngineQuickWidget
 {
     Q_Q(QWebEngineView);
 
+    bool hasFocus = oldWidget ? oldWidget->hasFocus() : false;
     if (oldWidget) {
         q->layout()->removeWidget(oldWidget);
         oldWidget->hide();
@@ -457,7 +458,7 @@ void QWebEngineViewPrivate::widgetChanged(QtWebEngineCore::WebEngineQuickWidget
 #endif
         q->layout()->addWidget(newWidget);
         q->setFocusProxy(newWidget);
-        if (oldWidget && oldWidget == QApplication::focusWidget())
+        if (hasFocus)
             newWidget->setFocus();
         newWidget->show();
     }
@@ -1480,7 +1481,7 @@ void QWebEngineView::printToPdf(const std::function<void(const QByteArray&)> &re
 
     When finished the signal printFinished() is emitted with the \c true for success or \c false for failure.
 
-    It is the users responsibility to ensure the \a printer remains valid until printFinished()
+    It is the user's responsibility to ensure the \a printer remains valid until printFinished()
     has been emitted.
 
     \note Printing runs on the browser process, which is by default not sandboxed.
diff --git a/src/webenginewidgets/doc/src/qtwebenginewidgets-examples.qdoc b/src/webenginewidgets/doc/src/qtwebenginewidgets-examples.qdoc
index c9bd76bf4e3..2dd55c0369c 100644
--- a/src/webenginewidgets/doc/src/qtwebenginewidgets-examples.qdoc
+++ b/src/webenginewidgets/doc/src/qtwebenginewidgets-examples.qdoc
@@ -10,6 +10,6 @@
     open source browser engine.
 
     These examples and demonstrations show a range of different uses for \QWE,
-    from displaying Web pages within a Qt user interface to an implementation of
-    a basic function Web browser.
+    from displaying web pages within a Qt user interface to an implementation of
+    a basic function web browser.
 */
diff --git a/src/webenginewidgets/doc/src/qtwebkitportingguide.qdoc b/src/webenginewidgets/doc/src/qtwebkitportingguide.qdoc
index 37b73c010cc..f3ac9fa555f 100644
--- a/src/webenginewidgets/doc/src/qtwebkitportingguide.qdoc
+++ b/src/webenginewidgets/doc/src/qtwebkitportingguide.qdoc
@@ -92,13 +92,13 @@
     \b {Qt \WebKit}
     \code
         QWebPage page;
-        connect(page.mainFrame(), SIGNAL(urlChanged(const QUrl&)), SLOT(mySlotName()));
+        connect(page.mainFrame(), SIGNAL(urlChanged(QUrl)), SLOT(mySlotName()));
         page.mainFrame()->load(url);
     \endcode
     \b {\QWE}
     \code
         QWebEnginePage page;
-        connect(&page, SIGNAL(urlChanged(const QUrl&)), SLOT(mySlotName()));
+        connect(&page, SIGNAL(urlChanged(QUrl)), SLOT(mySlotName()));
         page.load(url);
     \endcode
 
diff --git a/tests/auto/core/qwebengineclientcertificatestore/tst_qwebengineclientcertificatestore.cpp b/tests/auto/core/qwebengineclientcertificatestore/tst_qwebengineclientcertificatestore.cpp
index 27ef7383a3b..42c394a847b 100644
--- a/tests/auto/core/qwebengineclientcertificatestore/tst_qwebengineclientcertificatestore.cpp
+++ b/tests/auto/core/qwebengineclientcertificatestore/tst_qwebengineclientcertificatestore.cpp
@@ -55,22 +55,22 @@ void tst_QWebEngineClientCertificateStore::addAndListCertificates()
 {
     // Load QSslCertificate
     QFile certFile(":/resources/certificate.crt");
-    certFile.open(QIODevice::ReadOnly);
+    QVERIFY2(certFile.open(QIODevice::ReadOnly), qPrintable(certFile.errorString()));
     const QSslCertificate cert(certFile.readAll(), QSsl::Pem);
 
     // Load QSslKey
     QFile keyFile(":/resources/privatekey.key");
-    keyFile.open(QIODevice::ReadOnly);
+    QVERIFY2(keyFile.open(QIODevice::ReadOnly), qPrintable(keyFile.errorString()));
     const QSslKey sslKey(keyFile.readAll(), QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey, "");
 
     // Load second QSslCertificate
     QFile certFileSecond(":/resources/certificate1.crt");
-    certFileSecond.open(QIODevice::ReadOnly);
+    QVERIFY2(certFileSecond.open(QIODevice::ReadOnly), qPrintable(certFileSecond.errorString()));
     const QSslCertificate certSecond(certFileSecond.readAll(), QSsl::Pem);
 
     // Load second QSslKey
     QFile keyFileSecond(":/resources/privatekey1.key");
-    keyFileSecond.open(QIODevice::ReadOnly);
+    QVERIFY2(keyFileSecond.open(QIODevice::ReadOnly), qPrintable(keyFileSecond.errorString()));
     const QSslKey sslKeySecond(keyFileSecond.readAll(), QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey, "");
 
     // Add certificates to in-memory store
@@ -138,11 +138,11 @@ void tst_QWebEngineClientCertificateStore::clientAuthentication()
     });
 
     QFile certFile(client_certificate);
-    certFile.open(QIODevice::ReadOnly);
+    QVERIFY2(certFile.open(QIODevice::ReadOnly), qPrintable(certFile.errorString()));
     const QSslCertificate cert(certFile.readAll(), QSsl::Pem);
 
     QFile keyFile(client_key);
-    keyFile.open(QIODevice::ReadOnly);
+    QVERIFY2(keyFile.open(QIODevice::ReadOnly), qPrintable(keyFile.errorString()));
     const QSslKey sslKey(keyFile.readAll(), QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey, "");
 
     if (in_memory)
diff --git a/tests/auto/core/qwebenginecookiestore/tst_qwebenginecookiestore.cpp b/tests/auto/core/qwebenginecookiestore/tst_qwebenginecookiestore.cpp
index a75002ae51c..e0db542c827 100644
--- a/tests/auto/core/qwebenginecookiestore/tst_qwebenginecookiestore.cpp
+++ b/tests/auto/core/qwebenginecookiestore/tst_qwebenginecookiestore.cpp
@@ -79,8 +79,8 @@ void tst_QWebEngineCookieStore::cookieSignals()
     QWebEngineCookieStore *client = m_profile->cookieStore();
 
     QSignalSpy loadSpy(&page, SIGNAL(loadFinished(bool)));
-    QSignalSpy cookieAddedSpy(client, SIGNAL(cookieAdded(const QNetworkCookie &)));
-    QSignalSpy cookieRemovedSpy(client, SIGNAL(cookieRemoved(const QNetworkCookie &)));
+    QSignalSpy cookieAddedSpy(client, SIGNAL(cookieAdded(QNetworkCookie)));
+    QSignalSpy cookieRemovedSpy(client, SIGNAL(cookieRemoved(QNetworkCookie)));
 
     page.load(QUrl("qrc:///resources/index.html"));
 
@@ -108,8 +108,8 @@ void tst_QWebEngineCookieStore::setAndDeleteCookie()
     QWebEngineCookieStore *client = m_profile->cookieStore();
 
     QSignalSpy loadSpy(&page, SIGNAL(loadFinished(bool)));
-    QSignalSpy cookieAddedSpy(client, SIGNAL(cookieAdded(const QNetworkCookie &)));
-    QSignalSpy cookieRemovedSpy(client, SIGNAL(cookieRemoved(const QNetworkCookie &)));
+    QSignalSpy cookieAddedSpy(client, SIGNAL(cookieAdded(QNetworkCookie)));
+    QSignalSpy cookieRemovedSpy(client, SIGNAL(cookieRemoved(QNetworkCookie)));
 
     QNetworkCookie cookie1(QNetworkCookie::parseCookies(QByteArrayLiteral("khaos=I9GX8CWI; Domain=.example.com; Path=/docs")).first());
     QNetworkCookie cookie2(QNetworkCookie::parseCookies(QByteArrayLiteral("Test%20Cookie=foobar; domain=example.com; Path=/")).first());
@@ -155,8 +155,8 @@ void tst_QWebEngineCookieStore::setInvalidCookie()
     QWebEngineCookieStore *client = m_profile->cookieStore();
 
     QSignalSpy loadSpy(&page, SIGNAL(loadFinished(bool)));
-    QSignalSpy cookieAddedSpy(client, SIGNAL(cookieAdded(const QNetworkCookie &)));
-    QSignalSpy cookieRemovedSpy(client, SIGNAL(cookieRemoved(const QNetworkCookie &)));
+    QSignalSpy cookieAddedSpy(client, SIGNAL(cookieAdded(QNetworkCookie)));
+    QSignalSpy cookieRemovedSpy(client, SIGNAL(cookieRemoved(QNetworkCookie)));
 
     QNetworkCookie goodCookie(
             QNetworkCookie::parseCookies(
@@ -186,8 +186,8 @@ void tst_QWebEngineCookieStore::batchCookieTasks()
     QWebEngineCookieStore *client = m_profile->cookieStore();
 
     QSignalSpy loadSpy(&page, SIGNAL(loadFinished(bool)));
-    QSignalSpy cookieAddedSpy(client, SIGNAL(cookieAdded(const QNetworkCookie &)));
-    QSignalSpy cookieRemovedSpy(client, SIGNAL(cookieRemoved(const QNetworkCookie &)));
+    QSignalSpy cookieAddedSpy(client, SIGNAL(cookieAdded(QNetworkCookie)));
+    QSignalSpy cookieRemovedSpy(client, SIGNAL(cookieRemoved(QNetworkCookie)));
 
     QNetworkCookie cookie1(QNetworkCookie::parseCookies(QByteArrayLiteral("khaos=I9GX8CWI; Domain=.example.com; Path=/docs")).first());
     QNetworkCookie cookie2(QNetworkCookie::parseCookies(QByteArrayLiteral("Test%20Cookie=foobar; domain=example.com; Path=/")).first());
@@ -230,8 +230,8 @@ void tst_QWebEngineCookieStore::basicFilter()
     client->setCookieFilter([&](const QWebEngineCookieStore::FilterRequest &){ ++accessTested; return true;});
 
     QSignalSpy loadSpy(&page, SIGNAL(loadFinished(bool)));
-    QSignalSpy cookieAddedSpy(client, SIGNAL(cookieAdded(const QNetworkCookie &)));
-    QSignalSpy cookieRemovedSpy(client, SIGNAL(cookieRemoved(const QNetworkCookie &)));
+    QSignalSpy cookieAddedSpy(client, SIGNAL(cookieAdded(QNetworkCookie)));
+    QSignalSpy cookieRemovedSpy(client, SIGNAL(cookieRemoved(QNetworkCookie)));
 
     page.load(QUrl("qrc:///resources/index.html"));
 
@@ -284,9 +284,9 @@ void tst_QWebEngineCookieStore::basicFilterOverHTTP()
     });
 
     QSignalSpy loadSpy(&page, SIGNAL(loadFinished(bool)));
-    QSignalSpy cookieAddedSpy(client, SIGNAL(cookieAdded(const QNetworkCookie &)));
-    QSignalSpy cookieRemovedSpy(client, SIGNAL(cookieRemoved(const QNetworkCookie &)));
-    QSignalSpy serverSpy(&httpServer, SIGNAL(newRequest(HttpReqRep *)));
+    QSignalSpy cookieAddedSpy(client, SIGNAL(cookieAdded(QNetworkCookie)));
+    QSignalSpy cookieRemovedSpy(client, SIGNAL(cookieRemoved(QNetworkCookie)));
+    QSignalSpy serverSpy(&httpServer, SIGNAL(newRequest(HttpReqRep*)));
 
     QUrl firstPartyUrl = httpServer.url("/test.html");
     page.load(firstPartyUrl);
diff --git a/tests/auto/core/qwebengineframe/tst_qwebengineframe.cpp b/tests/auto/core/qwebengineframe/tst_qwebengineframe.cpp
index 0e036ac7449..fdfefea20c5 100644
--- a/tests/auto/core/qwebengineframe/tst_qwebengineframe.cpp
+++ b/tests/auto/core/qwebengineframe/tst_qwebengineframe.cpp
@@ -244,7 +244,7 @@ void tst_QWebEngineFrame::printToPdfFile()
     QVERIFY(maybeInnerFrame);
     auto innerFrame = *maybeInnerFrame;
 
-    QSignalSpy savePdfSpy{ &page, SIGNAL(pdfPrintingFinished(QString, bool)) };
+    QSignalSpy savePdfSpy{ &page, SIGNAL(pdfPrintingFinished(QString,bool)) };
 
     QString outerPath = tempDir.path() + "/outer.pdf";
     outerFrame.printToPdf(outerPath);
@@ -284,7 +284,7 @@ void tst_QWebEngineFrame::printToPdfFileFailures()
     QVERIFY(maybeInnerFrame);
     auto innerFrame = *maybeInnerFrame;
 
-    QSignalSpy savePdfSpy{ &page, SIGNAL(pdfPrintingFinished(QString, bool)) };
+    QSignalSpy savePdfSpy{ &page, SIGNAL(pdfPrintingFinished(QString,bool)) };
 
 #if !defined(Q_OS_WIN)
     auto badPath = tempDir.path() + "/print_//2_failed.pdf";
diff --git a/tests/auto/core/qwebengineglobalsettings/tst_qwebengineglobalsettings.cpp b/tests/auto/core/qwebengineglobalsettings/tst_qwebengineglobalsettings.cpp
index c7e9df51a7f..b2c0e246d22 100644
--- a/tests/auto/core/qwebengineglobalsettings/tst_qwebengineglobalsettings.cpp
+++ b/tests/auto/core/qwebengineglobalsettings/tst_qwebengineglobalsettings.cpp
@@ -115,7 +115,7 @@ void tst_QWebEngineGlobalSettings::dnsOverHttps()
             [&isLoadSuccessful](bool ok) { isLoadSuccessful = ok; });
 
     page.load(url);
-    QTRY_COMPARE_WITH_TIMEOUT(loadSpy.size(), 1, 20000);
+    QTRY_COMPARE_WITH_TIMEOUT(loadSpy.size(), 1, 30000);
 
     QTRY_COMPARE(isMockDnsServerCalled, isMockDnsServerCalledExpected);
     QCOMPARE(isLoadSuccessful, isDnsResolutionSuccessExpected);
diff --git a/tests/auto/core/qwebenginesettings/tst_qwebenginesettings.cpp b/tests/auto/core/qwebenginesettings/tst_qwebenginesettings.cpp
index 4c8b0db6df4..16a96f8e33c 100644
--- a/tests/auto/core/qwebenginesettings/tst_qwebenginesettings.cpp
+++ b/tests/auto/core/qwebenginesettings/tst_qwebenginesettings.cpp
@@ -335,7 +335,7 @@ void tst_QWebEngineSettings::javaScriptTouchEvents()
     QSignalSpy loadFinishedSpy(&page, SIGNAL(loadFinished(bool)));
 
     if (isExplicitlySet)
-        page.settings()->setAttribute(QWebEngineSettings::JSTouchEventsEnabled,
+        page.settings()->setAttribute(QWebEngineSettings::TouchEventsApiEnabled,
                                       jsTouchEventsEnabled);
 
     page.settings()->setAttribute(QWebEngineSettings::JavascriptEnabled, true);
diff --git a/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp b/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp
index 2d8dcdd2838..ad9f91a939b 100644
--- a/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp
+++ b/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp
@@ -1,8 +1,6 @@
 // Copyright (C) 2017 The Qt Company Ltd.
 // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
 
-#undef QT_NO_FOREACH // this file contains unported legacy Q_FOREACH uses
-
 #include <util.h>
 #include <QtTest/QtTest>
 #include <QtWebEngineCore/qwebengineurlrequestinfo.h>
@@ -162,7 +160,7 @@ class TestRequestInterceptor : public QWebEngineUrlRequestInterceptor
     {
         QList<RequestInfo> infos;
 
-        foreach (auto requestInfo, requestInfos) {
+        for (const auto &requestInfo : requestInfos) {
             if (shouldSkipRequest(requestInfo))
                 continue;
 
@@ -175,7 +173,7 @@ class TestRequestInterceptor : public QWebEngineUrlRequestInterceptor
 
     bool hasUrlRequestForType(QWebEngineUrlRequestInfo::ResourceType type)
     {
-        foreach (auto requestInfo, requestInfos) {
+        for (const auto &requestInfo : requestInfos) {
             if (shouldSkipRequest(requestInfo))
                 continue;
 
@@ -573,43 +571,43 @@ void tst_QWebEngineUrlRequestInterceptor::firstPartyUrlHttp()
     // Stylesheet
     QTRY_VERIFY(interceptor.hasUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeStylesheet));
     infos = interceptor.getUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeStylesheet);
-    foreach (auto info, infos)
+    for (const RequestInfo &info : std::as_const(infos))
         QCOMPARE(info.firstPartyUrl, firstPartyUrl);
 
     // Script
     QTRY_VERIFY(interceptor.hasUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeScript));
     infos = interceptor.getUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeScript);
-    foreach (auto info, infos)
+    for (const RequestInfo &info : std::as_const(infos))
         QCOMPARE(info.firstPartyUrl, firstPartyUrl);
 
     // Image
     QTRY_VERIFY(interceptor.hasUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeImage));
     infos = interceptor.getUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeImage);
-    foreach (auto info, infos)
+    for (const RequestInfo &info : std::as_const(infos))
         QCOMPARE(info.firstPartyUrl, firstPartyUrl);
 
     // FontResource
     QTRY_VERIFY(interceptor.hasUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeFontResource));
     infos = interceptor.getUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeFontResource);
-    foreach (auto info, infos)
+    for (const RequestInfo &info : std::as_const(infos))
         QCOMPARE(info.firstPartyUrl, firstPartyUrl);
 
     // Media
     QTRY_VERIFY(interceptor.hasUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeMedia));
     infos = interceptor.getUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeMedia);
-    foreach (auto info, infos)
+    for (const RequestInfo &info : std::as_const(infos))
         QCOMPARE(info.firstPartyUrl, firstPartyUrl);
 
     // Favicon
     QTRY_VERIFY(interceptor.hasUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeFavicon));
     infos = interceptor.getUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeFavicon);
-    foreach (auto info, infos)
+    for (const RequestInfo &info : std::as_const(infos))
         QCOMPARE(info.firstPartyUrl, firstPartyUrl);
 
     // XMLHttpRequest
     QTRY_VERIFY(interceptor.hasUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeXhr));
     infos = interceptor.getUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeXhr);
-    foreach (auto info, infos)
+    for (const RequestInfo &info : std::as_const(infos))
         QCOMPARE(info.firstPartyUrl, firstPartyUrl);
 }
 
@@ -725,43 +723,43 @@ void tst_QWebEngineUrlRequestInterceptor::initiator()
     // Stylesheet
     QTRY_VERIFY(interceptor.hasUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeStylesheet));
     infos = interceptor.getUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeStylesheet);
-    foreach (auto info, infos)
+    for (const RequestInfo &info : std::as_const(infos))
         QVERIFY(interceptor.requestInitiatorUrls[info.requestUrl].contains(info.initiator));
 
     // Script
     QTRY_VERIFY(interceptor.hasUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeScript));
     infos = interceptor.getUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeScript);
-    foreach (auto info, infos)
+    for (const RequestInfo &info : std::as_const(infos))
         QVERIFY(interceptor.requestInitiatorUrls[info.requestUrl].contains(info.initiator));
 
     // Image
     QTRY_VERIFY(interceptor.hasUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeImage));
     infos = interceptor.getUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeImage);
-    foreach (auto info, infos)
+    for (const RequestInfo &info : std::as_const(infos))
         QVERIFY(interceptor.requestInitiatorUrls[info.requestUrl].contains(info.initiator));
 
     // FontResource
     QTRY_VERIFY(interceptor.hasUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeFontResource));
     infos = interceptor.getUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeFontResource);
-    foreach (auto info, infos)
+    for (const RequestInfo &info : std::as_const(infos))
         QVERIFY(interceptor.requestInitiatorUrls[info.requestUrl].contains(info.initiator));
 
     // Media
     QTRY_VERIFY(interceptor.hasUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeMedia));
     infos = interceptor.getUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeMedia);
-    foreach (auto info, infos)
+    for (const RequestInfo &info : std::as_const(infos))
         QVERIFY(interceptor.requestInitiatorUrls[info.requestUrl].contains(info.initiator));
 
     // Favicon
     QTRY_VERIFY(interceptor.hasUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeFavicon));
     infos = interceptor.getUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeFavicon);
-    foreach (auto info, infos)
+    for (const RequestInfo &info : std::as_const(infos))
         QVERIFY(interceptor.requestInitiatorUrls[info.requestUrl].contains(info.initiator));
 
     // XMLHttpRequest
     QTRY_VERIFY(interceptor.hasUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeXhr));
     infos = interceptor.getUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeXhr);
-    foreach (auto info, infos)
+    for (const RequestInfo &info : std::as_const(infos))
         QVERIFY(interceptor.requestInitiatorUrls[info.requestUrl].contains(info.initiator));
 }
 
@@ -794,7 +792,7 @@ void tst_QWebEngineUrlRequestInterceptor::jsServiceWorker()
     // Service Worker
     QTRY_VERIFY(interceptor.hasUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeServiceWorker));
     infos = interceptor.getUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeServiceWorker);
-    foreach (auto info, infos)
+    for (const RequestInfo &info : std::as_const(infos))
         QCOMPARE(info.firstPartyUrl, firstPartyUrl);
 
     QVERIFY(server.stop());
@@ -803,17 +801,17 @@ void tst_QWebEngineUrlRequestInterceptor::jsServiceWorker()
 void tst_QWebEngineUrlRequestInterceptor::replaceInterceptor_data()
 {
     QTest::addColumn<bool>("firstInterceptIsInPage");
-    QTest::addColumn<bool>("keepInterceptionPoint");
+    QTest::addColumn<bool>("secondInterceptIsInPage");
     QTest::newRow("page")         << true << true;
     QTest::newRow("page-profile") << true << false;
-    QTest::newRow("profile")      << false << true;
-    QTest::newRow("profile-page") << false << false;
+    QTest::newRow("profile")      << false << false;
+    QTest::newRow("profile-page") << false << true;
 }
 
 void tst_QWebEngineUrlRequestInterceptor::replaceInterceptor()
 {
     QFETCH(bool, firstInterceptIsInPage);
-    QFETCH(bool, keepInterceptionPoint);
+    QFETCH(bool, secondInterceptIsInPage);
 
     HttpServer server;
     server.setResourceDirs({ ":/resources" });
@@ -838,17 +836,14 @@ void tst_QWebEngineUrlRequestInterceptor::replaceInterceptor()
         requestsOnReplace.push_back(interceptors[currentInterceptorIndex].requestInfos.size());
 
         bool isFirstReinstall = currentInterceptorIndex == 0;
-        bool interceptInPage = keepInterceptionPoint ? firstInterceptIsInPage : (isFirstReinstall ^ firstInterceptIsInPage);
+        bool interceptInPage = isFirstReinstall ? firstInterceptIsInPage : secondInterceptIsInPage;
         setInterceptor(&interceptors[++currentInterceptorIndex], interceptInPage);
-        if (!keepInterceptionPoint)
-            setInterceptor(nullptr, !interceptInPage);
+        setInterceptor(nullptr, !interceptInPage);
 
         if (isFirstReinstall) {
             page.triggerAction(QWebEnginePage::Reload);
         } else {
-            page.runJavaScript("fetch('http://nonexistent.invalid').catch(() => {})", [&, interceptInPage] (const QVariant &) {
-                requestsOnReplace.push_back(interceptors.back().requestInfos.size());
-                setInterceptor(nullptr, interceptInPage);
+            page.runJavaScript("fetch('http://nonexistent.invalid').catch(() => {})", [&fetchFinished] (const QVariant &) {
                 fetchFinished = true;
             });
         }
@@ -857,6 +852,10 @@ void tst_QWebEngineUrlRequestInterceptor::replaceInterceptor()
     page.setUrl(server.url("/favicon.html"));
     QTRY_COMPARE_WITH_TIMEOUT(spy.size(), 2, 20000);
     QTRY_VERIFY(fetchFinished);
+    QTRY_VERIFY(!interceptors.back().requestInfos.isEmpty());
+    setInterceptor(nullptr, true);
+    setInterceptor(nullptr, false);
+    requestsOnReplace.push_back(interceptors.back().requestInfos.size());
 
     QString s; QDebug d(&s);
     for (auto i = 0u; i < interceptors.size(); ++i) {
@@ -958,7 +957,8 @@ class TestPostRequestInterceptor : public QWebEngineUrlRequestInterceptor
 
         QIODevice *requestBodyDevice = info.requestBody();
 
-        requestBodyDevice->open(QIODevice::ReadOnly);
+        QVERIFY2(requestBodyDevice->open(QIODevice::ReadOnly),
+                 qPrintable(requestBodyDevice->errorString()));
 
         const QString webKitBoundary = requestBodyDevice->read(40);
         QVERIFY(webKitBoundary.contains("------WebKitFormBoundary"));
diff --git a/tests/auto/core/qwebengineurlrequestjob/tst_qwebengineurlrequestjob.cpp b/tests/auto/core/qwebengineurlrequestjob/tst_qwebengineurlrequestjob.cpp
index acddfb0e021..8552ba441b7 100644
--- a/tests/auto/core/qwebengineurlrequestjob/tst_qwebengineurlrequestjob.cpp
+++ b/tests/auto/core/qwebengineurlrequestjob/tst_qwebengineurlrequestjob.cpp
@@ -77,7 +77,7 @@ class AdditionalResponseHeadersHandler : public QWebEngineUrlSchemeHandler
         job->setAdditionalResponseHeaders(additionalResponseHeaders);
 
         QFile *file = new QFile(QStringLiteral(":additionalResponseHeadersScript.html"), job);
-        file->open(QIODevice::ReadOnly);
+        QVERIFY2(file->open(QIODevice::ReadOnly), qPrintable(file->errorString()));
 
         job->reply(QByteArrayLiteral("text/html"), file);
     }
@@ -106,12 +106,13 @@ class RequestBodyHandler : public QWebEngineUrlSchemeHandler
         QCOMPARE(job->requestMethod(), QByteArrayLiteral("POST"));
 
         QIODevice *requestBodyDevice = job->requestBody();
-        requestBodyDevice->open(QIODevice::ReadOnly);
+        QVERIFY2(requestBodyDevice->open(QIODevice::ReadOnly),
+                 qPrintable(requestBodyDevice->errorString()));
         QByteArray requestBody = requestBodyDevice->readAll();
         requestBodyDevice->close();
 
         QBuffer *buf = new QBuffer(job);
-        buf->open(QBuffer::ReadWrite);
+        QVERIFY2(buf->open(QBuffer::ReadWrite), qPrintable(buf->errorString()));
         buf->write(requestBody);
         job->reply(QByteArrayLiteral("text/plain"), buf);
         buf->close();
diff --git a/tests/auto/core/webenginedriver/tst_webenginedriver.cpp b/tests/auto/core/webenginedriver/tst_webenginedriver.cpp
index 66e14e68307..d83d850e2e0 100644
--- a/tests/auto/core/webenginedriver/tst_webenginedriver.cpp
+++ b/tests/auto/core/webenginedriver/tst_webenginedriver.cpp
@@ -116,8 +116,9 @@ class DriverServer : public QObject
 
                     for (QString line : m_stdout) {
                         if (line.contains(
-                                    QLatin1String("WebEngineDriver was started successfully.")))
+                                    QLatin1String("WebEngineDriver was started successfully"))) {
                             return true;
+                        }
                     }
 
                     return false;
diff --git a/tests/auto/pdf/qpdfdocument/tst_qpdfdocument.cpp b/tests/auto/pdf/qpdfdocument/tst_qpdfdocument.cpp
index 45d1d5a7b01..1e90b221d2d 100644
--- a/tests/auto/pdf/qpdfdocument/tst_qpdfdocument.cpp
+++ b/tests/auto/pdf/qpdfdocument/tst_qpdfdocument.cpp
@@ -62,7 +62,7 @@ struct TemporaryPdf: public QTemporaryFile
 
 TemporaryPdf::TemporaryPdf():QTemporaryFile(QStringLiteral("qpdfdocument"))
 {
-    open();
+    QVERIFY2(open(), qPrintable(errorString()));
     pageLayout = QPageLayout(QPageSize(QPageSize::A4), QPageLayout::Portrait, QMarginsF());
 
     {
diff --git a/tests/auto/pdfquick/multipageview/CMakeLists.txt b/tests/auto/pdfquick/multipageview/CMakeLists.txt
index 50f7d7d8f51..010cefdb09a 100644
--- a/tests/auto/pdfquick/multipageview/CMakeLists.txt
+++ b/tests/auto/pdfquick/multipageview/CMakeLists.txt
@@ -11,6 +11,7 @@ qt_internal_add_test(tst_multipageview
     LIBRARIES
         Qt::Gui
         Qt::Quick
+        Qt::PdfPrivate
         Qt::PdfQuickPrivate
     TESTDATA ${test_data}
 )
diff --git a/tests/auto/quick/publicapi/tst_publicapi.cpp b/tests/auto/quick/publicapi/tst_publicapi.cpp
index 2bfaa8eaea7..3fca0b44af3 100644
--- a/tests/auto/quick/publicapi/tst_publicapi.cpp
+++ b/tests/auto/quick/publicapi/tst_publicapi.cpp
@@ -140,6 +140,7 @@ static const QStringList expectedAPI = QStringList()
     << "QWebEngineCertificateError.CertificateSymantecLegacy --> Type"
     << "QWebEngineCertificateError.SslObsoleteVersion --> Type"
     << "QWebEngineCertificateError.SslPinnedKeyNotInCertificateChain --> Type"
+    << "QWebEngineCertificateError.Ok --> Type"
     << "QWebEngineCertificateError.defer() --> void"
     << "QWebEngineCertificateError.description --> QString"
     << "QWebEngineCertificateError.type --> QWebEngineCertificateError::Type"
@@ -523,8 +524,8 @@ static const QStringList expectedAPI = QStringList()
     << "QQuickWebEngineSettings.webRTCPublicInterfacesOnlyChanged() --> void"
     << "QQuickWebEngineSettings.readingFromCanvasEnabled --> bool"
     << "QQuickWebEngineSettings.readingFromCanvasEnabledChanged() --> void"
-    << "QQuickWebEngineSettings.jsTouchEventsEnabled --> bool"
-    << "QQuickWebEngineSettings.jsTouchEventsEnabledChanged() --> void"
+    << "QQuickWebEngineSettings.touchEventsApiEnabled --> bool"
+    << "QQuickWebEngineSettings.touchEventsApiEnabledChanged() --> void"
     << "QQuickWebEngineSingleton.defaultProfile --> QQuickWebEngineProfile*"
     << "QQuickWebEngineSingleton.settings --> QQuickWebEngineSettings*"
     << "QQuickWebEngineSingleton.script() --> QWebEngineScript"
diff --git a/tests/auto/quick/qmltests/data/tst_loadUrl.qml b/tests/auto/quick/qmltests/data/tst_loadUrl.qml
index 757343703c5..e43c8d5d983 100644
--- a/tests/auto/quick/qmltests/data/tst_loadUrl.qml
+++ b/tests/auto/quick/qmltests/data/tst_loadUrl.qml
@@ -265,7 +265,6 @@ TestWebEngineView {
             compare(loadRequest.status, WebEngineView.LoadStoppedStatus);
             compare(loadRequest.status, WebEngineLoadingInfo.LoadStoppedStatus);
             compare(loadRequest.url, stoppedUrl);
-            compare(loadRequest.activeUrl, initialUrl);
             webEngineView.clear();
         }
 
diff --git a/tests/auto/quick/qmltests/data/tst_userScripts.qml b/tests/auto/quick/qmltests/data/tst_userScripts.qml
index a64de389d8e..d18c1f44a10 100644
--- a/tests/auto/quick/qmltests/data/tst_userScripts.qml
+++ b/tests/auto/quick/qmltests/data/tst_userScripts.qml
@@ -65,6 +65,23 @@ Item {
         }
     }
 
+    // This previously crashed. See change: https://codereview.qt-project.org/c/qt/qtwebengine/+/558237
+    WebEngineView {
+        id: webEngineView3
+        width: 400
+        height: 300
+
+        userScripts {
+            collection: [
+                {
+                    injectionPoint: WebEngineScript.DocumentReady,
+                    sourceCode: Qt.resolvedUrl("append-document-title.js"),
+                    worldId: WebEngineScript.UserWorld
+                }
+            ]
+        }
+    }
+
     TestCase {
         name: "UserScripts"
 
diff --git a/tests/auto/quick/qquickwebengineview/html/resources/hello.js b/tests/auto/quick/qquickwebengineview/html/resources/hello.js
new file mode 100644
index 00000000000..6f5e79ebf4d
--- /dev/null
+++ b/tests/auto/quick/qquickwebengineview/html/resources/hello.js
@@ -0,0 +1,7 @@
+// Copyright (C) 2025 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+function sayHello()
+{
+    console.warn("hello");
+}
diff --git a/tests/auto/quick/qquickwebengineview/html/resources/hi.js b/tests/auto/quick/qquickwebengineview/html/resources/hi.js
new file mode 100644
index 00000000000..30e7cc972d1
--- /dev/null
+++ b/tests/auto/quick/qquickwebengineview/html/resources/hi.js
@@ -0,0 +1,8 @@
+// Copyright (C) 2025 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+function sayHi()
+{
+    // Placeholder
+    console.warn("hi");
+}
diff --git a/tests/auto/quick/qquickwebengineview/html/script2.html b/tests/auto/quick/qquickwebengineview/html/script2.html
new file mode 100644
index 00000000000..5faf58daab3
--- /dev/null
+++ b/tests/auto/quick/qquickwebengineview/html/script2.html
@@ -0,0 +1,4 @@
+<html><head>
+<script language="javascript" type="text/javascript" src="resources/hello.js"></script>
+<script language="javascript" type="text/javascript" src="resources/hi.js"></script>
+</head></html>
diff --git a/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp b/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp
index 4521f94bbfe..2f787f55907 100644
--- a/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp
+++ b/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp
@@ -1,11 +1,11 @@
 // Copyright (C) 2016 The Qt Company Ltd.
 // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
 
-#undef QT_NO_FOREACH // this file contains unported legacy Q_FOREACH uses
-
+#include "QtWidgets/qapplication.h"
 #include "testwindow.h"
 #include "quickutil.h"
 #include "util.h"
+#include "visualutil.h"
 
 #include <QScopedPointer>
 #include <QtCore/qelapsedtimer.h>
@@ -27,6 +27,8 @@
 
 #include <functional>
 
+using namespace Qt::StringLiterals;
+
 class tst_QQuickWebEngineView : public QObject {
     Q_OBJECT
 public:
@@ -76,10 +78,12 @@ private Q_SLOTS:
 #if QT_CONFIG(accessibility)
     void focusChild_data();
     void focusChild();
+    void accessibilityRect();
 #endif
     void htmlSelectPopup();
     void savePage_data();
     void savePage();
+    void javaScriptConsoleMessage();
 
 private:
     inline QQuickWebEngineView *newWebEngineView();
@@ -445,7 +449,11 @@ void tst_QQuickWebEngineView::transparentWebEngineViews()
 
 void tst_QQuickWebEngineView::inputMethod()
 {
+    SKIP_IF_NO_WINDOW_ACTIVATION();
+
     m_window->show();
+    m_window->requestActivate();
+    QVERIFY(QTest::qWaitForWindowActive(m_window.get()));
     QQuickItem *input;
 
     QQuickWebEngineView *view = webEngineView();
@@ -547,8 +555,11 @@ void tst_QQuickWebEngineView::interruptImeTextComposition_data()
 
 void tst_QQuickWebEngineView::interruptImeTextComposition()
 {
+    SKIP_IF_NO_WINDOW_ACTIVATION();
+
     m_window->show();
-    QTRY_VERIFY(qApp->focusObject());
+    m_window->requestActivate();
+    QVERIFY(QTest::qWaitForWindowActive(m_window.get()));
     QQuickItem *input;
 
     QQuickWebEngineView *view = webEngineView();
@@ -597,8 +608,11 @@ void tst_QQuickWebEngineView::interruptImeTextComposition()
 
 void tst_QQuickWebEngineView::inputContextQueryInput()
 {
+    SKIP_IF_NO_WINDOW_ACTIVATION();
+
     m_window->show();
-    QTRY_VERIFY(qApp->focusObject());
+    m_window->requestActivate();
+    QVERIFY(QTest::qWaitForWindowActive(m_window.get()));
     TestInputContext testContext;
 
     QQuickWebEngineView *view = webEngineView();
@@ -614,7 +628,7 @@ void tst_QQuickWebEngineView::inputContextQueryInput()
     QTest::mouseClick(view->window(), Qt::LeftButton, {}, textInputCenter);
     QTRY_COMPARE(testContext.infos.size(), 2);
     QCOMPARE(evaluateJavaScriptSync(view, "document.activeElement.id").toString(), QStringLiteral("input1"));
-    foreach (const InputMethodInfo &info, testContext.infos) {
+    for (const InputMethodInfo &info : std::as_const(testContext.infos)) {
         QCOMPARE(info.cursorPosition, 0);
         QCOMPARE(info.anchorPosition, 0);
         QCOMPARE(info.surroundingText, QStringLiteral(""));
@@ -709,7 +723,7 @@ void tst_QQuickWebEngineView::inputContextQueryInput()
         QGuiApplication::sendEvent(qApp->focusObject(), &event);
     }
     QTRY_COMPARE(testContext.infos.size(), 2);
-    foreach (const InputMethodInfo &info, testContext.infos) {
+    for (const InputMethodInfo &info : std::as_const(testContext.infos)) {
         QCOMPARE(info.cursorPosition, 0);
         QCOMPARE(info.anchorPosition, 0);
         QCOMPARE(info.surroundingText, QStringLiteral("QtWebEngine!"));
@@ -742,8 +756,11 @@ void tst_QQuickWebEngineView::inputContextQueryInput()
 
 void tst_QQuickWebEngineView::inputMethodHints()
 {
+    SKIP_IF_NO_WINDOW_ACTIVATION();
+
     m_window->show();
-    QTRY_VERIFY(qApp->focusObject());
+    m_window->requestActivate();
+    QVERIFY(QTest::qWaitForWindowActive(m_window.get()));
     QQuickItem *input;
 
     QQuickWebEngineView *view = webEngineView();
@@ -845,7 +862,7 @@ void tst_QQuickWebEngineView::printToPdf()
     view->setUrl(urlFromTestPath("html/basic_page.html"));
     QVERIFY(waitForLoadSucceeded(view));
 
-    QSignalSpy savePdfSpy(view, SIGNAL(pdfPrintingFinished(const QString&, bool)));
+    QSignalSpy savePdfSpy(view, SIGNAL(pdfPrintingFinished(QString,bool)));
     QString path = tempDir.path() + "/print_success.pdf";
     view->printToPdf(path, QQuickWebEngineView::A4, QQuickWebEngineView::Portrait);
     QTRY_VERIFY2(savePdfSpy.size() == 1, "Printing to PDF file failed without signal");
@@ -1256,6 +1273,74 @@ void tst_QQuickWebEngineView::focusChild()
     // <html> -> <body> -> <input>
     QCOMPARE(traverseToWebDocumentAccessibleInterface(iface)->child(0)->child(0), iface->focusChild());
 }
+
+void tst_QQuickWebEngineView::accessibilityRect()
+{
+    auto *engine = new QQmlEngine(this);
+    auto *component = new QQmlComponent(engine, this);
+    component->setData(QByteArrayLiteral("import QtQuick\n"
+                                           "import QtWebEngine\n"
+                                           "Window {\n"
+                                           " visible: true; width: 600; height: 400\n"
+                                           " Text { id: textId; text: \"text\"; width: 100; Accessible.focusable: true; Accessible.name: \"text\" }\n"
+                                           " WebEngineView { anchors.left: textId.right; anchors.top: textId.bottom; anchors.right: parent.right; anchors.bottom: parent.bottom }\n"
+                                           "}")
+                         , QUrl());
+    QObject *rootObject = component->create();
+    QVERIFY(rootObject);
+
+    QQuickWebEngineView *webView = rootObject->findChild<QQuickWebEngineView*>();
+    QVERIFY(webView);
+
+    webView->loadHtml("<html><body bgcolor=\"red\"><input type='text' id='input1' /></body></html>");
+    QVERIFY(waitForLoadSucceeded(webView));
+
+    QAccessibleInterface *rootObjectIface = QAccessible::queryAccessibleInterface(rootObject);
+    QVERIFY(rootObjectIface);
+    QCOMPARE(rootObjectIface->childCount(), 2);
+
+    QAccessibleInterface *textIface = rootObjectIface->child(0);
+    QVERIFY(textIface);
+    QCOMPARE(textIface->role(), QAccessible::StaticText);
+
+    QCOMPARE(textIface->rect().width(), 100);
+    QVERIFY(textIface->rect().height() > 0);
+
+    // It takes a while for the webIface to get its width, unfortunately we can't have a
+    // QTRY_COMPARE since it seems in some platforms the iface gets recreated and we end up
+    // accessible the wrong pointer, so roll up our own try+compare
+    QAccessibleInterface *webIface = nullptr;
+    QElapsedTimer t;
+    t.start();
+    bool isWebIfaceOfCorrectWidth = false;
+    while (!isWebIfaceOfCorrectWidth && t.elapsed() < 5000) {
+        QTest::qWait(100);
+        webIface = rootObjectIface->child(1)->child(0);
+        QVERIFY(webIface);
+        QCOMPARE(webIface->role(), QAccessible::WebDocument);
+        isWebIfaceOfCorrectWidth = webIface->rect().width() == 500;
+    }
+
+    QVERIFY(isWebIfaceOfCorrectWidth);
+    QCOMPARE(webIface->rect().height(), 400 - textIface->rect().height());
+    QCOMPARE(webIface->rect().x(), textIface->rect().x() + textIface->rect().width());
+    QCOMPARE(webIface->rect().y(), textIface->rect().y() + textIface->rect().height());
+
+    // Set active focus on the input field.
+    webView->runJavaScript("document.getElementById('input1').focus();");
+    QTRY_COMPARE(evaluateJavaScriptSync(webView, "document.activeElement.id").toString(), QStringLiteral("input1"));
+
+    // Check that children of the web rect are inside it
+    QAccessibleInterface *inputIface = webIface->focusChild();
+    QVERIFY(inputIface);
+    QTRY_COMPARE(inputIface->role(), QAccessible::EditableText);
+    QVERIFY(webIface->rect().contains(inputIface->rect()));
+
+    delete rootObject;
+    delete component;
+    delete engine;
+}
+
 #endif // QT_CONFIG(accessibility)
 
 void tst_QQuickWebEngineView::htmlSelectPopup()
@@ -1277,7 +1362,14 @@ void tst_QQuickWebEngineView::htmlSelectPopup()
 
     makeTouch(view.window(), elementCenter(&view, "select"));
     QPointer<QQuickWindow> popup;
-    QTRY_VERIFY((popup = m_window->findChild<QQuickWindow *>()));
+    auto findPopup = [](QQuickView *view) -> QQuickWindow * {
+        for (auto window : QApplication::topLevelWindows()) {
+            if (window->transientParent() == view)
+                return dynamic_cast<QQuickWindow *>(window);
+        }
+        return nullptr;
+    };
+    QTRY_VERIFY((popup = findPopup(m_window.get())));
     QCOMPARE(activeElementId(&view), QStringLiteral("select"));
 
     makeTouch(popup, QPoint(popup->width() / 2, popup->height() / 2));
@@ -1365,6 +1457,82 @@ void tst_QQuickWebEngineView::savePage()
              originalData);
 }
 
+class TestJSMessageHandler
+{
+public:
+    inline static QList<QtMsgType> levels;
+    inline static QStringList messages;
+    inline static QList<int> lineNumbers;
+    inline static QStringList sourceIDs;
+
+    static void handler(QtMsgType type, const QMessageLogContext &context, const QString &msg)
+    {
+        if (strcmp(context.category, "js") != 0) {
+            m_originalHandler(type, context, msg);
+            return;
+        }
+
+        levels.append(type);
+        messages.append(msg);
+        lineNumbers.append(context.line);
+        sourceIDs.append(context.file);
+    }
+
+    TestJSMessageHandler() { m_originalHandler = qInstallMessageHandler(handler); }
+    ~TestJSMessageHandler() { qInstallMessageHandler(m_originalHandler); }
+
+private:
+    inline static QtMessageHandler m_originalHandler = nullptr;
+};
+
+void tst_QQuickWebEngineView::javaScriptConsoleMessage()
+{
+    QQuickWebEngineView *view = webEngineView();
+
+    // Test QQuickWebEngineView::javaScriptConsoleMessage() signal.
+    {
+        QSignalSpy jsSpy(
+                view,
+                SIGNAL(javaScriptConsoleMessage(QQuickWebEngineView::JavaScriptConsoleMessageLevel,
+                                                const QString &, int, const QString &)));
+        view->setUrl(urlFromTestPath("html/script2.html"));
+        QVERIFY(waitForLoadSucceeded(view));
+
+        runJavaScript("sayHello()");
+        QTRY_COMPARE(jsSpy.size(), 1);
+        QCOMPARE(jsSpy.last().at(0).toInt(), QWebEnginePage::WarningMessageLevel);
+        QCOMPARE(jsSpy.last().at(1).toString(), "hello"_L1);
+        QCOMPARE(jsSpy.last().at(2).toInt(), 6);
+        QCOMPARE(jsSpy.last().at(3).toString(), urlFromTestPath("html/resources/hello.js"));
+
+        runJavaScript("sayHi()");
+        QTRY_COMPARE(jsSpy.size(), 2);
+        QCOMPARE(jsSpy.last().at(0).toInt(), QWebEnginePage::WarningMessageLevel);
+        QCOMPARE(jsSpy.last().at(1).toString(), "hi"_L1);
+        QCOMPARE(jsSpy.last().at(2).toInt(), 7);
+        QCOMPARE(jsSpy.last().at(3).toString(), urlFromTestPath("html/resources/hi.js"));
+    }
+
+    // Test default QQuickWebEngineViewPrivate::javaScriptConsoleMessage() handler.
+    {
+        TestJSMessageHandler handler;
+        view->setUrl(urlFromTestPath("html/script2.html"));
+        QVERIFY(waitForLoadSucceeded(view));
+
+        evaluateJavaScriptSync(view, "sayHello()");
+        QCOMPARE(handler.levels.last(), QtMsgType::QtWarningMsg);
+        QCOMPARE(handler.messages.last(), "hello"_L1);
+        QCOMPARE(handler.lineNumbers.last(), 6);
+        QCOMPARE(handler.sourceIDs.last(), urlFromTestPath("html/resources/hello.js"));
+
+        evaluateJavaScriptSync(view, "sayHi()");
+        QCOMPARE(handler.levels.last(), QtMsgType::QtWarningMsg);
+        QCOMPARE(handler.messages.last(), "hi"_L1);
+        QCOMPARE(handler.lineNumbers.last(), 7);
+        QCOMPARE(handler.sourceIDs.last(), urlFromTestPath("html/resources/hi.js"));
+    }
+}
+
 #if QT_CONFIG(accessibility)
 static QByteArrayList params = QByteArrayList()
     << "--force-renderer-accessibility";
diff --git a/tests/auto/quick/uidelegates/tst_uidelegates.cpp b/tests/auto/quick/uidelegates/tst_uidelegates.cpp
index 419f2f877fb..25702f4b870 100644
--- a/tests/auto/quick/uidelegates/tst_uidelegates.cpp
+++ b/tests/auto/quick/uidelegates/tst_uidelegates.cpp
@@ -3,6 +3,7 @@
 
 #include "testwindow.h"
 #include "quickutil.h"
+#include "visualutil.h"
 
 #include <QScopedPointer>
 #include <QtQml/QQmlEngine>
@@ -107,11 +108,14 @@ void tst_UIDelegates::javaScriptDialog_data()
 
 void tst_UIDelegates::javaScriptDialog()
 {
+    SKIP_IF_NO_WINDOW_ACTIVATION();
+
     QFETCH(QString, javaScriptCode);
     QFETCH(QString, expectedObjectName);
 
     m_window->show();
-    QTRY_VERIFY(qApp->focusObject());
+    m_window->requestActivate();
+    QVERIFY(QTest::qWaitForWindowActive(m_window.get()));
     QQuickWebEngineView *view = webEngineView();
 
     view->loadHtml("<html><body>"
@@ -124,8 +128,11 @@ void tst_UIDelegates::javaScriptDialog()
 
 void tst_UIDelegates::fileDialog()
 {
+    SKIP_IF_NO_WINDOW_ACTIVATION();
+
     m_window->show();
-    QTRY_VERIFY(qApp->focusObject());
+    m_window->requestActivate();
+    QVERIFY(QTest::qWaitForWindowActive(m_window.get()));
     QQuickWebEngineView *view = webEngineView();
 
     view->loadHtml("<html><body>"
@@ -140,8 +147,11 @@ void tst_UIDelegates::fileDialog()
 
 void tst_UIDelegates::contextMenu()
 {
+    SKIP_IF_NO_WINDOW_ACTIVATION();
+
     m_window->show();
-    QTRY_VERIFY(qApp->focusObject());
+    m_window->requestActivate();
+    QVERIFY(QTest::qWaitForWindowActive(m_window.get()));
     QQuickWebEngineView *view = webEngineView();
 
     view->loadHtml("<html><body>"
@@ -154,8 +164,11 @@ void tst_UIDelegates::contextMenu()
 
 void tst_UIDelegates::tooltip()
 {
+    SKIP_IF_NO_WINDOW_ACTIVATION();
+
     m_window->show();
-    QTRY_VERIFY(qApp->focusObject());
+    m_window->requestActivate();
+    QVERIFY(QTest::qWaitForWindowActive(m_window.get()));
     QQuickWebEngineView *view = webEngineView();
 
     view->loadHtml("<html><body>"
@@ -177,8 +190,11 @@ void tst_UIDelegates::tooltip()
 
 void tst_UIDelegates::colorDialog()
 {
+    SKIP_IF_NO_WINDOW_ACTIVATION();
+
     m_window->show();
-    QTRY_VERIFY(qApp->focusObject());
+    m_window->requestActivate();
+    QVERIFY(QTest::qWaitForWindowActive(m_window.get()));
     QQuickWebEngineView *view = webEngineView();
 
     view->loadHtml("<html><body>"
@@ -209,6 +225,8 @@ void tst_UIDelegates::authenticationDialog_data()
 
 void tst_UIDelegates::authenticationDialog()
 {
+    SKIP_IF_NO_WINDOW_ACTIVATION();
+
     QFETCH(QUrl, url);
     QFETCH(QByteArray, response);
 
@@ -218,7 +236,8 @@ void tst_UIDelegates::authenticationDialog()
     QVERIFY(server.start());
 
     m_window->show();
-    QTRY_VERIFY(qApp->focusObject());
+    m_window->requestActivate();
+    QVERIFY(QTest::qWaitForWindowActive(m_window.get()));
     QQuickWebEngineView *view = webEngineView();
     view->loadHtml("<html><body>"
                    "</body></html>");
diff --git a/tests/auto/util/visualutil.h b/tests/auto/util/visualutil.h
new file mode 100644
index 00000000000..ca967e71dda
--- /dev/null
+++ b/tests/auto/util/visualutil.h
@@ -0,0 +1,19 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#ifndef VISUALUTIL_H
+#define VISUALUTIL_H
+
+// Separate utils that require linking with GuiPrivate
+
+#include <QtTest/QtTest>
+#include <QtGui/private/qguiapplication_p.h>
+#include <QtGui/qpa/qplatformintegration.h>
+
+#define SKIP_IF_NO_WINDOW_ACTIVATION() \
+do { \
+    if (!(QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation))) \
+        QSKIP("Window activation is not supported on this platform"); \
+} while (false)
+
+#endif /* VISUALUTIL_H */
diff --git a/tests/auto/widgets/accessibility/tst_accessibility.cpp b/tests/auto/widgets/accessibility/tst_accessibility.cpp
index a4d87a7b256..8db7d3314cf 100644
--- a/tests/auto/widgets/accessibility/tst_accessibility.cpp
+++ b/tests/auto/widgets/accessibility/tst_accessibility.cpp
@@ -52,6 +52,7 @@ private Q_SLOTS:
     void objectName();
     void crossTreeParent();
     void tableCellInterface();
+    void tableInterface();
 };
 
 // This will be called before the first test function is executed.
@@ -341,8 +342,8 @@ void tst_Accessibility::roles_data()
 
     QTest::newRow("ax::mojom::Role::kAbbr") << QString("<abbr>a</abbr>") << 1 << QAccessible::StaticText;
     QTest::newRow("ax::mojom::Role::kAlert") << QString("<div role='alert'>alert</div>") << 0 << QAccessible::AlertMessage;
-    QTest::newRow("ax::mojom::Role::kAlertDialog") << QString("<div role='alertdialog'>alert</div>") << 0 << QAccessible::AlertMessage;
-    QTest::newRow("ax::mojom::Role::kAnchor") << QString("<a id='a'>Chapter a</a>") << 1 << QAccessible::Section;
+    QTest::newRow("ax::mojom::Role::kAlertDialog")
+            << QString("<div role='alertdialog'>alert</div>") << 0 << QAccessible::AlertMessage;
     QTest::newRow("ax::mojom::Role::kApplication") << QString("<div role='application'>landmark</div>") << 0 << QAccessible::Document;
     QTest::newRow("ax::mojom::Role::kArticle") << QString("<article>a</article>") << 0 << QAccessible::Section;
     QTest::newRow("ax::mojom::Role::kAudio") << QString("<audio controls><source src='test.mp3' type='audio/mpeg'></audio>") << 1 << QAccessible::Sound;
@@ -357,27 +358,33 @@ void tst_Accessibility::roles_data()
     QTest::newRow("ax::mojom::Role::kClient") << QString("") << 0 << QAccessible::Client;
     QTest::newRow("ax::mojom::Role::kCode") << QString("<code>a</code>") << 1 << QAccessible::StaticText;
     QTest::newRow("ax::mojom::Role::kColorWell") << QString("<input type='color'>a</input>") << 1 << QAccessible::ColorChooser;
-    //QTest::newRow("ax::mojom::Role::kColumn") << QString("<table><tr><td>a</td></tr></table>") << 0 << QAccessible::Column; // FIXME: The test case might be wrong (see AXTableColumn.h)
-    QTest::newRow("ax::mojom::Role::kColumnHeader") << QString("<table role=table><tr><th>a</th></tr><tr><td>a</td></tr></table>") << 2 << QAccessible::ColumnHeader;
+    // QTest::newRow("ax::mojom::Role::kColumn"); // No mapping to ARIA role
+    QTest::newRow("ax::mojom::Role::kColumnHeader") << QString("<table role=table><tr><th>a</th></tr><tr><td>a</td></tr></table>") << 2 << QAccessible::Cell;
     QTest::newRow("ax::mojom::Role::kComboBoxGrouping") << QString("<div role='combobox'><input></div>") << 0 << QAccessible::ComboBox;
     QTest::newRow("ax::mojom::Role::kComboBoxMenuButton") << QString("<div tabindex=0 role='combobox'>Select</div>") << 0 << QAccessible::ComboBox;
-    QTest::newRow("ax::mojom::Role::kTextFieldWithComboBox") << QString("<input role='combobox'>") << 1 << QAccessible::ComboBox;
+    // QTest::newRow("ax::mojom::Role::kComboBoxSelect"); // No mapping to ARIA role
     QTest::newRow("ax::mojom::Role::kComplementary") << QString("<aside>a</aside>") << 0 << QAccessible::ComplementaryContent;
     QTest::newRow("ax::mojom::Role::kComment") << QString("<div role='comment'></div>") << 0 << QAccessible::Section;
     QTest::newRow("ax::mojom::Role::kContentDeletion") << QString("<div role='deletion'></div>") << 0 << QAccessible::Grouping;
     QTest::newRow("ax::mojom::Role::kContentInsertion") << QString("<div role='insertion'></div>") << 0 << QAccessible::Grouping;
     QTest::newRow("ax::mojom::Role::kContentInfo") << QString("<div role='contentinfo'></div>") << 0 << QAccessible::Section;
-    QTest::newRow("ax::mojom::Role::kData") << QString("<input type='date'></input>") << 1 << QAccessible::Clock;
+    QTest::newRow("ax::mojom::Role::kDate")
+            << QString("<input type='date'></input>") << 1 << QAccessible::Clock;
     QTest::newRow("ax::mojom::Role::kDateTime") << QString("<input type='datetime-local'></input>") << 1 << QAccessible::Clock;
     QTest::newRow("ax::mojom::Role::kDefinition") << QString("<div role='definition'>landmark</div>") << 0 << QAccessible::Paragraph;
     QTest::newRow("ax::mojom::Role::kDescriptionList") << QString("<dl>a</dl>") << 0 << QAccessible::List;
-    QTest::newRow("ax::mojom::Role::kDescriptionListDetail") << QString("<dd>a</dd>") << 0 << QAccessible::Paragraph;
+    QTest::newRow("ax::mojom::Role::kDescriptionListDetailDeprecated")
+            << QString("<dd>a</dd>") << 0 << QAccessible::Paragraph;
+    // QTest::newRow("ax::mojom::Role::kDescriptionListTermDeprecated");
     QTest::newRow("ax::mojom::Role::kDetails") << QString("<details>a</details>") << 0 << QAccessible::Grouping;
     //QTest::newRow("ax::mojom::Role::kDesktop"); // No mapping to ARIA role
     QTest::newRow("ax::mojom::Role::kDialog") << QString("<div role='dialog'></div>") << 0 << QAccessible::Dialog;
-    //QTest::newRow("ax::mojom::Role::kDirectory") << QString("<ul role='directory'></ul>") << 0 << QAccessible::List; // FIXME: Aria role 'directory' should work
+    QTest::newRow("ax::mojom::Role::kDirectoryDeprecated")
+            << QString("<ul role='directory'></ul>") << 0 << QAccessible::List;
     QTest::newRow("ax::mojom::Role::kDisclosureTriangle") << QString("<details><summary>a</summary></details>") << 1 << QAccessible::Button;
-    QTest::newRow("ax::mojom::Role::kDisclosureTriangleGroup") << QString("<details name='groupName'><summary>a</summary></details>") << 1 << QAccessible::Button;
+    QTest::newRow("ax::mojom::Role::kDisclosureTriangleGrouped")
+            << QString("<details name='groupName'><summary>a</summary></details>") << 1
+            << QAccessible::Button;
     QTest::newRow("ax::mojom::Role::kGenericContainer") << QString("<div>a</div>") << 0 << QAccessible::Section;
     QTest::newRow("ax::mojom::Role::kDocCover") << QString("<div role='doc-cover'></div>") << 0 << QAccessible::Graphic;
     QTest::newRow("ax::mojom::Role::kDocBackLink") << QString("<div role='doc-backlink'></div>") << 0 << QAccessible::Link;
@@ -389,7 +396,8 @@ void tst_Accessibility::roles_data()
     QTest::newRow("ax::mojom::Role::kDocFootnote") << QString("<div role='doc-footnote'></div>") << 0 << QAccessible::ListItem;
     QTest::newRow("ax::mojom::Role::kDocPageBreak") << QString("<div role='doc-pagebreak'></div>") << 0 << QAccessible::Separator;
     QTest::newRow("ax::mojom::Role::kDocAbstract") << QString("<div role='doc-abstract'></div>") << 0 << QAccessible::Section;
-    QTest::newRow("ax::mojom::Role::kDocAcknowledgements") << QString("<div role='doc-acknowledgments'></div>") << 0 << QAccessible::Section;
+    QTest::newRow("ax::mojom::Role::kDocAcknowledgments")
+            << QString("<div role='doc-acknowledgments'></div>") << 0 << QAccessible::Section;
     QTest::newRow("ax::mojom::Role::kDocAfterword") << QString("<div role='doc-afterword'></div>") << 0 << QAccessible::Section;
     QTest::newRow("ax::mojom::Role::kDocAppendix") << QString("<div role='doc-appendix'></div>") << 0 << QAccessible::Section;
     QTest::newRow("ax::mojom::Role::kDocBibliography") << QString("<div role='doc-bibliography'></div>") << 0 << QAccessible::Section;
@@ -403,14 +411,18 @@ void tst_Accessibility::roles_data()
     QTest::newRow("ax::mojom::Role::kDocEpigraph") << QString("<div role='doc-epigraph'></div>") << 0 << QAccessible::Section;
     QTest::newRow("ax::mojom::Role::kDocEpilogue") << QString("<div role='doc-epilogue'></div>") << 0 << QAccessible::Section;
     QTest::newRow("ax::mojom::Role::kDocErrata") << QString("<div role='doc-errata'></div>") << 0 << QAccessible::Section;
-    QTest::newRow("ax::mojom::Role::kDocExample") << QString("<div role='doc-example'></div>") << 0 << QAccessible::Section;
-    QTest::newRow("ax::mojom::Role::kDocFooter") << QString("<section role='doc-pagefooter'>a</section>") << 0 << QAccessible::Footer;
+    QTest::newRow("ax::mojom::Role::kDocExample")
+            << QString("<div role='doc-example'></div>") << 0 << QAccessible::Section;
     QTest::newRow("ax::mojom::Role::kDocForeword") << QString("<div role='doc-foreword'></div>") << 0 << QAccessible::Section;
-    QTest::newRow("ax::mojom::Role::kDocGlossary") << QString("<div role='doc-glossary'></div>") << 0 << QAccessible::Section;
-    QTest::newRow("ax::mojom::Role::kDocHeader") << QString("<section role='doc-pageheader'>a</section>") << 0 << QAccessible::Heading;
+    QTest::newRow("ax::mojom::Role::kDocGlossary")
+            << QString("<div role='doc-glossary'></div>") << 0 << QAccessible::Section;
     QTest::newRow("ax::mojom::Role::kDocIndex") << QString("<div role='doc-index'></div>") << 0 << QAccessible::Section;
     QTest::newRow("ax::mojom::Role::kDocIntroduction") << QString("<div role='doc-introduction'></div>") << 0 << QAccessible::Section;
     QTest::newRow("ax::mojom::Role::kDocNotice") << QString("<div role='doc-notice'></div>") << 0 << QAccessible::Section;
+    QTest::newRow("ax::mojom::Role::kDocPageFooter")
+            << QString("<section role='doc-pagefooter'>a</section>") << 0 << QAccessible::Footer;
+    QTest::newRow("ax::mojom::Role::kDocPageHeader")
+            << QString("<section role='doc-pageheader'>a</section>") << 0 << QAccessible::Heading;
     QTest::newRow("ax::mojom::Role::kDocPageList") << QString("<div role='doc-pagelist'></div>") << 0 << QAccessible::Section;
     QTest::newRow("ax::mojom::Role::kDocPart") << QString("<div role='doc-part'></div>") << 0 << QAccessible::Section;
     QTest::newRow("ax::mojom::Role::kDocPreface") << QString("<div role='doc-preface'></div>") << 0 << QAccessible::Section;
@@ -421,34 +433,35 @@ void tst_Accessibility::roles_data()
     QTest::newRow("ax::mojom::Role::kDocTip") << QString("<div role='doc-tip'></div>") << 0 << QAccessible::Section;
     QTest::newRow("ax::mojom::Role::kDocToc") << QString("<div role='doc-toc'></div>") << 0 << QAccessible::Section;
     QTest::newRow("ax::mojom::Role::kDocument") << QString("<div role='document'>a</div>") << 0 << QAccessible::Document;
-    QTest::newRow("ax::mojom::Role::kEmbeddedObject") << QString("<object width='10' height='10'></object>") << 1 << QAccessible::Grouping;
+    QTest::newRow("ax::mojom::Role::kEmbeddedObject")
+            << QString("<embed src=''>") << 1 << QAccessible::Grouping;
     QTest::newRow("ax::mojom::Role::kEmphasis") << QString("<em>a</em>") << 1 << QAccessible::StaticText;
     QTest::newRow("ax::mojom::Role::kFeed") << QString("<div role='feed'>a</div>") << 0 << QAccessible::Section;
     QTest::newRow("ax::mojom::Role::kFigcaption") << QString("<figcaption>a</figcaption>") << 0 << QAccessible::Heading;
     QTest::newRow("ax::mojom::Role::kFigure") << QString("<figure>a</figure>") << 0 << QAccessible::Section;
     QTest::newRow("ax::mojom::Role::kFooter") << QString("<footer>a</footer>") << 0 << QAccessible::Section;
-    QTest::newRow("ax::mojom::Role::kFooterAsNonLandmark") << QString("<article><footer>a</footer><article>") << 1 << QAccessible::Section;
     QTest::newRow("ax::mojom::Role::kForm") << QString("<form aria-label=Name></form>") << 0 << QAccessible::Form;
     QTest::newRow("ax::mojom::Role::kGraphicsDocument") << QString("<div role='graphics-document'></div>") << 0 << QAccessible::Document;
     QTest::newRow("ax::mojom::Role::kGraphicsObject") << QString("<div role='graphics-object'></div>") << 0 << QAccessible::Pane;
     QTest::newRow("ax::mojom::Role::kGraphicsSymbol") << QString("<div role='graphics-symbol'></div>") << 0 << QAccessible::Graphic;
     QTest::newRow("ax::mojom::Role::kGrid") << QString("<div role='grid'></div>") << 0 << QAccessible::Table;
+    QTest::newRow("ax::mojom::Role::kGridCell")
+            << QString("<div role='gridcell'></div>") << 0 << QAccessible::Cell;
     QTest::newRow("ax::mojom::Role::kGroup") << QString("<fieldset></fieldset>") << 0 << QAccessible::Grouping;
-    QTest::newRow("ax::mojom::Role::Header") << QString("<header>a</header>") << 0 << QAccessible::Section;
-    QTest::newRow("ax::mojom::Role::HeaderAsNonLandMark") << QString("<article><header>a</header><article>") << 1 << QAccessible::Section;
+    QTest::newRow("ax::mojom::Role::kHeader")
+            << QString("<header>a</header>") << 0 << QAccessible::Section;
     QTest::newRow("ax::mojom::Role::kHeading") << QString("<h1>a</h1>") << 0 << QAccessible::Heading;
     QTest::newRow("ax::mojom::Role::kIframe") << QString("<iframe>a</iframe>") << 1 << QAccessible::WebDocument;
-    QTest::newRow("ax::mojom::Role::kIframePresentational") << QString("<iframe role='presentation'>a</iframe>") << 1 << QAccessible::Grouping;
-    //QTest::newRow("ax::mojom::Role::kIgnored") << QString("<tag>a</tag>") << 0 << QAccessible::NoRole; // FIXME: The HTML element should not be exposed as an element (see AXNodeObject.cpp)
+    QTest::newRow("ax::mojom::Role::kIframePresentational")
+            << QString("<iframe role='presentation'>a</iframe>") << 1 << QAccessible::Grouping;
     QTest::newRow("ax::mojom::Role::kImage") << QString("<img>") << 1 << QAccessible::Graphic;
-    //QTest::newRow("ax::mojom::Role::kImageMap") << QString("<img usemap='map'>") << 0 << QAccessible::Document; // FIXME: AXLayoutObject::DetermineAccessiblityRole returns kImageMap but something overrides it
     //QTest::newRow("ax::mojom::Role::kInlineTextBox"); // No mapping to ARIA role
-    QTest::newRow("ax::mojom::Role::kInputTime") << QString("<input type='time'></input>") << 1 << QAccessible::SpinBox;
-    //QTest::newRow("ax::mojom::Role::kKeyboard"); // No mapping to ARIA role
+    QTest::newRow("ax::mojom::Role::kInputTime")
+            << QString("<input type='time'></input>") << 1 << QAccessible::SpinBox;
     QTest::newRow("ax::mojom::Role::kLabelText") << QString("<label>a</label>") << 1 << QAccessible::StaticText;
     QTest::newRow("ax::mojom::Role::kLayoutTable") << QString("<table><tr><td></td></tr></table>") << 0 << QAccessible::Section;
-    QTest::newRow("ax::mojom::Role::kLayoutTableCell") << QString("<table><tr><td></td></tr></table>") << 2 << QAccessible::Section;
-    //QTest::newRow("ax::mojom::Role::kLayoutTableColumn") << QString("<table><tr></tr></table>") << 1 << QAccessible::Section; // FIXME: The test case might be wrong
+    QTest::newRow("ax::mojom::Role::kLayoutTableCell")
+            << QString("<table><tr><td></td></tr></table>") << 2 << QAccessible::Section;
     QTest::newRow("ax::mojom::Role::kLayoutTableRow") << QString("<table><tr><td></td></tr></table>") << 1 << QAccessible::Section;
     QTest::newRow("ax::mojom::Role::kLegend") << QString("<legend>a</legend>") << 0 << QAccessible::StaticText;
     QTest::newRow("ax::mojom::Role::kLineBreak") << QString("<br>") << 1 << QAccessible::Separator;
@@ -463,45 +476,119 @@ void tst_Accessibility::roles_data()
     QTest::newRow("ax::mojom::Role::kMain") << QString("<main>a</main>") << 0 << QAccessible::Grouping;
     QTest::newRow("ax::mojom::Role::kMark") << QString("<mark>a</mark>") << 1 << QAccessible::StaticText;
     QTest::newRow("ax::mojom::Role::kMarquee") << QString("<div role='marquee'>a</div>") << 0 << QAccessible::Section;
-    QTest::newRow("ax::mojom::Role::kMath") << QString("<math>a</math>") << 1 << QAccessible::Equation;
+    QTest::newRow("ax::mojom::Role::kMath")
+            << QString("<math>x</math>") << 1 << QAccessible::Equation;
+    QTest::newRow("ax::mojom::Role::kMathMLMath")
+            << QString("<math><mi>x</mi></math>") << 1 << QAccessible::Equation;
+    QTest::newRow("ax::mojom::Role::kMathMLFraction")
+            << QString("<math><mfrac><mn>1</mn><mn>2</mn></mfrac></math>") << 2
+            << QAccessible::Grouping;
+    QTest::newRow("ax::mojom::Role::kMathMLIdentifier")
+            << QString("<math><mi>x</mi></math>") << 2 << QAccessible::StaticText;
+    QTest::newRow("ax::mojom::Role::kMathMLMultiscripts")
+            << QString("<math><mmultiscripts><mi>X</mi><mi>a</mi><mi>b</mi></mmultiscripts></math>")
+            << 2 << QAccessible::Section;
+    QTest::newRow("ax::mojom::Role::kMathMLNoneScript")
+            << QString("<math><mmultiscripts><none/></mmultiscripts><math>") << 3
+            << QAccessible::Section;
+    QTest::newRow("ax::mojom::Role::kMathMLNumber")
+            << QString("<math><mn>1</mn></math>") << 2 << QAccessible::StaticText;
+    QTest::newRow("ax::mojom::Role::kMathMLOperator")
+            << QString("<math><mo>+</mo></math>") << 2 << QAccessible::StaticText;
+    QTest::newRow("ax::mojom::Role::kMathMLOver")
+            << QString("<math><mover><mi>x</mi><mo>-</mo></mover>") << 2 << QAccessible::Section;
+    QTest::newRow("ax::mojom::Role::kMathMLPrescriptDelimiter")
+            << QString("<math><mmultiscripts><mprescripts/></mmultiscripts></math>") << 3
+            << QAccessible::Section;
+    QTest::newRow("ax::mojom::Role::kMathMLRoot")
+            << QString("<math><mroot><mi>x</mi><mn>3</mn></mroot></math>") << 2
+            << QAccessible::Section;
+    QTest::newRow("ax::mojom::Role::kMathMLRow")
+            << QString("<math><mrow><mn>1</mn></mrow></mi>") << 2 << QAccessible::Section;
+    QTest::newRow("ax::mojom::Role::kMathMLSquareRoot")
+            << QString("<math><msqrt><mi>x</mi></msqrt></math>") << 2 << QAccessible::Section;
+    QTest::newRow("ax::mojom::Role::kMathMLStringLiteral")
+            << QString("<math><ms>a</ms></math>") << 2 << QAccessible::StaticText;
+    QTest::newRow("ax::mojom::Role::kMathMLSub")
+            << QString("<math><msub><mi>X</mi><mn>1</mn></msub></math>") << 2
+            << QAccessible::Section;
+    QTest::newRow("ax::mojom::Role::kMathMLSubSup")
+            << QString("<math><msubsup><mi>X</mi><mn>0</mn><mn>1</mn></msubsup></math>") << 2
+            << QAccessible::Section;
+    QTest::newRow("ax::mojom::Role::kMathMLSup")
+            << QString("<math><msup><mi>X</mi><mn>1</mn></msup></math>") << 2
+            << QAccessible::Section;
+    QTest::newRow("ax::mojom::Role::kMathMLTable")
+            << QString("<math><mtable><mtr><mtd><mi>x</mi></mtd></mtd></mtr></mtable></math>") << 2
+            << QAccessible::Table;
+    QTest::newRow("ax::mojom::Role::kMathMLTableCell")
+            << QString("<math><mtable><mtr><mtd><mi>x</mi></mtd></mtd></mtr></mtable></math>") << 4
+            << QAccessible::Cell;
+    QTest::newRow("ax::mojom::Role::kMathMLTableRow")
+            << QString("<math><mtable><mtr><mtd><mi>x</mi></mtd></mtd></mtr></mtable></math>") << 3
+            << QAccessible::Row;
+    QTest::newRow("ax::mojom::Role::kMathMLText")
+            << QString("<math><mtext>a</mtext></math>") << 2 << QAccessible::StaticText;
+    QTest::newRow("ax::mojom::Role::kMathMLUnder")
+            << QString("<math><munder><mi>x</mi><mo>-</mo></munder></math>") << 2
+            << QAccessible::Section;
+    QTest::newRow("ax::mojom::Role::kMathMLUnderOver")
+            << QString("<math><munderover><mi>x</mi><mo>+</mo><mo>-</mo></munderover>") << 2
+            << QAccessible::Section;
     QTest::newRow("ax::mojom::Role::kMenu") << QString("<div role='menu'>a</div>") << 0 << QAccessible::PopupMenu;
     QTest::newRow("ax::mojom::Role::kMenuBar") << QString("<div role='menubar'>a</div>") << 0 << QAccessible::MenuBar;
     QTest::newRow("ax::mojom::Role::kMenuItem") << QString("<menu role='group'><div role='menuitem'>a</div></menu>") << 1 << QAccessible::MenuItem;
     QTest::newRow("ax::mojom::Role::kMenuItemCheckBox") << QString("<menu role='menu'><input type='checkbox'></input></menu>") << 1 << QAccessible::CheckBox;
-    QTest::newRow("ax::mojom::Role::kMenuItemRadio") << QString("<menu role='menu'><input type='radio'></input></menu>") << 1 << QAccessible::RadioButton;
-    QTest::newRow("ax::mojom::Role::kMenuButton") << QString("<menu role='menu'><input type='button' /></menu>") << 1 << QAccessible::Button;
+    QTest::newRow("ax::mojom::Role::kMenuItemRadio")
+            << QString("<menu role='menu'><input type='radio'></input></menu>") << 1
+            << QAccessible::RadioButton;
     QTest::newRow("ax::mojom::Role::kMenuListOption") << QString("<select role='menu'><option>a</option></select>") << 2 << QAccessible::MenuItem;
     QTest::newRow("ax::mojom::Role::kMenuListPopup") << QString("<select role='menu'><option>a</option></select>") << 1 << QAccessible::PopupMenu;
     QTest::newRow("ax::mojom::Role::kMeter") << QString("<meter>a</meter>") << 1 << QAccessible::Chart;
     QTest::newRow("ax::mojom::Role::kNavigation") << QString("<nav>a</nav>") << 0 << QAccessible::Section;
     QTest::newRow("ax::mojom::Role::kNote") << QString("<div role='note'>a</div>") << 0 << QAccessible::Note;
     //QTest::newRow("ax::mojom::Role::kPane"); // No mapping to ARIA role
-    QTest::newRow("ax::mojom::Role::kParagraph") << QString("<p>a</p>") << 0 << QAccessible::Paragraph;
+    QTest::newRow("ax::mojom::Role::kParagraph") << QString("<p>a</p>") << 0 << QAccessible::Grouping;
+    // QTest::newRow("ax::mojom::Role::kPdfActionableHighlight"); // No mapping to ARIA role
+    // QTest::newRow("ax::mojom::Role::kPdfRoot"); // No mapping to ARIA role
+    QTest::newRow("ax::mojom::Role::kPluginObject")
+            << QString("<object width='10' height='10'></object>") << 1 << QAccessible::Grouping;
     QTest::newRow("ax::mojom::Role::kPopUpButton") << QString("<select><option>a</option></select>") << 1 << QAccessible::PopupMenu;
-    QTest::newRow("ax::mojom::Role::kPre") << QString("<pre>a</pre>") << 0 << QAccessible::Section;
-    //QTest::newRow("ax::mojom::Role::kPresentational") << QString("<div role='presentation'>a</div>") << 0 << QAccessible::NoRole; // FIXME: Aria role 'presentation' should work
+    // QTest::newRow("ax::mojom::Role::kPortalDeprecated"); // No mapping to ARIA role
+    // QTest::newRow("ax::mojom::Role::kPreDeprecated"); // No mapping to ARIA role
     QTest::newRow("ax::mojom::Role::kProgressIndicator") << QString("<div role='progressbar' aria-valuenow='77' aria-valuemin='22' aria-valuemax='99'></div>") << 0 << QAccessible::ProgressBar;
     QTest::newRow("ax::mojom::Role::kRadioButton") << QString("<input type='radio'></input>") << 1 << QAccessible::RadioButton;
     QTest::newRow("ax::mojom::Role::kRadioGroup") << QString("<fieldset role='radiogroup'></fieldset>") << 0 << QAccessible::Grouping;
-    QTest::newRow("ax::mojom::Role::kRegion") << QString("<div role='region'>a</div>") << 0 << QAccessible::Section;
+    QTest::newRow("ax::mojom::Role::kRegion")
+            << QString("<section aria-label='section with name'/>") << 0 << QAccessible::Section;
     QTest::newRow("ax::mojom::Role::kRow") << QString("<table role=table><tr><td>a</td></tr></table>") << 1 << QAccessible::Row;
     QTest::newRow("ax::mojom::Role::kRowGroup") << QString("<table role=table><tbody role=rowgroup><tr><td>a</td></tr></tbody></table>") << 1 << QAccessible::Section;
-    QTest::newRow("ax::mojom::Role::kRowHeader") << QString("<table role=table><tr><th>a</td><td>b</td></tr></table>") << 2 << QAccessible::RowHeader;
+    QTest::newRow("ax::mojom::Role::kRowHeader") << QString("<table role=table><tr><th>a</td><td>b</td></tr></table>") << 2 << QAccessible::Cell;
     QTest::newRow("ax::mojom::Role::kRuby") << QString("<ruby>a</ruby>") << 1 << QAccessible::Grouping;
     //QTest::newRow("ax::mojom::Role::kRubyAnnotation") // No mapping to ARIA role (presents as property on enclosing ruby element)
     QTest::newRow("ax::mojom::Role::kScrollBar") << QString("<div role='scrollbar'>a</a>") << 0 << QAccessible::ScrollBar;
     //QTest::newRow("ax::mojom::Role::kScrollView"); // No mapping to ARIA role
     QTest::newRow("ax::mojom::Role::kSearch") << QString("<div role='search'>landmark</div>") << 0 << QAccessible::Section;
     QTest::newRow("ax::mojom::Role::kSearchBox") << QString("<input type='search'></input>") << 1 << QAccessible::EditableText;
-    QTest::newRow("ax::mojom::Role::kSection") << QString("<section></section>") << 0 << QAccessible::Section;
-    QTest::newRow("ax::mojom::Role::kSlider") << QString("<input type='range'>") << 1 << QAccessible::Slider;
-    //QTest::newRow("ax::mojom::Role::kSliderThumb") << QString("<input type='range'>") << 1 << QAccessible::Slider; // TODO: blink/renderer/modules/accessibility/ax_slider.cc
+    // QTest::newRow("ax::mojom::Role::kSection"); // Abstract role, not used
+    QTest::newRow("ax::mojom::Role::kSectionFooter")
+            << QString("<article><footer>a</footer><article>") << 1 << QAccessible::Section;
+    QTest::newRow("ax::mojom::Role::kSectionHeader")
+            << QString("<article><header>a</header><article>") << 1 << QAccessible::Section;
+    QTest::newRow("ax::mojom::Role::kSectionWithoutName")
+            << QString("<section/>") << 0 << QAccessible::Section;
+    QTest::newRow("ax::mojom::Role::kSlider")
+            << QString("<input type='range'>") << 1 << QAccessible::Slider;
     QTest::newRow("ax::mojom::Role::kSpinButton") << QString("<input type='number'></input>") << 1 << QAccessible::SpinBox;
     QTest::newRow("ax::mojom::Role::kSplitter") << QString("<hr>") << 0 << QAccessible::Splitter;
     QTest::newRow("ax::mojom::Role::kStaticText") << QString("a") << 1 << QAccessible::StaticText;
     QTest::newRow("ax::mojom::Role::kStatus") << QString("<output>a</output>") << 1 << QAccessible::Indicator;
     QTest::newRow("ax::mojom::Role::kStrong") << QString("<strong>a</strong>") << 1 << QAccessible::StaticText;
+    QTest::newRow("ax::mojom::Role::kSubscript")
+            << QString("<sub>subscript</sub>") << 1 << QAccessible::Grouping;
     QTest::newRow("ax::mojom::Role::kSuggestion") << QString("<div role='suggestion'></div>") << 0 << QAccessible::Section;
+    QTest::newRow("ax::mojom::Role::kSuperscript")
+            << QString("<sup>superscript</sup>") << 1 << QAccessible::Grouping;
     QTest::newRow("ax::mojom::Role::kSvgRoot") << QString("<svg width='10' height='10'><text font-size='10'>SVG</text></svg>") << 1 << QAccessible::WebDocument;
     QTest::newRow("ax::mojom::Role::kSwitch") << QString("<button aria-checked='false'>a</button>") << 1 << QAccessible::Button;
     QTest::newRow("ax::mojom::Role::kTable") << QString("<table role=table><td>a</td></table>") << 0 << QAccessible::Table;
@@ -511,12 +598,15 @@ void tst_Accessibility::roles_data()
     QTest::newRow("ax::mojom::Role::kTabPanel") << QString("<div role='tabpanel'>a</div>") << 0 << QAccessible::Pane;
     QTest::newRow("ax::mojom::Role::kTerm") << QString("<div role='term'>a</div>") << 0 << QAccessible::StaticText;
     QTest::newRow("ax::mojom::Role::kTextField") << QString("<input type='text'></input>") << 1 << QAccessible::EditableText;
+    QTest::newRow("ax::mojom::Role::kTextFieldWithComboBox")
+            << QString("<input role='combobox'>") << 1 << QAccessible::ComboBox;
     QTest::newRow("ax::mojom::Role::kTime") << QString("<time>a</time>") << 1 << QAccessible::Clock;
     QTest::newRow("ax::mojom::Role::kTimer") << QString("<div role='timer'>a</div>") << 0 << QAccessible::Clock;
     //QTest::newRow("ax::mojom::Role::kTitleBar"); // No mapping to ARIA role
     QTest::newRow("ax::mojom::Role::kToggleButton") << QString("<button aria-pressed='false'>a</button>") << 1 << QAccessible::Button;
     QTest::newRow("ax::mojom::Role::kToolbar") << QString("<div role='toolbar'>a</div>") << 0 << QAccessible::ToolBar;
-    QTest::newRow("ax::mojom::Role::kToolTip") << QString("<div role='tooltip'>a</div>") << 0 << QAccessible::ToolTip;
+    QTest::newRow("ax::mojom::Role::kTooltip")
+            << QString("<div role='tooltip'>a</div>") << 0 << QAccessible::ToolTip;
     QTest::newRow("ax::mojom::Role::kTree") << QString("<div role='tree'>a</div>") << 0 << QAccessible::Tree;
     QTest::newRow("ax::mojom::Role::kTreeGrid") << QString("<div role='treegrid'>a</div>") << 0 << QAccessible::Tree;
     QTest::newRow("ax::mojom::Role::kTreeItem") << QString("<div role='treeitem'>a</div>") << 0 << QAccessible::TreeItem;
@@ -569,7 +659,7 @@ void tst_Accessibility::objectName()
     QAccessibleInterface *p = document->child(0);
     QVERIFY(p);
     QVERIFY(p->object());
-    QCOMPARE(p->role(), QAccessible::Paragraph);
+    QCOMPARE(p->role(), QAccessible::Grouping);
     QCOMPARE(p->object()->objectName(), QStringLiteral("my_id"));
 }
 
@@ -599,7 +689,7 @@ void tst_Accessibility::crossTreeParent()
     p = p->child(0);
     QVERIFY(p);
     QVERIFY(p->object());
-    QCOMPARE(p->role(), QAccessible::Paragraph);
+    QCOMPARE(p->role(), QAccessible::Grouping);
     QCOMPARE(p->parent(), subdocument);
     QCOMPARE(p->parent()->parent()->parent()->parent(), view->child(0));
     QCOMPARE(p->parent()->parent()->parent()->parent()->parent(), view);
@@ -658,6 +748,57 @@ void tst_Accessibility::tableCellInterface()
     }
 }
 
+void tst_Accessibility::tableInterface()
+{
+    QWebEngineView webView;
+    webView.resize(400, 400);
+    webView.show();
+    QVERIFY(QTest::qWaitForWindowExposed(&webView));
+
+    QSignalSpy spyFinished(&webView, &QWebEngineView::loadFinished);
+    webView.setHtml(QLatin1String(
+            "<table>"
+            "  <caption>"
+            "    Table Autotest"
+            "  </caption>"
+            "  <thead>"
+            "    <tr>"
+            "      <th scope='col'>Column Header 1</th>"
+            "      <th scope='col'>Column Header 2</th>"
+            "    </tr>"
+            "  </thead>"
+            "  <tbody>"
+            "    <tr>"
+            "      <th scope='row'>Row Header</th>"
+            "      <td>Cell</td>"
+            "    </tr>"
+            "  </tbody>"
+            "</table>"));
+    QTRY_COMPARE(spyFinished.size(), 1);
+
+    QAccessibleInterface *view = QAccessible::queryAccessibleInterface(&webView);
+    QTRY_COMPARE_WITH_TIMEOUT(view->child(0)->childCount(), 1, 20000);
+    QAccessibleInterface *document = view->child(0);
+    QAccessibleInterface *table = document->child(0);
+
+    QAccessibleTableInterface *tableInterface = table->tableInterface();
+    QVERIFY(tableInterface);
+
+    // Check the caption
+    QAccessibleInterface *caption = tableInterface->caption();
+    QVERIFY(caption);
+    QAccessibleInterface *captionChild = caption->child(0); // get the StaticText child
+    QVERIFY(captionChild);
+    auto text = captionChild->text(QAccessible::Name);
+    QCOMPARE(text, QLatin1String("Table Autotest"));
+
+    // Check the table cells
+    QCOMPARE(tableInterface->cellAt(0, 0)->child(0)->text(QAccessible::Name), QLatin1String("Column Header 1"));
+    QCOMPARE(tableInterface->cellAt(0, 1)->child(0)->text(QAccessible::Name), QLatin1String("Column Header 2"));
+    QCOMPARE(tableInterface->cellAt(1, 0)->child(0)->text(QAccessible::Name), QLatin1String("Row Header"));
+    QCOMPARE(tableInterface->cellAt(1, 1)->child(0)->text(QAccessible::Name), QLatin1String("Cell"));
+}
+
 static QByteArrayList params = QByteArrayList()
     << "--force-renderer-accessibility"
     << "--enable-features=AccessibilityExposeARIAAnnotations"
diff --git a/tests/auto/widgets/printing/tst_printing.cpp b/tests/auto/widgets/printing/tst_printing.cpp
index f08421b5ca3..58bfa144238 100644
--- a/tests/auto/widgets/printing/tst_printing.cpp
+++ b/tests/auto/widgets/printing/tst_printing.cpp
@@ -113,7 +113,7 @@ void tst_Printing::pdfContent()
 
     QBuffer buffer;
     buffer.setData((data));
-    buffer.open(QBuffer::ReadWrite);
+    QVERIFY2(buffer.open(QBuffer::ReadWrite), qPrintable(buffer.errorString()));
     document.load(&buffer);
     QTRY_COMPARE(statusChangedSpy.size(), 2);
     QCOMPARE(statusChangedSpy[1][0].value<QPdfDocument::Status>(), QPdfDocument::Status::Ready);
@@ -167,9 +167,12 @@ void tst_Printing::printFromPdfViewer()
 
         QBuffer buffer;
         buffer.setData((data));
-        buffer.open(QBuffer::ReadWrite);
+        if (!buffer.open(QBuffer::ReadWrite)) {
+            qWarning("Failed to open buffer: %s", qPrintable(buffer.errorString()));
+            return false;
+        }
         document.load(&buffer);
-        statusChangedSpy.wait(500);
+        statusChangedSpy.wait(1000);
         if (document.status() != QPdfDocument::Status::Ready)
             return false;
 
@@ -177,12 +180,12 @@ void tst_Printing::printFromPdfViewer()
         QSignalSpy countChangedSpy(&searchModel, &QPdfSearchModel::countChanged);
         searchModel.setDocument(&document);
         searchModel.setSearchString("Hello Paper World");
-        countChangedSpy.wait(500);
+        countChangedSpy.wait(1000);
         if (searchModel.count() != 1)
             return false;
 
         return true;
-    }, 15000);
+    }, 30000);
     QVERIFY(ok);
 #endif
 }
@@ -221,7 +224,7 @@ void tst_Printing::printHeaderAndFooter()
 
     QBuffer buffer;
     buffer.setData((data));
-    buffer.open(QBuffer::ReadWrite);
+    QVERIFY2(buffer.open(QBuffer::ReadWrite), qPrintable(buffer.errorString()));
     document.load(&buffer);
     QTRY_COMPARE(document.status(), QPdfDocument::Status::Ready);
 
diff --git a/tests/auto/widgets/qwebenginedownloadrequest/CMakeLists.txt b/tests/auto/widgets/qwebenginedownloadrequest/CMakeLists.txt
index 5b76909b159..13b86a95666 100644
--- a/tests/auto/widgets/qwebenginedownloadrequest/CMakeLists.txt
+++ b/tests/auto/widgets/qwebenginedownloadrequest/CMakeLists.txt
@@ -9,6 +9,7 @@ qt_internal_add_test(tst_qwebenginedownloadrequest
         tst_qwebenginedownloadrequest.cpp
     LIBRARIES
         Qt::WebEngineWidgets
+        Qt::GuiPrivate
         Test::HttpServer
         Test::Util
 )
diff --git a/tests/auto/widgets/qwebenginedownloadrequest/tst_qwebenginedownloadrequest.cpp b/tests/auto/widgets/qwebenginedownloadrequest/tst_qwebenginedownloadrequest.cpp
index 0a273828767..15e96bc0dcd 100644
--- a/tests/auto/widgets/qwebenginedownloadrequest/tst_qwebenginedownloadrequest.cpp
+++ b/tests/auto/widgets/qwebenginedownloadrequest/tst_qwebenginedownloadrequest.cpp
@@ -2,6 +2,7 @@
 // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
 
 #include <util.h>
+#include <visualutil.h>
 
 #include <QCoreApplication>
 #include <QSignalSpy>
@@ -16,6 +17,38 @@
 #include <QWebEngineView>
 #include <httpserver.h>
 
+using namespace Qt::StringLiterals;
+
+// Based on PageWithPaintListeners in tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp
+// TODO: Factor PageWithPaintListeners out to tests/auto/util/util.h
+class TestPage : public QWebEnginePage
+{
+    Q_OBJECT
+public:
+    TestPage(QWebEngineProfile *profile) : QWebEnginePage(profile)
+    {
+        QObject::connect(this, &QWebEnginePage::loadFinished, [this]() {
+            const QString jsLCPObserver = QStringLiteral(
+                    "new PerformanceObserver((list) => {"
+                    "    const entries = list.getEntries();"
+                    "    const lastEntry = entries[entries.length - 1];"
+                    "    console.log('largestContentfulPaint: ' + lastEntry.element);"
+                    "}).observe({type: 'largest-contentful-paint', buffered: true});");
+            runJavaScript(jsLCPObserver);
+        });
+    }
+
+    void javaScriptConsoleMessage(JavaScriptConsoleMessageLevel, const QString &message, int,
+                                  const QString &) override
+    {
+        if (message == "largestContentfulPaint: [object HTMLBodyElement]"_L1)
+            emit htmlBodyElementPainted();
+    }
+
+signals:
+    void htmlBodyElementPainted();
+};
+
 class tst_QWebEngineDownloadRequest : public QObject
 {
     Q_OBJECT
@@ -60,6 +93,7 @@ private Q_SLOTS:
     void downloadToDirectoryWithFileName();
     void downloadDataUrls_data();
     void downloadDataUrls();
+    void pauseDownload();
 
 private:
     void saveLink(QPoint linkPos);
@@ -68,7 +102,7 @@ private Q_SLOTS:
 
     HttpServer *m_server;
     QWebEngineProfile *m_profile;
-    QWebEnginePage *m_page;
+    TestPage *m_page;
     QWebEngineView *m_view;
     QSet<QWebEngineDownloadRequest *> m_requestedDownloads;
     QSet<QWebEngineDownloadRequest *> m_finishedDownloads;
@@ -93,11 +127,12 @@ void tst_QWebEngineDownloadRequest::initTestCase()
             m_finishedDownloads.insert(item);
         });
     });
-    m_page = new QWebEnginePage(m_profile);
+    m_page = new TestPage(m_profile);
     m_view = new QWebEngineView;
     m_view->setPage(m_page);
     m_view->resize(640, 480);
     m_view->show();
+    m_view->window()->windowHandle()->requestActivate();
 }
 
 void tst_QWebEngineDownloadRequest::init()
@@ -359,6 +394,8 @@ void tst_QWebEngineDownloadRequest::downloadLink_data()
 
 void tst_QWebEngineDownloadRequest::downloadLink()
 {
+    SKIP_IF_NO_WINDOW_ACTIVATION();
+
     QFETCH(UserAction, userAction);
     QFETCH(bool, anchorHasDownloadAttribute);
     QFETCH(QByteArray, fileName);
@@ -454,10 +491,12 @@ void tst_QWebEngineDownloadRequest::downloadLink()
     // The only variation being whether the <a> element has a "download"
     // attribute or not.
     QSignalSpy loadSpy(m_page, &QWebEnginePage::loadFinished);
+    QSignalSpy paintSpy(m_page, &TestPage::htmlBodyElementPainted);
     m_view->load(m_server->url());
     QTRY_COMPARE(loadSpy.size(), 1);
     QCOMPARE(loadSpy.takeFirst().value(0).toBool(), true);
     QCOMPARE(indexRequestCount, 1);
+    QTRY_COMPARE(paintSpy.size(), 1);
 
     simulateUserAction(QPoint(10, 10), userAction);
 
@@ -494,6 +533,8 @@ void tst_QWebEngineDownloadRequest::downloadTwoLinks_data()
 
 void tst_QWebEngineDownloadRequest::downloadTwoLinks()
 {
+    SKIP_IF_NO_WINDOW_ACTIVATION();
+
     QFETCH(UserAction, action1);
     QFETCH(UserAction, action2);
 
@@ -552,9 +593,11 @@ void tst_QWebEngineDownloadRequest::downloadTwoLinks()
     });
 
     QSignalSpy loadSpy(m_page, &QWebEnginePage::loadFinished);
+    QSignalSpy paintSpy(m_page, &TestPage::htmlBodyElementPainted);
     m_view->load(m_server->url());
     QTRY_COMPARE(loadSpy.size(), 1);
     QCOMPARE(loadSpy.takeFirst().value(0).toBool(), true);
+    QTRY_COMPARE(paintSpy.size(), 1);
 
     // Trigger downloads
     simulateUserAction(QPoint(10, 10), action1);
@@ -983,13 +1026,13 @@ void tst_QWebEngineDownloadRequest::downloadUniqueFilenameWithTimestamp()
     // Create the first empty file without uniquifier.
     {
         QFile file(m_profile->downloadPath() + "/" + fileName);
-        file.open(QIODevice::ReadWrite);
+        QVERIFY2(file.open(QIODevice::ReadWrite), qPrintable(file.errorString()));
     }
 
     // Create 99 empty files with uniquifier.
     for (int i = 1; i < 100; i++) {
         QFile file(m_profile->downloadPath() + "/" + baseName + " (" + QString::number(i) + ")." + extension);
-        file.open(QIODevice::ReadWrite);
+        QVERIFY2(file.open(QIODevice::ReadWrite), qPrintable(file.errorString()));
     }
 
     // Create 100th (kMaxUniqueFiles) empty file with uniquifier.
@@ -1311,6 +1354,8 @@ void tst_QWebEngineDownloadRequest::downloadDataUrls_data()
 
 void tst_QWebEngineDownloadRequest::downloadDataUrls()
 {
+    SKIP_IF_NO_WINDOW_ACTIVATION();
+
     QFETCH(QByteArray, htmlData);
     QFETCH(QString, expectedFileName);
     // Set up HTTP server
@@ -1336,14 +1381,65 @@ void tst_QWebEngineDownloadRequest::downloadDataUrls()
     });
 
     QSignalSpy loadSpy(m_page, &QWebEnginePage::loadFinished);
+    QSignalSpy paintSpy(m_page, &TestPage::htmlBodyElementPainted);
     m_view->load(m_server->url());
     QTRY_COMPARE(loadSpy.size(), 1);
     QCOMPARE(loadSpy.takeFirst().value(0).toBool(), true);
+    QTRY_COMPARE(paintSpy.size(), 1);
 
     // Trigger download
     simulateUserAction(QPoint(10, 10), UserAction::ClickLink);
     QTRY_COMPARE(downloadRequestCount, 1);
 }
 
+void tst_QWebEngineDownloadRequest::pauseDownload()
+{
+    const int fileSize = 1024 * 1024 * 512;
+
+    // Set up HTTP server
+    ScopedConnection sc1 = connect(m_server, &HttpServer::newRequest, [&](HttpReqRep *rr) {
+        if (rr->requestMethod() == "GET" && rr->requestPath() == "/") {
+            rr->setResponseHeader(QByteArrayLiteral("content-type"),
+                                  QByteArrayLiteral("application/octet-stream"));
+            static const QByteArray bigfile(fileSize, '0');
+            rr->setResponseBody(bigfile);
+            rr->sendResponse();
+        }
+    });
+
+    // Set up profile and download handler
+    QTemporaryDir tmpDir;
+    QVERIFY(tmpDir.isValid());
+    m_profile->setDownloadPath(tmpDir.path());
+
+    bool firstBytesReceived = true;
+    int pausedCount = 0;
+    ScopedConnection sc2 = connect(
+            m_profile, &QWebEngineProfile::downloadRequested, [&](QWebEngineDownloadRequest *item) {
+                QCOMPARE(item->state(), QWebEngineDownloadRequest::DownloadRequested);
+                connect(item, &QWebEngineDownloadRequest::receivedBytesChanged, [item, &firstBytesReceived] {
+                    if (firstBytesReceived) {
+                        firstBytesReceived = false;
+                        item->pause();
+                    }
+                });
+                connect(item, &QWebEngineDownloadRequest::isPausedChanged, [item, &pausedCount]() {
+                    if (item->isPaused()) {
+                        pausedCount++;
+                        item->resume();
+                    }
+                });
+                item->accept();
+            });
+
+    QSignalSpy loadSpy(m_page, &QWebEnginePage::loadFinished);
+    m_view->load(m_server->url());
+    QTRY_COMPARE_WITH_TIMEOUT(loadSpy.size(), 1, 10000);
+    QTRY_COMPARE_WITH_TIMEOUT(pausedCount, 1, 10000);
+    QTRY_COMPARE_WITH_TIMEOUT(m_finishedDownloads.size(), 1, 10000);
+    QTRY_COMPARE(m_finishedDownloads.values()[0]->isPaused(), false);
+    QTRY_COMPARE(m_finishedDownloads.values()[0]->receivedBytes(), fileSize);
+}
+
 QTEST_MAIN(tst_QWebEngineDownloadRequest)
 #include "tst_qwebenginedownloadrequest.moc"
diff --git a/tests/auto/widgets/qwebenginehistory/tst_qwebenginehistory.cpp b/tests/auto/widgets/qwebenginehistory/tst_qwebenginehistory.cpp
index ad66e972c61..b4084a22d56 100644
--- a/tests/auto/widgets/qwebenginehistory/tst_qwebenginehistory.cpp
+++ b/tests/auto/widgets/qwebenginehistory/tst_qwebenginehistory.cpp
@@ -145,7 +145,7 @@ void tst_QWebEngineHistory::count()
   */
 void tst_QWebEngineHistory::back()
 {
-    QSignalSpy titleChangedSpy(page, SIGNAL(titleChanged(const QString&)));
+    QSignalSpy titleChangedSpy(page, SIGNAL(titleChanged(QString)));
 
     for (int i = histsize;i > 1;i--) {
         QTRY_COMPARE(toPlainTextSync(page), QString("page") + QString::number(i));
@@ -171,7 +171,7 @@ void tst_QWebEngineHistory::forward()
         QTRY_COMPARE(loadFinishedSpy->size(), histBackCount);
     }
 
-    QSignalSpy titleChangedSpy(page, SIGNAL(titleChanged(const QString&)));
+    QSignalSpy titleChangedSpy(page, SIGNAL(titleChanged(QString)));
     for (int i = 1;i < histsize;i++) {
         QTRY_COMPARE(toPlainTextSync(page), QString("page") + QString::number(i));
         hist->forward();
diff --git a/tests/auto/widgets/qwebenginepage/CMakeLists.txt b/tests/auto/widgets/qwebenginepage/CMakeLists.txt
index 55c35af8810..a0470e25a37 100644
--- a/tests/auto/widgets/qwebenginepage/CMakeLists.txt
+++ b/tests/auto/widgets/qwebenginepage/CMakeLists.txt
@@ -30,6 +30,8 @@ set(tst_qwebenginepage_resource_files
     "resources/frame_c.html"
     "resources/framedindex.html"
     "resources/fullscreen.html"
+    "resources/hello.js"
+    "resources/hi.js"
     "resources/iframe.html"
     "resources/iframe2.html"
     "resources/iframe3.html"
@@ -40,6 +42,7 @@ set(tst_qwebenginepage_resource_files
     "resources/path with spaces.txt"
     "resources/reload.html"
     "resources/script.html"
+    "resources/script2.html"
     "resources/style.css"
     "resources/test1.html"
     "resources/test2.html"
diff --git a/tests/auto/widgets/qwebenginepage/resources/hello.js b/tests/auto/widgets/qwebenginepage/resources/hello.js
new file mode 100644
index 00000000000..6f5e79ebf4d
--- /dev/null
+++ b/tests/auto/widgets/qwebenginepage/resources/hello.js
@@ -0,0 +1,7 @@
+// Copyright (C) 2025 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+function sayHello()
+{
+    console.warn("hello");
+}
diff --git a/tests/auto/widgets/qwebenginepage/resources/hi.js b/tests/auto/widgets/qwebenginepage/resources/hi.js
new file mode 100644
index 00000000000..30e7cc972d1
--- /dev/null
+++ b/tests/auto/widgets/qwebenginepage/resources/hi.js
@@ -0,0 +1,8 @@
+// Copyright (C) 2025 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+function sayHi()
+{
+    // Placeholder
+    console.warn("hi");
+}
diff --git a/tests/auto/widgets/qwebenginepage/resources/script2.html b/tests/auto/widgets/qwebenginepage/resources/script2.html
new file mode 100644
index 00000000000..7d511503771
--- /dev/null
+++ b/tests/auto/widgets/qwebenginepage/resources/script2.html
@@ -0,0 +1,4 @@
+<html><head>
+<script language="javascript" type="text/javascript" src="hello.js"></script>
+<script language="javascript" type="text/javascript" src="hi.js"></script>
+</head></html>
diff --git a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp
index 23dda23bd64..f2fae8d61b0 100644
--- a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp
+++ b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp
@@ -20,6 +20,7 @@
 */
 
 #include <widgetutil.h>
+#include <visualutil.h>
 #include <QtNetwork/private/qtnetworkglobal_p.h>
 #include <QtWebEngineCore/qtwebenginecore-config.h>
 #include <QtWebEngineCore/private/qtwebenginecoreglobal_p.h>
@@ -77,6 +78,8 @@
 #include <QQuickRenderControl>
 #include <QQuickWindow>
 
+using namespace Qt::StringLiterals;
+
 static void removeRecursive(const QString& dirname)
 {
     QDir dir(dirname);
@@ -134,6 +137,7 @@ private Q_SLOTS:
     void backActionUpdate();
     void localStorageVisibility();
     void consoleOutput();
+    void javaScriptConsoleMessage();
     void userAgentNewlineStripping();
     void renderWidgetHostViewNotShowTopLevel();
     void getUserMediaRequest_data();
@@ -612,7 +616,7 @@ class ConsolePage : public QWebEnginePage
         sourceIDs.append(sourceID);
     }
 
-    QList<int> levels;
+    QList<JavaScriptConsoleMessageLevel> levels;
     QStringList messages;
     QList<int> lineNumbers;
     QStringList sourceIDs;
@@ -627,6 +631,78 @@ void tst_QWebEnginePage::consoleOutput()
     QCOMPARE(page.lineNumbers.at(0), 1);
 }
 
+class TestJSMessageHandler
+{
+public:
+    inline static QList<QtMsgType> levels;
+    inline static QStringList messages;
+    inline static QList<int> lineNumbers;
+    inline static QStringList sourceIDs;
+
+    static void handler(QtMsgType type, const QMessageLogContext &context, const QString &msg)
+    {
+        if (strcmp(context.category, "js") != 0) {
+            m_originalHandler(type, context, msg);
+            return;
+        }
+
+        levels.append(type);
+        messages.append(msg);
+        lineNumbers.append(context.line);
+        sourceIDs.append(context.file);
+    }
+
+    TestJSMessageHandler() { m_originalHandler = qInstallMessageHandler(handler); }
+    ~TestJSMessageHandler() { qInstallMessageHandler(m_originalHandler); }
+
+private:
+    inline static QtMessageHandler m_originalHandler = nullptr;
+};
+
+void tst_QWebEnginePage::javaScriptConsoleMessage()
+{
+    // Test overridden QWebEnginePage::javaScriptConsoleMessage().
+    {
+        ConsolePage page;
+        QSignalSpy loadSpy(&page, SIGNAL(loadFinished(bool)));
+        page.load(QUrl("qrc:///resources/script2.html"));
+        QTRY_COMPARE_WITH_TIMEOUT(loadSpy.size(), 1, 20000);
+
+        evaluateJavaScriptSync(&page, "sayHello()");
+        QCOMPARE(page.levels.last(), QWebEnginePage::WarningMessageLevel);
+        QCOMPARE(page.messages.last(), "hello"_L1);
+        QCOMPARE(page.lineNumbers.last(), 6);
+        QCOMPARE(page.sourceIDs.last(), "qrc:///resources/hello.js"_L1);
+
+        evaluateJavaScriptSync(&page, "sayHi()");
+        QCOMPARE(page.levels.last(), QWebEnginePage::WarningMessageLevel);
+        QCOMPARE(page.messages.last(), "hi"_L1);
+        QCOMPARE(page.lineNumbers.last(), 7);
+        QCOMPARE(page.sourceIDs.last(), "qrc:///resources/hi.js"_L1);
+    }
+
+    // Test default QWebEnginePage::javaScriptConsoleMessage() handler.
+    {
+        TestJSMessageHandler handler;
+        QWebEnginePage page;
+        QSignalSpy loadSpy(&page, SIGNAL(loadFinished(bool)));
+        page.load(QUrl("qrc:///resources/script2.html"));
+        QTRY_COMPARE_WITH_TIMEOUT(loadSpy.size(), 1, 20000);
+
+        evaluateJavaScriptSync(&page, "sayHello()");
+        QCOMPARE(handler.levels.last(), QtMsgType::QtWarningMsg);
+        QCOMPARE(handler.messages.last(), "hello"_L1);
+        QCOMPARE(handler.lineNumbers.last(), 6);
+        QCOMPARE(handler.sourceIDs.last(), "qrc:///resources/hello.js"_L1);
+
+        evaluateJavaScriptSync(&page, "sayHi()");
+        QCOMPARE(handler.levels.last(), QtMsgType::QtWarningMsg);
+        QCOMPARE(handler.messages.last(), "hi"_L1);
+        QCOMPARE(handler.lineNumbers.last(), 7);
+        QCOMPARE(handler.sourceIDs.last(), "qrc:///resources/hi.js"_L1);
+    }
+}
+
 class TestPage : public QWebEnginePage {
     Q_OBJECT
 public:
@@ -2582,7 +2658,7 @@ void tst_QWebEnginePage::setContent_data()
     QTest::newRow("UTF-8 plain text") << "text/plain; charset=utf-8" << str.toUtf8() << str;
 
     QBuffer out16;
-    out16.open(QIODevice::WriteOnly);
+    QVERIFY2(out16.open(QIODevice::WriteOnly), qPrintable(out16.errorString()));
     QTextStream stream16(&out16);
     stream16.setEncoding(QStringConverter::Utf16);
     stream16 << str;
@@ -3232,6 +3308,8 @@ void tst_QWebEnginePage::mouseButtonTranslation()
 
 void tst_QWebEnginePage::mouseMovementProperties()
 {
+    SKIP_IF_NO_WINDOW_ACTIVATION();
+
     if (QGuiApplication::platformName().startsWith(QLatin1String("wayland"), Qt::CaseInsensitive))
         QSKIP("Wayland: Can't manipulating the mouse cursor in auto test.");
 
@@ -3241,7 +3319,8 @@ void tst_QWebEnginePage::mouseMovementProperties()
     view.resize(640, 480);
     QTest::mouseMove(&view, QPoint(10, 10));
     view.show();
-    QVERIFY(QTest::qWaitForWindowExposed(&view));
+    view.window()->windowHandle()->requestActivate();
+    QVERIFY(QTest::qWaitForWindowActive(&view));
 
     QSignalSpy loadFinishedSpy(&page, SIGNAL(loadFinished(bool)));
     page.setHtml(QStringLiteral(
@@ -4584,7 +4663,7 @@ void tst_QWebEnginePage::discardAbortsPendingLoadAndPreservesCommittedLoad()
 
     connect(&page, &QWebEnginePage::loadStarted,
             [&]() { page.setLifecycleState(QWebEnginePage::LifecycleState::Discarded); });
-    QString url2 = QStringLiteral("about:blank");
+    QString url2 = QStringLiteral("qrc:/resources/test1.html");
     page.setUrl(url2);
     QTRY_COMPARE(loadStartedSpy.size(), 1);
     loadStartedSpy.clear();
diff --git a/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp b/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp
index d9997d50c36..eefb418638f 100644
--- a/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp
+++ b/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp
@@ -26,6 +26,8 @@
 #include <map>
 #include <mutex>
 
+using namespace Qt::StringLiterals;
+
 class tst_QWebEngineProfile : public QObject
 {
     Q_OBJECT
@@ -173,7 +175,7 @@ class TestServer : public HttpServer
         }
 
         QFile file(resourceDir.filePath(path));
-        file.open(QIODevice::ReadOnly);
+        QVERIFY2(file.open(QIODevice::ReadOnly), qPrintable(file.errorString()));
         QByteArray data = file.readAll();
         rr->setResponseBody(data);
         QMimeDatabase db;
@@ -205,6 +207,12 @@ void tst_QWebEngineProfile::clearDataFromCache()
     // Wait for GET /favicon.ico
     QTRY_COMPARE(serverSpy.size(), 3);
 
+#if defined(Q_OS_WIN)
+    // FIXME: A http cache entry might be still in use after all the wait above and this blocks
+    //        clearing the http cache. Find a better way to wait for cache entries.
+    QTest::qWait(500);
+#endif
+
     QVERIFY(cacheDir.exists("Cache"));
     qint64 sizeBeforeClear = totalSize(cacheDir);
     QCOMPARE_GT(sizeBeforeClear, 0);
@@ -665,7 +673,7 @@ class XhrStatusUrlSchemeHandler : public QWebEngineUrlSchemeHandler
         QString path = job->requestUrl().path();
         if (path == "/") {
             QBuffer *buffer = new QBuffer(job);
-            buffer->open(QBuffer::ReadWrite);
+            QVERIFY2(buffer->open(QBuffer::ReadWrite), qPrintable(buffer->errorString()));
             buffer->write(QByteArrayLiteral(R"(
 <html>
   <body>
@@ -689,7 +697,7 @@ class XhrStatusUrlSchemeHandler : public QWebEngineUrlSchemeHandler
             job->reply("text/html", buffer);
         } else if (path == "/qwebchannel.js") {
             QFile *file = new QFile(":/qtwebchannel/qwebchannel.js", job);
-            file->open(QFile::ReadOnly);
+            QVERIFY2(file->open(QFile::ReadOnly), qPrintable(file->errorString()));
             job->reply("application/javascript", file);
         } else if (path == "/ok") {
             QBuffer *buffer = new QBuffer(job);
@@ -841,6 +849,12 @@ void tst_QWebEngineProfile::httpAcceptLanguage()
     // Test changing an existing page and profile
     QWebEngineProfile::defaultProfile()->setHttpAcceptLanguage(testLang);
     QCOMPARE(evaluateJavaScriptSync(&page, QStringLiteral("navigator.languages")).toStringList(), QStringList(testLang));
+
+    // Test language list with quality values
+    QWebEngineProfile::defaultProfile()->setHttpAcceptLanguage(
+            u"en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7"_s);
+    QCOMPARE(evaluateJavaScriptSync(&page, u"navigator.languages"_s).toStringList(),
+             QStringList({u"en-US"_s, u"en"_s, u"zh-CN"_s, u"zh"_s}));
 }
 
 void tst_QWebEngineProfile::downloadItem()
@@ -848,7 +862,7 @@ void tst_QWebEngineProfile::downloadItem()
     qRegisterMetaType<QWebEngineDownloadRequest *>();
     QWebEngineProfile testProfile;
     QWebEnginePage page(&testProfile);
-    QSignalSpy downloadSpy(&testProfile, SIGNAL(downloadRequested(QWebEngineDownloadRequest *)));
+    QSignalSpy downloadSpy(&testProfile, SIGNAL(downloadRequested(QWebEngineDownloadRequest*)));
     page.load(QUrl::fromLocalFile(QCoreApplication::applicationFilePath()));
     QTRY_COMPARE(downloadSpy.size(), 1);
 }
diff --git a/tests/auto/widgets/qwebenginescript/tst_qwebenginescript.cpp b/tests/auto/widgets/qwebenginescript/tst_qwebenginescript.cpp
index 1a4ee9c4b4b..1dfa94565e7 100644
--- a/tests/auto/widgets/qwebenginescript/tst_qwebenginescript.cpp
+++ b/tests/auto/widgets/qwebenginescript/tst_qwebenginescript.cpp
@@ -359,7 +359,10 @@ class TestObject : public QObject
 static QString readFile(const QString &path)
 {
     QFile file(path);
-    file.open(QFile::ReadOnly);
+    if (!file.open(QFile::ReadOnly)) {
+        qWarning("Failed to read file %s: %s", qPrintable(path), qPrintable(file.errorString()));
+        return QString();
+    }
     QByteArray contents = file.readAll();
     file.close();
     return contents;
diff --git a/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp b/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp
index b8f2936b3e2..e35b752c4c6 100644
--- a/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp
+++ b/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp
@@ -19,11 +19,10 @@
     Boston, MA 02110-1301, USA.
 */
 
-#undef QT_NO_FOREACH // this file contains unported legacy Q_FOREACH uses
-
 #include <QtWebEngineCore/private/qtwebenginecore-config_p.h>
 #include <qtest.h>
 #include <util.h>
+#include <visualutil.h>
 #include <private/qinputmethod_p.h>
 #include <qpainter.h>
 #include <qpagelayout.h>
@@ -288,20 +287,20 @@ void tst_QWebEngineView::pageWithPaintListeners()
 
     page.setHtml(empty);
     QTest::qWait(500); // empty page should not trigger
-    QVERIFY(firstContentfulPaintSpy.size() == 0);
-    QVERIFY(largestContentfulPaintSpy.size() == 0);
+    QCOMPARE(firstContentfulPaintSpy.size(), 0);
+    QCOMPARE(largestContentfulPaintSpy.size(), 0);
 
     page.setHtml(backgroundColor);
-    QTRY_VERIFY(firstContentfulPaintSpy.size() == 1);
+    QTRY_COMPARE(firstContentfulPaintSpy.size(), 1);
 
     page.setHtml(text);
-    QTRY_VERIFY(firstContentfulPaintSpy.size() == 2);
-    QTRY_VERIFY(largestContentfulPaintSpy.size() == 1);
+    QTRY_COMPARE(firstContentfulPaintSpy.size(), 2);
+    QTRY_COMPARE(largestContentfulPaintSpy.size(), 1);
 
-#if !QT_CONFIG(webengine_embedded_build)
-    // Embedded builds have different scrollbars that are only painted on hover
+#if !QT_CONFIG(webengine_embedded_build) && !defined(Q_OS_MACOS)
+    // Embedded builds and macOS have different scrollbars that are only painted on hover
     page.setHtml(scrollBars);
-    QTRY_VERIFY(firstContentfulPaintSpy.size() == 3);
+    QTRY_COMPARE(firstContentfulPaintSpy.size(), 3);
 #endif
 }
 
@@ -1241,6 +1240,8 @@ void tst_QWebEngineView::focusOnNavigation()
 
 void tst_QWebEngineView::focusInternalRenderWidgetHostViewQuickItem()
 {
+    SKIP_IF_NO_WINDOW_ACTIVATION();
+
     // Create a container widget, that will hold a line edit that has initial focus, and a web
     // engine view.
     QScopedPointer<QWidget> containerWidget(new QWidget);
@@ -1262,7 +1263,8 @@ void tst_QWebEngineView::focusInternalRenderWidgetHostViewQuickItem()
     containerWidget->resize(300, 200);
     containerWidget->setLayout(layout);
     containerWidget->show();
-    QVERIFY(QTest::qWaitForWindowExposed(containerWidget.data()));
+    containerWidget->window()->windowHandle()->requestActivate();
+    QVERIFY(QTest::qWaitForWindowActive(containerWidget.data()));
 
     // Load the content, and check that focus is not set.
     QSignalSpy loadSpy(webView, SIGNAL(loadFinished(bool)));
@@ -1608,6 +1610,8 @@ class WebViewWithUrlBar : public QWidget {
 
 void tst_QWebEngineView::keyboardFocusAfterPopup()
 {
+    SKIP_IF_NO_WINDOW_ACTIVATION();
+
     const QString html = QStringLiteral(
         "<html>"
         "  <body onload=\"document.getElementById('input1').focus()\">"
@@ -1619,6 +1623,8 @@ void tst_QWebEngineView::keyboardFocusAfterPopup()
     connect(window.lineEdit, &QLineEdit::editingFinished, [&] { window.webView->setHtml(html); });
     window.webView->settings()->setAttribute(QWebEngineSettings::FocusOnNavigationEnabled, true);
     window.show();
+    window.window()->windowHandle()->requestActivate();
+    QVERIFY(QTest::qWaitForWindowActive(&window));
 
     // Focus will initially go to the QLineEdit.
     QTRY_COMPARE(QApplication::focusWidget(), window.lineEdit);
@@ -1842,6 +1848,8 @@ void tst_QWebEngineView::postData()
 
 void tst_QWebEngineView::inputFieldOverridesShortcuts()
 {
+    SKIP_IF_NO_WINDOW_ACTIVATION();
+
     if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(
                 QPlatformIntegration::WindowActivation))
         QSKIP("Cannot test on platforms without window activation capability");
@@ -1861,6 +1869,7 @@ void tst_QWebEngineView::inputFieldOverridesShortcuts()
     QVERIFY(loadFinishedSpy.wait());
 
     view.show();
+    view.window()->windowHandle()->requestActivate();
     QVERIFY(QTest::qWaitForWindowActive(&view));
 
     auto inputFieldValue = [&view] () -> QString {
@@ -2054,9 +2063,12 @@ void tst_QWebEngineView::softwareInputPanel()
 
 void tst_QWebEngineView::inputContextQueryInput()
 {
+    SKIP_IF_NO_WINDOW_ACTIVATION();
+
     QWebEngineView view;
     view.resize(640, 480);
     view.show();
+    view.window()->windowHandle()->requestActivate();
 
     // testContext will be destroyed before the view, so no events are sent accidentally
     // when the view is destroyed.
@@ -2068,7 +2080,7 @@ void tst_QWebEngineView::inputContextQueryInput()
                  "  <input type='text' id='input1' value='' size='50'/>"
                  "</body></html>");
     QTRY_COMPARE(loadFinishedSpy.size(), 1);
-    QVERIFY(QTest::qWaitForWindowExposed(&view));
+    QVERIFY(QTest::qWaitForWindowActive(&view));
     QCOMPARE(testContext.infos.size(), 0);
 
     // Set focus on an input field.
@@ -2076,7 +2088,7 @@ void tst_QWebEngineView::inputContextQueryInput()
     QTest::mouseClick(view.focusProxy(), Qt::LeftButton, {}, textInputCenter);
     QTRY_COMPARE(testContext.infos.size(), 2);
     QCOMPARE(evaluateJavaScriptSync(view.page(), "document.activeElement.id").toString(), QStringLiteral("input1"));
-    foreach (const InputMethodInfo &info, testContext.infos) {
+    for (const InputMethodInfo &info : std::as_const(testContext.infos)) {
         QCOMPARE(info.cursorPosition, 0);
         QCOMPARE(info.anchorPosition, 0);
         QCOMPARE(info.surroundingText, QStringLiteral(""));
@@ -2175,7 +2187,7 @@ void tst_QWebEngineView::inputContextQueryInput()
         QApplication::sendEvent(view.focusProxy(), &event);
     }
     QTRY_COMPARE(testContext.infos.size(), 2);
-    foreach (const InputMethodInfo &info, testContext.infos) {
+    for (const InputMethodInfo &info : std::as_const(testContext.infos)) {
         QCOMPARE(info.cursorPosition, 0);
         QCOMPARE(info.anchorPosition, 0);
         QCOMPARE(info.surroundingText, QStringLiteral("QtWebEngine!"));
@@ -2561,10 +2573,13 @@ void tst_QWebEngineView::emptyInputMethodEvent()
 
 void tst_QWebEngineView::imeComposition()
 {
+    SKIP_IF_NO_WINDOW_ACTIVATION();
+
     QWebEngineView view;
     view.settings()->setAttribute(QWebEngineSettings::FocusOnNavigationEnabled, true);
     view.resize(640, 480);
     view.show();
+    view.window()->windowHandle()->requestActivate();
 
     QSignalSpy selectionChangedSpy(&view, SIGNAL(selectionChanged()));
     QSignalSpy loadFinishedSpy(&view, SIGNAL(loadFinished(bool)));
@@ -2572,7 +2587,7 @@ void tst_QWebEngineView::imeComposition()
                  "  <input type='text' id='input1' value='QtWebEngine inputMethod'/>"
                  "</body></html>");
     QVERIFY(loadFinishedSpy.wait());
-    QVERIFY(QTest::qWaitForWindowExposed(&view));
+    QVERIFY(QTest::qWaitForWindowActive(&view));
 
     evaluateJavaScriptSync(view.page(), "var inputEle = document.getElementById('input1'); inputEle.focus(); inputEle.select();");
     QTRY_COMPARE(selectionChangedSpy.size(), 1);
@@ -2780,17 +2795,20 @@ void tst_QWebEngineView::imeComposition()
 
 void tst_QWebEngineView::newlineInTextarea()
 {
+    SKIP_IF_NO_WINDOW_ACTIVATION();
+
     QWebEngineView view;
     view.settings()->setAttribute(QWebEngineSettings::FocusOnNavigationEnabled, true);
     view.resize(640, 480);
     view.show();
+    view.window()->windowHandle()->requestActivate();
 
     QSignalSpy loadFinishedSpy(&view, SIGNAL(loadFinished(bool)));
     view.page()->setHtml("<html><body>"
                          "  <textarea rows='5' cols='1' id='input1'></textarea>"
                          "</body></html>");
     QVERIFY(loadFinishedSpy.wait());
-    QVERIFY(QTest::qWaitForWindowExposed(&view));
+    QVERIFY(QTest::qWaitForWindowActive(&view));
 
     evaluateJavaScriptSync(view.page(), "var inputEle = document.getElementById('input1'); inputEle.focus(); inputEle.select();");
     QTRY_VERIFY(evaluateJavaScriptSync(view.page(), "document.getElementById('input1').value").toString().isEmpty());
@@ -3027,18 +3045,21 @@ void tst_QWebEngineView::imeCompositionQueryEvent_data()
 
 void tst_QWebEngineView::imeCompositionQueryEvent()
 {
+    SKIP_IF_NO_WINDOW_ACTIVATION();
+
     QWebEngineView view;
     view.resize(640, 480);
     view.settings()->setAttribute(QWebEngineSettings::FocusOnNavigationEnabled, true);
 
     view.show();
+    view.window()->windowHandle()->requestActivate();
 
     QSignalSpy loadFinishedSpy(&view, SIGNAL(loadFinished(bool)));
     view.setHtml("<html><body>"
                  "  <input type='text' id='input1' />"
                  "</body></html>");
     QVERIFY(loadFinishedSpy.wait());
-    QVERIFY(QTest::qWaitForWindowExposed(&view));
+    QVERIFY(QTest::qWaitForWindowActive(&view));
 
     evaluateJavaScriptSync(view.page(), "document.getElementById('input1').focus()");
     QTRY_COMPARE(evaluateJavaScriptSync(view.page(), "document.activeElement.id").toString(), QStringLiteral("input1"));
@@ -4012,21 +4033,29 @@ void tst_QWebEngineView::longKeyEventText()
 
 void tst_QWebEngineView::deferredDelete()
 {
+    // TODO: Remove this workaround when temporary qt_desktopWidget is removed from
+    //       qapplication.cpp.
+    const size_t desktopWidget = QApplication::allWidgets().size();
+    QVERIFY(desktopWidget <= 1);
+
     {
         QWebEngineView view;
         QSignalSpy loadFinishedSpy(view.page(), &QWebEnginePage::loadFinished);
         view.load(QUrl("chrome://qt"));
         view.show();
         QTRY_VERIFY(loadFinishedSpy.size());
-        QCOMPARE(QApplication::allWidgets().size(), 2); // QWebEngineView and WebEngineQuickWidget
+        // QWebEngineView and WebEngineQuickWidget
+        QCOMPARE(QApplication::allWidgets().size(), desktopWidget + 2);
     }
 
-    QCOMPARE(QApplication::allWidgets().size(), 0);
+    QCOMPARE(QApplication::allWidgets().size(), desktopWidget);
 }
 
 // QTBUG-111927
 void tst_QWebEngineView::setCursorOnEmbeddedView()
 {
+    SKIP_IF_NO_WINDOW_ACTIVATION();
+
     if (QGuiApplication::platformName().startsWith(QLatin1String("wayland"), Qt::CaseInsensitive))
         QSKIP("Wayland: Can't manipulate the mouse cursor in auto test.");
 
@@ -4051,9 +4080,9 @@ void tst_QWebEngineView::setCursorOnEmbeddedView()
     view.setHtml(html);
     parentWidget.show();
     view.show();
+    parentWidget.window()->windowHandle()->requestActivate();
 
-    QVERIFY(QTest::qWaitForWindowExposed(&parentWidget));
-    QVERIFY(QTest::qWaitForWindowExposed(&view));
+    QVERIFY(QTest::qWaitForWindowActive(&parentWidget));
 
     QTRY_VERIFY(firstPaintSpy.size());
 
diff --git a/tests/auto/widgets/spellchecking/dict/en-US.dic b/tests/auto/widgets/spellchecking/dict/en-US.dic
index 63e9164ccd5..93c7198a385 100644
--- a/tests/auto/widgets/spellchecking/dict/en-US.dic
+++ b/tests/auto/widgets/spellchecking/dict/en-US.dic
@@ -10,3 +10,4 @@ she/Q
 they/Q
 we/Q
 you/Q
+very-long-word-to-test-old-fixed-size-buffer-limit-QTBUG-132564-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/Q
diff --git a/tests/manual/quick/geopermission/CMakeLists.txt b/tests/manual/quick/geopermission/CMakeLists.txt
index 6602ceb6ff6..e6f91356074 100644
--- a/tests/manual/quick/geopermission/CMakeLists.txt
+++ b/tests/manual/quick/geopermission/CMakeLists.txt
@@ -49,8 +49,13 @@ if (APPLE)
 
     if (NOT CMAKE_GENERATOR STREQUAL "Xcode")
         # Need to sign application for location permissions to work
+        if(QT_FEATURE_debug_and_release)
+            set(exe_path "${CMAKE_CURRENT_BINARY_DIR}/$<CONFIG>/")
+        else()
+            unset(exe_path)
+        endif()
         add_custom_command(TARGET tst_geopermission
-            POST_BUILD COMMAND codesign -s - tst_geopermission.app)
+            POST_BUILD COMMAND codesign --force -s - ${exe_path}tst_geopermission.app)
     endif()
 endif()
 
diff --git a/tests/manual/widgets/geolocation/CMakeLists.txt b/tests/manual/widgets/geolocation/CMakeLists.txt
index 2ca8c2f524b..25704bfdff2 100644
--- a/tests/manual/widgets/geolocation/CMakeLists.txt
+++ b/tests/manual/widgets/geolocation/CMakeLists.txt
@@ -49,7 +49,12 @@ if (APPLE)
 
     if (NOT CMAKE_GENERATOR STREQUAL "Xcode")
         # Need to sign application for location permissions to work
+        if(QT_FEATURE_debug_and_release)
+            set(exe_path "${CMAKE_CURRENT_BINARY_DIR}/$<CONFIG>/")
+        else()
+            unset(exe_path)
+        endif()
         add_custom_command(TARGET geolocation
-            POST_BUILD COMMAND codesign -s - geolocation.app)
+            POST_BUILD COMMAND codesign --force -s - ${exe_path}geolocation.app)
     endif()
 endif()
diff --git a/tools/scripts/take_snapshot.py b/tools/scripts/take_snapshot.py
index 4b4638381e4..aadf1cbf469 100755
--- a/tools/scripts/take_snapshot.py
+++ b/tools/scripts/take_snapshot.py
@@ -202,7 +202,7 @@ def isInChromiumBlacklist(file_path):
               and not file_path.startswith('third_party/node/node_modules/polymer-analyzer/')
               and not file_path.startswith('third_party/node/node_modules/polymer-css-build/')
               and not file_path.startswith('third_party/node/node_modules/resolve/')
-              and not file_path.startswith('third_party/node/node_modules/rollup/')
+              and not file_path.startswith('third_party/node/node_modules/@rollup/')
               and not file_path.startswith('third_party/node/node_modules/shady-css-parser/')
               and not file_path.startswith('third_party/node/node_modules/source-map/')
               and not file_path.startswith('third_party/node/node_modules/stable/')
@@ -283,7 +283,7 @@ def isInChromiumBlacklist(file_path):
         ))
         or ('/test' in file_path
          and ('/testdata/' in file_path
-           or '/tests/' in file_path
+           or ('/tests/' in file_path and not file_path.startswith('third_party/rust/'))
            or ('/test/' in file_path
              and not '/webrtc/' in file_path
              and not file_path.startswith('net/test/')
diff --git a/tools/scripts/version_resolver.py b/tools/scripts/version_resolver.py
index f7cdec6fe96..aa3dfd088ec 100644
--- a/tools/scripts/version_resolver.py
+++ b/tools/scripts/version_resolver.py
@@ -43,8 +43,8 @@ def get_recursedeps(self):
         return self.local_scope["recursedeps"]
 
 
-chromium_version = '126.0.6478.165'
-chromium_branch = '6478'
+chromium_version = '130.0.6723.192'
+chromium_branch = '6723'
 
 json_url = 'http://omahaproxy.appspot.com/all.json'
 
